Compare commits
1480 Commits
release-2.
...
release-3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3947f9c8ae | ||
|
|
6c6ebaf485 | ||
|
|
57915462b0 | ||
|
|
8b94da20d3 | ||
|
|
84c65c2b50 | ||
|
|
e8c9db0084 | ||
|
|
19419b85ff | ||
|
|
5eb8a2a9f0 | ||
|
|
95bdb61ad2 | ||
|
|
d79c79b4ae | ||
|
|
9b77d1f9f3 | ||
|
|
659fa242e2 | ||
|
|
1ba13b32a8 | ||
|
|
1c38568f42 | ||
|
|
7c1f712181 | ||
|
|
81d813c4c5 | ||
|
|
2cf7e94767 | ||
|
|
9f71dd2c61 | ||
|
|
f93374a946 | ||
|
|
4158465109 | ||
|
|
125d130984 | ||
|
|
f66ef95918 | ||
|
|
634b4d4f4d | ||
|
|
ced950a764 | ||
|
|
d84c367db5 | ||
|
|
79aa3dfbcf | ||
|
|
a308c6b9d0 | ||
|
|
614c1f5d6e | ||
|
|
fde9c2b9e9 | ||
|
|
84a39671de | ||
|
|
20086543de | ||
|
|
1002e69e44 | ||
|
|
09aa930142 | ||
|
|
ada76381a1 | ||
|
|
e4d5e38727 | ||
|
|
99349193b4 | ||
|
|
d69047df2e | ||
|
|
8318fc2b61 | ||
|
|
ff5a633a8e | ||
|
|
28fcadc9ee | ||
|
|
8a98cd5e20 | ||
|
|
0706c3b3c8 | ||
|
|
17188e31c5 | ||
|
|
45d1e93ad2 | ||
|
|
4c6f8413cb | ||
|
|
db5e06a48f | ||
|
|
e51013117c | ||
|
|
11148fcda6 | ||
|
|
d74e96f65f | ||
|
|
454cd4c120 | ||
|
|
8d5992d7cf | ||
|
|
c37ad843b4 | ||
|
|
2d130bfa85 | ||
|
|
4ac1f7b09e | ||
|
|
db8d8b73a1 | ||
|
|
c2dbf50d0b | ||
|
|
7bb99ceeea | ||
|
|
44fff4f503 | ||
|
|
a087232404 | ||
|
|
ac96667af2 | ||
|
|
8f5a0a273f | ||
|
|
74869d87f6 | ||
|
|
1f0ccabd1c | ||
|
|
c6e294a130 | ||
|
|
96bff490a3 | ||
|
|
7c3155ba44 | ||
|
|
74b26edc0d | ||
|
|
959ee4c46b | ||
|
|
4a9b772b72 | ||
|
|
d5aef5c8cc | ||
|
|
7780e9ad0a | ||
|
|
4612a5a882 | ||
|
|
3a5fe38be0 | ||
|
|
d68b0c529b | ||
|
|
c41082f610 | ||
|
|
b6af8f190c | ||
|
|
850018c86b | ||
|
|
7dbda1b3cf | ||
|
|
29ead90638 | ||
|
|
d9061416a0 | ||
|
|
42406b38fb | ||
|
|
102b1b2065 | ||
|
|
c110c5a084 | ||
|
|
e24fb4ec73 | ||
|
|
9f7d4f0898 | ||
|
|
c0b7cd79a8 | ||
|
|
d4c7b7be40 | ||
|
|
5cecdc18ed | ||
|
|
48240fbded | ||
|
|
dbab9e3b93 | ||
|
|
e4d1ee44a9 | ||
|
|
4ae6035ee9 | ||
|
|
722d851082 | ||
|
|
01f253b24a | ||
|
|
a4ab14e6d0 | ||
|
|
8676fbae02 | ||
|
|
203c1750a6 | ||
|
|
2db2f73b48 | ||
|
|
3efba63e23 | ||
|
|
8f29befc65 | ||
|
|
630fd7c344 | ||
|
|
c74334669b | ||
|
|
c7dc6d0edf | ||
|
|
0f9ece76f8 | ||
|
|
ec31081927 | ||
|
|
6598b3266c | ||
|
|
0d723af8f6 | ||
|
|
5559af8d07 | ||
|
|
f50290d46d | ||
|
|
0dd3f6672d | ||
|
|
d515a5b86a | ||
|
|
e810fa1053 | ||
|
|
12ea7efd5c | ||
|
|
bcf2534e23 | ||
|
|
412e6b0a43 | ||
|
|
0d85124a46 | ||
|
|
3abfbf107e | ||
|
|
643803edfd | ||
|
|
3fbb61033f | ||
|
|
ddbe96c807 | ||
|
|
44d0baf9a2 | ||
|
|
ae67141fed | ||
|
|
b9cb41cc4a | ||
|
|
2e3341172a | ||
|
|
4310b14e0e | ||
|
|
db96dede87 | ||
|
|
ba41a7bd9c | ||
|
|
7fb9a2196c | ||
|
|
781fcc800a | ||
|
|
819da54868 | ||
|
|
276377138e | ||
|
|
a23198324f | ||
|
|
7712ca3efd | ||
|
|
389c5fb114 | ||
|
|
a360e222e8 | ||
|
|
87e9adb666 | ||
|
|
d15107c1b4 | ||
|
|
e08ae6b668 | ||
|
|
c6bc4d2cd2 | ||
|
|
08cd1c9b0c | ||
|
|
909716849e | ||
|
|
3e0ea7b490 | ||
|
|
4402c7a8ef | ||
|
|
672cd5a999 | ||
|
|
14310f9b05 | ||
|
|
d0a4b2da79 | ||
|
|
1e802f2090 | ||
|
|
c311080d8d | ||
|
|
6a45e9dbd7 | ||
|
|
bbf47b0907 | ||
|
|
a1a5fb065e | ||
|
|
36ae095c69 | ||
|
|
4ac19e2b27 | ||
|
|
08138307da | ||
|
|
eeb43d6bfd | ||
|
|
4cd134a35e | ||
|
|
2b03f2382a | ||
|
|
dbf8675de3 | ||
|
|
b78ea79d30 | ||
|
|
89b82778e6 | ||
|
|
da561ccd38 | ||
|
|
11ebb9f0f7 | ||
|
|
e7c27c9b8b | ||
|
|
0f298397b3 | ||
|
|
70215bd3ff | ||
|
|
fcebe1e485 | ||
|
|
ae8c6ecf1c | ||
|
|
62cc91efc4 | ||
|
|
774d749eef | ||
|
|
2fc53613cd | ||
|
|
135165d856 | ||
|
|
0ea8fd6996 | ||
|
|
f8fdd58e20 | ||
|
|
6e9ed4ead7 | ||
|
|
d09b0d5f72 | ||
|
|
251d5b1921 | ||
|
|
4f8ccd0dfc | ||
|
|
04430a4cdd | ||
|
|
c7aa2cb684 | ||
|
|
65012bc517 | ||
|
|
0b0e137175 | ||
|
|
6bea659d50 | ||
|
|
37f821556e | ||
|
|
532bec5d87 | ||
|
|
74a1cce46c | ||
|
|
6cdbf6f869 | ||
|
|
51cde405f9 | ||
|
|
17c122e5ad | ||
|
|
4f99b04a42 | ||
|
|
c8cc727aea | ||
|
|
8ca7603f38 | ||
|
|
af40488e5c | ||
|
|
a1298fbf58 | ||
|
|
f276ad568e | ||
|
|
a1f82db5d5 | ||
|
|
9bd8b90dbe | ||
|
|
ed49c3ad31 | ||
|
|
3c813d456c | ||
|
|
881c2babe5 | ||
|
|
2a8b530b46 | ||
|
|
1b2de035b4 | ||
|
|
2ea427bd24 | ||
|
|
02fab15e7b | ||
|
|
3b43d48836 | ||
|
|
94cfba6f23 | ||
|
|
06cd53ab92 | ||
|
|
68602cb375 | ||
|
|
ecaa81da0f | ||
|
|
d3e744d0fb | ||
|
|
d57381a524 | ||
|
|
b033beec60 | ||
|
|
d05761f1f0 | ||
|
|
6ed0d4bc1c | ||
|
|
75ff773068 | ||
|
|
caf1a050c8 | ||
|
|
4cd3c144dc | ||
|
|
4d51cc6c0f | ||
|
|
f3e90265fd | ||
|
|
d97c1d2b6b | ||
|
|
ec4490a7cb | ||
|
|
d03261480d | ||
|
|
b610ab4825 | ||
|
|
4662bcf112 | ||
|
|
890f9a7e19 | ||
|
|
7f713cbd8c | ||
|
|
0841e91ac7 | ||
|
|
73d1abd6f0 | ||
|
|
f6f69ddf63 | ||
|
|
abe3cf9323 | ||
|
|
213fd9ffb7 | ||
|
|
e67156b403 | ||
|
|
5ccf3adb4d | ||
|
|
115855a177 | ||
|
|
a052963775 | ||
|
|
84b4e7b65e | ||
|
|
c96eff2c15 | ||
|
|
7d99b21c20 | ||
|
|
224772f4c2 | ||
|
|
02c161be60 | ||
|
|
53c1846757 | ||
|
|
17d3a51285 | ||
|
|
ed0acede20 | ||
|
|
14808d2bef | ||
|
|
4cd4ad457b | ||
|
|
bb6d7ba2ff | ||
|
|
cc04ebd45f | ||
|
|
0e72583c1f | ||
|
|
7d4a3e007e | ||
|
|
6c89df7206 | ||
|
|
dd78744695 | ||
|
|
d1020b0dc7 | ||
|
|
8664a4d7ba | ||
|
|
de3108e1e5 | ||
|
|
fd8a2e05a4 | ||
|
|
e028fa9be0 | ||
|
|
42e81b9d19 | ||
|
|
107906928a | ||
|
|
7adf012f9c | ||
|
|
13cd42f053 | ||
|
|
e1750c8994 | ||
|
|
82171f5a08 | ||
|
|
7a16146f6f | ||
|
|
4f063a478c | ||
|
|
864202c757 | ||
|
|
4b42480f74 | ||
|
|
9924bb94b2 | ||
|
|
19a5fc03aa | ||
|
|
836a7c8517 | ||
|
|
3104c6aba0 | ||
|
|
e192fd35c4 | ||
|
|
235bb7c3a4 | ||
|
|
fbd97aea3f | ||
|
|
6d9c3bc644 | ||
|
|
aa327fb2df | ||
|
|
080377b662 | ||
|
|
798bd2388b | ||
|
|
102b2dc738 | ||
|
|
fca0c8ace4 | ||
|
|
522d68ab0b | ||
|
|
a730c27aef | ||
|
|
743134856e | ||
|
|
47291ea7e7 | ||
|
|
85d4946486 | ||
|
|
b6c59fd70b | ||
|
|
050aadd3fa | ||
|
|
05fc956e61 | ||
|
|
323de569df | ||
|
|
216778be64 | ||
|
|
25f8740751 | ||
|
|
0cfa3ba06d | ||
|
|
8711722257 | ||
|
|
bf59997bac | ||
|
|
a36c52ea44 | ||
|
|
c6329f6327 | ||
|
|
f261c18d73 | ||
|
|
e604d78c3c | ||
|
|
64a26e596e | ||
|
|
af997c5802 | ||
|
|
f6e4ff1ab9 | ||
|
|
09abc9d8b7 | ||
|
|
18edf7a20c | ||
|
|
7f858dfef5 | ||
|
|
625cebcaad | ||
|
|
b00950aa7a | ||
|
|
267f30414d | ||
|
|
89e3500a8e | ||
|
|
2fa0f86df4 | ||
|
|
ea0d10ebc0 | ||
|
|
5c95048b74 | ||
|
|
32a8105590 | ||
|
|
6584de3a19 | ||
|
|
1047f14680 | ||
|
|
da169fd26e | ||
|
|
2ee57ddb20 | ||
|
|
b1b29b06fe | ||
|
|
f8ce9fa98d | ||
|
|
f3e0bf3584 | ||
|
|
b7758fd6ba | ||
|
|
a284f47c42 | ||
|
|
686fd33f3e | ||
|
|
3fc1f4e162 | ||
|
|
803dc1a571 | ||
|
|
33890c297f | ||
|
|
98403e3816 | ||
|
|
7f7802680b | ||
|
|
47ffe15793 | ||
|
|
52b2cba8e2 | ||
|
|
82a0c4585c | ||
|
|
ea3c6b6b09 | ||
|
|
8bd5576b1f | ||
|
|
c085648063 | ||
|
|
f1845813a0 | ||
|
|
c8d51e91f4 | ||
|
|
ba014d0033 | ||
|
|
b486d419dc | ||
|
|
b5d447e6d0 | ||
|
|
33d9ae1e4a | ||
|
|
d8afccf948 | ||
|
|
2a4e8c1b63 | ||
|
|
30bf0a4c5f | ||
|
|
e1d85627a8 | ||
|
|
44a4889074 | ||
|
|
64fabfed5b | ||
|
|
7b04e8204f | ||
|
|
65621e2886 | ||
|
|
23b52f3d11 | ||
|
|
fbaaf10ee5 | ||
|
|
f1a3a1424f | ||
|
|
073b09ab41 | ||
|
|
d4dd04cbdc | ||
|
|
8e7ef66011 | ||
|
|
6fde7050ec | ||
|
|
164f3b761d | ||
|
|
04ad78404c | ||
|
|
1e6aa54f0e | ||
|
|
a29f858f77 | ||
|
|
7c1e91f256 | ||
|
|
2dece90144 | ||
|
|
bc605fe09e | ||
|
|
d52d64cbaf | ||
|
|
050893d8df | ||
|
|
0c514a0f07 | ||
|
|
147068afbf | ||
|
|
cdc893a6cf | ||
|
|
84c2ba2f4e | ||
|
|
4ec176b683 | ||
|
|
6b660d505c | ||
|
|
2647d9e994 | ||
|
|
70a0de8de5 | ||
|
|
454dbd5cd8 | ||
|
|
a4085ef68c | ||
|
|
0e09717a02 | ||
|
|
647f81ff84 | ||
|
|
2c7441b31d | ||
|
|
3d9b4988d9 | ||
|
|
e797365e3d | ||
|
|
a261ab14ee | ||
|
|
be5a1ae272 | ||
|
|
9913484f68 | ||
|
|
2de8b9112d | ||
|
|
75e28bb3e6 | ||
|
|
7a99eb8e23 | ||
|
|
0b15515f59 | ||
|
|
9ff7eab83b | ||
|
|
b32a68318c | ||
|
|
029505bf1d | ||
|
|
01307b377e | ||
|
|
0322002b46 | ||
|
|
e5617f4cde | ||
|
|
64dad99c36 | ||
|
|
f227130388 | ||
|
|
38d78b7606 | ||
|
|
a77be2f6ce | ||
|
|
1ad9d9b4e0 | ||
|
|
f4e5d7bc11 | ||
|
|
22e2bafa7a | ||
|
|
562e9ce108 | ||
|
|
b8598bfc14 | ||
|
|
2a31d378a5 | ||
|
|
a33a959f63 | ||
|
|
1ff3818e6b | ||
|
|
116fa8936a | ||
|
|
78663b9c27 | ||
|
|
0213b5f511 | ||
|
|
559e0ac218 | ||
|
|
94b58ca229 | ||
|
|
7aa3eff845 | ||
|
|
9a0a26dae1 | ||
|
|
d1c3a07ba6 | ||
|
|
a30dc3a823 | ||
|
|
8464720d99 | ||
|
|
4f667c6e7d | ||
|
|
365ba4341a | ||
|
|
c928987313 | ||
|
|
d5aa316613 | ||
|
|
43271d3ea7 | ||
|
|
9aa0041422 | ||
|
|
f0e98e2828 | ||
|
|
1e7668608a | ||
|
|
f918e7f0b0 | ||
|
|
a685349ae6 | ||
|
|
7c2e679c8b | ||
|
|
b6e16fbdc0 | ||
|
|
a2d3a1c41c | ||
|
|
4af28bfe81 | ||
|
|
4ba5e43933 | ||
|
|
6debc1e958 | ||
|
|
9651d8736b | ||
|
|
07ec2cce31 | ||
|
|
698171bbcf | ||
|
|
3519cb281f | ||
|
|
df23fc1de2 | ||
|
|
f445c8f872 | ||
|
|
eb035e2199 | ||
|
|
dac3a1a0ca | ||
|
|
902aa4503e | ||
|
|
314fc003b3 | ||
|
|
c36b2774ed | ||
|
|
ec08bfac07 | ||
|
|
cd754fd239 | ||
|
|
a6e7588593 | ||
|
|
008ba33ce9 | ||
|
|
f49ba3e93d | ||
|
|
e98fb61400 | ||
|
|
13e57fb9dd | ||
|
|
7234a93293 | ||
|
|
56cff16b07 | ||
|
|
aa74244abb | ||
|
|
a998f4c980 | ||
|
|
5f2fe1d5a6 | ||
|
|
f01c301839 | ||
|
|
0c0c7459f1 | ||
|
|
34a88c83f0 | ||
|
|
a8f29e51c5 | ||
|
|
964b321458 | ||
|
|
dec726c0ae | ||
|
|
025f4f9737 | ||
|
|
66b982ad03 | ||
|
|
3309706964 | ||
|
|
9d275d6d34 | ||
|
|
91f9a46c18 | ||
|
|
e017ba6863 | ||
|
|
9c7807ded4 | ||
|
|
0fa0be2d0e | ||
|
|
4e0dc5d51a | ||
|
|
14bfc4f4ed | ||
|
|
7039e2b10f | ||
|
|
e5f0edaa0a | ||
|
|
72dd95a81e | ||
|
|
4e2750262d | ||
|
|
3b60c23178 | ||
|
|
12a6ecf353 | ||
|
|
c5b5241964 | ||
|
|
eb0d1748c3 | ||
|
|
1f0d4ce871 | ||
|
|
b64caf2cb8 | ||
|
|
b286bead09 | ||
|
|
dc4d0a7078 | ||
|
|
5ec68f3ca0 | ||
|
|
da3406b811 | ||
|
|
6c753ac183 | ||
|
|
1549a443c5 | ||
|
|
28df59b9e6 | ||
|
|
1f25e6d0fe | ||
|
|
47f5d165a8 | ||
|
|
13a195d73b | ||
|
|
04e4295140 | ||
|
|
fe98c36abf | ||
|
|
ee84af0826 | ||
|
|
e1d09303f9 | ||
|
|
3749817e1b | ||
|
|
a6e862d9ea | ||
|
|
c28641ba94 | ||
|
|
5e5d8118c7 | ||
|
|
b0a01f60f7 | ||
|
|
c04095673f | ||
|
|
88d22e4309 | ||
|
|
e05cce9b59 | ||
|
|
a7a4557b29 | ||
|
|
4cb783d5bf | ||
|
|
cd830768d6 | ||
|
|
6f46c60360 | ||
|
|
d9d63141bb | ||
|
|
b6f156b7dd | ||
|
|
a647968a6f | ||
|
|
93c64d03e3 | ||
|
|
6fddbd8178 | ||
|
|
67ca3315fd | ||
|
|
168de06d47 | ||
|
|
3ee79afe4f | ||
|
|
a3163a419a | ||
|
|
a2e4e2ad37 | ||
|
|
367b17e315 | ||
|
|
ccd50262c6 | ||
|
|
c7efd0dd05 | ||
|
|
287e2a7c2d | ||
|
|
9618cc1628 | ||
|
|
d435eae35c | ||
|
|
80021c4ef6 | ||
|
|
d959a5918c | ||
|
|
5b092b3aea | ||
|
|
749e668a03 | ||
|
|
257f75a201 | ||
|
|
cfa1e8441b | ||
|
|
5b66b7a24f | ||
|
|
78ee01b03c | ||
|
|
653d49ab3c | ||
|
|
c13776d000 | ||
|
|
e71facf6d6 | ||
|
|
f2f2dad402 | ||
|
|
c6ba3b4ca3 | ||
|
|
feadedf8ef | ||
|
|
ccce8f58c9 | ||
|
|
e85efb828d | ||
|
|
4d739d4050 | ||
|
|
b172196512 | ||
|
|
3e7329fb07 | ||
|
|
9b121fd5d0 | ||
|
|
405885209b | ||
|
|
12f0954c4c | ||
|
|
8046ba4103 | ||
|
|
dce5c217c8 | ||
|
|
0161e64481 | ||
|
|
b768005f44 | ||
|
|
6838edb4fe | ||
|
|
2309c25aa4 | ||
|
|
1090e87f3a | ||
|
|
104b2aecdc | ||
|
|
465eaf028e | ||
|
|
2a76ddb81d | ||
|
|
3f2098ff5d | ||
|
|
13cd4815ee | ||
|
|
5eaf4201ae | ||
|
|
606ee3c883 | ||
|
|
a1a73af7da | ||
|
|
ed26846a54 | ||
|
|
e7125d21cb | ||
|
|
64fb49e085 | ||
|
|
0c0a90c6c2 | ||
|
|
5ca5441a48 | ||
|
|
88960556e3 | ||
|
|
d3b4ec77bc | ||
|
|
08dc932d00 | ||
|
|
d6b99a8d70 | ||
|
|
e13eeeed60 | ||
|
|
b71570bdf7 | ||
|
|
a9cffd8863 | ||
|
|
0ace60a39b | ||
|
|
d740b051cb | ||
|
|
f369e22de0 | ||
|
|
64fd3044b1 | ||
|
|
bcd81c0791 | ||
|
|
965f7f5d26 | ||
|
|
636e052faa | ||
|
|
6e1f250470 | ||
|
|
92e24e332a | ||
|
|
687d192e71 | ||
|
|
4f1cb5ab7c | ||
|
|
2fbc979136 | ||
|
|
3e98bd49e2 | ||
|
|
186bbd7fc3 | ||
|
|
34fc7407a2 | ||
|
|
aecf069975 | ||
|
|
ec90fc480c | ||
|
|
4012a64327 | ||
|
|
646c6b6e64 | ||
|
|
3eae8b3db2 | ||
|
|
8148f9a95a | ||
|
|
a756c264f9 | ||
|
|
add29f9a5c | ||
|
|
6a16ca31a2 | ||
|
|
b1cf8c16df | ||
|
|
5b2947764d | ||
|
|
452fdbcc6f | ||
|
|
1b3a758f28 | ||
|
|
4db73d421d | ||
|
|
643840d969 | ||
|
|
062b7733b1 | ||
|
|
8302b9e1d7 | ||
|
|
12bd5c9dd7 | ||
|
|
57a609a62c | ||
|
|
26228e747d | ||
|
|
6f88b072d1 | ||
|
|
f55ea07c1d | ||
|
|
0cdb833aa6 | ||
|
|
54e99b73d6 | ||
|
|
680998f9c2 | ||
|
|
12d062cd7e | ||
|
|
bb1663636a | ||
|
|
c19b33afc1 | ||
|
|
7fba885d48 | ||
|
|
aee105ec6c | ||
|
|
b6cedbe4af | ||
|
|
c8753c96db | ||
|
|
1a5056763c | ||
|
|
6621a7aa1c | ||
|
|
737e9393f4 | ||
|
|
38f1d27223 | ||
|
|
37016aebad | ||
|
|
d6e067d654 | ||
|
|
6894a4b640 | ||
|
|
8a27c79716 | ||
|
|
f2c05131c3 | ||
|
|
31ffbb1edd | ||
|
|
177e6738e4 | ||
|
|
47c40b04e4 | ||
|
|
a899209a01 | ||
|
|
ef9cb84b01 | ||
|
|
3e979931d0 | ||
|
|
60c3244faa | ||
|
|
bd89dca0af | ||
|
|
b97c6cadee | ||
|
|
1a965cc0bd | ||
|
|
4749fa45e8 | ||
|
|
6b7bd55931 | ||
|
|
a50aa2d8e5 | ||
|
|
93cdd1b98c | ||
|
|
d6353fc3b2 | ||
|
|
1809de7f1a | ||
|
|
2e3cd114bc | ||
|
|
694477855b | ||
|
|
84322976ba | ||
|
|
b7de633090 | ||
|
|
6faa227df3 | ||
|
|
051341a42a | ||
|
|
634be0012f | ||
|
|
5a4dee374c | ||
|
|
f32818d811 | ||
|
|
7d49e8868c | ||
|
|
bd3dd337c1 | ||
|
|
d85ff9e088 | ||
|
|
c82174de6b | ||
|
|
05330632f2 | ||
|
|
7d1e2e2b2a | ||
|
|
76f959599f | ||
|
|
66a4777413 | ||
|
|
65660004c5 | ||
|
|
22ed4c08f8 | ||
|
|
3dd7ac0549 | ||
|
|
89d3678adc | ||
|
|
aeb5fa036c | ||
|
|
6cf2f942e7 | ||
|
|
8758be5912 | ||
|
|
c6edf31480 | ||
|
|
c221b08982 | ||
|
|
2fc9382d7e | ||
|
|
26314fae01 | ||
|
|
573dac0b91 | ||
|
|
3bc85c29ae | ||
|
|
51bc6bd95a | ||
|
|
3598235906 | ||
|
|
b651cdb4a1 | ||
|
|
7bd9139d28 | ||
|
|
32bfd8741f | ||
|
|
51aae059e3 | ||
|
|
c7f1f52f1c | ||
|
|
222e89a782 | ||
|
|
1b54b4dbb7 | ||
|
|
f347bdeab5 | ||
|
|
559ac673e2 | ||
|
|
806ab07865 | ||
|
|
819dcacae0 | ||
|
|
7e57a63ec5 | ||
|
|
3e294d6918 | ||
|
|
a214823dcf | ||
|
|
5488d55ca2 | ||
|
|
459d2c5408 | ||
|
|
f691ce2238 | ||
|
|
38f825c8c6 | ||
|
|
948702e98b | ||
|
|
4c24f5f513 | ||
|
|
b0972fdc94 | ||
|
|
7f10f04025 | ||
|
|
eb726c42c6 | ||
|
|
b2b959d5e3 | ||
|
|
6f693bc36e | ||
|
|
adb82dfc2e | ||
|
|
aa8e4ccdef | ||
|
|
37dec0d927 | ||
|
|
847da2b106 | ||
|
|
0088c67fa7 | ||
|
|
312263da49 | ||
|
|
d12c5cdf55 | ||
|
|
8a12382f1f | ||
|
|
64f944b571 | ||
|
|
b8720b8d1c | ||
|
|
83efb442ae | ||
|
|
cf3f0a606d | ||
|
|
2508d54c10 | ||
|
|
e3c78d3a81 | ||
|
|
a5a9b47ce4 | ||
|
|
d09a0f6167 | ||
|
|
c79e801929 | ||
|
|
2a5c9ae382 | ||
|
|
7af964cfe6 | ||
|
|
e482900754 | ||
|
|
de43a0b7a1 | ||
|
|
cf7bc882f5 | ||
|
|
06c8e658aa | ||
|
|
7aa39e42c1 | ||
|
|
ca2a659970 | ||
|
|
f73f267997 | ||
|
|
d7ea394993 | ||
|
|
3f755de80b | ||
|
|
00945e5749 | ||
|
|
c43c362903 | ||
|
|
268dad58f6 | ||
|
|
61511201db | ||
|
|
38daa23be2 | ||
|
|
45ba858022 | ||
|
|
8ad821c468 | ||
|
|
5fe5c4d147 | ||
|
|
f3e465c142 | ||
|
|
d849ac32f9 | ||
|
|
e0114ebffc | ||
|
|
0fdacf4d54 | ||
|
|
30be83d445 | ||
|
|
e9d075049b | ||
|
|
c7c627015d | ||
|
|
d62554aaba | ||
|
|
d2a6887248 | ||
|
|
879f8f080d | ||
|
|
10f147ff40 | ||
|
|
23ea811095 | ||
|
|
dac0d67717 | ||
|
|
399d957142 | ||
|
|
368ae43849 | ||
|
|
669d5a12a2 | ||
|
|
0fe09aa088 | ||
|
|
6711c58ff1 | ||
|
|
2b02ec3a4e | ||
|
|
e664047c5a | ||
|
|
d7c36c9c3c | ||
|
|
82fbb351dd | ||
|
|
726c5c5f7f | ||
|
|
99089356f5 | ||
|
|
fd2ba6f635 | ||
|
|
0d1f9fcc58 | ||
|
|
a70e565edb | ||
|
|
0efcdbaf52 | ||
|
|
12e24ade70 | ||
|
|
7b659add36 | ||
|
|
d1e30cacf8 | ||
|
|
aecdc57cd4 | ||
|
|
58bc10fc47 | ||
|
|
ad7c9ace50 | ||
|
|
b897708a41 | ||
|
|
d1060ac5f3 | ||
|
|
b8e5cc01c1 | ||
|
|
a26723a57a | ||
|
|
1811ec6cab | ||
|
|
c50c9239ea | ||
|
|
820d94e014 | ||
|
|
c03f2bffce | ||
|
|
9c61acc95d | ||
|
|
e62abdd651 | ||
|
|
75cf25de62 | ||
|
|
6a8f09f9ee | ||
|
|
7340f1dc26 | ||
|
|
a78cc700c0 | ||
|
|
41d4096890 | ||
|
|
8104c41332 | ||
|
|
81b0a7f785 | ||
|
|
e73bff817c | ||
|
|
486779ceb2 | ||
|
|
283a9950f3 | ||
|
|
7f0875cda7 | ||
|
|
4d601f5383 | ||
|
|
4d76bd33fc | ||
|
|
179985954c | ||
|
|
ef34285855 | ||
|
|
bbd1c9ee42 | ||
|
|
7cffd267d8 | ||
|
|
bb11d11a72 | ||
|
|
ae09bee193 | ||
|
|
abf8c179fc | ||
|
|
5874c7bd57 | ||
|
|
12280c6a0f | ||
|
|
c40801ce99 | ||
|
|
cc192d7d47 | ||
|
|
64c256109a | ||
|
|
d93a63e01a | ||
|
|
1c6ef50b77 | ||
|
|
497e2e92f8 | ||
|
|
2e950cc28b | ||
|
|
f09ea1a884 | ||
|
|
eebb7c8477 | ||
|
|
8feb6644a3 | ||
|
|
dd30ada095 | ||
|
|
0627968c2f | ||
|
|
89249c140f | ||
|
|
90373897d6 | ||
|
|
a85ddada25 | ||
|
|
3bb474e12f | ||
|
|
3b4a312b97 | ||
|
|
7a58df594d | ||
|
|
524f837ca5 | ||
|
|
4800b456c2 | ||
|
|
4652eb8ff3 | ||
|
|
c2096e2ecd | ||
|
|
e27a648594 | ||
|
|
90b1567d13 | ||
|
|
41132d39ae | ||
|
|
0ffba231d4 | ||
|
|
c6ab0b148b | ||
|
|
183453488e | ||
|
|
c96f14a7c8 | ||
|
|
c5841146ff | ||
|
|
4ff249525b | ||
|
|
5d5bf403a8 | ||
|
|
2747481816 | ||
|
|
c9591a66e8 | ||
|
|
02c4be4eaa | ||
|
|
ee96f83211 | ||
|
|
b095a1e3fe | ||
|
|
d5aaa24ad6 | ||
|
|
9efd576d53 | ||
|
|
8e0d01643f | ||
|
|
cb817bc06f | ||
|
|
1b905d5126 | ||
|
|
ca26cc0000 | ||
|
|
00f40e6771 | ||
|
|
7a64c1ebb4 | ||
|
|
5d5f3cbdfd | ||
|
|
8bd35852dc | ||
|
|
92189b6c50 | ||
|
|
e50ab2639e | ||
|
|
33832a46c1 | ||
|
|
6a905fc9e0 | ||
|
|
15d1e3505c | ||
|
|
fda1797149 | ||
|
|
096baaf441 | ||
|
|
69cb9b906f | ||
|
|
755dc40ee4 | ||
|
|
f601aa3cfb | ||
|
|
79cb430878 | ||
|
|
90f90936e1 | ||
|
|
a98ad63d8b | ||
|
|
6d31af676e | ||
|
|
1204bf6e80 | ||
|
|
48f2b6fb66 | ||
|
|
10a4556479 | ||
|
|
f4320cb58a | ||
|
|
d31d935522 | ||
|
|
85d2fd8ce0 | ||
|
|
ad79cbb9a1 | ||
|
|
bdb0e125a4 | ||
|
|
d26179cca0 | ||
|
|
8d612e8e2d | ||
|
|
e74b39f5af | ||
|
|
aaf3194670 | ||
|
|
74079b2c86 | ||
|
|
2eae22ac06 | ||
|
|
80359f3e5e | ||
|
|
ccefe68e4c | ||
|
|
f039cec4ca | ||
|
|
5a65580169 | ||
|
|
39ea57fe29 | ||
|
|
361db3d2cd | ||
|
|
83494f999a | ||
|
|
de4cb2ede7 | ||
|
|
2f6ef9af51 | ||
|
|
2f0e15bc25 | ||
|
|
0cd4c079e9 | ||
|
|
3197d5cc2f | ||
|
|
81e4e39878 | ||
|
|
55a6bc3855 | ||
|
|
acd4b64a8b | ||
|
|
984acc581c | ||
|
|
75a65a5f49 | ||
|
|
91af418254 | ||
|
|
901326c004 | ||
|
|
8986d87ef3 | ||
|
|
a0d21ead18 | ||
|
|
122655758d | ||
|
|
9a964d871d | ||
|
|
fc4989d738 | ||
|
|
5f59ab7e48 | ||
|
|
99557543fc | ||
|
|
d7c907d17d | ||
|
|
fd9ae50a57 | ||
|
|
1398a39768 | ||
|
|
7b4b2fe0f5 | ||
|
|
23848be6eb | ||
|
|
d55f3b5aff | ||
|
|
716e84264e | ||
|
|
600c33dfa3 | ||
|
|
e6e2baf3a8 | ||
|
|
cfb4ded943 | ||
|
|
dfe5fbe34c | ||
|
|
82788b9a02 | ||
|
|
ff3cc4b8de | ||
|
|
f74a471177 | ||
|
|
50ee44a1cf | ||
|
|
7a29f3d71d | ||
|
|
30d5273bb5 | ||
|
|
0f291629cc | ||
|
|
e6e63fa529 | ||
|
|
766b210d06 | ||
|
|
c502edf9e1 | ||
|
|
53f55a79b3 | ||
|
|
f05ecf900a | ||
|
|
810a9710d7 | ||
|
|
ef6c3f5a64 | ||
|
|
0e425d6a04 | ||
|
|
29d28b1d96 | ||
|
|
c12467ee3e | ||
|
|
82e2b3a6cd | ||
|
|
33a0828a33 | ||
|
|
95e2b7ee1a | ||
|
|
bc6fd3aa72 | ||
|
|
a940917144 | ||
|
|
7bd4a1b849 | ||
|
|
f62c38a8a7 | ||
|
|
41c503eb54 | ||
|
|
8cc538085f | ||
|
|
b93cebacb2 | ||
|
|
30a3110ca7 | ||
|
|
cf447296fb | ||
|
|
dfc5e02edd | ||
|
|
bcb29fb5fa | ||
|
|
41b57a0878 | ||
|
|
0b13fa6914 | ||
|
|
c32e651c39 | ||
|
|
fefc7df910 | ||
|
|
90b520651b | ||
|
|
3389820c73 | ||
|
|
85167c9043 | ||
|
|
ce6f942ed3 | ||
|
|
5cf7e47ffa | ||
|
|
bd4bb42e95 | ||
|
|
6778b7460a | ||
|
|
0c279e0567 | ||
|
|
1bee9c6a9d | ||
|
|
691b976e11 | ||
|
|
75efd4ea6b | ||
|
|
9363b1b4f2 | ||
|
|
a69cbd2289 | ||
|
|
ca6f732c7b | ||
|
|
5f5382297c | ||
|
|
a5452d04ae | ||
|
|
8f4c4e8c40 | ||
|
|
b1f1fbf114 | ||
|
|
a2d9cce181 | ||
|
|
06ccae591e | ||
|
|
30bc14c940 | ||
|
|
33f5c8e903 | ||
|
|
8e529fc179 | ||
|
|
f3448125c3 | ||
|
|
00b4ad6ec8 | ||
|
|
a8a7b61ea9 | ||
|
|
9acac03f14 | ||
|
|
b78d6ba243 | ||
|
|
d53ca1d096 | ||
|
|
50a3e4e776 | ||
|
|
a13bb06ec3 | ||
|
|
32a6c89c8c | ||
|
|
1905a6f0d1 | ||
|
|
3bc75bb068 | ||
|
|
f0f7924325 | ||
|
|
5e48708920 | ||
|
|
58603451b4 | ||
|
|
9e3deb68de | ||
|
|
2fea7eaef2 | ||
|
|
a53a70742d | ||
|
|
0c9dbc15f9 | ||
|
|
ed468083c5 | ||
|
|
737982e92f | ||
|
|
b43e641d21 | ||
|
|
c25586b500 | ||
|
|
60d9bfe077 | ||
|
|
0d0c7559bf | ||
|
|
de4559659d | ||
|
|
16071ec266 | ||
|
|
fb03682df4 | ||
|
|
68041e382d | ||
|
|
fb60a6489b | ||
|
|
dd7e515f9c | ||
|
|
1bc6130da5 | ||
|
|
323275c340 | ||
|
|
3da9fec665 | ||
|
|
f6254e9db6 | ||
|
|
f06f820047 | ||
|
|
05643ca5d9 | ||
|
|
c0eb048fe2 | ||
|
|
78bb4104b0 | ||
|
|
6c10936f6d | ||
|
|
4ca665eb0c | ||
|
|
39e1ebaa9b | ||
|
|
0a0033b242 | ||
|
|
9eea35f530 | ||
|
|
345e9ec870 | ||
|
|
53be56746b | ||
|
|
26b8decb24 | ||
|
|
a275e26ba7 | ||
|
|
96c918ff8d | ||
|
|
2283bd2358 | ||
|
|
f6b7b8bd6e | ||
|
|
1b8a2bf7c1 | ||
|
|
33325cdfee | ||
|
|
d81f633d6b | ||
|
|
422b483d78 | ||
|
|
ec5b9c769a | ||
|
|
74081bc6f8 | ||
|
|
3c650038e2 | ||
|
|
3e4f74ab4e | ||
|
|
f7c586b47a | ||
|
|
98b09f68ae | ||
|
|
357e309dad | ||
|
|
2e544f6a74 | ||
|
|
b0d6f3f9bf | ||
|
|
380989d808 | ||
|
|
6357d6372c | ||
|
|
d744968ea6 | ||
|
|
76ca967d70 | ||
|
|
9cff66df3f | ||
|
|
72af6cb206 | ||
|
|
c7043d5c39 | ||
|
|
1036990499 | ||
|
|
f386fd9e23 | ||
|
|
1e75fa9086 | ||
|
|
252d2009cd | ||
|
|
a48d36c9a2 | ||
|
|
01ad2e9746 | ||
|
|
2f7b20c704 | ||
|
|
aae85b4498 | ||
|
|
c39244aeb6 | ||
|
|
8f22279428 | ||
|
|
5a68bc5801 | ||
|
|
46a3b382db | ||
|
|
dae959a533 | ||
|
|
eeda9379d5 | ||
|
|
80bf89857a | ||
|
|
65eb40d1f5 | ||
|
|
9cf37f5364 | ||
|
|
1ad1498c5d | ||
|
|
405b804eb5 | ||
|
|
183e150da1 | ||
|
|
f98d4e9149 | ||
|
|
dad1568657 | ||
|
|
f13fd37819 | ||
|
|
ae692ba9b8 | ||
|
|
2036326403 | ||
|
|
3ad81595df | ||
|
|
9115a2ddc2 | ||
|
|
102e25771c | ||
|
|
d65fc4575a | ||
|
|
928936046e | ||
|
|
fe6df6176d | ||
|
|
6c52dbd477 | ||
|
|
37f5c8710e | ||
|
|
341a88c2ef | ||
|
|
efe2280224 | ||
|
|
a6294e5739 | ||
|
|
c9c481fe69 | ||
|
|
8219c29b0c | ||
|
|
1e1094f8da | ||
|
|
452a8b2ae2 | ||
|
|
bf746be692 | ||
|
|
de2d2c7469 | ||
|
|
384eae7014 | ||
|
|
09ef9947b0 | ||
|
|
4385b941bb | ||
|
|
ab0355f8d6 | ||
|
|
8f439589ea | ||
|
|
ce6348bc32 | ||
|
|
4c5dd66b0f | ||
|
|
5fe562c0fa | ||
|
|
61faf34ef7 | ||
|
|
1038376cdb | ||
|
|
28d1671bb8 | ||
|
|
8e026e68d7 | ||
|
|
4be897a4e5 | ||
|
|
3f4947259b | ||
|
|
e10a51e61e | ||
|
|
381eaf4b53 | ||
|
|
1b7e681e6d | ||
|
|
1ad764de7b | ||
|
|
246903fa0a | ||
|
|
b298f9a06e | ||
|
|
efdcdeb210 | ||
|
|
6e4826a512 | ||
|
|
28ba0c25a7 | ||
|
|
ea0f384dbf | ||
|
|
9218f69d87 | ||
|
|
b9b82e959b | ||
|
|
6606cf60af | ||
|
|
94a23cf1d4 | ||
|
|
15c3836a25 | ||
|
|
afbac42420 | ||
|
|
7354e9b738 | ||
|
|
8abb1d917b | ||
|
|
7bd8bb4880 | ||
|
|
3d5487dfcb | ||
|
|
be09284192 | ||
|
|
cdf68c90ba | ||
|
|
a46f665dd4 | ||
|
|
e5e254a184 | ||
|
|
2a55aba5fa | ||
|
|
f5d04a1be9 | ||
|
|
73132afe6c | ||
|
|
1d27fa9c03 | ||
|
|
1585b307bc | ||
|
|
c882bc8a1d | ||
|
|
aefa1dba18 | ||
|
|
7bd19f7696 | ||
|
|
c25f51e866 | ||
|
|
68b13f10fe | ||
|
|
9764fe2a91 | ||
|
|
7c29e613f0 | ||
|
|
2a88e790df | ||
|
|
deb7327ee6 | ||
|
|
a82ccd8e95 | ||
|
|
4ffe100287 | ||
|
|
5990615248 | ||
|
|
e83618a1b2 | ||
|
|
9e9cdedfd3 | ||
|
|
ed5e55f85d | ||
|
|
d2907dc08c | ||
|
|
69984f9550 | ||
|
|
94f92aa4f9 | ||
|
|
9e5ec56770 | ||
|
|
b58b4d0066 | ||
|
|
11a068dfdd | ||
|
|
deb7cb9d9e | ||
|
|
085ab0e660 | ||
|
|
2ff28ff46f | ||
|
|
eb159c0b18 | ||
|
|
51b3a5164d | ||
|
|
fa30d7bd1c | ||
|
|
ea159c0146 | ||
|
|
f4c2fdd2fd | ||
|
|
0c7643cfb3 | ||
|
|
3282e53e93 | ||
|
|
2e07e911e4 | ||
|
|
e838b515b3 | ||
|
|
7854911d2f | ||
|
|
7846afaeb8 | ||
|
|
72b27eecff | ||
|
|
8c491cc831 | ||
|
|
ac097b9904 | ||
|
|
9066520076 | ||
|
|
2d83482395 | ||
|
|
7a7016b4bd | ||
|
|
f2e222adb1 | ||
|
|
d4d3991795 | ||
|
|
6d9e519cdc | ||
|
|
16ad56c13f | ||
|
|
f2df8ce1d9 | ||
|
|
921512e51d | ||
|
|
3529c5c7a0 | ||
|
|
984e6f9927 | ||
|
|
8b2f7c4661 | ||
|
|
83ce77b398 | ||
|
|
170b0798fd | ||
|
|
4795e9980b | ||
|
|
83317ca2d0 | ||
|
|
02fbd6a135 | ||
|
|
53900c386b | ||
|
|
669d1a3a46 | ||
|
|
122db6a77e | ||
|
|
86d3c98069 | ||
|
|
dc87b9f9f4 | ||
|
|
c7c30ccaee | ||
|
|
b59dded2a4 | ||
|
|
b48b9479d2 | ||
|
|
65883317c3 | ||
|
|
18e08c319f | ||
|
|
6265e2e092 | ||
|
|
bc10bbe135 | ||
|
|
31aebdc7bf | ||
|
|
269a50efe5 | ||
|
|
9b31b1cd72 | ||
|
|
e989e686a4 | ||
|
|
d6b5627363 | ||
|
|
7381b0dcf6 | ||
|
|
8589eb7c0f | ||
|
|
284fbf5512 | ||
|
|
b9aec63e92 | ||
|
|
88c063cd4d | ||
|
|
ed3fa0ccee | ||
|
|
4ec78d1405 | ||
|
|
8bfbb98509 | ||
|
|
44011c9cd9 | ||
|
|
92c7996ff4 | ||
|
|
0a17eb32cc | ||
|
|
52e7d4ad03 | ||
|
|
f843a4b13a | ||
|
|
719c30c70b | ||
|
|
b41bcdc605 | ||
|
|
0ead6f72c6 | ||
|
|
104ebbc9a1 | ||
|
|
982098a205 | ||
|
|
d5bdd2ea3e | ||
|
|
641b38690c | ||
|
|
ea433c0619 | ||
|
|
8847df60e1 | ||
|
|
3995af6489 | ||
|
|
4412476109 | ||
|
|
0c2a121304 | ||
|
|
885753391d | ||
|
|
cff7174bbb | ||
|
|
40bd040c4a | ||
|
|
0241fa7593 | ||
|
|
2f06099518 | ||
|
|
4489934c21 | ||
|
|
10d815c60d | ||
|
|
c85cb8799e | ||
|
|
fd4f46485c | ||
|
|
3154461f28 | ||
|
|
da32321f10 | ||
|
|
aec3087528 | ||
|
|
9d83439b83 | ||
|
|
684e00d639 | ||
|
|
f982501576 | ||
|
|
87a744fcf6 | ||
|
|
aca939f0ce | ||
|
|
675e8282b0 | ||
|
|
a1272fff82 | ||
|
|
5579c7ff3d | ||
|
|
f5d4404b67 | ||
|
|
851a677a48 | ||
|
|
fd8157f6ba | ||
|
|
450c1fc124 | ||
|
|
493d6ce702 | ||
|
|
35a2b227b2 | ||
|
|
6b0c976a0d | ||
|
|
f9c4150374 | ||
|
|
fad028cfa2 | ||
|
|
d9aa8cf4fd | ||
|
|
6b2da46e87 | ||
|
|
037cc655ba | ||
|
|
58bfa6f1bb | ||
|
|
0a6f591cf5 | ||
|
|
4ee623f921 | ||
|
|
e85059521e | ||
|
|
2a4abe6a77 | ||
|
|
8217ddc705 | ||
|
|
5f301b5a04 | ||
|
|
9a5568349f | ||
|
|
dc2de49cdb | ||
|
|
c63503aaa6 | ||
|
|
eaac9180e5 | ||
|
|
b8797d075f | ||
|
|
ea04f79e0f | ||
|
|
6a3d0da4ad | ||
|
|
4828a05ced | ||
|
|
f379084b68 | ||
|
|
c7314b99ea | ||
|
|
d0afd46fd3 | ||
|
|
ba7ece348c | ||
|
|
01b5844174 | ||
|
|
dfa16320f0 | ||
|
|
93a84655b6 | ||
|
|
a24dc147ab | ||
|
|
e247d0e5dc | ||
|
|
b410b7751e | ||
|
|
028051d6a5 | ||
|
|
7d4a1bc92a | ||
|
|
924b09b0f1 | ||
|
|
188a8ae4f5 | ||
|
|
1489a6bbd6 | ||
|
|
9c57cca93c | ||
|
|
6ed4724e33 | ||
|
|
63feffd985 | ||
|
|
d988b0df9c | ||
|
|
85d6365bc2 | ||
|
|
784d972602 | ||
|
|
ce4d25952c | ||
|
|
3e27595cf1 | ||
|
|
44ab905131 | ||
|
|
2a04ac55de | ||
|
|
45ad494a3e | ||
|
|
78fe44ec01 | ||
|
|
536bd85fd0 | ||
|
|
84705489fc | ||
|
|
ff085e955e | ||
|
|
4b62c24e54 | ||
|
|
c7658e2e96 | ||
|
|
9fe693630c | ||
|
|
3bba7578af | ||
|
|
53b6a25442 | ||
|
|
5e7de313fc | ||
|
|
8c91e9d4e2 | ||
|
|
078ee59b4e | ||
|
|
438e277c42 | ||
|
|
a4c1b93a42 | ||
|
|
82877a9afa | ||
|
|
6bee757652 | ||
|
|
d8cdc3094a | ||
|
|
db455c9832 | ||
|
|
b6c931905a | ||
|
|
6647973391 | ||
|
|
4c85ea678d | ||
|
|
dc27b5e976 | ||
|
|
4828f6190e | ||
|
|
84a0f92546 | ||
|
|
e3a9194010 | ||
|
|
727e212b8e | ||
|
|
df64ede724 | ||
|
|
8a07e01181 | ||
|
|
d67d4a38ce | ||
|
|
3b898c52d3 | ||
|
|
4e79411d9f | ||
|
|
524875e458 | ||
|
|
3c75774cfb | ||
|
|
596737ba2f | ||
|
|
e142aafea1 | ||
|
|
09da69918e | ||
|
|
e0c2e3dd2c | ||
|
|
5dc79e67fc | ||
|
|
14341f3be2 | ||
|
|
2acf90d813 | ||
|
|
ae1d6492d0 | ||
|
|
0a0579bc8b | ||
|
|
ead93baa21 | ||
|
|
39bad79f5a | ||
|
|
f25b198516 | ||
|
|
15d3b07f34 | ||
|
|
feeecbf395 | ||
|
|
e7abeb9bd4 | ||
|
|
879a010c3d | ||
|
|
89e64a212e | ||
|
|
82c7c02611 | ||
|
|
b6c3189fe3 | ||
|
|
82e41f36ee | ||
|
|
4b1eade157 | ||
|
|
b79ed40e32 | ||
|
|
d06e0b639e | ||
|
|
d1cfb4f066 | ||
|
|
efa1f4ebb4 | ||
|
|
fa4eda9c87 | ||
|
|
1efb122d9c | ||
|
|
c2e5ecaaa0 | ||
|
|
313dfd6475 | ||
|
|
8dd753ce46 | ||
|
|
435d0e1019 | ||
|
|
37cd9c5b7b | ||
|
|
8b9971003d | ||
|
|
79cdad47f1 | ||
|
|
8f1276350e | ||
|
|
c05e6ba580 | ||
|
|
2da5e03741 | ||
|
|
a9ce197d04 | ||
|
|
1bce5b7837 | ||
|
|
74718bc568 | ||
|
|
217937217d | ||
|
|
af1dfd41ab | ||
|
|
54c6ccc087 | ||
|
|
d9e15e40f4 | ||
|
|
12d1e852f4 | ||
|
|
802d262776 | ||
|
|
04b63829d7 | ||
|
|
8568b29cc1 | ||
|
|
b1471c2a45 | ||
|
|
a86b87244d | ||
|
|
e431b96ca1 | ||
|
|
ce5cdd0eea | ||
|
|
c5a831b8ec | ||
|
|
872002b730 | ||
|
|
cb6fad87de | ||
|
|
0f1473e212 | ||
|
|
b45171ba43 | ||
|
|
28b8f36f16 | ||
|
|
35c1389794 | ||
|
|
6ae7db4afb | ||
|
|
7b646018ea | ||
|
|
4c7a5633da | ||
|
|
76d3e9033d | ||
|
|
c9d5370dc4 | ||
|
|
7cdbe8ef34 | ||
|
|
8b819d7e9e | ||
|
|
7f0c8dde24 | ||
|
|
74c32a0ecd | ||
|
|
87174ef3a4 | ||
|
|
462c821df9 | ||
|
|
42d7e20c1d | ||
|
|
933b924766 | ||
|
|
be15e6d34c | ||
|
|
d6997e7833 | ||
|
|
e94769b58b | ||
|
|
7616c22897 | ||
|
|
138cd90736 | ||
|
|
9aae8040ef | ||
|
|
2d5612435c | ||
|
|
2b1e4912f2 | ||
|
|
b1fe50e056 | ||
|
|
09a45abd92 | ||
|
|
adf615d0cc | ||
|
|
954e010493 | ||
|
|
86b4db75be | ||
|
|
587c4f3b14 | ||
|
|
8238c13dc0 | ||
|
|
5c8dd9f0fb | ||
|
|
dfcdb18b41 | ||
|
|
e402674092 | ||
|
|
783004ae58 | ||
|
|
6ff7c6ed06 | ||
|
|
a0ecbe01a1 | ||
|
|
47c2f2e30a | ||
|
|
721fa821f7 | ||
|
|
6580d23263 | ||
|
|
0b874d9c42 | ||
|
|
679c91435d | ||
|
|
d68b7fc9cb | ||
|
|
02722dc3c9 | ||
|
|
844bd52c67 | ||
|
|
51bc67042e | ||
|
|
a8978b2ae4 | ||
|
|
fcf3b8e14a | ||
|
|
015bdc7930 | ||
|
|
370b986ab1 | ||
|
|
9d7591fc84 | ||
|
|
9b6b357c9e | ||
|
|
8fd7b86f45 | ||
|
|
35a4e4aa1c | ||
|
|
d24abc3088 | ||
|
|
615e08b74f | ||
|
|
4644b5cf15 | ||
|
|
cb719e2bf5 | ||
|
|
ab8e35b6b4 | ||
|
|
76ea7525e3 | ||
|
|
64615adc23 | ||
|
|
a205591178 | ||
|
|
25e27f4614 | ||
|
|
4a66c33a2c | ||
|
|
16be6fe474 | ||
|
|
e170d9c3a8 | ||
|
|
3adc58bb87 | ||
|
|
55aa6c36ee | ||
|
|
350bf0ffd4 | ||
|
|
a9565e363a | ||
|
|
378e24411c | ||
|
|
22c785b951 | ||
|
|
eb0053fe48 | ||
|
|
6996ccc2c8 | ||
|
|
fcef304427 | ||
|
|
bf5c1951ba | ||
|
|
e931209860 | ||
|
|
db4520a13b | ||
|
|
4305e6b1e0 | ||
|
|
b173458814 | ||
|
|
833750513b | ||
|
|
9e63a0babb | ||
|
|
e48909dea4 | ||
|
|
f306d02ac9 | ||
|
|
f9f3642116 | ||
|
|
1537c70988 | ||
|
|
847a6c75d7 | ||
|
|
ecffc5e550 | ||
|
|
65e9401c5d | ||
|
|
ae3632e5c1 | ||
|
|
9ba3862be1 | ||
|
|
793c1be9bd | ||
|
|
1ce6f4a7c3 | ||
|
|
816cfefbac | ||
|
|
0eec718354 | ||
|
|
b80148c7e4 | ||
|
|
3bc946bfb9 | ||
|
|
a62169001e |
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
src/geoip/GeoIP.dat
|
||||
src/qbittorrent
|
||||
qbittorrent.pro.user*
|
||||
conf.pri
|
||||
Makefile
|
||||
*.pyc
|
||||
*.log
|
||||
# Compiled object files
|
||||
*.o
|
||||
# Generated MOC, resource and UI files
|
||||
moc_*.cpp
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
*.moc
|
||||
src/lang/qbittorrent_*.qm
|
||||
53
.travis.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
language:
|
||||
- cpp
|
||||
|
||||
env:
|
||||
# use libtorrent 0.15.10
|
||||
- lt_source=from_dist gui=true
|
||||
- lt_source=from_dist gui=false
|
||||
# use libtorrent 0.16.X from RC_0_16 svn branch
|
||||
- lt_source=from_svn gui=true
|
||||
- lt_source=from_svn gui=false
|
||||
|
||||
branches:
|
||||
except:
|
||||
- search_encoding_windows
|
||||
- v2_9_x
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
|
||||
before_install:
|
||||
- shopt -s expand_aliases
|
||||
- alias sudo="sudo "
|
||||
# Using nprocs/2 sometimes may fail (gcc is killed by system), just use two threads
|
||||
- alias make="colormake -j2 "
|
||||
|
||||
# Also setup a virtual display for after_success target when gui == true
|
||||
- if ! $gui; then qbtconf="$qbtconf --disable-gui"; else export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ; fi
|
||||
- ltconf=" --with-libgeoip=system"
|
||||
|
||||
- echo settings
|
||||
- echo $lt_source
|
||||
- echo $ltconf
|
||||
- echo $gui
|
||||
- echo $qbtconf
|
||||
|
||||
- sudo apt-get -qq update
|
||||
# Travis can stall during heavy load if these packages are installed in one step - split the command
|
||||
- sudo apt-get -qq install debhelper qconf colormake libssl-dev libgeoip-dev
|
||||
- sudo apt-get -qq install libboost-dev libboost-filesystem-dev libboost-system-dev
|
||||
- sudo apt-get -qq install libqt4-dev
|
||||
|
||||
install:
|
||||
- if [[ "$lt_source" == "from_dist" ]]; then sudo apt-get -qq install libtorrent-rasterbar-dev; fi
|
||||
- if [[ "$lt_source" == "from_svn" ]]; then cd .. && svn co svn://svn.code.sf.net/p/libtorrent/code/branches/RC_0_16 ./libtorrent && (cd libtorrent && ./autotool.sh && ./configure $ltconf && sudo make install) && sudo ldconfig /usr/local/lib && cd $TRAVIS_BUILD_DIR ; fi
|
||||
|
||||
script:
|
||||
- qt-qconf
|
||||
- ./configure $qbtconf && sudo make install
|
||||
|
||||
after_success:
|
||||
- if $gui ; then qbittorrent --version ; else qbittorrent-nox --version ; fi
|
||||
18
.tx/config
Normal file
@@ -0,0 +1,18 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[qbittorrent.qbittorrent_v3_1_x]
|
||||
file_filter = src/lang/qbittorrent_<lang>.ts
|
||||
source_file = src/lang/qbittorrent_en.ts
|
||||
source_lang = en
|
||||
type = QT
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
|
||||
|
||||
[qbittorrent.qbittorrentdesktop_master]
|
||||
source_file = src/Icons/qBittorrent.desktop
|
||||
source_lang = en
|
||||
type = DESKTOP
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
55
AUTHORS
@@ -1,4 +1,7 @@
|
||||
Author:
|
||||
Current maintainer:
|
||||
* Sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||
|
||||
Original author:
|
||||
* Christophe Dumez <chris@qbittorrent.org>
|
||||
|
||||
Contributors:
|
||||
@@ -11,6 +14,7 @@ Contributors:
|
||||
* Grigis Gaëtan <cipher16@gmail.com>
|
||||
* Christian Kandeler <zambesi@users.sourceforge.net>
|
||||
* Silvan Scherrer <silvan.scherrer@aroa.ch>
|
||||
* Nick Tiskov <daymansmail@gmail.com>
|
||||
|
||||
Code from other projects:
|
||||
* files src/qtsingleapp/* src/lineedit/*
|
||||
@@ -25,6 +29,10 @@ Code from other projects:
|
||||
copyright: Dan Haim <negativeiq@users.sourceforge.net>
|
||||
license: BSD
|
||||
|
||||
* file src/stacktrace_win.h
|
||||
copyright: Quassel Project
|
||||
license: GPLv2/3
|
||||
|
||||
Images Authors:
|
||||
* files: src/Icons/*.png
|
||||
copyright: Gnome Icon Theme
|
||||
@@ -50,6 +58,10 @@ Images Authors:
|
||||
copyright: Greg Houston <gregory.houston@gmail.com>
|
||||
license: MIT
|
||||
|
||||
* file: src/Icons/skin/qbittorrent_mono*
|
||||
copyright: Daniel Eguren <deguren@gmail.com>
|
||||
license: LGPL
|
||||
|
||||
* file: src/search_engine/engines/btjunkie.png
|
||||
copyright: Downloaded from btjunkie.org
|
||||
|
||||
@@ -67,37 +79,46 @@ Images Authors:
|
||||
|
||||
Translations authors:
|
||||
* files: src/lang/*.ts
|
||||
* file: src/Icons/qBittorrent.desktop
|
||||
copyright:
|
||||
- Arabic: SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)
|
||||
- Arabic: SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)
|
||||
- Armenian: Hrant Ohanyan (hrantohanyan@mail.am)
|
||||
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
|
||||
- Basque: Xabier Aramendi (azpidatziak@gmail.com)
|
||||
- Belarusian: Mihas Varantsou (meequz@gmail.com)
|
||||
- Bulgarian: Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)
|
||||
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
|
||||
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
|
||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
|
||||
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com) and 冥王歐西里斯 s8321414(Transifex)
|
||||
- Croatian: Oliver Mucafir (oliver.untwist@gmail.com)
|
||||
- Czech: Jirka Vilim (web@tets.cz)
|
||||
- Czech: Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex)
|
||||
- Danish: Mathias Nielsen (comoneo@gmail.com)
|
||||
- Dutch: Pieter Heyvaert (pieter_heyvaert@hotmail.com)
|
||||
- English: Christophe Dumez (chris@qbittorrent.org)
|
||||
- Finnish: Niklas Laxström (nikerabbit@users.sourceforge.net)
|
||||
- English(Australia): Robert Readman readmanr(Transifex)
|
||||
- English(United Kingdom): Robert Readman readmanr(Transifex)
|
||||
- Finnish: Niklas Laxström (nikerabbit@users.sourceforge.net), Pekka Niemi (pekka.niemi@iki.fi) and Jiri Grönroos artnay(Transifex)
|
||||
- French: Christophe Dumez (chris@qbittorrent.org)
|
||||
- Galician: Marcos Lans (marcoslansgarza@gmail.com)
|
||||
- Galician: Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex)
|
||||
- Georgian: Beqa Arabuli (arabulibeqa@yahoo.com)
|
||||
- German: Niels Hoffmann (zentralmaschine@users.sourceforge.net)
|
||||
- Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net) and Stephanos Antaris (santaris@csd.auth.gr)
|
||||
- Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net), Stephanos Antaris (santaris@csd.auth.gr), sledgehammer999(hammered999@gmail.com) and Γιάννης Ανθυμίδης Evropi(Transifex)
|
||||
- Hebrew: David Deutsch (d.deffo@gmail.com)
|
||||
- Hungarian: Majoros Péter (majoros.j.p@t-online.hu)
|
||||
- Italian: Matteo Sechi (bu17714@gmail.com)
|
||||
- Japanese: Nardog (alphisation@gmail.com)
|
||||
- Italian: bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)
|
||||
- Japanese: Masato Hashimoto (cabezon.hashimoto@gmail.com)
|
||||
- Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
|
||||
- Norwegian: Lars-Erik Labori (hamil@users.sourceforge.net)
|
||||
- Lithuanian: Naglis Jonaitis (njonaitis@gmail.com)
|
||||
- Norwegian: Tomaso
|
||||
- Polish: Mariusz Fik (fisiu@opensuse.org)
|
||||
- Portuguese: Nick Marinho (nickmarinho@gmail.com)
|
||||
- Romanian: Obada Denis (obadadenis@users.sourceforge.net)
|
||||
- Russian: Nick Khazov (m2k3d0n at users.sourceforge.net)
|
||||
- Portuguese: Sérgio Marques smarquespt(Transifex)
|
||||
- Portuguese(Brazil): Nick Marinho (nickmarinho@gmail.com)
|
||||
- Romanian: Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex)
|
||||
- Russian: Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex)
|
||||
- Serbian: Anaximandar Milet (anaximandar at operamail.com)
|
||||
- Slovak: helix84
|
||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
||||
- Swedish: Daniel Nylander (po@danielnylander.se)
|
||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com), Alfredo Monclus alfrix(Transifex) and José Antonio Moray moray33(Transifex)
|
||||
- Swedish: Daniel Nylander (po@danielnylander.se) and Emil Hammarberg Ooglogput(Transifex)
|
||||
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
|
||||
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)
|
||||
- Ukrainian: Oleh Prypin (blaxpirit@gmail.com) and zubr139(Transifex)
|
||||
- Vietnamese: Anh Phan ppanhh(Transifex)
|
||||
license: GPLv2
|
||||
|
||||
10
COPYING
@@ -69,7 +69,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -124,7 +124,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -182,7 +182,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -239,7 +239,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -292,7 +292,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
|
||||
207
Changelog
@@ -1,39 +1,180 @@
|
||||
* Sun Jan 23 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.4
|
||||
- BUGFIX: Added unicode support to email notification
|
||||
- BUGFIX: Improved compatibility with various SMTP servers
|
||||
- BUGFIX: Fix Labeling in RSS downloader
|
||||
- BUGFIX: Avoid main window flashing on startup (closes #703984)
|
||||
- BUGFIX: Improved hostname resolution code
|
||||
- BUGFIX: Dropped dependency on libboost-thread
|
||||
- BUGFIX: Display legal notice on screen center
|
||||
- BUGFIX: Fix renaming of single-file torrents (by Vladimir Golovnev)
|
||||
- I18N: More dialog buttons are now translated (by Vladimir Golovnev)
|
||||
- I18N: Fix translation of size units (by Vladimir Golovnev)
|
||||
* Thu 16 Jan 2014 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.5
|
||||
- BUGFIX: Fix compilation with Qt 4.7. Closes #1215. (sledgehammer999)
|
||||
- BUGFIX: Third attempt at fixing saving settings on OS shutdown. (sledgehammer999)
|
||||
- BUGFIX: Preview now correctly uses the selected file. Closes #1222 #1182. (sledgehammer999)
|
||||
- BUGFIX: Allow to resize the columns in Add New Torrent dialog. Closes #1207 #676 (sledgehammer999)
|
||||
- BUGFIX: Ensure that at least one column in the tranferlist is always visible. Closes #1165. (sledgehammer999)
|
||||
- BUGFIX: Ensure that the options window will always be placed onscreen. Closes #1226. (sledgehammer999)
|
||||
- BUGFIX: Delete temporary files after they aren't needed. Closes #1188. (sledgehammer999)
|
||||
- BUGFIX: Correctly detect libtorrent version. (sledgehammer999)
|
||||
- BUGFIX: Various code cppcheck fixes (Konstantin Goncharik)
|
||||
- BUGFIX: Remove isohunt search engine and update thepiratebay url (sledgehammer999)
|
||||
- BUGFIX: Fix rss settings corruption when checking regexp and going to other rule. (Gelmir)
|
||||
- BUGFIX: Don't count paused torrents for the autoshutdown. Closes #1280. (sledgehammer999)
|
||||
- LINUX: Fix notifications with xfce4-notifyd.
|
||||
- OSX: Added basic retina support. Closes #1251. (Sébastien Lavoie)
|
||||
- OTHER: Sync translations from Transifex.
|
||||
|
||||
* Sat Jan 15 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.3
|
||||
- BUGFIX: Fix possible crashes in full allocation mode
|
||||
- BUGFIX: Fix icon size issues (Linux, icon theme)
|
||||
- BUGFIX: Fixed file priority context menu
|
||||
- BUGFIX: Remove dbus dependency in nox mode
|
||||
- BUGFIX: Fix compilation on FreeBSD
|
||||
- I18N: Improve Web UI translation
|
||||
- I18N: Updated Polish translation
|
||||
* Sun 29 Dec 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.4
|
||||
- FEATURE: Statistics dialog (Gelmir)
|
||||
- FEATURE: Tooltips explaining each peer's connection flags (sledgehammer999)
|
||||
- FEATURE: Win/Mac Check for program updates every 15min and allow the user to manually check for updates through the help menu. (sledgehammer999)
|
||||
- BUGFIX: Better dialog message for torrent delete confirmation (sledgehammer999)
|
||||
- BUGFIX: Fix resizing grip location. Closes #1146. (sledgehammer999)
|
||||
- BUGFIX: Lock toolbar in place. Closes #1144. (sledgehammer999)
|
||||
- BUGFIX: Second attempt at fixing saving settings on shutdown. (sledgehammer999)
|
||||
- BUGFIX: Sort labels in 'Add new torrent' dialog. Closes #1150 #411. (sledgehammer999)
|
||||
- LINUX: Fix build under Ubuntu 13.10 (sledgehammer999)
|
||||
- LINUX: Make sleep and shutdown functions work on systemd's logind (Faheem Pervez)
|
||||
|
||||
* Wed Jan 12 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.2
|
||||
- BUGFIX: Do not report PeX as being disabled when DHT is
|
||||
- BUGFIX: Fix possible crash on adding magnet links
|
||||
- BUGFIX: Fix torrent import (was not working)
|
||||
- I18N: Updated Greek, Croatian, Russian, Unkrainian and Bulgarian translations
|
||||
- I18N: Added Armenian translation (New)
|
||||
- I18N: Remove country flags from program preferences (language selection)
|
||||
- I18N: Translate locale names (language selection)
|
||||
* Mon Nov 20 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.3
|
||||
- FEATURE: Add a key shortcut to "Add link to torrent..." (Angel Alonso)
|
||||
- BUGFIX: Make all columns and headers use the same text alignment in the transferlist. (sledgehammer999)
|
||||
- BUGFIX: Fix build system for Unix/Linux. (sledgehammer999)
|
||||
- BUGFIX: Case insensitive sort in Peers list. Closes #1066. (sledgehammer999)
|
||||
- BUGFIX: Small optimization of WebUI responses when there isn't a data payload. (sledgehammer999)
|
||||
- BUGFIX: Hide empty folders after filtering. Closes #74. (sledgehammer999)
|
||||
- BUGFIX: Expand folders when filtering files. Closes #1076. (sledgehammer999)
|
||||
- BUGFIX: Updated search plugin's URL (Zach Thibeau)
|
||||
- BUGFIX: Strip some png to fix incorrect sRGB profiles. (Angel Alonso)
|
||||
- BUGFIX: Fixed font issues on OSX Mavericks (Zach Thibeau)
|
||||
- BUGFIX: Improve text in the About dialog (Artem S. Tashkinov)
|
||||
- BUGFIX: Always show a peer IP address as a tool tip (Artem S. Tashkinov)
|
||||
- BUGFIX: Fix inhibit system functionality. Closes #766. (sledgehammer999)
|
||||
- BUGFIX: WebUI: Don't gzip too small payloads. (sledgehammer999)
|
||||
- BUGFIX: Correctly detect if the browser supports gzip compression. (sledgehammer999)
|
||||
- BUGFIX: Fix WebUI link to 'Anonymous mode' explanation. Closes #1093. (sledgehammer999)
|
||||
- BUGFIX: Correctly update tracker tier number in the trackers tab. Closes #1075. (sledgehammer999)
|
||||
- BUGFIX: Speed improvements.(sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
|
||||
* Tue Nov 05 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.2
|
||||
- BUGFIX: Fix WebUI gzip compression. Closes #1037. (sledgehammer999)
|
||||
- BUGFIX: Fix compilation with qt < 4.8.0. Closes #1043. (sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
|
||||
* Mon Jan 10 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.1
|
||||
- BUGFIX: Really disable torrent addition dialog by default
|
||||
- BUGFIX: Fix some missing icons in the Web UI
|
||||
- BUGFIX: Fix magnet torrent name update problem
|
||||
- COSMETIC: Use 24px size for toolbar icons and reduce spacing
|
||||
- COSMETIC: Move transfer list filter on the right side of the toolbar
|
||||
* Mon Oct 28 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.1
|
||||
- FEATURE: Show external IP in the log. Closes #968. (sledgehammer999)
|
||||
- FEATURE: Enable gzip compression in the webui. It should be faster now. (sledgehammer999)
|
||||
- FEATURE: Torrents show more states(queued for checking, downloading metadata, allocating, checking resume). (sledgehammer999)
|
||||
- FEATURE: Reenable "force reannounce" to all trackers. (sledgehammer999)
|
||||
- FEATURE: Allow to clear the UI lock password. Closes #973. (sledgehammer999)
|
||||
- FEATURE: New translations: English(Australia) and English(United Kingdom)
|
||||
- BUGFIX: Expose all available translation in the WebUI. Closes #976. (sledgehammer999)
|
||||
- BUGFIX: Copy IP copied wrong data. Closes #970 (sledgehammer999)
|
||||
- BUGFIX: "Preview file..." didn't work on single file torrents. (sledgehammer999)
|
||||
- BUGFIX: Fix and improve the scheduler (Gelmir and sledgehammer999)
|
||||
- BUGFIX: RSS fixes. Closes #960, #998 (Gelmir)
|
||||
- BUGFIX: Fix 'append label to save path' with magnet links. (sledgehammer999)
|
||||
- BUGFIX: Can download up to 10MB .torrent file when a link is provided. Closes #879 (sledgehammer999)
|
||||
- OTHER: Updated translations.
|
||||
- LINUX: Fix missing conf.pri error (leigh123linux)
|
||||
- WINDOWS: Don't remove file associations if they aren't our own. (sledgehammer999)
|
||||
|
||||
* Sat Oct 12 2013 - Christophe Dumez <chris@qbittorrent.org> and sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.1.0
|
||||
- FEATURE: Add command line option to daemonize qbittorrent-nox (ngaro)
|
||||
- FEATURE: Add "Shutdown qBittorrent" button to Web UI (ngaro)
|
||||
- FEATURE: Add setting to copy .torrent files for finished downloads (Driim)
|
||||
- FEATURE: Add option to start qBittorrent on Windows startup (sledgehammer999)
|
||||
- FEATURE: Add context menu to Web seed list (Gelmir)
|
||||
- FEATURE: Add support for tracker tiers / groups to creator (Gelmir)
|
||||
- FEATURE: Allow clearing execution and ban logs (Gelmir)
|
||||
- FEATURE: Add option to use random port on each startup (ireallylikeher)
|
||||
- FEATURE: Expose the cache expiry to the user (Gelmir)
|
||||
- FEATURE: Support Atom feeds (Gelmir)
|
||||
- FEATURE: Add "save path" column (John Peterson)
|
||||
- FEATURE: Add μTorrent-compatible "Flags" column in the peer tab(sledgehammer999)
|
||||
- FEATURE: Load magnet metadata in the background while the "Add New Torrent" Dialog is showing (Gelmir)
|
||||
- FEATURE: Allow to enter only an info-hash for download(sledgehammer999)
|
||||
- FEATURE: Bring the "Add New Torrent" Dialog to the front(glassez)
|
||||
- BUGFIX: Add confirmation dialog for "Force recheck" action (closes #131)
|
||||
- BUGFIX: Greatly improve RSS manager performance (closes #34)
|
||||
- BUGFIX: Ensure that all columns in the tranferlist have a size > 0.
|
||||
- BUGFIX: Don't mark RSS item as read when it failed to download (Gelmir)
|
||||
- BUGFIX: Fix ETA calculation when some files are downloaded and marked afterwards as 'do not download'(sledgehammer999)
|
||||
- BUGFIX: Make the UI show that PEX/DHT/LSD are actually disabled on private torrents(sledgehammer999)
|
||||
- BUGFIX: Scheduler should be much more robust and correct now(sledgehammer999)
|
||||
- BUGFIX: Now qBt won't forget torrent settings after an unclean shutdown(sledgehammer999)
|
||||
- BUGFIX: Text boxes in edit dialogs will fit to text width(Gelmir)
|
||||
- BUGFIX: Enable edit/rename via F2 or double click in various places(Gelmir)
|
||||
- BUGFIX: Allow to edit trackers and copy their urls(Gelmir and Driim)
|
||||
- BUGFIX: Add Uploaded column to main view(Gelmir)
|
||||
- BUGFIX: Calculate ETA for seeding torrents(Gelmir)
|
||||
- BUGFIX: Add option to ignore global share ratio limits for created torrents(Gelmir)
|
||||
- OTHER: Many RSS bugfixes and improvements all over the place(Gelmir)
|
||||
- OTHER: Generate translations at configure time to reduce tarball size
|
||||
- OTHER: Make peer tab sortable by ip too (Gelmir)
|
||||
- OTHER: Translations moved to Transifex(https://www.transifex.com/projects/p/qbittorrent/)
|
||||
- OTHER: New Translation - Vietnamese (Anh Phan)
|
||||
- PERFORMANCE: Impove drawing speed of tranferlist when there are many torrents(>100)
|
||||
- PERFORMANCE: Impove drawing speed of peers list when there are many peers
|
||||
|
||||
* Thu Aug 09 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.0
|
||||
- FEATURE: Brand new torrent addition dialog
|
||||
- FEATURE: Add the ability to choose the save path when using magnet links (mutoso)
|
||||
- FEATURE: Add support for adding multiple local torrents at once (Web UI)
|
||||
- COSMETIC: Improve style of left panel
|
||||
- BUGFIX: Lower panels no longer gets disabled
|
||||
- BUGFIX: Major code refactoring and various optimizations.
|
||||
- BUGFIX: No longer strip root folder from torrent files
|
||||
- OTHER: Drop support for libtorrent v0.14.x
|
||||
- OTHER: Drop support for Qt 4.5
|
||||
|
||||
* Sat Oct 08 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.0
|
||||
- FEATURE: Add file association settings to program preferences (Windows)
|
||||
- FEATURE: Add setting to ignore slow torrents in queueing system
|
||||
- FEATURE: Add advanced setting to announce to all trackers
|
||||
- FEATURE: Add support for anonymous mode (libtorrent >= v0.16)
|
||||
- FEATURE: Add quick "set as default save path" checkbox to torrent addition dialog (sledgehammer999)
|
||||
- BUGFIX: Add tray menu entry for toggling window visibility
|
||||
- BUGFIX: Fix execution log lines selection and copying
|
||||
- BUGFIX: Reduce CPU usage when running Web UI
|
||||
- BUGFIX: Save RSS items to disk regularly for safety
|
||||
- BUGFIX: Fix ratio calculation (use all_time_download)
|
||||
- BUGFIX: Fix torrent upload issues (Web UI)
|
||||
- BUGFIX: Fix some IE incompatibilities (Web UI)
|
||||
- COSMETIC: Display speed at the beginning of the Window title
|
||||
- COSMETIC: Several cosmetic fixes to the Web UI
|
||||
- COSMETIC: Make top toolbar follow system style
|
||||
- OTHER: Display libraries versions in about dialog (sledgehammer999)
|
||||
- OTHER: Display qBittorrent version in Web UI about dialog
|
||||
|
||||
* Thu Jun 02 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.8.0
|
||||
- FEATURE: Added full libtorrent v0.16 support (uTP, ...)
|
||||
- FEATURE: Proxy can be disabled for peer connections
|
||||
- FEATURE: Added support for secure SMTP connection (SSL)
|
||||
- FEATURE: Added support for SMTP authentication
|
||||
- FEATURE: Added UPnP/NAT-PMP port forward for the Web UI port
|
||||
- FEATURE: qBittorrent can update dynamic DNS services (DynDNS, no-ip)
|
||||
- FEATURE: Display peer connection type in peer list (BT, uTP, Web)
|
||||
- FEATURE: Added full regex support to RSS downloader
|
||||
- FEATURE: Added regex help and validation in RSS downloader
|
||||
- FEATURE: Added HTTPS support to Web UI (Ishan Arora)
|
||||
- BUGFIX: Change systray icon on the fly (no restart needed)
|
||||
- BUGFIX: Remember peer-level rate limits (requires libtorrent v0.16)
|
||||
- BUGFIX: Stop annoncing to trackers an all tiers (more respectful)
|
||||
- BUGFIX: Stop sharing private trackers with other peers
|
||||
- BUGFIX: Tracker exchange extension can be disabled
|
||||
- BUGFIX: Cleaner program exit on system log out
|
||||
- BUGFIX: Fix possible magnet link parsing problems
|
||||
- BUGFIX: Fix possible RSS URL parsing problems
|
||||
- COSMETIC: Added monochrome icon for light themes
|
||||
|
||||
* Sun Mar 20 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.7.0
|
||||
- FEATURE: Added search field for torrent content
|
||||
- FEATURE: Added auto-shutdown confirmation dialog
|
||||
- FEATURE: Added option to skip torrent deletion confirmation (Ville Kiiskinen)
|
||||
- FEATURE: IP address reported to trackers is now customizable
|
||||
- FEATURE: Inhibit system sleep when torrents are active (Vladimir Golovnev)
|
||||
- FEATURE: Added option to bypass Web UI authentication for localhost
|
||||
- FEATURE: Added option to disable program exit confirmation
|
||||
- FEATURE: Added per-torrent ratio limiting (Christian Kandeler)
|
||||
- FEATURE: Torrent content list is now sortable
|
||||
- BUGFIX: Fix compilation with namespaced Qt (Christian Kandeler)
|
||||
- BUGFIX: Added length restriction on UI lock password
|
||||
- COSMETIC: Added monochrome tray icon
|
||||
- COSMETIC: Improved status bar's style
|
||||
- OTHER: Make QtDBus dependency optional (X11)
|
||||
|
||||
* Sun Jan 9 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.6.0
|
||||
- FEATURE: Use system icons (Linux, Qt >= 4.6)
|
||||
|
||||
16
INSTALL
@@ -10,25 +10,23 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
|
||||
Dependencies:
|
||||
- Qt >= 4.5.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
|
||||
- Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
||||
|
||||
- pkg-config executable
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, compatible with v0.15.x)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.15.0)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
- libboost 1.34.x (libboost-filesystem, libboost-date-time) + libasio
|
||||
- libboost 1.34.x (libboost-filesystem°) + libasio
|
||||
or
|
||||
- libboost >= 1.35.x (libboost-system, libboost-filesystem, libboost-date-time)
|
||||
- libboost >= 1.35.x (libboost-system, libboost-filesystem°)
|
||||
|
||||
°libboost-filesystem is not needed if libtorrent-rasterbar >= v0.16.x is used
|
||||
|
||||
- python >= 2.3 (needed by search engine)
|
||||
* Run time only dependency
|
||||
|
||||
- libnotify >= 0.4.2, glib-2.0 (optional)
|
||||
* Can be used for system notifications to replace standard Qt notifications
|
||||
so that it integrates better into the Desktop
|
||||
|
||||
- geoip-database (optional)
|
||||
* If qBittorrent cannot find this database, it will try to resolve countries using the Internet but it will be a lot slower.
|
||||
* Run time only dependency
|
||||
@@ -46,7 +44,7 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
|
||||
- pkg-config executable
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, >= v0.15.0 ADVISED)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= v0.15.0)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
|
||||
16
README.os2
@@ -27,7 +27,6 @@ First you need to create the conf.pri file in the same dir as this readme.os2 is
|
||||
the conf.pri file has the following content:
|
||||
|
||||
##### conf.pri content beginn #####
|
||||
PREFIX = .
|
||||
BINDIR = ./bin
|
||||
INCDIR = ./include
|
||||
LIBDIR = ./lib
|
||||
@@ -43,7 +42,10 @@ LIBS += -Lx:/trees/libtorrent/trunk/src/.libs \
|
||||
|
||||
Of course all the above path references have to be adjusted to your build env.
|
||||
|
||||
It should now be easy to build qBittorrent:
|
||||
Now you can either do a normal build or a shadow build. A shadow build has the
|
||||
advantage that no created files are in the same dir as the sources are.
|
||||
|
||||
For a normal build do the following:
|
||||
|
||||
Simply type:
|
||||
$ qmake
|
||||
@@ -51,6 +53,16 @@ $ qmake
|
||||
Followed by:
|
||||
$ make
|
||||
|
||||
For a shadow build do the following:
|
||||
given your sources are in x:\trees\qbittorrent\trunk create a
|
||||
x:\trees\qbittorrent\build directory
|
||||
|
||||
Now switch to the created directory and type:
|
||||
$ qmake ..\trunk
|
||||
|
||||
Followed by:
|
||||
$ make
|
||||
|
||||
If all works fine you should get a working qbittorrent executable.
|
||||
|
||||
If you have any question regarding the eCS (OS/2) port of qBittorrent you can meet me (_diver) on IRC:
|
||||
|
||||
253
configure
vendored
@@ -22,11 +22,11 @@ Dependency options:
|
||||
--disable-gui Disable qBittorrent
|
||||
Graphical user interface for
|
||||
headless running
|
||||
--disable-qt-dbus Disable use of qt-dbus
|
||||
--with-libboost-inc=[path] Path to libboost include
|
||||
files
|
||||
--with-libboost-lib=[path] Path to libboost library
|
||||
files
|
||||
--disable-libnotify Disable use of libnotify
|
||||
--disable-geoip-database Disable use of geoip-database
|
||||
--with-geoip-database-embedded Geoip Database will be
|
||||
embedded in qBittorrent
|
||||
@@ -162,6 +162,11 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-qt-dbus)
|
||||
QC_DISABLE_qt_dbus="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libboost-inc=*)
|
||||
QC_WITH_LIBBOOST_INC=$optarg
|
||||
shift
|
||||
@@ -172,11 +177,6 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-libnotify)
|
||||
QC_DISABLE_libnotify="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-geoip-database)
|
||||
QC_DISABLE_geoip_database="Y"
|
||||
shift
|
||||
@@ -215,9 +215,9 @@ echo DATADIR=$DATADIR
|
||||
echo EX_QTDIR=$EX_QTDIR
|
||||
echo QC_ENABLE_DEBUG=$QC_ENABLE_DEBUG
|
||||
echo QC_DISABLE_GUI=$QC_DISABLE_GUI
|
||||
echo QC_DISABLE_qt_dbus=$QC_DISABLE_qt_dbus
|
||||
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
||||
echo QC_WITH_LIBBOOST_LIB=$QC_WITH_LIBBOOST_LIB
|
||||
echo QC_DISABLE_libnotify=$QC_DISABLE_libnotify
|
||||
echo QC_DISABLE_geoip_database=$QC_DISABLE_geoip_database
|
||||
echo QC_WITH_GEOIP_DATABASE_EMBEDDED=$QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
echo QC_WITH_QTSINGLEAPPLICATION=$QC_WITH_QTSINGLEAPPLICATION
|
||||
@@ -325,7 +325,7 @@ cat >$1/modules.cpp <<EOT
|
||||
#line 1 "qt4.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.5
|
||||
name: Qt >= 4.6
|
||||
arg: enable-debug, Enable debug mode
|
||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||
-----END QCMOD-----
|
||||
@@ -334,8 +334,8 @@ class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.5"; }
|
||||
QString shortname() const { return "Qt 4.5"; }
|
||||
QString name() const { return "Qt >= 4.6"; }
|
||||
QString shortname() const { return "Qt 4.6"; }
|
||||
bool exec()
|
||||
{
|
||||
// NOX mode
|
||||
@@ -344,7 +344,11 @@ public:
|
||||
}
|
||||
// Debug mode
|
||||
if(!conf->getenv("QC_ENABLE_DEBUG").isEmpty()) {
|
||||
conf->addExtra("CONFIG -= release");
|
||||
conf->addExtra("CONFIG += debug");
|
||||
} else {
|
||||
conf->addExtra("CONFIG -= debug");
|
||||
conf->addExtra("CONFIG += release");
|
||||
}
|
||||
#ifdef Q_OS_FREEBSD
|
||||
conf->addLib("-lexecinfo");
|
||||
@@ -352,7 +356,39 @@ public:
|
||||
#else
|
||||
conf->addExtra("MANPREFIX = \$\$PREFIX/share");
|
||||
#endif
|
||||
return(QT_VERSION >= 0x040500);
|
||||
return(QT_VERSION >= 0x040600);
|
||||
}
|
||||
};
|
||||
#line 1 "qt-dbus.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-dbus
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_dbus : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_dbus(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtDBus >= 4.5"; }
|
||||
QString shortname() const { return "qt-dbus"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtDBus", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += dbus");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#line 1 "pkg-config.qcm"
|
||||
@@ -383,20 +419,17 @@ class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.4"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.15.0"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.4";
|
||||
QString req_ver = "0.15.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -409,12 +442,15 @@ arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
@@ -438,141 +474,62 @@ public:
|
||||
}
|
||||
return name;
|
||||
}
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "boost/format.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "boost/format.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
|
||||
bool exec(){
|
||||
QStringList sl;
|
||||
QString s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if (!s.isEmpty())
|
||||
sl << s;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach (s, sl) {
|
||||
if (conf->checkHeader(s, "boost/format.hpp")
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
&& conf->checkHeader(s, "boost/filesystem/path.hpp")
|
||||
#endif
|
||||
) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
conf->addIncludePath(s);
|
||||
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" ;
|
||||
}
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
required_libs << "filesystem" ;
|
||||
#endif
|
||||
//required_libs << "thread";
|
||||
QStringList libDirs;
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
if (!s.isEmpty())
|
||||
libDirs << s;
|
||||
libDirs << "/usr/lib/" << "/usr/lib/i386-linux-gnu/" << "/usr/lib64/" << "/usr/lib/x86_64-linux-gnu/" << "/usr/local/lib/" << "/usr/lib/local/i386-linux-gnu/" << "/usr/local/lib64/" << "/usr/local/lib/x86_64-linux-gnu/";
|
||||
|
||||
foreach(const QString& lib, required_libs) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "libnotify.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libnotify
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libnotify : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libnotify(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libnotify >= 0.4.2 (optional)"; }
|
||||
QString shortname() const { return "libnotify"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_libnotify").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_libnotify").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
QStringList incs;
|
||||
QString req_ver = "0.4.2";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("libnotify", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += libnotify");
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
QStringList incs2;
|
||||
QString req_ver2 = "2.0";
|
||||
QString version2, libs2, other2;
|
||||
if(conf->findPkgConfig("glib-2.0", mode, req_ver2, &version2, &incs2, &libs2, &other2)) {
|
||||
for(int n = 0; n < incs2.count(); ++n)
|
||||
conf->addIncludePath(incs2[n]);
|
||||
if(!libs2.isEmpty())
|
||||
conf->addLib(libs2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
QStringList incs3;
|
||||
QString req_ver3 = "2.0";
|
||||
QString version3, libs3, other3;
|
||||
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
|
||||
for(int n = 0; n < incs3.count(); ++n)
|
||||
conf->addIncludePath(incs3[n]);
|
||||
if(!libs3.isEmpty())
|
||||
conf->addLib(libs3);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "geoip-database.qcm"
|
||||
/*
|
||||
@@ -645,6 +602,9 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_qt4(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_qt_dbus(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_pkg_config(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
@@ -654,9 +614,6 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_libboost(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_libnotify(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_geoip_database(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
@@ -1610,9 +1567,9 @@ export DATADIR
|
||||
export EX_QTDIR
|
||||
export QC_ENABLE_DEBUG
|
||||
export QC_DISABLE_GUI
|
||||
export QC_DISABLE_qt_dbus
|
||||
export QC_WITH_LIBBOOST_INC
|
||||
export QC_WITH_LIBBOOST_LIB
|
||||
export QC_DISABLE_libnotify
|
||||
export QC_DISABLE_geoip_database
|
||||
export QC_WITH_GEOIP_DATABASE_EMBEDDED
|
||||
export QC_WITH_QTSINGLEAPPLICATION
|
||||
|
||||
@@ -8,7 +8,7 @@ qBittorrent\-nox \- a command line Bittorrent client written in C++ / Qt4
|
||||
|
||||
.SH "SYNOPSIS"
|
||||
|
||||
\fBqbittorrent\-nox\fR [\-\-webui-port=x] [TORRENT_FILE | URL]...
|
||||
\fBqbittorrent\-nox\fR [\-\-d|\-\-daemon] [\-\-webui-port=x] [TORRENT_FILE | URL]...
|
||||
|
||||
\fBqbittorrent\-nox\fR \-\-help
|
||||
|
||||
|
||||
131
install.os2
@@ -11,7 +11,7 @@ QBittorrent installation
|
||||
|
||||
3. INSTALLATION
|
||||
|
||||
4. CONTACT
|
||||
4. BUGREPORTS
|
||||
|
||||
5. CREDITS
|
||||
|
||||
@@ -29,17 +29,70 @@ Welcome to QBittorrent port for OS/2 and eComStation.
|
||||
2. REQUIREMENTS
|
||||
===============
|
||||
|
||||
* klibc 0.6.3 or later
|
||||
The following requirements can be installed either by rpm or by zip files.
|
||||
|
||||
ftp://ftp.netlabs.org/pub/gcc/libc-0_6_3-csd3.wpi
|
||||
RPM Installation:
|
||||
|
||||
* openssl 1.0
|
||||
|
||||
ftp://ftp.netlabs.org/pub/unixos2/ssl10.zip
|
||||
klibc
|
||||
-----
|
||||
|
||||
* Qt4 dll
|
||||
1. yum install libc
|
||||
|
||||
see http://svn.netlabs.org/qt4 for more information whats needed and where to get the latest
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. yum install openssl
|
||||
|
||||
pthread
|
||||
-------
|
||||
|
||||
1. yum install pthread
|
||||
|
||||
GCC4Core
|
||||
--------
|
||||
|
||||
1. yum install libgcc
|
||||
2. yum install gcc-stack-protector
|
||||
3. yum install gcc-stdc++-shared-library
|
||||
4. yum install gcc-supc++-shared-library
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. yum install libqt4
|
||||
|
||||
|
||||
ZIP Installation:
|
||||
|
||||
klibc
|
||||
-----
|
||||
|
||||
1. Download klibc 0.6.5 or better (see http://svn.netlabs.org/libc for more information)
|
||||
2. Install the files to your libpath eg x:\ecs\dll
|
||||
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. Download the zip file from http://rpm.netlabs.org/release/00/zip
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
pthread
|
||||
-------
|
||||
|
||||
1. Download pthread 2012-03-13 or better from http://rpm.netlabs.org/release/00/zip
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
GCC4Core
|
||||
--------
|
||||
|
||||
1. Download GCC4Core 1.2.1 or better from http://ftp.netlabs.org/pub/gcc
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. Download Qt4 4.7.3 or better (see http://svn.netlabs.org/qt4 for more information)
|
||||
2. Install the files according to the readme
|
||||
|
||||
|
||||
3. INSTALLATION
|
||||
@@ -47,30 +100,6 @@ Welcome to QBittorrent port for OS/2 and eComStation.
|
||||
|
||||
To install QBittorrent, do the following:
|
||||
|
||||
klibc
|
||||
-----
|
||||
|
||||
1. Download klibc 0.6.3 csd3 or later.
|
||||
2. Install the package by double-clicking on the WPI file.
|
||||
|
||||
|
||||
openssl 1.0
|
||||
-----------
|
||||
|
||||
1. Download the zip file
|
||||
2. Install the files to your libpath eg. x:\ecs\dll
|
||||
|
||||
Qt4 dll
|
||||
-------
|
||||
|
||||
1. Download the package
|
||||
2. Install the package by double-clicking on the wpi file.
|
||||
|
||||
|
||||
|
||||
QBittorrent
|
||||
-----------
|
||||
|
||||
1. Create a directory for QBittorrent.
|
||||
2. Extract the QBittorrent package to the new directory.
|
||||
3. Create a WPS object for QBittorrent.exe.
|
||||
@@ -78,18 +107,13 @@ QBittorrent
|
||||
5. Happy torrenting
|
||||
|
||||
|
||||
4. BUGREPORTS
|
||||
=============
|
||||
|
||||
4. CONTACT
|
||||
==========
|
||||
|
||||
Please send bugreports to:
|
||||
|
||||
ecs@aroa.ch
|
||||
|
||||
Please create bugreports at http://svn.netlabs.org/qtapps
|
||||
Only bug reports with a reproducable bug are accepted. :-)
|
||||
|
||||
|
||||
|
||||
5. CREDITS
|
||||
==========
|
||||
|
||||
@@ -122,6 +146,33 @@ development, you can do so in one of the following ways:
|
||||
7. HISTORY
|
||||
==========
|
||||
|
||||
2012-09-19
|
||||
|
||||
* updated to 3.0.4 code level of QBittorrent
|
||||
* updated libtorrent to 0.16.3 level
|
||||
|
||||
2012-09-06
|
||||
|
||||
* updated to 3.0.2 code level of QBittorrent
|
||||
|
||||
2012-05-14
|
||||
|
||||
* updated to 2.9.8 code level of QBittorrent
|
||||
|
||||
2012-03-15
|
||||
|
||||
* updated to 2.9.5 code level of QBittorrent
|
||||
|
||||
2011-09-26
|
||||
|
||||
* updated to 2.8.5 code level of QBittorrent
|
||||
* updated to Qt 4.7.3
|
||||
|
||||
2011-06-20
|
||||
|
||||
* updated to 2.7.3 code level of QBittorrent
|
||||
* updated libtorrent to 0.15.6 level
|
||||
|
||||
2010-12-23
|
||||
|
||||
* updated to 2.5.2 code level of QBittorrent
|
||||
|
||||
63
macxconf.pri
@@ -2,15 +2,66 @@ PREFIX = /usr/local
|
||||
BINDIR = /usr/local/bin
|
||||
DATADIR = /usr/local/share
|
||||
|
||||
INCLUDEPATH += /usr/local/include/libtorrent /usr/include/openssl /usr/include /opt/local/include/boost /opt/local/include
|
||||
LIBS += -ltorrent-rasterbar -lcrypto -L/opt/local/lib -lboost_system-mt -lboost_filesystem-mt -lboost_thread-mt -framework Cocoa -framework Carbon
|
||||
# Use pkg-config to get all necessary libtorrent DEFINES
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libtorrent-rasterbar
|
||||
DEFINES += BOOST_ASIO_DYN_LINK
|
||||
|
||||
# Special include/libs paths (macports)
|
||||
INCLUDEPATH += /usr/include/openssl /usr/include /opt/local/include/boost /opt/local/include
|
||||
LIBS += -L/opt/local/lib
|
||||
|
||||
# OpenSSL lib
|
||||
LIBS += -lssl -lcrypto
|
||||
# Boost system lib
|
||||
LIBS += -lboost_system-mt
|
||||
# Boost filesystem lib (Not needed for libtorrent >= 0.16.0)
|
||||
#LIBS += -lboost_filesystem-mt
|
||||
# Carbon
|
||||
LIBS += -framework Carbon -framework IOKit
|
||||
# Zlib
|
||||
LIBS += -lz
|
||||
|
||||
document_icon.path = Contents/Resources
|
||||
document_icon.files = Icons/qBitTorrentDocument.icns
|
||||
|
||||
document_icon.files = mac/qBitTorrentDocument.icns
|
||||
QMAKE_BUNDLE_DATA += document_icon
|
||||
ICON = Icons/qbittorrent_mac.icns
|
||||
QMAKE_INFO_PLIST = Info.plist
|
||||
|
||||
qt_conf.path = Contents/Resources
|
||||
qt_conf.files = mac/qt.conf
|
||||
QMAKE_BUNDLE_DATA += qt_conf
|
||||
|
||||
qt_translations.path = Contents/MacOS/translations
|
||||
qt_translations.files = qt-translations/qt_ar.qm \
|
||||
qt-translations/qt_bg.qm \
|
||||
qt-translations/qt_ca.qm \
|
||||
qt-translations/qt_cs.qm \
|
||||
qt-translations/qt_da.qm \
|
||||
qt-translations/qt_de.qm \
|
||||
qt-translations/qt_es.qm \
|
||||
qt-translations/qt_fi.qm \
|
||||
qt-translations/qt_fr.qm \
|
||||
qt-translations/qt_gl.qm \
|
||||
qt-translations/qt_he.qm \
|
||||
qt-translations/qt_hu.qm \
|
||||
qt-translations/qt_it.qm \
|
||||
qt-translations/qt_ja.qm \
|
||||
qt-translations/qt_ko.qm \
|
||||
qt-translations/qt_lt.qm \
|
||||
qt-translations/qt_nl.qm \
|
||||
qt-translations/qt_pl.qm \
|
||||
qt-translations/qt_pt.qm \
|
||||
qt-translations/qt_pt_BR.qm \
|
||||
qt-translations/qt_ru.qm \
|
||||
qt-translations/qt_sk.qm \
|
||||
qt-translations/qt_sv.qm \
|
||||
qt-translations/qt_tr.qm \
|
||||
qt-translations/qt_uk.qm \
|
||||
qt-translations/qt_zh_CN.qm \
|
||||
qt-translations/qt_zh_TW.qm
|
||||
QMAKE_BUNDLE_DATA += qt_translations
|
||||
|
||||
ICON = mac/qbittorrent_mac.icns
|
||||
QMAKE_INFO_PLIST = mac/Info.plist
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On Mac OS X, GeoIP database must be embedded.")
|
||||
|
||||
@@ -7,9 +7,13 @@ LIBS += -ltorrent-rasterbar \
|
||||
-lboost_thread \
|
||||
-lboost_system \
|
||||
-lboost_filesystem \
|
||||
-lssl -lcrypto -lidn -lpthread
|
||||
-lssl -lcrypto -lidn -lpthread -lz
|
||||
|
||||
RC_FILE = qbittorrent_os2.rc
|
||||
|
||||
# LIBTORRENT DEFINES
|
||||
DEFINES += WITH_SHIPPED_GEOIP_H
|
||||
DEFINES += BOOST_ASIO_DYN_LINK
|
||||
|
||||
DEFINES += WITH_GEOIP_EMBEDDED
|
||||
message("On eCS(OS/2), GeoIP database must be embedded.")
|
||||
|
||||
@@ -2,3 +2,18 @@ TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += src
|
||||
|
||||
include(version.pri)
|
||||
include(qm_gen.pri)
|
||||
|
||||
# Dist
|
||||
dist.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
|
||||
dist.commands += git clone . ../$${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.git &&
|
||||
dist.commands += rm -f ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.gitignore &&
|
||||
dist.commands += cd .. &&
|
||||
dist.commands += tar czf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar.gz $${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += tar cf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar $${PROJECT_NAME}-$${PROJECT_VERSION} &&
|
||||
dist.commands += xz -f $${PROJECT_NAME}-$${PROJECT_VERSION}.tar &&
|
||||
dist.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION}
|
||||
|
||||
QMAKE_EXTRA_TARGETS += dist
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<dep type='qt4'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='qt-dbus'>
|
||||
</dep>
|
||||
<dep type='pkg-config'>
|
||||
<required/>
|
||||
</dep>
|
||||
@@ -15,8 +17,6 @@
|
||||
<dep type='libboost'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libnotify'>
|
||||
</dep>
|
||||
<dep type='geoip-database'>
|
||||
</dep>
|
||||
<dep type='qtsingleapplication'>
|
||||
|
||||
119
qcm/libboost.qcm
@@ -6,12 +6,15 @@ arg: with-libboost-lib=[path], Path to libboost library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <boost/version.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
class qc_libboost : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
qc_libboost(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libboost"; }
|
||||
QString shortname() const { return "libboost"; }
|
||||
|
||||
QString findBoostLib(QString path, QString lib) const {
|
||||
QString name;
|
||||
QDir libDir(path);
|
||||
@@ -35,78 +38,60 @@ public:
|
||||
}
|
||||
return name;
|
||||
}
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "boost/format.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "boost/format.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/date_time/posix_time/posix_time.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "boost/filesystem/path.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
|
||||
bool exec(){
|
||||
QStringList sl;
|
||||
QString s = conf->getenv("QC_WITH_LIBBOOST_INC");
|
||||
if (!s.isEmpty())
|
||||
sl << s;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach (s, sl) {
|
||||
if (conf->checkHeader(s, "boost/format.hpp")
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
&& conf->checkHeader(s, "boost/filesystem/path.hpp")
|
||||
#endif
|
||||
) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
conf->addIncludePath(s);
|
||||
|
||||
// Find library
|
||||
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
|
||||
QStringList required_libs;
|
||||
#if BOOST_VERSION >= 103500
|
||||
required_libs << "system";
|
||||
#endif
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
// Not required by nox
|
||||
required_libs << "filesystem" ;
|
||||
}
|
||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||
required_libs << "filesystem" ;
|
||||
#endif
|
||||
//required_libs << "thread";
|
||||
QStringList libDirs;
|
||||
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
|
||||
if (!s.isEmpty())
|
||||
libDirs << s;
|
||||
libDirs << "/usr/lib/" << "/usr/lib/i386-linux-gnu/" << "/usr/lib64/" << "/usr/lib/x86_64-linux-gnu/" << "/usr/local/lib/" << "/usr/lib/local/i386-linux-gnu/" << "/usr/local/lib64/" << "/usr/local/lib/x86_64-linux-gnu/";
|
||||
|
||||
foreach(const QString& lib, required_libs) {
|
||||
if(!s.isEmpty()) {
|
||||
QString detected_name = findBoostLib(s, lib);
|
||||
if(detected_name.isEmpty()) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
foreach(const QString& libDir, libDirs) {
|
||||
QString detected_name = findBoostLib(libDir, lib);
|
||||
if(!detected_name.isEmpty()) {
|
||||
conf->addLib("-l"+detected_name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
printf("Could not find boost %s library!\n", qPrintable(lib));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,20 +8,17 @@ class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.4"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.15.0"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.4";
|
||||
QString req_ver = "0.15.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
|
||||
conf->addLib("-lcrypto");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
31
qcm/qt-dbus.qcm
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-dbus
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_dbus : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_dbus(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtDBus >= 4.5"; }
|
||||
QString shortname() const { return "qt-dbus"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_dbus").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtDBus", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += dbus");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
31
qcm/qt-svg.qcm
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: qt-svg
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_qt_svg : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt_svg(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "QtSvg >= 4.5"; }
|
||||
QString shortname() const { return "qt-svg"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_qt_svg").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_qt_svg").isEmpty() || !conf->getenv("QC_DISABLE_GUI").isEmpty())
|
||||
return false;
|
||||
QStringList incs;
|
||||
QString req_ver = "4.5.0";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(conf->findPkgConfig("QtSvg", mode, req_ver, &version, &incs, &libs, &other)) {
|
||||
conf->addExtra("CONFIG += svg");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
12
qcm/qt4.qcm
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.5
|
||||
name: Qt >= 4.6
|
||||
arg: enable-debug, Enable debug mode
|
||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||
-----END QCMOD-----
|
||||
@@ -9,8 +9,8 @@ class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.5"; }
|
||||
QString shortname() const { return "Qt 4.5"; }
|
||||
QString name() const { return "Qt >= 4.6"; }
|
||||
QString shortname() const { return "Qt 4.6"; }
|
||||
bool exec()
|
||||
{
|
||||
// NOX mode
|
||||
@@ -19,7 +19,11 @@ public:
|
||||
}
|
||||
// Debug mode
|
||||
if(!conf->getenv("QC_ENABLE_DEBUG").isEmpty()) {
|
||||
conf->addExtra("CONFIG -= release");
|
||||
conf->addExtra("CONFIG += debug");
|
||||
} else {
|
||||
conf->addExtra("CONFIG -= debug");
|
||||
conf->addExtra("CONFIG += release");
|
||||
}
|
||||
#ifdef Q_OS_FREEBSD
|
||||
conf->addLib("-lexecinfo");
|
||||
@@ -27,6 +31,6 @@ public:
|
||||
#else
|
||||
conf->addExtra("MANPREFIX = $$PREFIX/share");
|
||||
#endif
|
||||
return(QT_VERSION >= 0x040500);
|
||||
return(QT_VERSION >= 0x040600);
|
||||
}
|
||||
};
|
||||
|
||||
19
qm_gen.pri
Normal file
@@ -0,0 +1,19 @@
|
||||
TS_IN = $$fromfile(src/src.pro,TRANSLATIONS)
|
||||
TS_IN_NOEXT = $$replace(TS_IN,".ts","")
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32|os2:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
unix {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt4 }
|
||||
} else {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
|
||||
}
|
||||
}
|
||||
|
||||
message("Building translations")
|
||||
for(L,TS_IN_NOEXT) {
|
||||
message("Processing $${L}")
|
||||
system("$$QMAKE_LRELEASE -silent src/$${L}.ts -qm src/$${L}.qm")
|
||||
!exists("src/$${L}.qm"):error("Building translations failed, cannot continue")
|
||||
}
|
||||
|
Before Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
src/Icons/oxygen/security-high.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Icons/oxygen/security-low.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Icons/oxygen/task-attention.png
Normal file
|
After Width: | Height: | Size: 651 B |
BIN
src/Icons/oxygen/view-statistics.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,38 +1,119 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V2.6.4
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[ar]=العميل Bittorrent
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[cs]=Bittorrent klient
|
||||
GenericName[de]=Bittorren Client
|
||||
GenericName[el]=Bittorrent πελάτης
|
||||
GenericName[es]=Cliente Bittorrent
|
||||
GenericName[fi]=Bittorrent-ohjelma
|
||||
GenericName[fr]=Client Bittorrent
|
||||
GenericName[hr]=Bittorrent klijent
|
||||
GenericName[hu]=Bittorrent kliens
|
||||
GenericName[it]=Client Bittorrent
|
||||
GenericName[ja]=Bittorrent クライアント
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
GenericName[nl]=Bittorrent-cliënt
|
||||
GenericName[pl]=Klient Bittorrent
|
||||
GenericName[pt]=Cliente Bittorrent
|
||||
GenericName[pt_BR]=Cliente Bittorrent
|
||||
GenericName[ro]=Client Bittorrent
|
||||
GenericName[ru]=клиент Bittorrent
|
||||
GenericName[sk]=Klient siete Bittorrent
|
||||
GenericName[sr]=Bittorrent-клијент
|
||||
GenericName[sv]=Bittorrent-klient
|
||||
GenericName[tr]=Bittorrent istemcisi
|
||||
GenericName[uk]=Bittorrent-клієнт
|
||||
GenericName[zh]=Bittorrent之用户
|
||||
GenericName[zh_TW]=Bittorrent客戶端
|
||||
Categories=Network;FileTransfer;P2P;Qt;
|
||||
Exec=qbittorrent %U
|
||||
GenericName=BitTorrent client
|
||||
Comment=Download and share files over BitTorrent
|
||||
Icon=qbittorrent
|
||||
MimeType=application/x-bittorrent;
|
||||
MimeType=application/x-bittorrent;x-scheme-handler/magnet;
|
||||
Name=qBittorrent
|
||||
Name[ko]=큐비토런트
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
GenericName[ar]=العميل BitTorrent
|
||||
Comment[be]=Сцягванне і раздача файлаў праз пратакол BitTorrent
|
||||
GenericName[be]=BitTorrent-кліент
|
||||
Name[be]=qBittorrent
|
||||
Icon[be]=qbittorrent
|
||||
GenericName[bg]=Торент клиент
|
||||
Comment[cs]=Stahování a sdílení souborů přes síť BitTorrent
|
||||
GenericName[cs]=BitTorrent klient
|
||||
Name[cs]=qBittorrent
|
||||
Icon[cs]=qbittorrent
|
||||
GenericName[de]=BitTorren Client
|
||||
Comment[el]=Λήψη και διαμοιρασμός αρχείων μέσω BitTorrent
|
||||
GenericName[el]=BitTorrent πελάτης
|
||||
Name[el]=qBittorrent
|
||||
Icon[el]=qbittorrent
|
||||
Comment[en_GB]=Download and share files over BitTorrent
|
||||
GenericName[en_GB]=BitTorrent client
|
||||
Name[en_GB]=qBittorrent
|
||||
Icon[en_GB]=qbittorrent
|
||||
Comment[es]=Descarga y comparte archivos por BitTorrent
|
||||
GenericName[es]=Cliente BitTorrent
|
||||
Name[es]=qBittorrent
|
||||
Icon[es]=qbittorrent
|
||||
Comment[eu]=Jeitsi eta elkarbanatu agiriak BitTorrent-en
|
||||
GenericName[eu]=BitTorrent bezeroa
|
||||
Name[eu]=qBittorrent
|
||||
Icon[eu]=qbittorrent
|
||||
Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen
|
||||
GenericName[fi]=BitTorrent-ohjelma
|
||||
Name[fi]=qBittorrent
|
||||
Icon[fi]=qbittorrent
|
||||
Comment[fr]=Télécharger et partager des fichiers avec BitTorrent
|
||||
GenericName[fr]=Client BitTorrent
|
||||
Comment[gl]=Descargue e comparta ficheiros co protocolo BitTorrent
|
||||
GenericName[gl]=Cliente BitTorrent
|
||||
Name[gl]=qBittorrent
|
||||
Icon[gl]=qbittorrent
|
||||
GenericName[hr]=BitTorrent klijent
|
||||
GenericName[hu]=BitTorrent kliens
|
||||
Comment[it]=Client BitTorrent per il download di file via internet
|
||||
GenericName[it]=Client BitTorrent
|
||||
Name[it]=qBittorrent
|
||||
Icon[it]=qbittorrent
|
||||
Comment[ja]=BitTorrent でファイルをダウンロードおよび共有します
|
||||
GenericName[ja]=BitTorrent クライアント
|
||||
Name[ja]=qBittorrent
|
||||
Icon[ja]=qbittorrent
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
Name[ko]=큐비토런트
|
||||
GenericName[zh]=BitTorrent之用户
|
||||
Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle
|
||||
GenericName[lt]=BitTorrent klientas
|
||||
Name[lt]=qBittorrent
|
||||
Icon[lt]=qbittorrent
|
||||
Comment[nb]=Last ned og del filer over BitTorrent
|
||||
GenericName[nb]=BitTorrent-klient
|
||||
Name[nb]=qBittorrent
|
||||
Icon[nb]=qbittorrent
|
||||
GenericName[nl]=BitTorrent-cliënt
|
||||
Comment[pl]=Dzielenie się plikami przez BitTorrent
|
||||
GenericName[pl]=Klient BitTorrent
|
||||
Name[pl]=qBittorrent
|
||||
Icon[pl]=qbittorrent
|
||||
Comment[pt]=Transferir e partilhar ficheiros por BitTorrent
|
||||
GenericName[pt]=Aplicação BitTorrent
|
||||
Name[pt]=qBittorrent
|
||||
Icon[pt]=qbittorrent
|
||||
Comment[pt_BR]=Baixe e compartilhe arquivos através do qBittorrent
|
||||
GenericName[pt_BR]=Cliente BitTorrent
|
||||
Name[pt_BR]=qBittorrent
|
||||
Icon[pt_BR]=qbittorrent
|
||||
Comment[ro]=Descărcați și partajați fișiere prin BitTorrent
|
||||
GenericName[ro]=Client BitTorrent
|
||||
Name[ro]=qBittorrent
|
||||
Icon[ro]=qbittorrent
|
||||
Comment[ru]=Скачивайте и делитесь файлами с помощью BitTorrent
|
||||
GenericName[ru]=клиент BitTorrent
|
||||
Name[ru]=qBittorrent
|
||||
Icon[ru]=qbittorrent
|
||||
GenericName[sk]=Klient siete BitTorrent
|
||||
GenericName[sr]=BitTorrent-клијент
|
||||
Comment[sv]=Hämta och dela filer över BitTorrent
|
||||
GenericName[sv]=BitTorrent-klient
|
||||
Name[sv]=qBittorrent
|
||||
Icon[sv]=qbittorrent
|
||||
GenericName[tr]=BitTorrent istemcisi
|
||||
Comment[uk]=Завантажувати і обмінюватися файлами через BitTorrent
|
||||
GenericName[uk]=BitTorrent-клієнт
|
||||
Name[uk]=qBittorrent
|
||||
Icon[uk]=qbittorrent
|
||||
Comment[vi]=Tải về và chia sẻ các tập tin thông qua BitTorrent
|
||||
GenericName[vi]=Máy trạm dạng BitTorrent
|
||||
Name[vi]=qBittorrent
|
||||
Icon[vi]=qbittorrent
|
||||
Comment[zh_TW]=經由 BitTorrent 下載並分享檔案
|
||||
GenericName[zh_TW]=BitTorrent 客戶端
|
||||
Name[zh_TW]=qBittorrent
|
||||
Icon[zh_TW]=qbittorrent
|
||||
Comment[en_AU]=Download and share files over BitTorrent
|
||||
GenericName[en_AU]=BitTorrent client
|
||||
Name[en_AU]=qBittorrent
|
||||
Icon[en_AU]=qbittorrent
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 590 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 443 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 495 B |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 359 B |
83
src/Icons/skin/qbittorrent_mono.svg
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="32"
|
||||
height="32"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="qbittorrent_mono.svg">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="717"
|
||||
id="namedview9"
|
||||
showgrid="false"
|
||||
inkscape:zoom="17.866666"
|
||||
inkscape:cx="15.004649"
|
||||
inkscape:cy="12.151033"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3030"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-49.656249,-638.375)"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3030">
|
||||
<path
|
||||
style="opacity:0.95;fill:none;stroke:#f5f5f5;stroke-width:2.09332085;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 79.602741,654.3166 c 0.353782,9.2059 -9.874651,16.51452 -18.469307,13.19706 -8.505573,-2.56766 -12.284789,-13.92871 -7.003202,-21.07663 4.900144,-7.80142 17.468596,-8.0676 22.694637,-0.48063 1.795761,2.39071 2.785631,5.37058 2.777872,8.3602 z"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="scale(0.9569639,1.0449715)"
|
||||
style="font-size:5.99402952px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#fafafa;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
id="text3757">
|
||||
<path
|
||||
d="m 65.221466,636.08054 0,-5.47891 c -0.295027,0.41443 -0.709458,0.75862 -1.243293,1.03256 -0.526826,0.27395 -1.088766,0.41092 -1.685821,0.41092 -1.327589,0 -2.472541,-0.53033 -3.43486,-1.59099 -0.9553,-1.06066 -1.432949,-2.51468 -1.432948,-4.36207 -10e-7,-1.12387 0.193166,-2.13185 0.579501,-3.02394 0.393356,-0.89207 0.958808,-1.5664 1.696357,-2.02298 0.744567,-0.46359 1.55938,-0.69539 2.44444,-0.6954 1.383772,10e-6 2.47253,0.58302 3.266279,1.74904 l 0,-1.49617 1.706893,0 0,15.47794 -1.896548,0 m -5.847692,-9.91473 c -2e-6,1.43998 0.30204,2.52171 0.906129,3.2452 0.604082,0.71648 1.327579,1.07472 2.170494,1.07472 0.807783,0 1.503184,-0.34068 2.086204,-1.02203 0.583005,-0.68838 0.874511,-1.73148 0.87452,-3.12931 -9e-6,-1.48913 -0.309076,-2.6095 -0.927202,-3.3611 -0.611117,-0.75159 -1.331103,-1.12739 -2.159958,-1.1274 -0.821843,10e-6 -1.520755,0.35122 -2.09674,1.05364 -0.568967,0.69541 -0.853449,1.78417 -0.853447,3.26628"
|
||||
style="font-size:21.57850838px;font-variant:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#fafafa;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="path2988" />
|
||||
<path
|
||||
d="m 71.84885,631.79224 -1.759576,0 0,-15.44634 1.896549,0 0,5.51053 c 0.80076,-1.00446 1.822788,-1.50669 3.066086,-1.5067 0.68837,10e-6 1.338113,0.14049 1.949231,0.42145 0.618125,0.27396 1.123871,0.6638 1.517239,1.16954 0.400372,0.49873 0.712951,1.10282 0.937738,1.81226 0.224765,0.70945 0.337153,1.46807 0.337164,2.27586 -1.1e-5,1.91762 -0.474148,3.39974 -1.422412,4.44635 -0.948283,1.04661 -2.086211,1.56992 -3.413787,1.56992 -1.320565,0 -2.356641,-0.5514 -3.108232,-1.65421 l 0,1.40134 m -0.02107,-5.67911 c -3e-6,1.34163 0.182627,2.31098 0.547892,2.90804 0.597057,0.97637 1.404845,1.46456 2.423367,1.46456 0.828855,0 1.545329,-0.35824 2.149422,-1.07472 0.604077,-0.72349 0.90612,-1.7982 0.906129,-3.22413 -9e-6,-1.46104 -0.291516,-2.53926 -0.87452,-3.23467 -0.575996,-0.69539 -1.274909,-1.04309 -2.09674,-1.0431 -0.828867,10e-6 -1.54534,0.36176 -2.149421,1.08525 -0.60409,0.71648 -0.906132,1.75607 -0.906129,3.11877"
|
||||
style="font-size:21.57850838px;font-variant:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#fafafa;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="path2990" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
BIN
src/Icons/skin/qbittorrent_mono_dark.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/skin/qbittorrent_mono_light.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Icons/skin/ratio.png
Normal file
|
After Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 538 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 583 B |
|
Before Width: | Height: | Size: 787 B |
426
src/about.ui
@@ -51,7 +51,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><h3><b>qBittorrent</b></h3></string>
|
||||
<string notr="true"><h3><b>qBittorrent</b></h3></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@@ -78,7 +78,7 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab2">
|
||||
<widget class="QWidget" name="tab6">
|
||||
<attribute name="title">
|
||||
<string>About</string>
|
||||
</attribute>
|
||||
@@ -89,7 +89,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../icons.qrc">:/Icons/skin/mascot.png</pixmap>
|
||||
<pixmap resource="icons.qrc">:/Icons/skin/mascot.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -102,13 +102,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">A Bittorrent client programmed in C++, based on Qt4 toolkit </span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">and libtorrent-rasterbar. <br /><br />Copyright ©2006-2010 Christophe Dumez<br /><br /></span><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">Home Page:</span><span style=" font-family:'DejaVu Sans';"> </span><a href="http://www.qbittorrent.org"><span style=" text-decoration: underline; color:#0000ff;">http://www.qbittorrent.org</span></a><span style=" font-family:'DejaVu Sans';"><br /></span><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">Forum:</span><span style=" font-family:'DejaVu Sans';"> </span><a href="http://forum.qbittorrent.org"><span style=" text-decoration: underline; color:#0000ff;">http://forum.qbittorrent.org</span></a></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; text-decoration: underline;">IRC:</span><span style=" font-family:'DejaVu Sans';"> #qbittorrent on Freenode</span></p></body></html></string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@@ -129,7 +123,7 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab3">
|
||||
<widget class="QWidget" name="tab5">
|
||||
<attribute name="title">
|
||||
<string>Author</string>
|
||||
</attribute>
|
||||
@@ -140,95 +134,16 @@ p, li { white-space: pre-wrap; }
|
||||
<item>
|
||||
<widget class="QFrame" name="te_authors">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@@ -241,6 +156,205 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string notr="true">Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string notr="true">chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Greece</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string notr="true">sledgehammer999@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string notr="true">Sledgehammer999</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Current maintainer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Original author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -259,7 +373,7 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab5">
|
||||
<widget class="QWidget" name="tab3">
|
||||
<attribute name="title">
|
||||
<string>Translation</string>
|
||||
</attribute>
|
||||
@@ -276,7 +390,7 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab1">
|
||||
<widget class="QWidget" name="tab2">
|
||||
<attribute name="title">
|
||||
<string>License</string>
|
||||
</attribute>
|
||||
@@ -289,13 +403,121 @@ p, li { white-space: pre-wrap; }
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab1">
|
||||
<attribute name="title">
|
||||
<string>Libraries</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>This version of qBittorrent was built against the following libraries:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string notr="true">Qt:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string notr="true">Boost:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string notr="true">Libtorrent:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
#include "ui_about.h"
|
||||
#include <QFile>
|
||||
#include <QtGlobal>
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
class about : public QDialog, private Ui::AboutDlg{
|
||||
Q_OBJECT
|
||||
@@ -42,13 +45,31 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
qDebug("Deleting about dlg");
|
||||
}
|
||||
|
||||
about(QWidget *parent): QDialog(parent){
|
||||
about(QWidget *parent): QDialog(parent) {
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// About
|
||||
QString aboutText =
|
||||
QString::fromUtf8("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\"><html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; }</style></head><body style=\" font-size:11pt; font-weight:400; font-style:normal;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("An advanced BitTorrent client programmed in C++, based on Qt4 toolkit and libtorrent-rasterbar.") +
|
||||
QString::fromUtf8(" <br /><br />") +
|
||||
trUtf8("Copyright ©2006-2013 The qBittorrent project") +
|
||||
QString::fromUtf8("<br /><br />") +
|
||||
tr("Home Page: ") +
|
||||
QString::fromUtf8("<a href=\"http://www.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://www.qbittorrent.org</span></a></p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("Bug Tracker: ") +
|
||||
QString::fromUtf8("<a href=\"http://bugs.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://bugs.qbittorrent.org</span></a><br />") +
|
||||
tr("Forum: ") +
|
||||
QString::fromUtf8(
|
||||
"<a href=\"http://forum.qbittorrent.org\"><span style=\" text-decoration: underline; color:#0000ff;\">http://forum.qbittorrent.org</span></a></p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
|
||||
tr("IRC: #qbittorrent on Freenode") +
|
||||
QString::fromUtf8(
|
||||
"</p></body></html>");
|
||||
lb_about->setText(aboutText);
|
||||
// Set icons
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
||||
//Title
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
// Thanks
|
||||
QString thanks_txt;
|
||||
thanks_txt += QString::fromUtf8("<p>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</p>");
|
||||
@@ -59,45 +80,57 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
te_thanks->setHtml(thanks_txt);
|
||||
// Translation
|
||||
QString trans_txt = "<p>"+tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"</p>";
|
||||
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)</li>\
|
||||
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)</li>\
|
||||
<li><u>Armenian:</u> Hrant Ohanyan (hrantohanyan@mail.am)</li>\
|
||||
<li><u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Basque:</u> Xabier Aramendi (azpidatziak@gmail.com)</li>\
|
||||
<li><u>Belarusian:</u> Mihas Varantsou (meequz@gmail.com)</li>\
|
||||
<li><u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)</li>\
|
||||
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)</li>\
|
||||
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com) and 冥王歐西里斯 s8321414(Transifex)</li>\
|
||||
<li><u>Croatian:</u> Oliver Mucafir (oliver.untwist@gmail.com)</li>\
|
||||
<li><u>Czech:</u> Jirka Vilim (web@tets.cz)</li>\
|
||||
<li><u>Czech:</u> Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex)</li>\
|
||||
<li><u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)</li>\
|
||||
<li><u>Dutch:</u> Pieter Heyvaert (pieter_heyvaert@hotmail.com)</li>\
|
||||
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)</li>\
|
||||
<li><u>Galician:</u> Marcos Lans (marcoslansgarza@gmail.com)</li>\
|
||||
<li><u>English(Australia):</u> Robert Readman readmanr(Transifex)</li>\
|
||||
<li><u>English(United Kingdom):</u> Robert Readman readmanr(Transifex)</li>\
|
||||
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net), Pekka Niemi (pekka.niemi@iki.fi) and Jiri Grönroos artnay(Transifex)</li>\
|
||||
<li><u>Galician:</u> Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex)</li>\
|
||||
<li><u>Georgian:</u> Beqa Arabuli (arabulibeqa@yahoo.com)</li>\
|
||||
<li><u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)</li>\
|
||||
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)</li>\
|
||||
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net), Stephanos Antaris (santaris@csd.auth.gr), sledgehammer999(hammered999@gmail.com) and Γιάννης Ανθυμίδης Evropi(Transifex)</li>\
|
||||
<li><u>Hebrew:</u> David Deutsch (d.deffo@gmail.com)</li>\
|
||||
<li><u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)</li>\
|
||||
<li><u>Italian:</u> Matteo Sechi (bu17714@gmail.com)</li>\
|
||||
<li><u>Japanese:</u> Nardog (alphisation@gmail.com)</li>\
|
||||
<li><u>Italian:</u> bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)</li>\
|
||||
<li><u>Japanese:</u> Masato Hashimoto (cabezon.hashimoto@gmail.com)</li>\
|
||||
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
|
||||
<li><u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)</li>\
|
||||
<li><u>Lithuanian:</u> Naglis Jonaitis (njonaitis@gmail.com)</li>\
|
||||
<li><u>Norwegian:</u> Tomaso</li>\
|
||||
<li><u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)</li>\
|
||||
<li><u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)</li>\
|
||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
|
||||
<li><u>Portuguese:</u> Sérgio Marques smarquespt(Transifex)</li>\
|
||||
<li><u>Portuguese(Brazil):</u> Nick Marinho (nickmarinho@gmail.com)</li>\
|
||||
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex)</li>\
|
||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex)</li>\
|
||||
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
|
||||
<li><u>Slovak:</u> helix84</li>\
|
||||
<li><u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
|
||||
<li><u>Spanish:</u> Alfredo Monclús (alfrix), Francisco Luque Contreras (frannoe@ya.com) and José Antonio Moray moray33(Transifex)</li>\
|
||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se) and Emil Hammarberg Ooglogput(Transifex)</li>\
|
||||
<li><u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)</li>\
|
||||
<li><u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)</li></ul>");
|
||||
<li><u>Ukrainian:</u> Oleh Prypin (blaxpirit@gmail.com)</li>\
|
||||
<li><u>Vietnamese:</u> Anh Phan ppanhh(Transifex)</li></ul>");
|
||||
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
|
||||
te_translation->setHtml(trans_txt);
|
||||
// License
|
||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
QFile licensefile(":/gpl.html");
|
||||
if(licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
if (licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
te_license->setHtml(licensefile.readAll());
|
||||
licensefile.close();
|
||||
}
|
||||
// Libraries
|
||||
label_11->setText(QT_VERSION_STR);
|
||||
label_12->setText(LIBTORRENT_VERSION);
|
||||
label_13->setText(QString::number(BOOST_VERSION / 100000) + "." + QString::number((BOOST_VERSION / 100) % 1000) + "." + QString::number(BOOST_VERSION % 100));
|
||||
show();
|
||||
}
|
||||
};
|
||||
|
||||
736
src/addnewtorrentdialog.cpp
Normal file
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "addnewtorrentdialog.h"
|
||||
#include "ui_addnewtorrentdialog.h"
|
||||
#include "proplistdelegate.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "preferences.h"
|
||||
#include "qinisettings.h"
|
||||
#include "torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QFileDialog>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
AddNewTorrentDialog::AddNewTorrentDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddNewTorrentDialog),
|
||||
m_contentModel(0),
|
||||
m_contentDelegate(0),
|
||||
m_isMagnet(false),
|
||||
m_hasMetadata(false),
|
||||
m_hasRenamedFile(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->lblMetaLoading->setVisible(false);
|
||||
ui->progMetaLoading->setVisible(false);
|
||||
|
||||
QIniSettings settings;
|
||||
Preferences pref;
|
||||
ui->start_torrent_cb->setChecked(!pref.addTorrentsInPause());
|
||||
ui->save_path_combo->addItem(fsutils::toDisplayPath(pref.getSavePath()), pref.getSavePath());
|
||||
loadSavePathHistory();
|
||||
ui->save_path_combo->insertSeparator(ui->save_path_combo->count());
|
||||
ui->save_path_combo->addItem(tr("Other...", "Other save path..."));
|
||||
connect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
|
||||
ui->default_save_path_cb->setVisible(false); // Default path is selected by default
|
||||
|
||||
// Load labels
|
||||
const QStringList customLabels = settings.value("TransferListFilters/customLabels", QStringList()).toStringList();
|
||||
ui->label_combo->addItem("");
|
||||
foreach (const QString& label, customLabels) {
|
||||
ui->label_combo->addItem(label);
|
||||
}
|
||||
ui->label_combo->model()->sort(0);
|
||||
ui->content_tree->header()->setSortIndicator(0, Qt::AscendingOrder);
|
||||
loadState();
|
||||
// Signal / slots
|
||||
connect(ui->adv_button, SIGNAL(clicked(bool)), SLOT(showAdvancedSettings(bool)));
|
||||
editHotkey = new QShortcut(QKeySequence("F2"), ui->content_tree, 0, 0, Qt::WidgetShortcut);
|
||||
connect(editHotkey, SIGNAL(activated()), SLOT(renameSelectedFile()));
|
||||
connect(ui->content_tree, SIGNAL(doubleClicked(QModelIndex)), SLOT(renameSelectedFile()));
|
||||
}
|
||||
|
||||
AddNewTorrentDialog::~AddNewTorrentDialog()
|
||||
{
|
||||
saveState();
|
||||
delete ui;
|
||||
if (m_contentModel)
|
||||
delete m_contentModel;
|
||||
delete editHotkey;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::loadState()
|
||||
{
|
||||
QIniSettings settings;
|
||||
settings.beginGroup(QString::fromUtf8("AddNewTorrentDialog"));
|
||||
QByteArray state = settings.value("treeHeaderState").toByteArray();
|
||||
if (!state.isEmpty())
|
||||
ui->content_tree->header()->restoreState(state);
|
||||
int width = settings.value("width", -1).toInt();
|
||||
if (width >= 0) {
|
||||
QRect geo = geometry();
|
||||
geo.setWidth(width);
|
||||
setGeometry(geo);
|
||||
}
|
||||
ui->adv_button->setChecked(settings.value("expanded", false).toBool());
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveState()
|
||||
{
|
||||
QIniSettings settings;
|
||||
settings.beginGroup(QString::fromUtf8("AddNewTorrentDialog"));
|
||||
if (m_contentModel)
|
||||
settings.setValue("treeHeaderState", ui->content_tree->header()->saveState());
|
||||
settings.setValue("y", pos().y());
|
||||
settings.setValue("width", width());
|
||||
settings.setValue("expanded", ui->adv_button->isChecked());
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showTorrent(const QString &torrent_path, const QString& from_url)
|
||||
{
|
||||
AddNewTorrentDialog dlg;
|
||||
if (dlg.loadTorrent(torrent_path, from_url))
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showMagnet(const QString& link)
|
||||
{
|
||||
AddNewTorrentDialog dlg;
|
||||
if (dlg.loadMagnet(link))
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::showEvent(QShowEvent *event) {
|
||||
QDialog::showEvent(event);
|
||||
Preferences pref;
|
||||
if (!pref.AdditionDialogFront())
|
||||
return;
|
||||
activateWindow();
|
||||
raise();
|
||||
}
|
||||
|
||||
|
||||
void AddNewTorrentDialog::showAdvancedSettings(bool show)
|
||||
{
|
||||
if (show) {
|
||||
ui->adv_button->setText(QString::fromUtf8("▲"));
|
||||
ui->settings_group->setVisible(true);
|
||||
ui->info_group->setVisible(m_hasMetadata);
|
||||
if (m_hasMetadata && (m_torrentInfo->num_files() > 1)) {
|
||||
ui->content_tree->setVisible(true);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
} else {
|
||||
ui->content_tree->setVisible(false);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
}
|
||||
static_cast<QVBoxLayout*>(layout())->insertWidget(layout()->indexOf(ui->never_show_cb)+1, ui->adv_button);
|
||||
} else {
|
||||
ui->adv_button->setText(QString::fromUtf8("▼"));
|
||||
ui->settings_group->setVisible(false);
|
||||
ui->info_group->setVisible(false);
|
||||
ui->buttonsHLayout->insertWidget(0, layout()->takeAt(layout()->indexOf(ui->never_show_cb)+1)->widget());
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
}
|
||||
relayout();
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadTorrent(const QString& torrent_path, const QString& from_url)
|
||||
{
|
||||
m_isMagnet = false;
|
||||
m_url = from_url;
|
||||
if (torrent_path.startsWith("file://", Qt::CaseInsensitive))
|
||||
m_filePath = QUrl::fromEncoded(torrent_path.toLocal8Bit()).toLocalFile();
|
||||
else
|
||||
m_filePath = torrent_path;
|
||||
|
||||
if (!QFile::exists(m_filePath)) {
|
||||
QMessageBox::critical(0, tr("I/O Error"), tr("The torrent file does not exist."));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasMetadata = true;
|
||||
|
||||
try {
|
||||
m_torrentInfo = new torrent_info(m_filePath.toUtf8().data());
|
||||
m_hash = misc::toQString(m_torrentInfo->info_hash());
|
||||
} catch(const std::exception& e) {
|
||||
QMessageBox::critical(0, tr("Invalid torrent"), tr("Failed to load the torrent: %1").arg(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
QMessageBox::information(0, tr("Already in download list"), tr("Torrent is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set dialog title
|
||||
setWindowTitle(misc::toQStringU(m_torrentInfo->name()));
|
||||
|
||||
// Set torrent information
|
||||
QString comment = misc::toQString(m_torrentInfo->comment());
|
||||
ui->comment_lbl->setText(comment.replace('\n', ' '));
|
||||
ui->date_lbl->setText(m_torrentInfo->creation_date() ? misc::toQString(*m_torrentInfo->creation_date()) : tr("Not available"));
|
||||
updateDiskSpaceLabel();
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
file_storage fs = m_torrentInfo->files();
|
||||
#endif
|
||||
|
||||
// Populate m_filesList
|
||||
for (int i = 0; i < m_torrentInfo->num_files(); ++i) {
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
m_filesPath << misc::toQStringU(fs.file_path(m_torrentInfo->file_at(i)));
|
||||
#else
|
||||
m_filesPath << misc::toQStringU(m_torrentInfo->file_at(i).path.string());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare content tree
|
||||
if (m_torrentInfo->num_files() > 1) {
|
||||
m_contentModel = new TorrentContentFilterModel(this);
|
||||
connect(m_contentModel->model(), SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabel()));
|
||||
ui->content_tree->setModel(m_contentModel);
|
||||
ui->content_tree->hideColumn(PROGRESS);
|
||||
m_contentDelegate = new PropListDelegate();
|
||||
ui->content_tree->setItemDelegate(m_contentDelegate);
|
||||
connect(ui->content_tree, SIGNAL(clicked(const QModelIndex&)), ui->content_tree, SLOT(edit(const QModelIndex&)));
|
||||
connect(ui->content_tree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContentTreeMenu(const QPoint&)));
|
||||
|
||||
// List files in torrent
|
||||
m_contentModel->model()->setupModelData(*m_torrentInfo);
|
||||
|
||||
// Expand root folder
|
||||
ui->content_tree->setExpanded(m_contentModel->index(0, 0), true);
|
||||
} else {
|
||||
// Update save paths (append file name to them)
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
QString single_file_relpath = misc::toQStringU(fs.file_path(m_torrentInfo->file_at(0)));
|
||||
#else
|
||||
QString single_file_relpath = misc::toQStringU(m_torrentInfo->file_at(0).path.string());
|
||||
#endif
|
||||
for (int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
ui->save_path_combo->setItemText(i, fsutils::toDisplayPath(QDir(ui->save_path_combo->itemText(i)).absoluteFilePath(single_file_relpath)));
|
||||
}
|
||||
}
|
||||
|
||||
QIniSettings settings;
|
||||
showAdvancedSettings(settings.value("AddNewTorrentDialog/expanded").toBool());
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddNewTorrentDialog::loadMagnet(const QString &magnet_uri)
|
||||
{
|
||||
connect(QBtSession::instance(), SIGNAL(metadataReceivedHidden(const QTorrentHandle&)), SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
m_isMagnet = true;
|
||||
m_url = magnet_uri;
|
||||
m_hash = misc::magnetUriToHash(m_url);
|
||||
if (m_hash.isEmpty()) {
|
||||
QMessageBox::critical(0, tr("Invalid magnet link"), tr("This magnet link was not recognized"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (QBtSession::instance()->getTorrentHandle(m_hash).is_valid()) {
|
||||
QMessageBox::information(0, tr("Already in download list"), tr("Magnet link is already in download list. Merging trackers."), QMessageBox::Ok);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set dialog title
|
||||
QString torrent_name = misc::magnetUriToName(m_url);
|
||||
setWindowTitle(torrent_name.isEmpty() ? tr("Magnet link") : torrent_name);
|
||||
|
||||
QIniSettings settings;
|
||||
showAdvancedSettings(settings.value("AddNewTorrentDialog/expanded").toBool());
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
|
||||
Preferences pref;
|
||||
// Override save path
|
||||
TorrentTempData::setSavePath(m_hash, QString(QDir::tempPath() + QDir::separator() + m_hash).replace("\\", "/"));
|
||||
HiddenData::addData(m_hash);
|
||||
QBtSession::instance()->addMagnetUri(m_url, false);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::saveSavePathHistory() const
|
||||
{
|
||||
QDir selected_save_path(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
QIniSettings settings;
|
||||
// Get current history
|
||||
QStringList history = settings.value("TorrentAdditionDlg/save_path_history").toStringList();
|
||||
QList<QDir> history_dirs;
|
||||
foreach(const QString dir, history)
|
||||
history_dirs << QDir(dir);
|
||||
if (!history_dirs.contains(selected_save_path)) {
|
||||
// Add save path to history
|
||||
history << selected_save_path.absolutePath();
|
||||
// Limit list size
|
||||
if (history.size() > 8)
|
||||
history.removeFirst();
|
||||
// Save history
|
||||
settings.setValue("TorrentAdditionDlg/save_path_history", history);
|
||||
}
|
||||
}
|
||||
|
||||
// save_path is a folder, not an absolute file path
|
||||
int AddNewTorrentDialog::indexOfSavePath(const QString &save_path)
|
||||
{
|
||||
QDir saveDir(save_path);
|
||||
for(int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
if (QDir(ui->save_path_combo->itemData(i).toString()) == saveDir)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateFileNameInSavePaths(const QString &new_filename)
|
||||
{
|
||||
for(int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
const QDir folder(ui->save_path_combo->itemData(i).toString());
|
||||
ui->save_path_combo->setItemText(i, fsutils::toDisplayPath(folder.absoluteFilePath(new_filename)));
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateDiskSpaceLabel()
|
||||
{
|
||||
Q_ASSERT(m_hasMetadata);
|
||||
// Determine torrent size
|
||||
qulonglong torrent_size = 0;
|
||||
if (m_contentModel) {
|
||||
const std::vector<int> priorities = m_contentModel->model()->getFilesPriorities();
|
||||
Q_ASSERT(priorities.size() == (uint) m_torrentInfo->num_files());
|
||||
for (uint i=0; i<priorities.size(); ++i) {
|
||||
if (priorities[i] > 0)
|
||||
torrent_size += m_torrentInfo->file_at(i).size;
|
||||
}
|
||||
} else {
|
||||
torrent_size = m_torrentInfo->total_size();
|
||||
}
|
||||
QString size_string = misc::friendlyUnit(torrent_size);
|
||||
size_string += " (";
|
||||
size_string += tr("Disk space: %1").arg(misc::friendlyUnit(fsutils::freeDiskSpaceOnPath(ui->save_path_combo->currentText())));
|
||||
size_string += ")";
|
||||
ui->size_lbl->setText(size_string);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::onSavePathChanged(int index)
|
||||
{
|
||||
static int old_index = 0;
|
||||
Preferences pref;
|
||||
|
||||
if (index == (ui->save_path_combo->count() - 1)) {
|
||||
disconnect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSavePathChanged(int)));
|
||||
// User is asking for a new save path
|
||||
QString cur_save_path = ui->save_path_combo->itemText(old_index);
|
||||
QString new_path, old_filename, new_filename;
|
||||
|
||||
if (m_torrentInfo && m_torrentInfo->num_files() == 1) {
|
||||
old_filename = fsutils::fileName(cur_save_path);
|
||||
new_path = QFileDialog::getSaveFileName(this, tr("Choose save path"), cur_save_path, QString(), 0, QFileDialog::DontConfirmOverwrite);
|
||||
if (!new_path.isEmpty())
|
||||
new_path = fsutils::branchPath(new_path, &new_filename);
|
||||
qDebug() << "new_path: " << new_path;
|
||||
qDebug() << "new_filename: " << new_filename;
|
||||
} else {
|
||||
if (!cur_save_path.isEmpty() && QDir(cur_save_path).exists())
|
||||
new_path = QFileDialog::getExistingDirectory(this, tr("Choose save path"), cur_save_path);
|
||||
else
|
||||
new_path = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
|
||||
}
|
||||
if (!new_path.isEmpty()) {
|
||||
const int existing_index = indexOfSavePath(new_path);
|
||||
if (existing_index >= 0)
|
||||
ui->save_path_combo->setCurrentIndex(existing_index);
|
||||
else {
|
||||
// New path, prepend to combo box
|
||||
if (!new_filename.isEmpty())
|
||||
ui->save_path_combo->insertItem(0, fsutils::toDisplayPath(QDir(new_path).absoluteFilePath(new_filename)), new_path);
|
||||
else
|
||||
ui->save_path_combo->insertItem(0, fsutils::toDisplayPath(new_path), new_path);
|
||||
ui->save_path_combo->setCurrentIndex(0);
|
||||
}
|
||||
// Update file name in all save_paths
|
||||
if (!new_filename.isEmpty() && !fsutils::sameFileNames(old_filename, new_filename)) {
|
||||
m_hasRenamedFile = true;
|
||||
m_filesPath[0] = new_filename;
|
||||
updateFileNameInSavePaths(new_filename);
|
||||
}
|
||||
} else {
|
||||
// Restore index
|
||||
ui->save_path_combo->setCurrentIndex(old_index);
|
||||
}
|
||||
connect(ui->save_path_combo, SIGNAL(currentIndexChanged(int)), SLOT(onSavePathChanged(int)));
|
||||
}
|
||||
// Toggle default save path setting checkbox visibility
|
||||
ui->default_save_path_cb->setChecked(false);
|
||||
ui->default_save_path_cb->setVisible(QDir(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString()) != pref.getSavePath());
|
||||
relayout();
|
||||
// Remember index
|
||||
old_index = ui->save_path_combo->currentIndex();
|
||||
if (m_hasMetadata)
|
||||
updateDiskSpaceLabel();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::relayout()
|
||||
{
|
||||
qApp->processEvents();
|
||||
int min_width = minimumWidth();
|
||||
setMinimumWidth(width());
|
||||
adjustSize();
|
||||
setMinimumWidth(min_width);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::renameSelectedFile()
|
||||
{
|
||||
const QModelIndexList selectedIndexes = ui->content_tree->selectionModel()->selectedRows(0);
|
||||
if (selectedIndexes.size() != 1)
|
||||
return;
|
||||
const QModelIndex &index = selectedIndexes.first();
|
||||
// Ask for new name
|
||||
bool ok;
|
||||
const QString new_name_last = AutoExpandableDialog::getText(this, tr("Rename the file"),
|
||||
tr("New name:"), QLineEdit::Normal,
|
||||
index.data().toString(), &ok).trimmed();
|
||||
if (ok && !new_name_last.isEmpty()) {
|
||||
if (!fsutils::isValidFileSystemName(new_name_last)) {
|
||||
QMessageBox::warning(this, tr("The file could not be renamed"),
|
||||
tr("This file name contains forbidden characters, please choose a different one."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (m_contentModel->itemType(index) == TorrentContentModelItem::FileType) {
|
||||
// File renaming
|
||||
const int file_index = m_contentModel->getFileIndex(index);
|
||||
QString old_name = m_filesPath.at(file_index);
|
||||
old_name.replace("\\", "/");
|
||||
qDebug("Old name: %s", qPrintable(old_name));
|
||||
QStringList path_items = old_name.split("/");
|
||||
path_items.removeLast();
|
||||
path_items << new_name_last;
|
||||
QString new_name = path_items.join("/");
|
||||
if (fsutils::sameFileNames(old_name, new_name)) {
|
||||
qDebug("Name did not change");
|
||||
return;
|
||||
}
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("New name: %s", qPrintable(new_name));
|
||||
// Check if that name is already used
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
if (i == file_index) continue;
|
||||
if (fsutils::sameFileNames(m_filesPath.at(i), new_name)) {
|
||||
// Display error message
|
||||
QMessageBox::warning(this, tr("The file could not be renamed"),
|
||||
tr("This name is already in use in this folder. Please use a different name."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("Renaming %s to %s", qPrintable(old_name), qPrintable(new_name));
|
||||
// Rename file in files_path
|
||||
m_filesPath.replace(file_index, new_name);
|
||||
m_hasRenamedFile = true;
|
||||
// Rename in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
} else {
|
||||
// Folder renaming
|
||||
QStringList path_items;
|
||||
path_items << index.data().toString();
|
||||
QModelIndex parent = m_contentModel->parent(index);
|
||||
while(parent.isValid()) {
|
||||
path_items.prepend(parent.data().toString());
|
||||
parent = m_contentModel->parent(parent);
|
||||
}
|
||||
const QString old_path = path_items.join("/");
|
||||
path_items.removeLast();
|
||||
path_items << new_name_last;
|
||||
QString new_path = path_items.join("/");
|
||||
if (!new_path.endsWith("/")) new_path += "/";
|
||||
// Check for overwriting
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
|
||||
if (current_name.startsWith(new_path, Qt::CaseSensitive)) {
|
||||
#else
|
||||
if (current_name.startsWith(new_path, Qt::CaseInsensitive)) {
|
||||
#endif
|
||||
QMessageBox::warning(this, tr("The folder could not be renamed"),
|
||||
tr("This name is already in use in this folder. Please use a different name."),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Replace path in all files
|
||||
for (int i=0; i<m_torrentInfo->num_files(); ++i) {
|
||||
const QString ¤t_name = m_filesPath.at(i);
|
||||
if (current_name.startsWith(old_path)) {
|
||||
QString new_name = current_name;
|
||||
new_name.replace(0, old_path.length(), new_path);
|
||||
new_name = QDir::cleanPath(new_name);
|
||||
qDebug("Rename %s to %s", qPrintable(current_name), qPrintable(new_name));
|
||||
// Rename in files_path
|
||||
m_filesPath.replace(i, new_name);
|
||||
}
|
||||
}
|
||||
m_hasRenamedFile = true;
|
||||
// Rename folder in torrent files model too
|
||||
m_contentModel->setData(index, new_name_last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setdialogPosition()
|
||||
{
|
||||
qApp->processEvents();
|
||||
QPoint center(misc::screenCenter(this));
|
||||
// Adjust y
|
||||
QIniSettings settings;
|
||||
int y = settings.value("AddNewTorrentDialog/y", -1).toInt();
|
||||
if (y >= 0) {
|
||||
center.setY(y);
|
||||
} else {
|
||||
center.ry() -= 120;
|
||||
if (center.y() < 0)
|
||||
center.setY(0);
|
||||
}
|
||||
move(center);
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::loadSavePathHistory()
|
||||
{
|
||||
QIniSettings settings;
|
||||
QDir default_save_path(Preferences().getSavePath());
|
||||
// Load save path history
|
||||
QStringList raw_path_history = settings.value("TorrentAdditionDlg/save_path_history").toStringList();
|
||||
foreach (const QString &sp, raw_path_history) {
|
||||
if (QDir(sp) != default_save_path)
|
||||
ui->save_path_combo->addItem(fsutils::toDisplayPath(sp), sp);
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::displayContentTreeMenu(const QPoint&) {
|
||||
QMenu myFilesLlistMenu;
|
||||
const QModelIndexList selectedRows = ui->content_tree->selectionModel()->selectedRows(0);
|
||||
QAction *actRename = 0;
|
||||
if (selectedRows.size() == 1 && m_torrentInfo->num_files() > 1) {
|
||||
actRename = myFilesLlistMenu.addAction(IconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
|
||||
myFilesLlistMenu.addSeparator();
|
||||
}
|
||||
QMenu subMenu;
|
||||
subMenu.setTitle(tr("Priority"));
|
||||
subMenu.addAction(ui->actionNot_downloaded);
|
||||
subMenu.addAction(ui->actionNormal);
|
||||
subMenu.addAction(ui->actionHigh);
|
||||
subMenu.addAction(ui->actionMaximum);
|
||||
myFilesLlistMenu.addMenu(&subMenu);
|
||||
// Call menu
|
||||
QAction *act = myFilesLlistMenu.exec(QCursor::pos());
|
||||
if (act) {
|
||||
if (act == actRename) {
|
||||
renameSelectedFile();
|
||||
} else {
|
||||
int prio = prio::NORMAL;
|
||||
if (act == ui->actionHigh)
|
||||
prio = prio::HIGH;
|
||||
else {
|
||||
if (act == ui->actionMaximum) {
|
||||
prio = prio::MAXIMUM;
|
||||
} else {
|
||||
if (act == ui->actionNot_downloaded)
|
||||
prio = prio::IGNORED;
|
||||
}
|
||||
}
|
||||
qDebug("Setting files priority");
|
||||
foreach (const QModelIndex &index, selectedRows) {
|
||||
qDebug("Setting priority(%d) for file at row %d", prio, index.row());
|
||||
m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), prio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::accept()
|
||||
{
|
||||
if (m_isMagnet)
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
|
||||
Preferences pref;
|
||||
// Save Temporary data about torrent
|
||||
QString save_path = ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString();
|
||||
TorrentTempData::setSavePath(m_hash, save_path);
|
||||
if (ui->skip_check_cb->isChecked()) {
|
||||
// TODO: Check if destination actually exists
|
||||
TorrentTempData::setSeedingMode(m_hash, true);
|
||||
}
|
||||
pref.addTorrentsInPause(!ui->start_torrent_cb->isChecked());
|
||||
|
||||
// Label
|
||||
const QString label = ui->label_combo->currentText();
|
||||
if (!label.isEmpty())
|
||||
TorrentTempData::setLabel(m_hash, label);
|
||||
|
||||
// Save file priorities
|
||||
if (m_contentModel)
|
||||
TorrentTempData::setFilesPriority(m_hash, m_contentModel->model()->getFilesPriorities());
|
||||
|
||||
// Rename files if necessary
|
||||
if (m_hasRenamedFile)
|
||||
TorrentTempData::setFilesPath(m_hash, m_filesPath);
|
||||
|
||||
// Add torrent
|
||||
if (m_isMagnet)
|
||||
QBtSession::instance()->unhideMagnet(m_hash);
|
||||
else
|
||||
QBtSession::instance()->addTorrent(m_filePath, false, m_url);
|
||||
|
||||
saveSavePathHistory();
|
||||
// Save settings
|
||||
pref.useAdditionDialog(!ui->never_show_cb->isChecked());
|
||||
if (ui->default_save_path_cb->isChecked()) {
|
||||
pref.setSavePath(ui->save_path_combo->itemData(ui->save_path_combo->currentIndex()).toString());
|
||||
QBtSession::instance()->setDefaultSavePath(pref.getSavePath());
|
||||
}
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::reject() {
|
||||
if (m_isMagnet) {
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
setMetadataProgressIndicator(false);
|
||||
QBtSession::instance()->deleteTorrent(m_hash, true);
|
||||
}
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::updateMetadata(const QTorrentHandle &h) {
|
||||
try {
|
||||
if (h.hash() != m_hash)
|
||||
return;
|
||||
|
||||
disconnect(this, SLOT(updateMetadata(const QTorrentHandle&)));
|
||||
Q_ASSERT(h.has_metadata());
|
||||
|
||||
m_torrentInfo = new torrent_info(h.get_torrent_info());
|
||||
|
||||
// Good to go
|
||||
m_hasMetadata = true;
|
||||
setMetadataProgressIndicator(true, tr("Parsing metadata..."));
|
||||
|
||||
// Update UI
|
||||
// Set dialog title
|
||||
setWindowTitle(misc::toQStringU(m_torrentInfo->name()));
|
||||
|
||||
// Set torrent information
|
||||
QString comment = misc::toQString(m_torrentInfo->comment());
|
||||
ui->comment_lbl->setText(comment.replace('\n', ' '));
|
||||
ui->date_lbl->setText(m_torrentInfo->creation_date() ? misc::toQString(*m_torrentInfo->creation_date()) : tr("Not available"));
|
||||
updateDiskSpaceLabel();
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
file_storage fs = m_torrentInfo->files();
|
||||
#endif
|
||||
|
||||
// Populate m_filesList
|
||||
for (int i = 0; i < m_torrentInfo->num_files(); ++i) {
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
m_filesPath << misc::toQStringU(fs.file_path(m_torrentInfo->file_at(i)));
|
||||
#else
|
||||
m_filesPath << misc::toQStringU(m_torrentInfo->file_at(i).path.string());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare content tree
|
||||
if (m_torrentInfo->num_files() > 1) {
|
||||
m_contentModel = new TorrentContentFilterModel(this);
|
||||
connect(m_contentModel->model(), SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabel()));
|
||||
ui->content_tree->setModel(m_contentModel);
|
||||
ui->content_tree->hideColumn(PROGRESS);
|
||||
m_contentDelegate = new PropListDelegate();
|
||||
ui->content_tree->setItemDelegate(m_contentDelegate);
|
||||
connect(ui->content_tree, SIGNAL(clicked(const QModelIndex&)), ui->content_tree, SLOT(edit(const QModelIndex&)));
|
||||
connect(ui->content_tree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContentTreeMenu(const QPoint&)));
|
||||
|
||||
// List files in torrent
|
||||
m_contentModel->model()->setupModelData(*m_torrentInfo);
|
||||
|
||||
// Expand root folder
|
||||
ui->content_tree->setExpanded(m_contentModel->index(0, 0), true);
|
||||
} else {
|
||||
// Update save paths (append file name to them)
|
||||
#if LIBTORRENT_VERSION_NUM >= 1600
|
||||
QString single_file_relpath = misc::toQStringU(fs.file_path(m_torrentInfo->file_at(0)));
|
||||
#else
|
||||
QString single_file_relpath = misc::toQStringU(m_torrentInfo->file_at(0).path.string());
|
||||
#endif
|
||||
for (int i=0; i<ui->save_path_combo->count()-1; ++i) {
|
||||
ui->save_path_combo->setItemText(i, fsutils::toDisplayPath(QDir(ui->save_path_combo->itemText(i)).absoluteFilePath(single_file_relpath)));
|
||||
}
|
||||
}
|
||||
|
||||
QIniSettings settings;
|
||||
showAdvancedSettings(settings.value("AddNewTorrentDialog/expanded").toBool());
|
||||
// Set dialog position
|
||||
setdialogPosition();
|
||||
setMetadataProgressIndicator(false, tr("Metadata retrieval complete"));
|
||||
} catch (invalid_handle&) {
|
||||
QMessageBox::critical(0, tr("I/O Error"), ("Unknown error."));
|
||||
setMetadataProgressIndicator(false, tr("Unknown error"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AddNewTorrentDialog::setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText) {
|
||||
// Always show info label when waiting for metadata
|
||||
ui->lblMetaLoading->setVisible(true);
|
||||
ui->lblMetaLoading->setText(labelText);
|
||||
ui->progMetaLoading->setVisible(visibleIndicator);
|
||||
}
|
||||
103
src/addnewtorrentdialog.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef ADDNEWTORRENTDIALOG_H
|
||||
#define ADDNEWTORRENTDIALOG_H
|
||||
|
||||
#include <QShortcut>
|
||||
#include <QDialog>
|
||||
#include <QUrl>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class AddNewTorrentDialog;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class TorrentContentFilterModel;
|
||||
class PropListDelegate;
|
||||
|
||||
class AddNewTorrentDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~AddNewTorrentDialog();
|
||||
|
||||
static void showTorrent(const QString& torrent_path, const QString& from_url = QString());
|
||||
static void showMagnet(const QString& torrent_link);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
|
||||
private slots:
|
||||
void showAdvancedSettings(bool show);
|
||||
void displayContentTreeMenu(const QPoint&);
|
||||
void updateDiskSpaceLabel();
|
||||
void onSavePathChanged(int);
|
||||
void relayout();
|
||||
void renameSelectedFile();
|
||||
void setdialogPosition();
|
||||
void updateMetadata(const QTorrentHandle& h);
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
virtual void reject();
|
||||
|
||||
private:
|
||||
explicit AddNewTorrentDialog(QWidget *parent = 0);
|
||||
bool loadTorrent(const QString& torrent_path, const QString& from_url);
|
||||
bool loadMagnet(const QString& magnet_uri);
|
||||
void loadSavePathHistory();
|
||||
void saveSavePathHistory() const;
|
||||
int indexOfSavePath(const QString& save_path);
|
||||
void updateFileNameInSavePaths(const QString& new_filename);
|
||||
void loadState();
|
||||
void saveState();
|
||||
void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = QString());
|
||||
|
||||
private:
|
||||
Ui::AddNewTorrentDialog *ui;
|
||||
TorrentContentFilterModel *m_contentModel;
|
||||
PropListDelegate *m_contentDelegate;
|
||||
bool m_isMagnet;
|
||||
bool m_hasMetadata;
|
||||
QString m_filePath;
|
||||
QString m_url;
|
||||
QString m_hash;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> m_torrentInfo;
|
||||
QStringList m_filesPath;
|
||||
bool m_hasRenamedFile;
|
||||
QShortcut *editHotkey;
|
||||
};
|
||||
|
||||
#endif // ADDNEWTORRENTDIALOG_H
|
||||
300
src/addnewtorrentdialog.ui
Normal file
@@ -0,0 +1,300 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AddNewTorrentDialog</class>
|
||||
<widget class="QDialog" name="AddNewTorrentDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>414</width>
|
||||
<height>590</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Save as</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="save_path_combo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="default_save_path_cb">
|
||||
<property name="text">
|
||||
<string>Set as default save path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="never_show_cb">
|
||||
<property name="text">
|
||||
<string>Never show again</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="adv_button">
|
||||
<property name="text">
|
||||
<string notr="true">▼</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="settings_group">
|
||||
<property name="title">
|
||||
<string>Torrent settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3" columnstretch="1,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="start_torrent_cb">
|
||||
<property name="text">
|
||||
<string>Start torrent</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Label:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="label_combo">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertAtTop</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="skip_check_cb">
|
||||
<property name="text">
|
||||
<string>Skip hash check</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="info_group">
|
||||
<property name="title">
|
||||
<string>Torrent Information</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0" columnstretch="0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="size_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">xx GB (xx GB available)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Comment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="comment_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">comment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Date:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="date_lbl">
|
||||
<property name="text">
|
||||
<string notr="true">02/03/2012 20:30</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="content_tree">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="buttonsHLayout">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progMetaLoading">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string notr="true">%p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblMetaLoading">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionNormal">
|
||||
<property name="text">
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHigh">
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMaximum">
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNot_downloaded">
|
||||
<property name="text">
|
||||
<string>Do not download</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AddNewTorrentDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AddNewTorrentDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
121
src/autoexpandabledialog.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2013 Nick Tiskov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : daymansmail@gmail.com
|
||||
*/
|
||||
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "ui_autoexpandabledialog.h"
|
||||
|
||||
AutoExpandableDialog::AutoExpandableDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AutoExpandableDialog) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AutoExpandableDialog::~AutoExpandableDialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString AutoExpandableDialog::getText(QWidget *parent, const QString &title, const QString &label,
|
||||
QLineEdit::EchoMode mode, const QString &text, bool *ok,
|
||||
Qt::InputMethodHints inputMethodHints) {
|
||||
|
||||
AutoExpandableDialog d(parent);
|
||||
d.setWindowTitle(title);
|
||||
d.ui->textLabel->setText(label);
|
||||
d.ui->textEdit->setText(text);
|
||||
d.ui->textEdit->setEchoMode(mode);
|
||||
d.ui->textEdit->setInputMethodHints(inputMethodHints);
|
||||
|
||||
bool res = d.exec();
|
||||
if (ok)
|
||||
*ok = res;
|
||||
|
||||
if (!res)
|
||||
return QString();
|
||||
|
||||
return d.ui->textEdit->text();
|
||||
}
|
||||
|
||||
void AutoExpandableDialog::showEvent(QShowEvent *e) {
|
||||
// Overriding showEvent is required for consistent UI with fixed size under custom DPI
|
||||
// Show dialog
|
||||
QDialog::showEvent(e);
|
||||
// and resize textbox to fit the text
|
||||
|
||||
// NOTE: For some strange reason QFontMetrics gets more accurate
|
||||
// when called from showEvent. Only 6 symbols off instead of 11 symbols off.
|
||||
int textW = ui->textEdit->fontMetrics().width(ui->textEdit->text()) + 4;
|
||||
int screenW = QApplication::desktop()->width() / 4;
|
||||
int wd = textW;
|
||||
|
||||
if (!windowTitle().isEmpty()) {
|
||||
int _w = fontMetrics().width(windowTitle());
|
||||
if (_w > wd)
|
||||
wd = _w;
|
||||
}
|
||||
|
||||
if (!ui->textLabel->text().isEmpty()) {
|
||||
int _w = ui->textLabel->fontMetrics().width(ui->textLabel->text());
|
||||
if (_w > wd)
|
||||
wd = _w;
|
||||
}
|
||||
|
||||
|
||||
// Now resize the dialog to fit the contents
|
||||
// Maximum value is whichever is smaller:
|
||||
// 1. screen width / 4
|
||||
// 2. max width of text from either of: label, title, textedit
|
||||
// If the value is less than dialog default size default size is used
|
||||
wd = textW < screenW ? textW : screenW;
|
||||
if (wd > width())
|
||||
resize(width() - ui->horizontalLayout->sizeHint().width() + wd, height());
|
||||
|
||||
// Use old dialog behavior: prohibit resizing the dialog
|
||||
setFixedHeight(height());
|
||||
|
||||
// Update geometry: center on screen
|
||||
QDesktopWidget *desk = QApplication::desktop();
|
||||
MainWindow *wnd = qobject_cast<MainWindow*>(QApplication::activeWindow());
|
||||
QPoint p = QCursor::pos();
|
||||
|
||||
int screenNum = 0;
|
||||
if (wnd == 0)
|
||||
screenNum = desk->screenNumber(p);
|
||||
else if (!wnd->isHidden())
|
||||
screenNum = desk->screenNumber(wnd);
|
||||
else
|
||||
screenNum = desk->screenNumber(p);
|
||||
|
||||
QRect screenRes = desk->screenGeometry(screenNum);
|
||||
|
||||
QRect geom = geometry();
|
||||
geom.moveCenter(QPoint(screenRes.width() / 2, screenRes.height() / 2));
|
||||
setGeometry(geom);
|
||||
}
|
||||
60
src/autoexpandabledialog.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2013 Nick Tiskov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : daymansmail@gmail.com
|
||||
*/
|
||||
|
||||
#ifndef AUTOEXPANDABLEDIALOG_H
|
||||
#define AUTOEXPANDABLEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace Ui {
|
||||
class AutoExpandableDialog;
|
||||
}
|
||||
|
||||
class AutoExpandableDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AutoExpandableDialog(QWidget *parent = 0);
|
||||
~AutoExpandableDialog();
|
||||
|
||||
static QString getText(QWidget *parent, const QString& title, const QString& label,
|
||||
QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(),
|
||||
bool * ok = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *e);
|
||||
|
||||
private:
|
||||
Ui::AutoExpandableDialog *ui;
|
||||
};
|
||||
|
||||
#endif // AUTOEXPANDABLEDIALOG_H
|
||||
120
src/autoexpandabledialog.ui
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AutoExpandableDialog</class>
|
||||
<widget class="QDialog" name="AutoExpandableDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>222</width>
|
||||
<height>94</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textEdit">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AutoExpandableDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AutoExpandableDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -44,7 +44,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Are you sure you want to delete the selected torrents from the transfer list?</string>
|
||||
<string notr="true">deletion message goes here</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
|
||||
@@ -40,8 +40,12 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DeletionConfirmationDlg(QWidget *parent=0): QDialog(parent) {
|
||||
DeletionConfirmationDlg(QWidget *parent, const int &size, const QString &name): QDialog(parent) {
|
||||
setupUi(this);
|
||||
if (size == 1)
|
||||
label->setText(tr("Are you sure you want to delete \"%1\" from the transfer list?", "Are you sure you want to delete \"ubuntu-linux-iso\" from the transfer list?").arg(name));
|
||||
else
|
||||
label->setText(tr("Are you sure you want to delete these %1 torrents from the transfer list?", "Are you sure you want to delete these 5 torrents from the transfer list?").arg(QString::number(size)));
|
||||
// Icons
|
||||
lbl_warn->setPixmap(IconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height()));
|
||||
lbl_warn->setFixedWidth(lbl_warn->height());
|
||||
@@ -57,10 +61,10 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
||||
return checkPermDelete->isChecked();
|
||||
}
|
||||
|
||||
static bool askForDeletionConfirmation(bool *delete_local_files) {
|
||||
DeletionConfirmationDlg dlg;
|
||||
if(dlg.exec() == QDialog::Accepted) {
|
||||
*delete_local_files = dlg.shouldDeleteLocalFiles();
|
||||
static bool askForDeletionConfirmation(bool& delete_local_files, const int& size, const QString& name) {
|
||||
DeletionConfirmationDlg dlg(NULL, size, name);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
delete_local_files = dlg.shouldDeleteLocalFiles();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
288
src/dnsupdater.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include "dnsupdater.h"
|
||||
#include "qbtsession.h"
|
||||
|
||||
DNSUpdater::DNSUpdater(QObject *parent) :
|
||||
QObject(parent), m_state(OK), m_service(DNS::NONE)
|
||||
{
|
||||
updateCredentials();
|
||||
|
||||
// Load saved settings from previous session
|
||||
QIniSettings settings;
|
||||
m_lastIPCheckTime = settings.value("DNSUpdater/lastUpdateTime").toDateTime();
|
||||
m_lastIP = QHostAddress(settings.value("DNSUpdater/lastIP").toString());
|
||||
|
||||
// Start IP checking timer
|
||||
m_ipCheckTimer.setInterval(IP_CHECK_INTERVAL_MS);
|
||||
connect(&m_ipCheckTimer, SIGNAL(timeout()), SLOT(checkPublicIP()));
|
||||
m_ipCheckTimer.start();
|
||||
|
||||
// Check lastUpdate to avoid flooding
|
||||
if (!m_lastIPCheckTime.isValid() ||
|
||||
m_lastIPCheckTime.secsTo(QDateTime::currentDateTime())*1000 > IP_CHECK_INTERVAL_MS) {
|
||||
checkPublicIP();
|
||||
}
|
||||
}
|
||||
|
||||
DNSUpdater::~DNSUpdater() {
|
||||
// Save lastupdate time and last ip
|
||||
QIniSettings settings;
|
||||
settings.setValue("DNSUpdater/lastUpdateTime", m_lastIPCheckTime);
|
||||
settings.setValue("DNSUpdater/lastIP", m_lastIP.toString());
|
||||
}
|
||||
|
||||
void DNSUpdater::checkPublicIP()
|
||||
{
|
||||
Q_ASSERT(m_state == OK);
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||
SLOT(ipRequestFinished(QNetworkReply*)));
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl("http://checkip.dyndns.org"));
|
||||
request.setRawHeader("User-Agent", "qBittorrent/"VERSION" chris@qbittorrent.org");
|
||||
manager->get(request);
|
||||
}
|
||||
|
||||
void DNSUpdater::ipRequestFinished(QNetworkReply *reply)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (reply->error()) {
|
||||
// Error
|
||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||
} else {
|
||||
// Parse response
|
||||
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
|
||||
QString ret = reply->readAll();
|
||||
if (ipregex.indexIn(ret) >= 0) {
|
||||
QString ip_str = ipregex.cap(1);
|
||||
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ip_str;
|
||||
QHostAddress new_ip(ip_str);
|
||||
if (!new_ip.isNull()) {
|
||||
if (m_lastIP != new_ip) {
|
||||
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
|
||||
qDebug() << m_lastIP.toString() << "->" << new_ip.toString();
|
||||
m_lastIP = new_ip;
|
||||
updateDNSService();
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to construct a QHostAddress from the IP string";
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Regular expression failed ot capture the IP address";
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
reply->deleteLater();
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void DNSUpdater::updateDNSService()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// Prepare request
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||
SLOT(ipUpdateFinished(QNetworkReply*)));
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
QNetworkRequest request;
|
||||
request.setUrl(getUpdateUrl());
|
||||
request.setRawHeader("User-Agent", "qBittorrent/"VERSION" chris@qbittorrent.org");
|
||||
manager->get(request);
|
||||
}
|
||||
|
||||
QUrl DNSUpdater::getUpdateUrl() const
|
||||
{
|
||||
QUrl url;
|
||||
#ifdef QT_NO_OPENSSL
|
||||
url.setScheme("http");
|
||||
#else
|
||||
url.setScheme("https");
|
||||
#endif
|
||||
url.setUserName(m_username);
|
||||
url.setPassword(m_password);
|
||||
|
||||
Q_ASSERT(!m_lastIP.isNull());
|
||||
// Service specific
|
||||
switch(m_service) {
|
||||
case DNS::DYNDNS:
|
||||
url.setHost("members.dyndns.org");
|
||||
break;
|
||||
case DNS::NOIP:
|
||||
url.setHost("dynupdate.no-ip.com");
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Unrecognized Dynamic DNS service!";
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
url.setPath("/nic/update");
|
||||
url.addQueryItem("hostname", m_domain);
|
||||
url.addQueryItem("myip", m_lastIP.toString());
|
||||
Q_ASSERT(url.isValid());
|
||||
qDebug() << Q_FUNC_INFO << url.toString();
|
||||
return url;
|
||||
}
|
||||
|
||||
void DNSUpdater::ipUpdateFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (reply->error()) {
|
||||
// Error
|
||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||
} else {
|
||||
// Pase reply
|
||||
processIPUpdateReply(reply->readAll());
|
||||
}
|
||||
// Clean up
|
||||
reply->deleteLater();
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void DNSUpdater::processIPUpdateReply(const QString &reply)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << reply;
|
||||
QString code = reply.split(" ").first();
|
||||
qDebug() << Q_FUNC_INFO << "Code:" << code;
|
||||
if (code == "good" || code == "nochg") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Your dynamic DNS was successfully updated."), "green");
|
||||
return;
|
||||
}
|
||||
if (code == "911" || code == "dnserr") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
// It will retry in 30 minutes because the timer was not stopped
|
||||
return;
|
||||
}
|
||||
// Everything bellow is an error, stop updating until the user updates something
|
||||
m_ipCheckTimer.stop();
|
||||
m_lastIP.clear();
|
||||
if (code == "nohost") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: hostname supplied does not exist under specified account."),
|
||||
"red");
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
if (code == "badauth") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Invalid username/password."), "red");
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
if (code == "badagent") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
if (code == "!donator") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: %1 was returned by the service, please report a bug at http://bugs.qbittorrent.org.").arg("!donator"),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
if (code == "abuse") {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."),
|
||||
"red");
|
||||
m_state = FATAL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DNSUpdater::updateCredentials()
|
||||
{
|
||||
if (m_state == FATAL) return;
|
||||
Preferences pref;
|
||||
bool change = false;
|
||||
// Get DNS service information
|
||||
if (m_service != pref.getDynDNSService()) {
|
||||
m_service = pref.getDynDNSService();
|
||||
change = true;
|
||||
}
|
||||
if (m_domain != pref.getDynDomainName()) {
|
||||
m_domain = pref.getDynDomainName();
|
||||
QRegExp domain_regex("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$");
|
||||
if (domain_regex.indexIn(m_domain) < 0) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied domain name is invalid."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
if (m_username != pref.getDynDNSUsername()) {
|
||||
m_username = pref.getDynDNSUsername();
|
||||
if (m_username.length() < 4) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied username is too short."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
if (m_password != pref.getDynDNSPassword()) {
|
||||
m_password = pref.getDynDNSPassword();
|
||||
if (m_password.length() < 4) {
|
||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied password is too short."),
|
||||
"red");
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
m_state = INVALID_CREDS;
|
||||
return;
|
||||
}
|
||||
change = true;
|
||||
}
|
||||
|
||||
if (m_state == INVALID_CREDS && change) {
|
||||
m_state = OK; // Try again
|
||||
m_ipCheckTimer.start();
|
||||
checkPublicIP();
|
||||
}
|
||||
}
|
||||
|
||||
QUrl DNSUpdater::getRegistrationUrl(int service)
|
||||
{
|
||||
switch(service) {
|
||||
case DNS::DYNDNS:
|
||||
return QUrl("https://www.dyndns.com/account/services/hosts/add.html");
|
||||
case DNS::NOIP:
|
||||
return QUrl("http://www.no-ip.com/services/managed_dns/free_dynamic_dns.html");
|
||||
default:
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
return QUrl();
|
||||
}
|
||||
81
src/dnsupdater.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef DNSUPDATER_H
|
||||
#define DNSUPDATER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkReply>
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
#include "preferences.h"
|
||||
|
||||
/*!
|
||||
* Based on http://www.dyndns.com/developers/specs/
|
||||
*/
|
||||
class DNSUpdater : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DNSUpdater(QObject *parent = 0);
|
||||
~DNSUpdater();
|
||||
static QUrl getRegistrationUrl(int service);
|
||||
|
||||
public slots:
|
||||
void updateCredentials();
|
||||
|
||||
private slots:
|
||||
void checkPublicIP();
|
||||
void ipRequestFinished(QNetworkReply* reply);
|
||||
void updateDNSService();
|
||||
void ipUpdateFinished(QNetworkReply* reply);
|
||||
|
||||
private:
|
||||
QUrl getUpdateUrl() const;
|
||||
void processIPUpdateReply(const QString &reply);
|
||||
|
||||
private:
|
||||
QHostAddress m_lastIP;
|
||||
QDateTime m_lastIPCheckTime;
|
||||
QTimer m_ipCheckTimer;
|
||||
int m_state;
|
||||
// Service creds
|
||||
DNS::Service m_service;
|
||||
QString m_domain;
|
||||
QString m_username;
|
||||
QString m_password;
|
||||
|
||||
private:
|
||||
static const int IP_CHECK_INTERVAL_MS = 1800000; // 30 min
|
||||
enum State { OK, INVALID_CREDS, FATAL };
|
||||
};
|
||||
|
||||
#endif // DNSUPDATER_H
|
||||
@@ -43,47 +43,65 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
downloadFromURL(QWidget *parent): QDialog(parent){
|
||||
downloadFromURL(QWidget *parent): QDialog(parent) {
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setModal(true);
|
||||
show();
|
||||
// Paste clipboard if there is an URL in it
|
||||
QString clip_txt = qApp->clipboard()->text();
|
||||
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive) || clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
textUrls->setText(clip_txt);
|
||||
QStringList clip_txt_list = clip_txt.split(QString::fromUtf8("\n"));
|
||||
clip_txt.clear();
|
||||
QStringList clip_txt_list_cleaned;
|
||||
foreach (clip_txt, clip_txt_list) {
|
||||
clip_txt = clip_txt.trimmed();
|
||||
if (!clip_txt.isEmpty()) {
|
||||
if (clip_txt_list_cleaned.indexOf(QRegExp(clip_txt, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) {
|
||||
if (clip_txt.startsWith("http://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("https://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("ftp://", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("magnet:", Qt::CaseInsensitive)
|
||||
|| clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)
|
||||
|| (clip_txt.size() == 40 && !clip_txt.contains(QRegExp("[^0-9A-Fa-f]")))
|
||||
|| (clip_txt.size() == 32 && !clip_txt.contains(QRegExp("[^2-7A-Za-z]")))) {
|
||||
clip_txt_list_cleaned << clip_txt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clip_txt_list_cleaned.size() > 0)
|
||||
textUrls->setText(clip_txt_list_cleaned.join("\n"));
|
||||
}
|
||||
|
||||
~downloadFromURL(){}
|
||||
~downloadFromURL() {}
|
||||
|
||||
signals:
|
||||
void urlsReadyToBeDownloaded(const QStringList& torrent_urls);
|
||||
|
||||
public slots:
|
||||
void on_downloadButton_clicked(){
|
||||
void on_downloadButton_clicked() {
|
||||
close();
|
||||
QString urls = textUrls->toPlainText();
|
||||
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
||||
QString url;
|
||||
QStringList url_list_cleaned;
|
||||
foreach(url, url_list){
|
||||
foreach (url, url_list) {
|
||||
url = url.trimmed();
|
||||
if(!url.isEmpty()){
|
||||
if(url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0){
|
||||
if (!url.isEmpty()) {
|
||||
if (url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) {
|
||||
url_list_cleaned << url;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!url_list_cleaned.size()){
|
||||
if (!url_list_cleaned.size()) {
|
||||
QMessageBox::critical(0, tr("No URL entered"), tr("Please type at least one URL."));
|
||||
return;
|
||||
}
|
||||
emit urlsReadyToBeDownloaded(url_list_cleaned);
|
||||
qDebug("Emitted urlsReadytobedownloaded signal");
|
||||
close();
|
||||
}
|
||||
|
||||
void on_cancelButton_clicked(){
|
||||
void on_cancelButton_clicked() {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,31 +14,14 @@
|
||||
<string>Download from urls</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadURL_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
@@ -65,28 +48,16 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>true</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Both HTTP and Magnet links are supported</string>
|
||||
<string>One per line (HTTP links, Magnet links and info-hashes are supported)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
|
||||
@@ -32,159 +32,203 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkCookieJar>
|
||||
|
||||
#include "downloadthread.h"
|
||||
#include "preferences.h"
|
||||
#ifndef DISABLE_GUI
|
||||
#include "rsssettings.h"
|
||||
#include "rsssettings.h"
|
||||
#endif
|
||||
#include "qinisettings.h"
|
||||
#include <zlib.h>
|
||||
|
||||
/** Download Thread **/
|
||||
|
||||
downloadThread::downloadThread(QObject* parent) : QObject(parent) {
|
||||
DownloadThread::DownloadThread(QObject* parent) : QObject(parent) {
|
||||
connect(&m_networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
|
||||
#ifndef QT_NO_OPENSSL
|
||||
connect(&m_networkManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void downloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
QByteArray DownloadThread::gUncompress(Bytef *inData, size_t len) {
|
||||
if (len <= 4) {
|
||||
qWarning("gUncompress: Input data is truncated");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray result;
|
||||
|
||||
z_stream strm;
|
||||
static const int CHUNK_SIZE = 1024;
|
||||
char out[CHUNK_SIZE];
|
||||
|
||||
/* allocate inflate state */
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = len;
|
||||
strm.next_in = inData;
|
||||
|
||||
const int windowBits = 15;
|
||||
const int ENABLE_ZLIB_GZIP = 32;
|
||||
|
||||
int ret = inflateInit2(&strm, windowBits|ENABLE_ZLIB_GZIP ); // gzip decoding
|
||||
if (ret != Z_OK)
|
||||
return QByteArray();
|
||||
|
||||
// run inflate()
|
||||
do {
|
||||
strm.avail_out = CHUNK_SIZE;
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(out);
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
||||
|
||||
switch (ret) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
(void) inflateEnd(&strm);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
result.append(out, CHUNK_SIZE - strm.avail_out);
|
||||
} while (!strm.avail_out);
|
||||
|
||||
// clean up and return
|
||||
inflateEnd(&strm);
|
||||
return result;
|
||||
}
|
||||
|
||||
void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
||||
QString url = reply->url().toString();
|
||||
qDebug("Download finished: %s", qPrintable(url));
|
||||
if(reply->error() != QNetworkReply::NoError) {
|
||||
// Check if the request was successful
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
// Failure
|
||||
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
|
||||
emit downloadFailure(url, errorCodeToString(reply->error()));
|
||||
} else {
|
||||
QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if(redirection.isValid()) {
|
||||
// We should redirect
|
||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(redirection.toUrl().toString()));
|
||||
m_redirectMapping.insert(redirection.toUrl().toString(), url);
|
||||
downloadUrl(redirection.toUrl().toString());
|
||||
return;
|
||||
}
|
||||
// Checking if it was redirecting, restoring initial URL
|
||||
if(m_redirectMapping.contains(url)) {
|
||||
url = m_redirectMapping.take(url);
|
||||
}
|
||||
// Success
|
||||
QString filePath;
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
// Check if the server ask us to redirect somewhere lese
|
||||
const QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (redirection.isValid()) {
|
||||
// We should redirect
|
||||
QUrl newUrl = redirection.toUrl();
|
||||
// Resolve relative urls
|
||||
if (newUrl.isRelative())
|
||||
newUrl = reply->url().resolved(newUrl);
|
||||
const QString newUrlString = newUrl.toString();
|
||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString));
|
||||
m_redirectMapping.insert(newUrlString, url);
|
||||
// redirecting with first cookies
|
||||
downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url));
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
// Checking if it was redirected, restoring initial URL
|
||||
if (m_redirectMapping.contains(url)) {
|
||||
url = m_redirectMapping.take(url);
|
||||
}
|
||||
// Success
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
if (tmpfile->open()) {
|
||||
tmpfile->setAutoRemove(false);
|
||||
if (tmpfile->open()) {
|
||||
filePath = tmpfile->fileName();
|
||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||
if(reply->open(QIODevice::ReadOnly)) {
|
||||
// TODO: Support GZIP compression
|
||||
tmpfile->write(reply->readAll());
|
||||
reply->close();
|
||||
tmpfile->close();
|
||||
delete tmpfile;
|
||||
// Send finished signal
|
||||
emit downloadFinished(url, filePath);
|
||||
} else {
|
||||
// Error when reading the request
|
||||
tmpfile->close();
|
||||
delete tmpfile;
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
QString filePath = tmpfile->fileName();
|
||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||
if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
|
||||
QByteArray replyData = reply->readAll();
|
||||
if (reply->rawHeader("Content-Encoding") == "gzip") {
|
||||
// uncompress gzip reply
|
||||
replyData = gUncompress(reinterpret_cast<unsigned char*>(replyData.data()), replyData.length());
|
||||
}
|
||||
tmpfile->write(replyData);
|
||||
tmpfile->close();
|
||||
// XXX: tmpfile needs to be deleted on Windows before using the file
|
||||
// or it will complain that the file is used by another process.
|
||||
delete tmpfile;
|
||||
// Send finished signal
|
||||
emit downloadFinished(url, filePath);
|
||||
} else {
|
||||
delete tmpfile;
|
||||
fsutils::forceRemove(filePath);
|
||||
// Error when reading the request
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
}
|
||||
} else {
|
||||
delete tmpfile;
|
||||
emit downloadFailure(url, tr("I/O Error"));
|
||||
}
|
||||
// Clean up
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
void downloadThread::loadCookies(const QString &host_name, QString url) {
|
||||
const QList<QByteArray> raw_cookies = RssSettings().getHostNameCookies(host_name);
|
||||
QNetworkCookieJar *cookie_jar = m_networkManager.cookieJar();
|
||||
QList<QNetworkCookie> cookies;
|
||||
qDebug("Loading cookies for host name: %s", qPrintable(host_name));
|
||||
foreach(const QByteArray& raw_cookie, raw_cookies) {
|
||||
QList<QByteArray> cookie_parts = raw_cookie.split('=');
|
||||
if(cookie_parts.size() == 2) {
|
||||
qDebug("Loading cookie: %s", raw_cookie.constData());
|
||||
cookies << QNetworkCookie(cookie_parts.first(), cookie_parts.last());
|
||||
}
|
||||
}
|
||||
cookie_jar->setCookiesFromUrl(cookies, url);
|
||||
m_networkManager.setCookieJar(cookie_jar);
|
||||
}
|
||||
#endif
|
||||
|
||||
void downloadThread::downloadTorrentUrl(QString url) {
|
||||
#ifndef DISABLE_GUI
|
||||
// Load cookies
|
||||
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
|
||||
if(!host_name.isEmpty())
|
||||
loadCookies(host_name, url);
|
||||
#endif
|
||||
void DownloadThread::downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& cookies)
|
||||
{
|
||||
// Process request
|
||||
QNetworkReply *reply = downloadUrl(url);
|
||||
QNetworkReply *reply = downloadUrl(url, cookies);
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||
}
|
||||
|
||||
QNetworkReply* downloadThread::downloadUrl(QString url){
|
||||
QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QList<QNetworkCookie>& cookies) {
|
||||
// Update proxy settings
|
||||
applyProxySettings();
|
||||
#ifndef DISABLE_GUI
|
||||
// Load cookies
|
||||
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
|
||||
if(!host_name.isEmpty())
|
||||
loadCookies(host_name, url);
|
||||
#endif
|
||||
// Set cookies
|
||||
if (!cookies.empty()) {
|
||||
qDebug("Setting %d cookies for url: %s", cookies.size(), qPrintable(url));
|
||||
m_networkManager.cookieJar()->setCookiesFromUrl(cookies, url);
|
||||
}
|
||||
// Process download request
|
||||
qDebug("url is %s", qPrintable(url));
|
||||
const QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
|
||||
const QUrl qurl = QUrl::fromEncoded(url.toUtf8());
|
||||
QNetworkRequest request(qurl);
|
||||
// Spoof Firefox 3.5 user agent to avoid
|
||||
// Web server banning
|
||||
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");
|
||||
qDebug("Downloading %s...", request.url().toEncoded().data());
|
||||
qDebug("%d cookies for this URL", m_networkManager.cookieJar()->cookiesForUrl(url).size());
|
||||
for(int i=0; i<m_networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
|
||||
for (int i=0; i<m_networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
|
||||
qDebug("%s=%s", m_networkManager.cookieJar()->cookiesForUrl(url).at(i).name().data(), m_networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data());
|
||||
qDebug("Domain: %s, Path: %s", qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).domain()), qPrintable(m_networkManager.cookieJar()->cookiesForUrl(url).at(i).path()));
|
||||
}
|
||||
// accept gzip
|
||||
request.setRawHeader("Accept-Encoding", "gzip");
|
||||
return m_networkManager.get(request);
|
||||
}
|
||||
|
||||
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
if(bytesTotal > 0) {
|
||||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
|
||||
void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) return;
|
||||
if (bytesTotal > 0) {
|
||||
// Total number of bytes is available
|
||||
if(bytesTotal > 1048576) {
|
||||
// More than 1MB, this is probably not a torrent file, aborting...
|
||||
if (bytesTotal > 1048576*10) {
|
||||
// More than 10MB, this is probably not a torrent file, aborting...
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
} else {
|
||||
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||
}
|
||||
} else {
|
||||
if(bytesReceived > 1048576) {
|
||||
// More than 1MB, this is probably not a torrent file, aborting...
|
||||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
|
||||
if (bytesReceived > 1048576*10) {
|
||||
// More than 10MB, this is probably not a torrent file, aborting...
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void downloadThread::applyProxySettings() {
|
||||
void DownloadThread::applyProxySettings() {
|
||||
QNetworkProxy proxy;
|
||||
const Preferences pref;
|
||||
if(pref.isProxyEnabled()) {
|
||||
if (pref.isProxyEnabled()) {
|
||||
// Proxy enabled
|
||||
proxy.setHostName(pref.getProxyIp());
|
||||
proxy.setPort(pref.getProxyPort());
|
||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||
const int proxy_type = pref.getProxyType();
|
||||
if(proxy_type == Proxy::SOCKS5 || proxy_type == Proxy::SOCKS5_PW) {
|
||||
if (proxy_type == Proxy::SOCKS5 || proxy_type == Proxy::SOCKS5_PW) {
|
||||
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
} else {
|
||||
@@ -192,7 +236,7 @@ void downloadThread::applyProxySettings() {
|
||||
proxy.setType(QNetworkProxy::HttpProxy);
|
||||
}
|
||||
// Authentication?
|
||||
if(pref.isProxyAuthEnabled()) {
|
||||
if (pref.isProxyAuthEnabled()) {
|
||||
qDebug("Proxy requires authentication, authenticating");
|
||||
proxy.setUser(pref.getProxyUsername());
|
||||
proxy.setPassword(pref.getProxyPassword());
|
||||
@@ -203,8 +247,8 @@ void downloadThread::applyProxySettings() {
|
||||
m_networkManager.setProxy(proxy);
|
||||
}
|
||||
|
||||
QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
switch(status){
|
||||
QString DownloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
switch(status) {
|
||||
case QNetworkReply::HostNotFoundError:
|
||||
return tr("The remote host name was not found (invalid hostname)");
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
@@ -253,7 +297,7 @@ QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void downloadThread::ignoreSslErrors(QNetworkReply* reply,QList<QSslError> errors) {
|
||||
void DownloadThread::ignoreSslErrors(QNetworkReply* reply, const QList<QSslError> &errors) {
|
||||
Q_UNUSED(errors)
|
||||
// Ignore all SSL errors
|
||||
reply->ignoreSslErrors();
|
||||
|
||||
@@ -32,38 +32,40 @@
|
||||
#define DOWNLOADTHREAD_H
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkCookie>
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QSslError>
|
||||
#include <zlib.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QNetworkAccessManager;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class downloadThread : public QObject {
|
||||
class DownloadThread : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
downloadThread(QObject* parent = 0);
|
||||
QNetworkReply* downloadUrl(QString url);
|
||||
void downloadTorrentUrl(QString url);
|
||||
DownloadThread(QObject* parent = 0);
|
||||
QNetworkReply* downloadUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
void downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
//void setProxy(QString IP, int port, QString username, QString password);
|
||||
|
||||
signals:
|
||||
void downloadFinished(QString url, QString file_path);
|
||||
void downloadFailure(QString url, QString reason);
|
||||
void downloadFinished(const QString &url, const QString &file_path);
|
||||
void downloadFailure(const QString &url, const QString &reason);
|
||||
|
||||
private slots:
|
||||
void processDlFinished(QNetworkReply* reply);
|
||||
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void ignoreSslErrors(QNetworkReply*,QList<QSslError>);
|
||||
void ignoreSslErrors(QNetworkReply*,const QList<QSslError>&);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static QByteArray gUncompress(Bytef *inData, size_t len);
|
||||
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||
void applyProxySettings();
|
||||
#ifndef DISABLE_GUI
|
||||
void loadCookies(const QString &host_name, QString url);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QNetworkAccessManager m_networkManager;
|
||||
|
||||
@@ -1,32 +1,79 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QListWidgetItem>
|
||||
#include <QLabel>
|
||||
#include "executionlog.h"
|
||||
#include "ui_executionlog.h"
|
||||
#include "qbtsession.h"
|
||||
#include "iconprovider.h"
|
||||
#include "loglistwidget.h"
|
||||
|
||||
ExecutionLog::ExecutionLog(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExecutionLog)
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExecutionLog),
|
||||
m_logList(new LogListWidget(MAX_LOG_MESSAGES)),
|
||||
m_banList(new LogListWidget(MAX_LOG_MESSAGES))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->tabConsole->setTabIcon(0, IconProvider::instance()->getIcon("view-calendar-journal"));
|
||||
ui->tabConsole->setTabIcon(1, IconProvider::instance()->getIcon("view-filter"));
|
||||
ui->textConsole->setHtml(QBtSession::instance()->getConsoleMessages().join("<br>"));
|
||||
ui->tabGeneral->layout()->addWidget(m_logList);
|
||||
ui->tabBan->layout()->addWidget(m_banList);
|
||||
|
||||
const QStringList log_msgs = QBtSession::instance()->getConsoleMessages();
|
||||
foreach (const QString& msg, log_msgs)
|
||||
addLogMessage(msg);
|
||||
const QStringList ban_msgs = QBtSession::instance()->getPeerBanMessages();
|
||||
foreach (const QString& msg, ban_msgs)
|
||||
addBanMessage(msg);
|
||||
connect(QBtSession::instance(), SIGNAL(newConsoleMessage(QString)), SLOT(addLogMessage(QString)));
|
||||
ui->textBannedPeers->setHtml(QBtSession::instance()->getPeerBanMessages().join("<br>"));
|
||||
connect(QBtSession::instance(), SIGNAL(newBanMessage(QString)), SLOT(addBanMessage(QString)));
|
||||
connect(m_logList, SIGNAL(logCleared()), QBtSession::instance(), SLOT(clearConsoleMessages()));
|
||||
connect(m_banList, SIGNAL(logCleared()), QBtSession::instance(), SLOT(clearPeerBanMessages()));
|
||||
}
|
||||
|
||||
ExecutionLog::~ExecutionLog()
|
||||
{
|
||||
delete m_logList;
|
||||
delete m_banList;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ExecutionLog::addLogMessage(const QString &msg)
|
||||
{
|
||||
ui->textConsole->setHtml(msg+ui->textConsole->toHtml());
|
||||
m_logList->appendLine(msg);
|
||||
}
|
||||
|
||||
void ExecutionLog::addBanMessage(const QString &msg)
|
||||
{
|
||||
ui->textBannedPeers->setHtml(msg+ui->textBannedPeers->toHtml());
|
||||
m_banList->appendLine(msg);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2011 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef EXECUTIONLOG_H
|
||||
#define EXECUTIONLOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class ExecutionLog;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
class LogListWidget;
|
||||
|
||||
class ExecutionLog : public QWidget
|
||||
{
|
||||
@@ -20,7 +53,10 @@ public slots:
|
||||
void addBanMessage(const QString &msg);
|
||||
|
||||
private:
|
||||
Ui::ExecutionLog *ui;
|
||||
Ui::ExecutionLog *ui;
|
||||
|
||||
LogListWidget *m_logList;
|
||||
LogListWidget *m_banList;
|
||||
};
|
||||
|
||||
#endif // EXECUTIONLOG_H
|
||||
|
||||
@@ -22,25 +22,17 @@
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textConsole"/>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QVBoxLayout"/>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<widget class="QWidget" name="tabBan">
|
||||
<attribute name="title">
|
||||
<string>Blocked IPs</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="_2">
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBannedPeers"/>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QVBoxLayout" name="_2"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifndef CIFS_MAGIC_NUMBER
|
||||
@@ -59,11 +60,11 @@ private:
|
||||
private:
|
||||
static bool isNetworkFileSystem(QString path) {
|
||||
QString file = path;
|
||||
if(!file.endsWith(QDir::separator()))
|
||||
if (!file.endsWith(QDir::separator()))
|
||||
file += QDir::separator();
|
||||
file += ".";
|
||||
struct statfs buf;
|
||||
if(!statfs(file.toLocal8Bit().constData(), &buf)) {
|
||||
if (!statfs(file.toLocal8Bit().constData(), &buf)) {
|
||||
#ifdef Q_WS_MAC
|
||||
// XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined?
|
||||
return (strcmp(buf.f_fstypename, "nfs") == 0 || strcmp(buf.f_fstypename, "cifs") == 0 || strcmp(buf.f_fstypename, "smbfs") == 0);
|
||||
@@ -118,23 +119,23 @@ private:
|
||||
|
||||
public:
|
||||
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
||||
m_filters << "*.torrent";
|
||||
m_filters << "*.torrent" << "*.magnet";
|
||||
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
||||
}
|
||||
|
||||
~FileSystemWatcher() {
|
||||
#ifndef Q_WS_WIN
|
||||
if(watch_timer)
|
||||
if (watch_timer)
|
||||
delete watch_timer;
|
||||
#endif
|
||||
if(m_partialTorrentTimer)
|
||||
if (m_partialTorrentTimer)
|
||||
delete m_partialTorrentTimer;
|
||||
}
|
||||
|
||||
QStringList directories() const {
|
||||
QStringList dirs;
|
||||
#ifndef Q_WS_WIN
|
||||
if(watch_timer) {
|
||||
if (watch_timer) {
|
||||
foreach (const QDir &dir, watched_folders)
|
||||
dirs << dir.canonicalPath();
|
||||
}
|
||||
@@ -149,7 +150,7 @@ public:
|
||||
if (!dir.exists())
|
||||
return;
|
||||
// Check if the path points to a network file system or not
|
||||
if(isNetworkFileSystem(path)) {
|
||||
if (isNetworkFileSystem(path)) {
|
||||
// Network mode
|
||||
qDebug("Network folder detected: %s", qPrintable(path));
|
||||
qDebug("Using file polling mode instead of inotify...");
|
||||
@@ -194,7 +195,7 @@ protected slots:
|
||||
// Local folders scan
|
||||
addTorrentsFromDir(QDir(path), torrents);
|
||||
// Report detected torrent files
|
||||
if(!torrents.empty()) {
|
||||
if (!torrents.empty()) {
|
||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||
emit torrentsAdded(torrents);
|
||||
}
|
||||
@@ -210,7 +211,7 @@ protected slots:
|
||||
addTorrentsFromDir(dir, torrents);
|
||||
}
|
||||
// Report detected torrent files
|
||||
if(!torrents.empty()) {
|
||||
if (!torrents.empty()) {
|
||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||
emit torrentsAdded(torrents);
|
||||
}
|
||||
@@ -221,16 +222,16 @@ protected slots:
|
||||
QStringList no_longer_partial;
|
||||
|
||||
// Check which torrents are still partial
|
||||
foreach(const QString& torrent_path, m_partialTorrents.keys()) {
|
||||
if(!QFile::exists(torrent_path)) {
|
||||
foreach (const QString& torrent_path, m_partialTorrents.keys()) {
|
||||
if (!QFile::exists(torrent_path)) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
continue;
|
||||
}
|
||||
if(misc::isValidTorrentFile(torrent_path)) {
|
||||
if (fsutils::isValidTorrentFile(torrent_path)) {
|
||||
no_longer_partial << torrent_path;
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
} else {
|
||||
if(m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||
if (m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||
m_partialTorrents.remove(torrent_path);
|
||||
QFile::rename(torrent_path, torrent_path+".invalid");
|
||||
} else {
|
||||
@@ -240,7 +241,7 @@ protected slots:
|
||||
}
|
||||
|
||||
// Stop the partial timer if necessary
|
||||
if(m_partialTorrents.empty()) {
|
||||
if (m_partialTorrents.empty()) {
|
||||
m_partialTorrentTimer->stop();
|
||||
m_partialTorrentTimer->deleteLater();
|
||||
qDebug("No longer any partial torrent.");
|
||||
@@ -249,7 +250,7 @@ protected slots:
|
||||
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
||||
}
|
||||
// Notify of new torrents
|
||||
if(!no_longer_partial.isEmpty())
|
||||
if (!no_longer_partial.isEmpty())
|
||||
emit torrentsAdded(no_longer_partial);
|
||||
}
|
||||
|
||||
@@ -259,7 +260,7 @@ signals:
|
||||
private:
|
||||
void startPartialTorrentTimer() {
|
||||
Q_ASSERT(!m_partialTorrents.isEmpty());
|
||||
if(!m_partialTorrentTimer) {
|
||||
if (!m_partialTorrentTimer) {
|
||||
m_partialTorrentTimer = new QTimer();
|
||||
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
|
||||
m_partialTorrentTimer->setSingleShot(true);
|
||||
@@ -269,19 +270,25 @@ private:
|
||||
|
||||
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
|
||||
const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted);
|
||||
foreach(const QString &file, files) {
|
||||
foreach (const QString &file, files) {
|
||||
const QString file_abspath = dir.absoluteFilePath(file);
|
||||
if(misc::isValidTorrentFile(file_abspath)) {
|
||||
if (file_abspath.endsWith(".magnet")) {
|
||||
QFile f(file_abspath);
|
||||
if (f.open(QIODevice::ReadOnly)
|
||||
&& !misc::magnetUriToHash(QString::fromLocal8Bit(f.readAll())).isEmpty()) {
|
||||
torrents << file_abspath;
|
||||
}
|
||||
} else if (fsutils::isValidTorrentFile(file_abspath)) {
|
||||
torrents << file_abspath;
|
||||
} else {
|
||||
if(!m_partialTorrents.contains(file_abspath)) {
|
||||
if (!m_partialTorrents.contains(file_abspath)) {
|
||||
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
|
||||
qDebug("Delay the file's processing...");
|
||||
m_partialTorrents.insert(file_abspath, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!m_partialTorrents.empty())
|
||||
if (!m_partialTorrents.empty())
|
||||
startPartialTorrentTimer();
|
||||
}
|
||||
|
||||
|
||||
503
src/fs_utils.cpp
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#ifdef DISABLE_GUI
|
||||
#include <QCoreApplication>
|
||||
#else
|
||||
#include <QApplication>
|
||||
#endif
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
#if defined(Q_WS_MAC) || defined(Q_OS_FREEBSD)
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#else
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#else
|
||||
#include <shlobj.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
#include <QDesktopServices>
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
/**
|
||||
* Converts a path to a string suitable for display.
|
||||
* This function makes sure the directory separator used is consistent
|
||||
* with the OS being run.
|
||||
*/
|
||||
QString fsutils::toDisplayPath(const QString& path)
|
||||
{
|
||||
return QDir::toNativeSeparators(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file extension part of a file name.
|
||||
*/
|
||||
QString fsutils::fileExtension(const QString &filename)
|
||||
{
|
||||
const int point_index = filename.lastIndexOf(".");
|
||||
return (point_index >= 0) ? filename.mid(point_index + 1) : QString();
|
||||
}
|
||||
|
||||
QString fsutils::fileName(const QString& file_path)
|
||||
{
|
||||
const int slash_index = file_path.lastIndexOf(QRegExp("[/\\\\]"));
|
||||
if (slash_index == -1)
|
||||
return file_path;
|
||||
return file_path.mid(slash_index + 1);
|
||||
}
|
||||
|
||||
bool fsutils::isValidTorrentFile(const QString& torrent_path) {
|
||||
try {
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t = new torrent_info(torrent_path.toUtf8().constData());
|
||||
if (!t->is_valid() || t->num_files() == 0)
|
||||
return false;
|
||||
} catch(std::exception&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty folder tree.
|
||||
*
|
||||
* This function will also remove .DS_Store files on Mac OS and
|
||||
* Thumbs.db on Windows.
|
||||
*/
|
||||
bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << dir_path;
|
||||
if (dir_path.isEmpty())
|
||||
return false;
|
||||
|
||||
QDir dir(dir_path);
|
||||
if (!dir.exists())
|
||||
return true;
|
||||
|
||||
// Remove Files created by the OS
|
||||
#if defined Q_WS_MAC
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/.DS_Store"));
|
||||
#elif defined Q_WS_WIN
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/Thumbs.db"));
|
||||
#endif
|
||||
|
||||
QFileInfoList sub_files = dir.entryInfoList();
|
||||
foreach (const QFileInfo& info, sub_files) {
|
||||
QString sub_name = info.fileName();
|
||||
if (sub_name == "." || sub_name == "..")
|
||||
continue;
|
||||
|
||||
QString sub_path = info.absoluteFilePath();
|
||||
qDebug() << Q_FUNC_INFO << "sub file: " << sub_path;
|
||||
if (info.isDir()) {
|
||||
if (!smartRemoveEmptyFolderTree(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove folder: " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (info.isHidden()) {
|
||||
qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path;
|
||||
if (!fsutils::forceRemove(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Folder is not empty, aborting. Found: " << sub_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "Calling rmdir on " << dir_path;
|
||||
return QDir().rmdir(dir_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the file with the given file_path.
|
||||
*
|
||||
* This function will try to fix the file permissions before removing it.
|
||||
*/
|
||||
bool fsutils::forceRemove(const QString& file_path)
|
||||
{
|
||||
QFile f(file_path);
|
||||
if (!f.exists())
|
||||
return true;
|
||||
// Make sure we have read/write permissions
|
||||
f.setPermissions(f.permissions()|QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
|
||||
// Remove the file
|
||||
return f.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a file.
|
||||
* If the file is a folder, it will compute its size based on its content.
|
||||
*
|
||||
* Returns -1 in case of error.
|
||||
*/
|
||||
qint64 fsutils::computePathSize(const QString& path)
|
||||
{
|
||||
// Check if it is a file
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists()) return -1;
|
||||
if (fi.isFile()) return fi.size();
|
||||
// Compute folder size based on its content
|
||||
qint64 size = 0;
|
||||
foreach (const QFileInfo &subfi, QDir(path).entryInfoList(QDir::Dirs|QDir::Files)) {
|
||||
if (subfi.fileName().startsWith(".")) continue;
|
||||
if (subfi.isDir())
|
||||
size += fsutils::computePathSize(subfi.absoluteFilePath());
|
||||
else
|
||||
size += subfi.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes deep comparison of two files to make sure they are identical.
|
||||
*/
|
||||
bool fsutils::sameFiles(const QString& path1, const QString& path2)
|
||||
{
|
||||
QFile f1(path1), f2(path2);
|
||||
if (!f1.exists() || !f2.exists()) return false;
|
||||
if (f1.size() != f2.size()) return false;
|
||||
if (!f1.open(QIODevice::ReadOnly)) return false;
|
||||
if (!f2.open(QIODevice::ReadOnly)) {
|
||||
f1.close();
|
||||
return false;
|
||||
}
|
||||
bool same = true;
|
||||
while(!f1.atEnd() && !f2.atEnd()) {
|
||||
if (f1.read(1024) != f2.read(1024)) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f1.close(); f2.close();
|
||||
return same;
|
||||
}
|
||||
|
||||
QString fsutils::updateLabelInSavePath(QString defaultSavePath,QString save_path, const QString& old_label, const QString& new_label) {
|
||||
if (old_label == new_label) return save_path;
|
||||
defaultSavePath.replace("\\", "/");
|
||||
save_path.replace("\\", "/");
|
||||
qDebug("UpdateLabelInSavePath(%s, %s, %s)", qPrintable(save_path), qPrintable(old_label), qPrintable(new_label));
|
||||
if (!save_path.startsWith(defaultSavePath)) return save_path;
|
||||
QString new_save_path = save_path;
|
||||
new_save_path.replace(defaultSavePath, "");
|
||||
QStringList path_parts = new_save_path.split("/", QString::SkipEmptyParts);
|
||||
if (path_parts.empty()) {
|
||||
if (!new_label.isEmpty())
|
||||
path_parts << new_label;
|
||||
} else {
|
||||
if (old_label.isEmpty() || path_parts.first() != old_label) {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.prepend(new_label);
|
||||
} else {
|
||||
if (new_label.isEmpty()) {
|
||||
path_parts.removeAt(0);
|
||||
} else {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.replace(0, new_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
new_save_path = defaultSavePath;
|
||||
if (!new_save_path.endsWith(QDir::separator())) new_save_path += QDir::separator();
|
||||
new_save_path += path_parts.join(QDir::separator());
|
||||
qDebug("New save path is %s", qPrintable(new_save_path));
|
||||
return new_save_path;
|
||||
}
|
||||
|
||||
QString fsutils::toValidFileSystemName(QString filename) {
|
||||
qDebug("toValidFSName: %s", qPrintable(filename));
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
filename.replace(regex, " ");
|
||||
qDebug("toValidFSName, result: %s", qPrintable(filename));
|
||||
return filename.trimmed();
|
||||
}
|
||||
|
||||
bool fsutils::isValidFileSystemName(const QString& filename) {
|
||||
if (filename.isEmpty()) return false;
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
return !filename.contains(regex);
|
||||
}
|
||||
|
||||
long long fsutils::freeDiskSpaceOnPath(QString path) {
|
||||
if (path.isEmpty()) return -1;
|
||||
path.replace("\\", "/");
|
||||
QDir dir_path(path);
|
||||
if (!dir_path.exists()) {
|
||||
QStringList parts = path.split("/");
|
||||
while (parts.size() > 1 && !QDir(parts.join("/")).exists()) {
|
||||
parts.removeLast();
|
||||
}
|
||||
dir_path = QDir(parts.join("/"));
|
||||
if (!dir_path.exists()) return -1;
|
||||
}
|
||||
Q_ASSERT(dir_path.exists());
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
unsigned long long available;
|
||||
struct statfs stats;
|
||||
const QString statfs_path = dir_path.path()+"/.";
|
||||
const int ret = statfs (qPrintable(statfs_path), &stats) ;
|
||||
if (ret == 0) {
|
||||
available = ((unsigned long long)stats.f_bavail) *
|
||||
((unsigned long long)stats.f_bsize) ;
|
||||
return available;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER);
|
||||
GetDiskFreeSpaceEx_t
|
||||
pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
|
||||
(
|
||||
::GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetDiskFreeSpaceExW"
|
||||
);
|
||||
if ( pGetDiskFreeSpaceEx )
|
||||
{
|
||||
ULARGE_INTEGER bytesFree, bytesTotal;
|
||||
unsigned long long *ret;
|
||||
if (pGetDiskFreeSpaceEx((LPCTSTR)(QDir::toNativeSeparators(dir_path.path())).utf16(), &bytesFree, &bytesTotal, NULL)) {
|
||||
ret = (unsigned long long*)&bytesFree;
|
||||
return *ret;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::branchPath(const QString& file_path, QString* removed)
|
||||
{
|
||||
QString ret = file_path;
|
||||
if (ret.endsWith("/") || ret.endsWith("\\"))
|
||||
ret.chop(1);
|
||||
const int slashIndex = ret.lastIndexOf(QRegExp("[/\\\\]"));
|
||||
if (slashIndex >= 0) {
|
||||
if (removed)
|
||||
*removed = ret.mid(slashIndex + 1);
|
||||
ret = ret.left(slashIndex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool fsutils::sameFileNames(const QString &first, const QString &second)
|
||||
{
|
||||
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
|
||||
return QString::compare(first, second, Qt::CaseSensitive) == 0;
|
||||
#else
|
||||
return QString::compare(first, second, Qt::CaseInsensitive) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Replace ~ in path
|
||||
QString fsutils::expandPath(const QString& path) {
|
||||
QString ret = path.trimmed();
|
||||
if (ret.isEmpty()) return ret;
|
||||
if (ret == "~")
|
||||
return QDir::homePath();
|
||||
if (ret[0] == '~' && (ret[1] == '/' || ret[1] == '\\')) {
|
||||
ret.replace(0, 1, QDir::homePath());
|
||||
} else {
|
||||
if (!QDir::isAbsolutePath(ret))
|
||||
ret = QDir(ret).absolutePath();
|
||||
}
|
||||
return QDir::cleanPath(path);
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDataLocation() {
|
||||
#ifdef Q_WS_WIN
|
||||
LPWSTR path=new WCHAR[256];
|
||||
QString result;
|
||||
#if defined Q_WS_WINCE
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE))
|
||||
#else
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||
#endif
|
||||
result = QString::fromWCharArray(path);
|
||||
if (!QCoreApplication::applicationName().isEmpty())
|
||||
result = result + QLatin1String("\\") + qApp->applicationName();
|
||||
if (!result.endsWith("\\"))
|
||||
result += "\\";
|
||||
return result;
|
||||
#else
|
||||
#ifdef Q_WS_MAC
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
path = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
path += QLatin1Char('/') + qApp->applicationName();
|
||||
return path;
|
||||
#else
|
||||
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
||||
if (xdgDataHome.isEmpty())
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||
xdgDataHome += QLatin1String("/data/")
|
||||
+ qApp->applicationName();
|
||||
return xdgDataHome;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesCacheLocation() {
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
return QDesktopServicesDataLocation() + QLatin1String("\\cache");
|
||||
#else
|
||||
#ifdef Q_WS_MAC
|
||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
path = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
path += QLatin1Char('/') + qApp->applicationName();
|
||||
return path;
|
||||
#else
|
||||
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
||||
if (xdgCacheHome.isEmpty())
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
|
||||
return xdgCacheHome;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDownloadLocation() {
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
|
||||
// as long as it stays WinXP like we do the same on OS/2
|
||||
// TODO: Use IKnownFolderManager to get path of FOLDERID_Downloads
|
||||
// instead of hardcoding "Downloads"
|
||||
// Unfortunately, this would break compatibility with WinXP
|
||||
return QDir(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).absoluteFilePath(tr("Downloads"));
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
QString save_path;
|
||||
// Default save path on Linux
|
||||
QString config_path = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME").constData());
|
||||
if (config_path.isEmpty())
|
||||
config_path = QDir::home().absoluteFilePath(".config");
|
||||
|
||||
QString user_dirs_file = config_path + "/user-dirs.dirs";
|
||||
if (QFile::exists(user_dirs_file)) {
|
||||
QSettings settings(user_dirs_file, QSettings::IniFormat);
|
||||
// We need to force UTF-8 encoding here since this is not
|
||||
// the default for Ini files.
|
||||
settings.setIniCodec("UTF-8");
|
||||
QString xdg_download_dir = settings.value("XDG_DOWNLOAD_DIR").toString();
|
||||
if (!xdg_download_dir.isEmpty()) {
|
||||
// Resolve $HOME environment variables
|
||||
xdg_download_dir.replace("$HOME", QDir::homePath());
|
||||
save_path = xdg_download_dir;
|
||||
qDebug() << Q_FUNC_INFO << "SUCCESS: Using XDG path for downloads: " << save_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if (!save_path.isEmpty() && !QFile::exists(save_path)) {
|
||||
QDir().mkpath(save_path);
|
||||
}
|
||||
|
||||
if (save_path.isEmpty() || !QFile::exists(save_path)) {
|
||||
save_path = QDir::home().absoluteFilePath(tr("Downloads"));
|
||||
qDebug() << Q_FUNC_INFO << "using" << save_path << "as fallback since the XDG detection did not work";
|
||||
}
|
||||
|
||||
return save_path;
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
// TODO: How to support this on Mac OS X?
|
||||
#endif
|
||||
|
||||
// Fallback
|
||||
return QDir::home().absoluteFilePath(tr("Downloads"));
|
||||
}
|
||||
|
||||
QString fsutils::searchEngineLocation() {
|
||||
QString folder = "nova";
|
||||
if (misc::pythonVersion() >= 3)
|
||||
folder = "nova3";
|
||||
const QString location = QDir::cleanPath(QDesktopServicesDataLocation()
|
||||
+ QDir::separator() + folder);
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::BTBackupLocation() {
|
||||
const QString location = QDir::cleanPath(QDesktopServicesDataLocation()
|
||||
+ QDir::separator() + "BT_backup");
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::cacheLocation() {
|
||||
QString location = QDir::cleanPath(QDesktopServicesCacheLocation());
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
73
src/fs_utils.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FS_UTILS_H
|
||||
#define FS_UTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QCoreApplication>
|
||||
|
||||
/**
|
||||
* Utility functions related to file system.
|
||||
*/
|
||||
class fsutils
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(fsutils)
|
||||
|
||||
public:
|
||||
static QString toDisplayPath(const QString& path);
|
||||
static QString fileExtension(const QString& filename);
|
||||
static QString fileName(const QString& file_path);
|
||||
static qint64 computePathSize(const QString& path);
|
||||
static bool sameFiles(const QString& path1, const QString& path2);
|
||||
static QString updateLabelInSavePath(QString defaultSavePath, QString save_path, const QString& old_label, const QString& new_label);
|
||||
static QString toValidFileSystemName(QString filename);
|
||||
static bool isValidFileSystemName(const QString& filename);
|
||||
static long long freeDiskSpaceOnPath(QString path);
|
||||
static QString branchPath(const QString& file_path, QString* removed = 0);
|
||||
static bool sameFileNames(const QString& first, const QString& second);
|
||||
static QString expandPath(const QString& path);
|
||||
static bool isValidTorrentFile(const QString& path);
|
||||
static bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
||||
static bool forceRemove(const QString& file_path);
|
||||
|
||||
/* Ported from Qt4 to drop dependency on QtGui */
|
||||
static QString QDesktopServicesDataLocation();
|
||||
static QString QDesktopServicesCacheLocation();
|
||||
static QString QDesktopServicesDownloadLocation();
|
||||
/* End of Qt4 code */
|
||||
static QString searchEngineLocation();
|
||||
static QString BTBackupLocation();
|
||||
static QString cacheLocation();
|
||||
|
||||
};
|
||||
|
||||
#endif // FS_UTILS_H
|
||||
|
||||
@@ -64,20 +64,20 @@
|
||||
#include <QFile>
|
||||
#include <QChar>
|
||||
|
||||
#include "misc.h"
|
||||
#include "fs_utils.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
QString GeoIPManager::geoipFolder(bool embedded) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
if(embedded)
|
||||
if (embedded)
|
||||
return ":/geoip/";
|
||||
return misc::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
||||
return fsutils::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
||||
#else
|
||||
Q_UNUSED(embedded);
|
||||
if(QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||
if (QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
|
||||
return "/usr/local/share/GeoIP/";
|
||||
if(QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
|
||||
if (QFile::exists("/var/lib/GeoIP/GeoIP.dat"))
|
||||
return "/var/lib/GeoIP/";
|
||||
return "/usr/share/GeoIP/";
|
||||
#endif
|
||||
@@ -89,22 +89,22 @@ QString GeoIPManager::geoipDBpath(bool embedded) {
|
||||
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
void GeoIPManager::exportEmbeddedDb() {
|
||||
if(!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
|
||||
if (!QFile::exists(geoipDBpath(false)) || QFile(geoipDBpath(false)).size() != QFile(geoipDBpath(true)).size()) { // Export is required
|
||||
qDebug("A local Geoip database update is required, proceeding...");
|
||||
// Create geoip folder is necessary
|
||||
QDir gfolder(geoipFolder(false));
|
||||
if(!gfolder.exists()) {
|
||||
if(!gfolder.mkpath(geoipFolder(false))) {
|
||||
if (!gfolder.exists()) {
|
||||
if (!gfolder.mkpath(geoipFolder(false))) {
|
||||
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Remove destination files
|
||||
if(QFile::exists(geoipDBpath(false)))
|
||||
misc::safeRemove(geoipDBpath(false));
|
||||
if (QFile::exists(geoipDBpath(false)))
|
||||
fsutils::forceRemove(geoipDBpath(false));
|
||||
// Copy from executable to hard disk
|
||||
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
|
||||
if(!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
if (!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
|
||||
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
|
||||
}
|
||||
qDebug("Local Geoip database was updated");
|
||||
@@ -116,7 +116,7 @@ void GeoIPManager::loadDatabase(session *s) {
|
||||
#ifdef WITH_GEOIP_EMBEDDED
|
||||
exportEmbeddedDb();
|
||||
#endif
|
||||
if(QFile::exists(geoipDBpath(false))) {
|
||||
if (QFile::exists(geoipDBpath(false))) {
|
||||
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
||||
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
|
||||
} else {
|
||||
@@ -183,9 +183,9 @@ const char * country_name[253] =
|
||||
"Saint Barthelemy","Saint Martin"};
|
||||
|
||||
QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||
if(iso[0] == 0) return "N/A";
|
||||
for(uint i = 0; i < num_countries; ++i) {
|
||||
if(iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||
if (iso[0] == 0) return "N/A";
|
||||
for (uint i = 0; i < num_countries; ++i) {
|
||||
if (iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||
return QLatin1String(country_name[i]);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||
|
||||
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
QIcon GeoIPManager::CountryISOCodeToIcon(const char* iso) {
|
||||
if(iso[0] == 0 || iso[0] == '!') return QIcon();
|
||||
if (iso[0] == 0 || iso[0] == '!') return QIcon();
|
||||
const QString isoStr = QString(QByteArray(iso, 2)).toLower();
|
||||
return QIcon(":/Icons/flags/"+isoStr+".png");
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class HeadlessLoader: public QObject {
|
||||
|
||||
public:
|
||||
HeadlessLoader(const QStringList &torrentCmdLine) {
|
||||
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(shutdownCleanUp()), Qt::DirectConnection);
|
||||
Preferences pref;
|
||||
// Enable Web UI
|
||||
pref.setWebUiEnabled(true);
|
||||
@@ -55,17 +56,18 @@ public:
|
||||
std::cout << qPrintable(tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(pref.getWebUiPort()))) << std::endl;
|
||||
std::cout << qPrintable(tr("The Web UI administrator user name is: %1").arg(pref.getWebUiUsername())) << std::endl;
|
||||
qDebug() << "Password:" << pref.getWebUiPassword();
|
||||
if(pref.getWebUiPassword() == "32fe0bd2bb001911bb8bcfe23fc92b63") {
|
||||
if (pref.getWebUiPassword() == "32fe0bd2bb001911bb8bcfe23fc92b63") {
|
||||
std::cout << qPrintable(tr("The Web UI administrator password is still the default one: %1").arg("adminadmin")) << std::endl;
|
||||
std::cout << qPrintable(tr("This is a security risk, please consider changing your password from program preferences.")) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
~HeadlessLoader() {
|
||||
public slots:
|
||||
void shutdownCleanUp() {
|
||||
Preferences().sync();
|
||||
QBtSession::drop();
|
||||
}
|
||||
|
||||
public slots:
|
||||
// Call this function to exit qBittorrent headless loader
|
||||
// and return to prompt (object will be deleted by main)
|
||||
void exit() {
|
||||
@@ -85,16 +87,16 @@ public slots:
|
||||
// the right addTorrent function, considering
|
||||
// the parameter type.
|
||||
void processParams(const QStringList& params) {
|
||||
foreach(QString param, params) {
|
||||
foreach (QString param, params) {
|
||||
param = param.trimmed();
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
if (param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->downloadFromUrl(param);
|
||||
}else{
|
||||
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
if (param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
param = misc::bcLinkToMagnet(param);
|
||||
}
|
||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
if (param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||
QBtSession::instance()->addMagnetUri(param);
|
||||
} else {
|
||||
QBtSession::instance()->addTorrent(param);
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
protected:
|
||||
void tabInserted(int index) {
|
||||
QTabWidget::tabInserted(index);
|
||||
if(count() == 1) {
|
||||
if (count() == 1) {
|
||||
showTabBar(false);
|
||||
} else {
|
||||
showTabBar(true);
|
||||
@@ -53,7 +53,7 @@ protected:
|
||||
|
||||
void tabRemoved(int index) {
|
||||
QTabWidget::tabInserted(index);
|
||||
if(count() == 1) {
|
||||
if (count() == 1) {
|
||||
showTabBar(false);
|
||||
} else {
|
||||
showTabBar(true);
|
||||
|
||||
@@ -35,21 +35,21 @@ IconProvider* IconProvider::m_instance = 0;
|
||||
|
||||
IconProvider::IconProvider()
|
||||
{
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
#if defined(Q_WS_X11)
|
||||
m_useSystemTheme = Preferences().useSystemIconTheme();
|
||||
#endif
|
||||
}
|
||||
|
||||
IconProvider * IconProvider::instance()
|
||||
{
|
||||
if(!m_instance)
|
||||
if (!m_instance)
|
||||
m_instance = new IconProvider;
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void IconProvider::drop()
|
||||
{
|
||||
if(m_instance) {
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
@@ -57,8 +57,8 @@ void IconProvider::drop()
|
||||
|
||||
QIcon IconProvider::getIcon(const QString &iconId)
|
||||
{
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
if(m_useSystemTheme) {
|
||||
#if defined(Q_WS_X11)
|
||||
if (m_useSystemTheme) {
|
||||
QIcon icon = QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
|
||||
icon = generateDifferentSizes(icon);
|
||||
return icon;
|
||||
@@ -67,27 +67,31 @@ QIcon IconProvider::getIcon(const QString &iconId)
|
||||
return QIcon(":/Icons/oxygen/"+iconId+".png");
|
||||
}
|
||||
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
#if defined(Q_WS_X11)
|
||||
void IconProvider::useSystemIconTheme(bool enable)
|
||||
{
|
||||
m_useSystemTheme = enable;
|
||||
}
|
||||
|
||||
QIcon IconProvider::generateDifferentSizes(const QIcon &icon)
|
||||
// Makes sure the icon is at least available in 16px and 24px size
|
||||
// It scales the icon from the theme if necessary
|
||||
// Otherwise, the UI looks broken if the icon is not available
|
||||
// in the correct size.
|
||||
QIcon IconProvider::generateDifferentSizes(const QIcon& icon)
|
||||
{
|
||||
QIcon new_icon;
|
||||
QList<QSize> required_sizes;
|
||||
required_sizes << QSize(16, 16) << QSize(24, 24);
|
||||
QList<QIcon::Mode> modes;
|
||||
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
|
||||
foreach(const QSize& size, required_sizes) {
|
||||
foreach(QIcon::Mode mode, modes) {
|
||||
foreach (const QSize& size, required_sizes) {
|
||||
foreach (QIcon::Mode mode, modes) {
|
||||
QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off);
|
||||
if(pixoff.height() > size.height())
|
||||
if (pixoff.height() > size.height())
|
||||
pixoff = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
new_icon.addPixmap(pixoff, mode, QIcon::Off);
|
||||
QPixmap pixon = icon.pixmap(size, mode, QIcon::On);
|
||||
if(pixon.height() > size.height())
|
||||
if (pixon.height() > size.height())
|
||||
pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
new_icon.addPixmap(pixon, mode, QIcon::On);
|
||||
}
|
||||
@@ -96,14 +100,14 @@ QIcon IconProvider::generateDifferentSizes(const QIcon &icon)
|
||||
}
|
||||
#endif
|
||||
|
||||
QString IconProvider::getIconPath(const QString &iconId)
|
||||
QString IconProvider::getIconPath(const QString& iconId)
|
||||
{
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
if(m_useSystemTheme) {
|
||||
#if defined(Q_WS_X11)
|
||||
if (m_useSystemTheme) {
|
||||
QString path = QDir::temp().absoluteFilePath(iconId+".png");
|
||||
if(!QFile::exists(path)) {
|
||||
if (!QFile::exists(path)) {
|
||||
const QIcon icon = QIcon::fromTheme(iconId);
|
||||
if(icon.isNull()) return ":/Icons/oxygen/"+iconId+".png";
|
||||
if (icon.isNull()) return ":/Icons/oxygen/"+iconId+".png";
|
||||
QPixmap px = icon.pixmap(32);
|
||||
px.save(path);
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ public:
|
||||
static IconProvider* instance();
|
||||
static void drop();
|
||||
QIcon getIcon(const QString& iconId);
|
||||
QString getIconPath(const QString &iconId);
|
||||
QString getIconPath(const QString& iconId);
|
||||
|
||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
||||
#if defined(Q_WS_X11)
|
||||
public:
|
||||
void useSystemIconTheme(bool enable);
|
||||
|
||||
|
||||
643
src/icons.qrc
@@ -1,348 +1,353 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/3-state-checkbox.gif</file>
|
||||
<file>Icons/uparrow.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/downarrow.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/L.gif</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/magnet.png</file>
|
||||
<file>Icons/slow.png</file>
|
||||
<file>Icons/L.gif</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/connected.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/disconnected.png</file>
|
||||
<file>Icons/skin/mascot.png</file>
|
||||
<file>Icons/skin/paused.png</file>
|
||||
<file>Icons/skin/slider-area.gif</file>
|
||||
<file>Icons/skin/stalledDL.png</file>
|
||||
<file>Icons/skin/error.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/skin/uploading.png</file>
|
||||
<file>Icons/skin/queued.png</file>
|
||||
<file>Icons/skin/checking.png</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/arrow-right.gif</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/skin/bg-handle-horizontal.gif</file>
|
||||
<file>Icons/skin/download.png</file>
|
||||
<file>Icons/flags/sm.png</file>
|
||||
<file>Icons/flags/lt.png</file>
|
||||
<file>Icons/flags/th.png</file>
|
||||
<file>Icons/flags/sd.png</file>
|
||||
<file>Icons/flags/mr.png</file>
|
||||
<file>Icons/flags/by.png</file>
|
||||
<file>Icons/flags/sc.png</file>
|
||||
<file>Icons/flags/mz.png</file>
|
||||
<file>Icons/flags/tt.png</file>
|
||||
<file>Icons/flags/kp.png</file>
|
||||
<file>Icons/flags/re.png</file>
|
||||
<file>Icons/flags/um.png</file>
|
||||
<file>Icons/flags/ec.png</file>
|
||||
<file>Icons/flags/fk.png</file>
|
||||
<file>Icons/flags/aw.png</file>
|
||||
<file>Icons/flags/lb.png</file>
|
||||
<file>Icons/flags/vg.png</file>
|
||||
<file>Icons/flags/do.png</file>
|
||||
<file>Icons/flags/ee.png</file>
|
||||
<file>Icons/flags/ck.png</file>
|
||||
<file>Icons/flags/gn.png</file>
|
||||
<file>Icons/flags/cg.png</file>
|
||||
<file>Icons/flags/ao.png</file>
|
||||
<file>Icons/flags/dk.png</file>
|
||||
<file>Icons/flags/ms.png</file>
|
||||
<file>Icons/flags/sg.png</file>
|
||||
<file>Icons/flags/bw.png</file>
|
||||
<file>Icons/flags/br.png</file>
|
||||
<file>Icons/flags/cn.png</file>
|
||||
<file>Icons/flags/ua.png</file>
|
||||
<file>Icons/flags/ae.png</file>
|
||||
<file>Icons/flags/tg.png</file>
|
||||
<file>Icons/flags/ge.png</file>
|
||||
<file>Icons/flags/ne.png</file>
|
||||
<file>Icons/flags/km.png</file>
|
||||
<file>Icons/flags/bf.png</file>
|
||||
<file>Icons/flags/nf.png</file>
|
||||
<file>Icons/flags/az.png</file>
|
||||
<file>Icons/flags/sl.png</file>
|
||||
<file>Icons/flags/md.png</file>
|
||||
<file>Icons/flags/ph.png</file>
|
||||
<file>Icons/flags/mc.png</file>
|
||||
<file>Icons/flags/mq.png</file>
|
||||
<file>Icons/flags/ng.png</file>
|
||||
<file>Icons/flags/vu.png</file>
|
||||
<file>Icons/flags/et.png</file>
|
||||
<file>Icons/flags/bj.png</file>
|
||||
<file>Icons/flags/nl.png</file>
|
||||
<file>Icons/slow_off.png</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/flags/ad.png</file>
|
||||
<file>Icons/flags/tv.png</file>
|
||||
<file>Icons/flags/fj.png</file>
|
||||
<file>Icons/flags/to.png</file>
|
||||
<file>Icons/flags/ru.png</file>
|
||||
<file>Icons/flags/jp.png</file>
|
||||
<file>Icons/flags/ma.png</file>
|
||||
<file>Icons/flags/bz.png</file>
|
||||
<file>Icons/flags/vn.png</file>
|
||||
<file>Icons/flags/bt.png</file>
|
||||
<file>Icons/flags/ht.png</file>
|
||||
<file>Icons/flags/kw.png</file>
|
||||
<file>Icons/flags/tr.png</file>
|
||||
<file>Icons/flags/sy.png</file>
|
||||
<file>Icons/flags/nr.png</file>
|
||||
<file>Icons/flags/nz.png</file>
|
||||
<file>Icons/flags/np.png</file>
|
||||
<file>Icons/flags/uz.png</file>
|
||||
<file>Icons/flags/in.png</file>
|
||||
<file>Icons/flags/ga.png</file>
|
||||
<file>Icons/flags/sa.png</file>
|
||||
<file>Icons/flags/tl.png</file>
|
||||
<file>Icons/flags/ly.png</file>
|
||||
<file>Icons/flags/lr.png</file>
|
||||
<file>Icons/flags/cz.png</file>
|
||||
<file>Icons/flags/bm.png</file>
|
||||
<file>Icons/flags/us.png</file>
|
||||
<file>Icons/flags/ye.png</file>
|
||||
<file>Icons/flags/gs.png</file>
|
||||
<file>Icons/flags/sb.png</file>
|
||||
<file>Icons/flags/hm.png</file>
|
||||
<file>Icons/flags/ke.png</file>
|
||||
<file>Icons/flags/so.png</file>
|
||||
<file>Icons/flags/ni.png</file>
|
||||
<file>Icons/flags/cm.png</file>
|
||||
<file>Icons/flags/li.png</file>
|
||||
<file>Icons/flags/gp.png</file>
|
||||
<file>Icons/flags/co.png</file>
|
||||
<file>Icons/flags/kz.png</file>
|
||||
<file>Icons/flags/de.png</file>
|
||||
<file>Icons/flags/mm.png</file>
|
||||
<file>Icons/flags/gb.png</file>
|
||||
<file>Icons/flags/mx.png</file>
|
||||
<file>Icons/flags/la.png</file>
|
||||
<file>Icons/flags/ae.png</file>
|
||||
<file>Icons/flags/af.png</file>
|
||||
<file>Icons/flags/ag.png</file>
|
||||
<file>Icons/flags/ai.png</file>
|
||||
<file>Icons/flags/al.png</file>
|
||||
<file>Icons/flags/am.png</file>
|
||||
<file>Icons/flags/an.png</file>
|
||||
<file>Icons/flags/ao.png</file>
|
||||
<file>Icons/flags/ar.png</file>
|
||||
<file>Icons/flags/as.png</file>
|
||||
<file>Icons/flags/at.png</file>
|
||||
<file>Icons/flags/au.png</file>
|
||||
<file>Icons/flags/aw.png</file>
|
||||
<file>Icons/flags/ax.png</file>
|
||||
<file>Icons/flags/az.png</file>
|
||||
<file>Icons/flags/ba.png</file>
|
||||
<file>Icons/flags/bb.png</file>
|
||||
<file>Icons/flags/bd.png</file>
|
||||
<file>Icons/flags/be.png</file>
|
||||
<file>Icons/flags/bf.png</file>
|
||||
<file>Icons/flags/bg.png</file>
|
||||
<file>Icons/flags/bh.png</file>
|
||||
<file>Icons/flags/bi.png</file>
|
||||
<file>Icons/flags/bj.png</file>
|
||||
<file>Icons/flags/bm.png</file>
|
||||
<file>Icons/flags/bn.png</file>
|
||||
<file>Icons/flags/bo.png</file>
|
||||
<file>Icons/flags/br.png</file>
|
||||
<file>Icons/flags/bs.png</file>
|
||||
<file>Icons/flags/bt.png</file>
|
||||
<file>Icons/flags/bv.png</file>
|
||||
<file>Icons/flags/bw.png</file>
|
||||
<file>Icons/flags/by.png</file>
|
||||
<file>Icons/flags/bz.png</file>
|
||||
<file>Icons/flags/ca.png</file>
|
||||
<file>Icons/flags/cc.png</file>
|
||||
<file>Icons/flags/cd.png</file>
|
||||
<file>Icons/flags/cf.png</file>
|
||||
<file>Icons/flags/cg.png</file>
|
||||
<file>Icons/flags/ch.png</file>
|
||||
<file>Icons/flags/ci.png</file>
|
||||
<file>Icons/flags/ck.png</file>
|
||||
<file>Icons/flags/cl.png</file>
|
||||
<file>Icons/flags/cm.png</file>
|
||||
<file>Icons/flags/cn.png</file>
|
||||
<file>Icons/flags/co.png</file>
|
||||
<file>Icons/flags/cr.png</file>
|
||||
<file>Icons/flags/cs.png</file>
|
||||
<file>Icons/flags/cu.png</file>
|
||||
<file>Icons/flags/cv.png</file>
|
||||
<file>Icons/flags/cx.png</file>
|
||||
<file>Icons/flags/cy.png</file>
|
||||
<file>Icons/flags/cz.png</file>
|
||||
<file>Icons/flags/de.png</file>
|
||||
<file>Icons/flags/dj.png</file>
|
||||
<file>Icons/flags/dk.png</file>
|
||||
<file>Icons/flags/dm.png</file>
|
||||
<file>Icons/flags/do.png</file>
|
||||
<file>Icons/flags/dz.png</file>
|
||||
<file>Icons/flags/ec.png</file>
|
||||
<file>Icons/flags/ee.png</file>
|
||||
<file>Icons/flags/eg.png</file>
|
||||
<file>Icons/flags/eh.png</file>
|
||||
<file>Icons/flags/er.png</file>
|
||||
<file>Icons/flags/es.png</file>
|
||||
<file>Icons/flags/et.png</file>
|
||||
<file>Icons/flags/fi.png</file>
|
||||
<file>Icons/flags/fj.png</file>
|
||||
<file>Icons/flags/fk.png</file>
|
||||
<file>Icons/flags/fm.png</file>
|
||||
<file>Icons/flags/fo.png</file>
|
||||
<file>Icons/flags/fr.png</file>
|
||||
<file>Icons/flags/ga.png</file>
|
||||
<file>Icons/flags/gb.png</file>
|
||||
<file>Icons/flags/gd.png</file>
|
||||
<file>Icons/flags/ge.png</file>
|
||||
<file>Icons/flags/gf.png</file>
|
||||
<file>Icons/flags/gh.png</file>
|
||||
<file>Icons/flags/gi.png</file>
|
||||
<file>Icons/flags/gl.png</file>
|
||||
<file>Icons/flags/gm.png</file>
|
||||
<file>Icons/flags/gn.png</file>
|
||||
<file>Icons/flags/gp.png</file>
|
||||
<file>Icons/flags/gq.png</file>
|
||||
<file>Icons/flags/gr.png</file>
|
||||
<file>Icons/flags/gs.png</file>
|
||||
<file>Icons/flags/gt.png</file>
|
||||
<file>Icons/flags/gu.png</file>
|
||||
<file>Icons/flags/gw.png</file>
|
||||
<file>Icons/flags/lc.png</file>
|
||||
<file>Icons/flags/st.png</file>
|
||||
<file>Icons/flags/nc.png</file>
|
||||
<file>Icons/flags/ch.png</file>
|
||||
<file>Icons/flags/cd.png</file>
|
||||
<file>Icons/flags/mh.png</file>
|
||||
<file>Icons/flags/pg.png</file>
|
||||
<file>Icons/flags/bh.png</file>
|
||||
<file>Icons/flags/kr.png</file>
|
||||
<file>Icons/flags/is.png</file>
|
||||
<file>Icons/flags/gh.png</file>
|
||||
<file>Icons/flags/mp.png</file>
|
||||
<file>Icons/flags/ca.png</file>
|
||||
<file>Icons/flags/bi.png</file>
|
||||
<file>Icons/flags/yt.png</file>
|
||||
<file>Icons/flags/it.png</file>
|
||||
<file>Icons/flags/kn.png</file>
|
||||
<file>Icons/flags/ve.png</file>
|
||||
<file>Icons/flags/cu.png</file>
|
||||
<file>Icons/flags/bs.png</file>
|
||||
<file>Icons/flags/rs.png</file>
|
||||
<file>Icons/flags/tw.png</file>
|
||||
<file>Icons/flags/bd.png</file>
|
||||
<file>Icons/flags/pr.png</file>
|
||||
<file>Icons/flags/lk.png</file>
|
||||
<file>Icons/flags/sn.png</file>
|
||||
<file>Icons/flags/gr.png</file>
|
||||
<file>Icons/flags/gm.png</file>
|
||||
<file>Icons/flags/na.png</file>
|
||||
<file>Icons/flags/om.png</file>
|
||||
<file>Icons/flags/tz.png</file>
|
||||
<file>Icons/flags/as.png</file>
|
||||
<file>Icons/flags/no.png</file>
|
||||
<file>Icons/flags/mv.png</file>
|
||||
<file>Icons/flags/ki.png</file>
|
||||
<file>Icons/flags/eg.png</file>
|
||||
<file>Icons/flags/tj.png</file>
|
||||
<file>Icons/flags/sj.png</file>
|
||||
<file>Icons/flags/fi.png</file>
|
||||
<file>Icons/flags/lv.png</file>
|
||||
<file>Icons/flags/cx.png</file>
|
||||
<file>Icons/flags/ci.png</file>
|
||||
<file>Icons/flags/vi.png</file>
|
||||
<file>Icons/flags/be.png</file>
|
||||
<file>Icons/flags/mw.png</file>
|
||||
<file>Icons/flags/zw.png</file>
|
||||
<file>Icons/flags/si.png</file>
|
||||
<file>Icons/flags/dm.png</file>
|
||||
<file>Icons/flags/jo.png</file>
|
||||
<file>Icons/flags/hk.png</file>
|
||||
<file>Icons/flags/me.png</file>
|
||||
<file>Icons/flags/va.png</file>
|
||||
<file>Icons/flags/pm.png</file>
|
||||
<file>Icons/flags/qa.png</file>
|
||||
<file>Icons/flags/cc.png</file>
|
||||
<file>Icons/flags/kh.png</file>
|
||||
<file>Icons/flags/id.png</file>
|
||||
<file>Icons/flags/ai.png</file>
|
||||
<file>Icons/flags/mn.png</file>
|
||||
<file>Icons/flags/gd.png</file>
|
||||
<file>Icons/flags/mt.png</file>
|
||||
<file>Icons/flags/gq.png</file>
|
||||
<file>Icons/flags/hr.png</file>
|
||||
<file>Icons/flags/sv.png</file>
|
||||
<file>Icons/flags/dz.png</file>
|
||||
<file>Icons/flags/kg.png</file>
|
||||
<file>Icons/flags/gy.png</file>
|
||||
<file>Icons/flags/bv.png</file>
|
||||
<file>Icons/flags/ag.png</file>
|
||||
<file>Icons/flags/hk.png</file>
|
||||
<file>Icons/flags/hm.png</file>
|
||||
<file>Icons/flags/hn.png</file>
|
||||
<file>Icons/flags/ml.png</file>
|
||||
<file>Icons/flags/fo.png</file>
|
||||
<file>Icons/flags/pw.png</file>
|
||||
<file>Icons/flags/mg.png</file>
|
||||
<file>Icons/flags/iq.png</file>
|
||||
<file>Icons/flags/jm.png</file>
|
||||
<file>Icons/flags/bo.png</file>
|
||||
<file>Icons/flags/sk.png</file>
|
||||
<file>Icons/flags/sh.png</file>
|
||||
<file>Icons/flags/tf.png</file>
|
||||
<file>Icons/flags/mk.png</file>
|
||||
<file>Icons/flags/my.png</file>
|
||||
<file>Icons/flags/es.png</file>
|
||||
<file>Icons/flags/py.png</file>
|
||||
<file>Icons/flags/ax.png</file>
|
||||
<file>Icons/flags/ls.png</file>
|
||||
<file>Icons/flags/tn.png</file>
|
||||
<file>Icons/flags/ps.png</file>
|
||||
<file>Icons/flags/bn.png</file>
|
||||
<file>Icons/flags/dj.png</file>
|
||||
<file>Icons/flags/cs.png</file>
|
||||
<file>Icons/flags/pl.png</file>
|
||||
<file>Icons/flags/cl.png</file>
|
||||
<file>Icons/flags/pf.png</file>
|
||||
<file>Icons/flags/gi.png</file>
|
||||
<file>Icons/flags/bb.png</file>
|
||||
<file>Icons/flags/ws.png</file>
|
||||
<file>Icons/flags/cy.png</file>
|
||||
<file>Icons/flags/pt.png</file>
|
||||
<file>Icons/flags/ba.png</file>
|
||||
<file>Icons/flags/gl.png</file>
|
||||
<file>Icons/flags/ie.png</file>
|
||||
<file>Icons/flags/fr.png</file>
|
||||
<file>Icons/flags/tm.png</file>
|
||||
<file>Icons/flags/er.png</file>
|
||||
<file>Icons/flags/cr.png</file>
|
||||
<file>Icons/flags/af.png</file>
|
||||
<file>Icons/flags/mu.png</file>
|
||||
<file>Icons/flags/lu.png</file>
|
||||
<file>Icons/flags/pk.png</file>
|
||||
<file>Icons/flags/am.png</file>
|
||||
<file>Icons/flags/ar.png</file>
|
||||
<file>Icons/flags/uy.png</file>
|
||||
<file>Icons/flags/hr.png</file>
|
||||
<file>Icons/flags/ht.png</file>
|
||||
<file>Icons/flags/hu.png</file>
|
||||
<file>Icons/flags/pn.png</file>
|
||||
<file>Icons/flags/gf.png</file>
|
||||
<file>Icons/flags/ir.png</file>
|
||||
<file>Icons/flags/pe.png</file>
|
||||
<file>Icons/flags/nu.png</file>
|
||||
<file>Icons/flags/ro.png</file>
|
||||
<file>Icons/flags/mo.png</file>
|
||||
<file>Icons/flags/za.png</file>
|
||||
<file>Icons/flags/ky.png</file>
|
||||
<file>Icons/flags/zm.png</file>
|
||||
<file>Icons/flags/se.png</file>
|
||||
<file>Icons/flags/id.png</file>
|
||||
<file>Icons/flags/ie.png</file>
|
||||
<file>Icons/flags/il.png</file>
|
||||
<file>Icons/flags/fm.png</file>
|
||||
<file>Icons/flags/sr.png</file>
|
||||
<file>Icons/flags/pa.png</file>
|
||||
<file>Icons/flags/cv.png</file>
|
||||
<file>Icons/flags/tc.png</file>
|
||||
<file>Icons/flags/an.png</file>
|
||||
<file>Icons/flags/sz.png</file>
|
||||
<file>Icons/flags/in.png</file>
|
||||
<file>Icons/flags/io.png</file>
|
||||
<file>Icons/flags/iq.png</file>
|
||||
<file>Icons/flags/ir.png</file>
|
||||
<file>Icons/flags/is.png</file>
|
||||
<file>Icons/flags/it.png</file>
|
||||
<file>Icons/flags/jm.png</file>
|
||||
<file>Icons/flags/jo.png</file>
|
||||
<file>Icons/flags/jp.png</file>
|
||||
<file>Icons/flags/ke.png</file>
|
||||
<file>Icons/flags/kg.png</file>
|
||||
<file>Icons/flags/kh.png</file>
|
||||
<file>Icons/flags/ki.png</file>
|
||||
<file>Icons/flags/km.png</file>
|
||||
<file>Icons/flags/kn.png</file>
|
||||
<file>Icons/flags/kp.png</file>
|
||||
<file>Icons/flags/kr.png</file>
|
||||
<file>Icons/flags/kw.png</file>
|
||||
<file>Icons/flags/ky.png</file>
|
||||
<file>Icons/flags/kz.png</file>
|
||||
<file>Icons/flags/la.png</file>
|
||||
<file>Icons/flags/lb.png</file>
|
||||
<file>Icons/flags/lc.png</file>
|
||||
<file>Icons/flags/li.png</file>
|
||||
<file>Icons/flags/lk.png</file>
|
||||
<file>Icons/flags/lr.png</file>
|
||||
<file>Icons/flags/ls.png</file>
|
||||
<file>Icons/flags/lt.png</file>
|
||||
<file>Icons/flags/lu.png</file>
|
||||
<file>Icons/flags/lv.png</file>
|
||||
<file>Icons/flags/ly.png</file>
|
||||
<file>Icons/flags/ma.png</file>
|
||||
<file>Icons/flags/mc.png</file>
|
||||
<file>Icons/flags/md.png</file>
|
||||
<file>Icons/flags/me.png</file>
|
||||
<file>Icons/flags/mg.png</file>
|
||||
<file>Icons/flags/mh.png</file>
|
||||
<file>Icons/flags/mk.png</file>
|
||||
<file>Icons/flags/ml.png</file>
|
||||
<file>Icons/flags/mm.png</file>
|
||||
<file>Icons/flags/mn.png</file>
|
||||
<file>Icons/flags/mo.png</file>
|
||||
<file>Icons/flags/mp.png</file>
|
||||
<file>Icons/flags/mq.png</file>
|
||||
<file>Icons/flags/mr.png</file>
|
||||
<file>Icons/flags/ms.png</file>
|
||||
<file>Icons/flags/mt.png</file>
|
||||
<file>Icons/flags/mu.png</file>
|
||||
<file>Icons/flags/mv.png</file>
|
||||
<file>Icons/flags/mw.png</file>
|
||||
<file>Icons/flags/mx.png</file>
|
||||
<file>Icons/flags/my.png</file>
|
||||
<file>Icons/flags/mz.png</file>
|
||||
<file>Icons/flags/na.png</file>
|
||||
<file>Icons/flags/nc.png</file>
|
||||
<file>Icons/flags/ne.png</file>
|
||||
<file>Icons/flags/nf.png</file>
|
||||
<file>Icons/flags/ng.png</file>
|
||||
<file>Icons/flags/ni.png</file>
|
||||
<file>Icons/flags/nl.png</file>
|
||||
<file>Icons/flags/no.png</file>
|
||||
<file>Icons/flags/np.png</file>
|
||||
<file>Icons/flags/nr.png</file>
|
||||
<file>Icons/flags/nu.png</file>
|
||||
<file>Icons/flags/nz.png</file>
|
||||
<file>Icons/flags/om.png</file>
|
||||
<file>Icons/flags/pa.png</file>
|
||||
<file>Icons/flags/pe.png</file>
|
||||
<file>Icons/flags/pf.png</file>
|
||||
<file>Icons/flags/pg.png</file>
|
||||
<file>Icons/flags/ph.png</file>
|
||||
<file>Icons/flags/pk.png</file>
|
||||
<file>Icons/flags/pl.png</file>
|
||||
<file>Icons/flags/pm.png</file>
|
||||
<file>Icons/flags/pn.png</file>
|
||||
<file>Icons/flags/pr.png</file>
|
||||
<file>Icons/flags/ps.png</file>
|
||||
<file>Icons/flags/pt.png</file>
|
||||
<file>Icons/flags/pw.png</file>
|
||||
<file>Icons/flags/py.png</file>
|
||||
<file>Icons/flags/qa.png</file>
|
||||
<file>Icons/flags/re.png</file>
|
||||
<file>Icons/flags/ro.png</file>
|
||||
<file>Icons/flags/rs.png</file>
|
||||
<file>Icons/flags/ru.png</file>
|
||||
<file>Icons/flags/rw.png</file>
|
||||
<file>Icons/flags/eh.png</file>
|
||||
<file>Icons/flags/cf.png</file>
|
||||
<file>Icons/flags/gt.png</file>
|
||||
<file>Icons/flags/al.png</file>
|
||||
<file>Icons/flags/ug.png</file>
|
||||
<file>Icons/flags/sa.png</file>
|
||||
<file>Icons/flags/sb.png</file>
|
||||
<file>Icons/flags/sc.png</file>
|
||||
<file>Icons/flags/sd.png</file>
|
||||
<file>Icons/flags/se.png</file>
|
||||
<file>Icons/flags/sg.png</file>
|
||||
<file>Icons/flags/sh.png</file>
|
||||
<file>Icons/flags/si.png</file>
|
||||
<file>Icons/flags/sj.png</file>
|
||||
<file>Icons/flags/sk.png</file>
|
||||
<file>Icons/flags/sl.png</file>
|
||||
<file>Icons/flags/sm.png</file>
|
||||
<file>Icons/flags/sn.png</file>
|
||||
<file>Icons/flags/so.png</file>
|
||||
<file>Icons/flags/sr.png</file>
|
||||
<file>Icons/flags/st.png</file>
|
||||
<file>Icons/flags/sv.png</file>
|
||||
<file>Icons/flags/sy.png</file>
|
||||
<file>Icons/flags/sz.png</file>
|
||||
<file>Icons/flags/tc.png</file>
|
||||
<file>Icons/flags/td.png</file>
|
||||
<file>Icons/flags/at.png</file>
|
||||
<file>Icons/flags/vc.png</file>
|
||||
<file>Icons/flags/tf.png</file>
|
||||
<file>Icons/flags/tg.png</file>
|
||||
<file>Icons/flags/th.png</file>
|
||||
<file>Icons/flags/tj.png</file>
|
||||
<file>Icons/flags/tk.png</file>
|
||||
<file>Icons/flags/bg.png</file>
|
||||
<file>Icons/flags/tl.png</file>
|
||||
<file>Icons/flags/tm.png</file>
|
||||
<file>Icons/flags/tn.png</file>
|
||||
<file>Icons/flags/to.png</file>
|
||||
<file>Icons/flags/tr.png</file>
|
||||
<file>Icons/flags/tt.png</file>
|
||||
<file>Icons/flags/tv.png</file>
|
||||
<file>Icons/flags/tw.png</file>
|
||||
<file>Icons/flags/tz.png</file>
|
||||
<file>Icons/flags/ua.png</file>
|
||||
<file>Icons/flags/ug.png</file>
|
||||
<file>Icons/flags/um.png</file>
|
||||
<file>Icons/flags/us.png</file>
|
||||
<file>Icons/flags/uy.png</file>
|
||||
<file>Icons/flags/uz.png</file>
|
||||
<file>Icons/flags/va.png</file>
|
||||
<file>Icons/flags/vc.png</file>
|
||||
<file>Icons/flags/ve.png</file>
|
||||
<file>Icons/flags/vg.png</file>
|
||||
<file>Icons/flags/vi.png</file>
|
||||
<file>Icons/flags/vn.png</file>
|
||||
<file>Icons/flags/vu.png</file>
|
||||
<file>Icons/flags/wf.png</file>
|
||||
<file>Icons/oxygen/preferences-system.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/document-edit-verify.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/edit-clear-history.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/document-edit.png</file>
|
||||
<file>Icons/oxygen/insert-link.png</file>
|
||||
<file>Icons/oxygen/network-wired.png</file>
|
||||
<file>Icons/oxygen/mail-mark-read.png</file>
|
||||
<file>Icons/oxygen/go-up.png</file>
|
||||
<file>Icons/flags/ws.png</file>
|
||||
<file>Icons/flags/ye.png</file>
|
||||
<file>Icons/flags/yt.png</file>
|
||||
<file>Icons/flags/za.png</file>
|
||||
<file>Icons/flags/zm.png</file>
|
||||
<file>Icons/flags/zw.png</file>
|
||||
<file>Icons/oxygen/application-exit.png</file>
|
||||
<file>Icons/oxygen/edit-rename.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/media-playback-start.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/edit-find-user.png</file>
|
||||
<file>Icons/oxygen/media-playback-pause.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/inode-directory.png</file>
|
||||
<file>Icons/oxygen/tools-report-bug.png</file>
|
||||
<file>Icons/oxygen/view-filter.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/oxygen/view-preview.png</file>
|
||||
<file>Icons/oxygen/view-refresh.png</file>
|
||||
<file>Icons/oxygen/text-plain.png</file>
|
||||
<file>Icons/oxygen/edit-delete.png</file>
|
||||
<file>Icons/oxygen/application-rss+xml.png</file>
|
||||
<file>Icons/oxygen/application-x-mswinurl.png</file>
|
||||
<file>Icons/oxygen/chronometer.png</file>
|
||||
<file>Icons/oxygen/dialog-cancel.png</file>
|
||||
<file>Icons/oxygen/preferences-system-network.png</file>
|
||||
<file>Icons/oxygen/document-properties.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/wallet-open.png</file>
|
||||
<file>Icons/oxygen/preferences-web-browser-cookies.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/document-save.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/view-categories.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/dialog-information.png</file>
|
||||
<file>Icons/oxygen/preferences-other.png</file>
|
||||
<file>Icons/oxygen/object-locked.png</file>
|
||||
<file>Icons/oxygen/view-calendar-journal.png</file>
|
||||
<file>Icons/oxygen/application-rss+xml.png</file>
|
||||
<file>Icons/oxygen/dialog-warning.png</file>
|
||||
<file>Icons/oxygen/document-edit-verify.png</file>
|
||||
<file>Icons/oxygen/document-edit.png</file>
|
||||
<file>Icons/oxygen/document-encrypt.png</file>
|
||||
<file>Icons/oxygen/help-contents.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/application-x-mswinurl.png</file>
|
||||
<file>Icons/oxygen/go-down.png</file>
|
||||
<file>Icons/oxygen/document-import.png</file>
|
||||
<file>Icons/oxygen/document-new.png</file>
|
||||
<file>Icons/oxygen/document-properties.png</file>
|
||||
<file>Icons/oxygen/document-save.png</file>
|
||||
<file>Icons/oxygen/download.png</file>
|
||||
<file>Icons/oxygen/edit-find.png</file>
|
||||
<file>Icons/oxygen/edit-clear-history.png</file>
|
||||
<file>Icons/oxygen/edit-clear.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/oxygen/edit-copy.png</file>
|
||||
<file>Icons/oxygen/edit-cut.png</file>
|
||||
<file>Icons/oxygen/edit-delete.png</file>
|
||||
<file>Icons/oxygen/edit-find-user.png</file>
|
||||
<file>Icons/oxygen/edit-find.png</file>
|
||||
<file>Icons/oxygen/edit-paste.png</file>
|
||||
<file>Icons/oxygen/edit-rename.png</file>
|
||||
<file>Icons/oxygen/folder-documents.png</file>
|
||||
<file>Icons/oxygen/folder-new.png</file>
|
||||
<file>Icons/oxygen/folder-remote.png</file>
|
||||
<file>Icons/oxygen/gear.png</file>
|
||||
<file>Icons/oxygen/gear32.png</file>
|
||||
<file>Icons/oxygen/go-down.png</file>
|
||||
<file>Icons/oxygen/go-up.png</file>
|
||||
<file>Icons/oxygen/help-about.png</file>
|
||||
<file>Icons/oxygen/help-contents.png</file>
|
||||
<file>Icons/oxygen/inode-directory.png</file>
|
||||
<file>Icons/oxygen/insert-link.png</file>
|
||||
<file>Icons/oxygen/list-add.png</file>
|
||||
<file>Icons/oxygen/list-remove.png</file>
|
||||
<file>Icons/oxygen/mail-folder-inbox.png</file>
|
||||
<file>Icons/oxygen/mail-mark-read.png</file>
|
||||
<file>Icons/oxygen/media-playback-pause.png</file>
|
||||
<file>Icons/oxygen/media-playback-start.png</file>
|
||||
<file>Icons/oxygen/network-server.png</file>
|
||||
<file>Icons/oxygen/network-wired.png</file>
|
||||
<file>Icons/oxygen/object-locked.png</file>
|
||||
<file>Icons/oxygen/preferences-desktop.png</file>
|
||||
<file>Icons/oxygen/preferences-other.png</file>
|
||||
<file>Icons/oxygen/preferences-system-network.png</file>
|
||||
<file>Icons/oxygen/preferences-system.png</file>
|
||||
<file>Icons/oxygen/preferences-web-browser-cookies.png</file>
|
||||
<file>Icons/oxygen/security-high.png</file>
|
||||
<file>Icons/oxygen/security-low.png</file>
|
||||
<file>Icons/oxygen/services.png</file>
|
||||
<file>Icons/oxygen/tab-close.png</file>
|
||||
<file>Icons/oxygen/task-attention.png</file>
|
||||
<file>Icons/oxygen/text-plain.png</file>
|
||||
<file>Icons/oxygen/tools-report-bug.png</file>
|
||||
<file>Icons/oxygen/unavailable.png</file>
|
||||
<file>Icons/oxygen/user-group-delete.png</file>
|
||||
<file>Icons/oxygen/user-group-new.png</file>
|
||||
<file>Icons/oxygen/view-calendar-journal.png</file>
|
||||
<file>Icons/oxygen/view-categories.png</file>
|
||||
<file>Icons/oxygen/view-filter.png</file>
|
||||
<file>Icons/oxygen/view-preview.png</file>
|
||||
<file>Icons/oxygen/view-refresh.png</file>
|
||||
<file>Icons/oxygen/view-statistics.png</file>
|
||||
<file>Icons/oxygen/wallet-open.png</file>
|
||||
<file>Icons/oxygen/webui.png</file>
|
||||
<file>Icons/skin/arrow-right.gif</file>
|
||||
<file>Icons/skin/bg-handle-horizontal.gif</file>
|
||||
<file>Icons/skin/checking.png</file>
|
||||
<file>Icons/skin/connected.png</file>
|
||||
<file>Icons/skin/disconnected.png</file>
|
||||
<file>Icons/skin/download.png</file>
|
||||
<file>Icons/skin/downloading.png</file>
|
||||
<file>Icons/skin/error.png</file>
|
||||
<file>Icons/skin/filteractive.png</file>
|
||||
<file>Icons/skin/filterall.png</file>
|
||||
<file>Icons/skin/filterinactive.png</file>
|
||||
<file>Icons/skin/firewalled.png</file>
|
||||
<file>Icons/skin/handle-icon-horizontal.gif</file>
|
||||
<file>Icons/skin/handle-icon.gif</file>
|
||||
<file>Icons/skin/knob.gif</file>
|
||||
<file>Icons/skin/mascot.png</file>
|
||||
<file>Icons/skin/paused.png</file>
|
||||
<file>Icons/skin/qbittorrent16.png</file>
|
||||
<file>Icons/skin/qbittorrent22.png</file>
|
||||
<file>Icons/skin/qbittorrent32.png</file>
|
||||
<file>Icons/skin/qbittorrent_mono_dark.png</file>
|
||||
<file>Icons/skin/qbittorrent_mono_light.png</file>
|
||||
<file>Icons/skin/queued.png</file>
|
||||
<file>Icons/skin/ratio.png</file>
|
||||
<file>Icons/skin/seeding.png</file>
|
||||
<file>Icons/skin/slider-area.gif</file>
|
||||
<file>Icons/skin/splash.png</file>
|
||||
<file>Icons/skin/stalledDL.png</file>
|
||||
<file>Icons/skin/stalledUP.png</file>
|
||||
<file>Icons/skin/tabs.gif</file>
|
||||
<file>Icons/skin/toolbox-divider.gif</file>
|
||||
<file>Icons/skin/uploading.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
66
src/lang.qrc
@@ -1,36 +1,44 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_ru.qm</file>
|
||||
<file>lang/qbittorrent_zh_TW.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_gl.qm</file>
|
||||
<file>lang/qbittorrent_sr.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ar.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_be.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_cs.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_en_AU.qm</file>
|
||||
<file>lang/qbittorrent_en_GB.qm</file>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_eu.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_gl.qm</file>
|
||||
<file>lang/qbittorrent_he.qm</file>
|
||||
<file>lang/qbittorrent_hr.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_hy.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_ka.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_lt.qm</file>
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
<file>lang/qbittorrent_ru.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_sr.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_vi.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_zh_TW.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
</RCC>
|
||||
42
src/lang/TRANSLATION_INSTRUCTIONS
Normal file
@@ -0,0 +1,42 @@
|
||||
For future maintainers on how to update translations from Transifex.
|
||||
|
||||
Project page: https://www.transifex.com/projects/p/qbittorrent/
|
||||
|
||||
Most of the options are setup in the .tx/config file. You will need to have the Transifex client app in your path.
|
||||
The examples use the tx app on Windows. Other OSs should be similar.
|
||||
|
||||
===Updating the translations===
|
||||
1. In the root folder of the project just run "tx pull"
|
||||
2. Commit to git
|
||||
|
||||
===Pulling new translation files===
|
||||
1. In the root folder of the project just run "tx pull -a"
|
||||
2. Commit to git each translation file separately with its own message.
|
||||
3. After you commit all new files expose them in app. Edit:
|
||||
a. lang.qrc
|
||||
b. options_imp.cpp: options_imp::languageToLocalizedString()
|
||||
c. src.pro: The TRANSLATIONS var
|
||||
d. preferences_content.html: search for: <select id="locale_select">
|
||||
|
||||
Note: This will also pull updated translations if you haven't already 'tx pull'.
|
||||
|
||||
===Updating the qBittorrent.desktop file===
|
||||
1. In the root folder of the project just run "tx pull -s -r qbittorrent.qbittorrentdesktop_master"
|
||||
2. Commit to git
|
||||
|
||||
It will pull the source file (en). However, in this case .desktop files contain all other translations
|
||||
when you pull the source file.
|
||||
|
||||
===When making new branch===
|
||||
1. Switch to new branch
|
||||
2. Edit the .tx.config file. You should change the resource for the qbt translations from 'qbittorrent.qbittorrent_master'
|
||||
to eg 'qbittorrent.qbittorrent_v3_1_x'. It follows this spec: <project>.<resource_slug>_<branchname>'
|
||||
3. Commit to git
|
||||
4. Use this command to create the new resource on the server and push the translations files "tx push -s -t"
|
||||
|
||||
===Updating the source file==
|
||||
When you run lupdate Transifex needs to know that the source is updated. When creating a new resource on transifex
|
||||
you should go to the website, select the resource and hit "edit resource". From there you should update the
|
||||
"Source file URL". It should point to the exact file in the github repository(eg src/lang/qbittorrent_en.ts). Be sure to copy
|
||||
the 'raw' link presented by github and not the regular one. This will make Transifex fetch automatically the source file
|
||||
from the repo(maybe once a day). If you want to instantly update the resouce then on the correct branch run "tx push -s"
|
||||
5622
src/lang/qbittorrent_be.ts
Normal file
@@ -1 +0,0 @@
|
||||
<クdハ<>箆!ソ`。スン
|
||||