You've already forked qBittorrent
mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-10-28 14:50:53 +01:00
Compare commits
584 Commits
release-2.
...
release-3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cb3439422 | ||
|
|
6eb2315f9a | ||
|
|
6f5bc824e3 | ||
|
|
f56def1508 | ||
|
|
e3ea8b0213 | ||
|
|
a7056f5a66 | ||
|
|
601cb8bcfe | ||
|
|
a7bf28b78f | ||
|
|
afd7867151 | ||
|
|
f490ea9583 | ||
|
|
eb4a61ac02 | ||
|
|
d0aabafb72 | ||
|
|
cf301b865c | ||
|
|
af0384b4ab | ||
|
|
bd52ae74e6 | ||
|
|
f59bad7aba | ||
|
|
2c088df20b | ||
|
|
d1347417db | ||
|
|
7aab902a55 | ||
|
|
7f66b0c80e | ||
|
|
572098bab6 | ||
|
|
f71c0f0a7e | ||
|
|
a069394d8c | ||
|
|
74a852e8a6 | ||
|
|
8da508d107 | ||
|
|
94cf8ca5aa | ||
|
|
a85b16bf14 | ||
|
|
9120afa123 | ||
|
|
dabb47efb1 | ||
|
|
c9e71c3e19 | ||
|
|
9df25098b3 | ||
|
|
af29f6a42b | ||
|
|
3afd01d617 | ||
|
|
ace4989763 | ||
|
|
a09b10e3ec | ||
|
|
9b16be2bf4 | ||
|
|
c20dfe22a5 | ||
|
|
7675c85839 | ||
|
|
95cce1d678 | ||
|
|
b0ed148c4c | ||
|
|
67416c595a | ||
|
|
037598a68a | ||
|
|
cb59cd21d6 | ||
|
|
874ab523e1 | ||
|
|
7b0a13750e | ||
|
|
1eed7cde3c | ||
|
|
512516225b | ||
|
|
1ef35da8eb | ||
|
|
f334286a39 | ||
|
|
a7daedb9b7 | ||
|
|
47564a6774 | ||
|
|
672e2e4a43 | ||
|
|
1857960775 | ||
|
|
4db41da967 | ||
|
|
3977583329 | ||
|
|
abcdada850 | ||
|
|
ae5618c070 | ||
|
|
55572d34b6 | ||
|
|
3d71b071a6 | ||
|
|
2f2b0afa12 | ||
|
|
96c7fc8e48 | ||
|
|
6935b8a7b6 | ||
|
|
f4fd2b196f | ||
|
|
2797964947 | ||
|
|
9e7a958421 | ||
|
|
12d51b86db | ||
|
|
16d8073367 | ||
|
|
0725a97586 | ||
|
|
83e738ab46 | ||
|
|
e5b14995c3 | ||
|
|
0e15ffb2a4 | ||
|
|
5022cce568 | ||
|
|
0c0c81bc52 | ||
|
|
c0394ce5a9 | ||
|
|
b2b7bdb2bb | ||
|
|
723f909f3b | ||
|
|
eb38058c99 | ||
|
|
f43565f0f2 | ||
|
|
98d5cca3d6 | ||
|
|
d1012a1b15 | ||
|
|
573edb9bce | ||
|
|
a04af57301 | ||
|
|
1ec2f8278a | ||
|
|
c137e2eb0b | ||
|
|
0e59642d99 | ||
|
|
8d033ac0e7 | ||
|
|
578a43f445 | ||
|
|
d8367a15fa | ||
|
|
5b6d873fec | ||
|
|
76b6d4ee2f | ||
|
|
0996bd1165 | ||
|
|
67a7f00e5e | ||
|
|
60c6a8c279 | ||
|
|
0c71d3f46d | ||
|
|
082dce0a66 | ||
|
|
29603d1902 | ||
|
|
8f12cfc817 | ||
|
|
933b2817ce | ||
|
|
df86fbb1d7 | ||
|
|
b1aa89fa21 | ||
|
|
be739bb22d | ||
|
|
d095d7fc17 | ||
|
|
ae3eda2c7e | ||
|
|
876216972d | ||
|
|
fea51f6b60 | ||
|
|
30db37605a | ||
|
|
2e2a5c1fb6 | ||
|
|
5056faed92 | ||
|
|
a27c5efbb5 | ||
|
|
b7d7bb3687 | ||
|
|
6550c4f31e | ||
|
|
4a05e100b7 | ||
|
|
5dc3f3bf3e | ||
|
|
bd2de9b0dc | ||
|
|
c01a9d5a80 | ||
|
|
52b1cdce6f | ||
|
|
731963ef31 | ||
|
|
43f5f81410 | ||
|
|
04ff48fa0b | ||
|
|
f051228666 | ||
|
|
84500fdd0c | ||
|
|
55259ff3ba | ||
|
|
da5b49fe5a | ||
|
|
89bc0fb3e3 | ||
|
|
c86bfe53d0 | ||
|
|
dd177c03e6 | ||
|
|
6615d4987b | ||
|
|
c6e0facc0b | ||
|
|
c6845781c7 | ||
|
|
5decf71772 | ||
|
|
b7f313a35c | ||
|
|
8c14c7926f | ||
|
|
ca6ec01f1f | ||
|
|
2c42ab7544 | ||
|
|
2dbbfc1031 | ||
|
|
3762401cd9 | ||
|
|
65c0f3f041 | ||
|
|
7ab877c95e | ||
|
|
7b658a52dd | ||
|
|
3705cb8067 | ||
|
|
8b4be9bef6 | ||
|
|
38bef752dc | ||
|
|
a61a84d419 | ||
|
|
553abb6442 | ||
|
|
14419c190e | ||
|
|
4e6ab18446 | ||
|
|
fdeec686bf | ||
|
|
25e4f562e7 | ||
|
|
d86baf1ed8 | ||
|
|
8112405498 | ||
|
|
7f73eca01d | ||
|
|
9951017f8b | ||
|
|
57bbaeab06 | ||
|
|
52fefd3dd6 | ||
|
|
c1cddd2f7a | ||
|
|
caabe526ca | ||
|
|
19475f5abb | ||
|
|
dca36a4817 | ||
|
|
e38ef96c94 | ||
|
|
43aff3885d | ||
|
|
4b4d52d8d3 | ||
|
|
735247f41f | ||
|
|
422d0c9210 | ||
|
|
6ea90c9741 | ||
|
|
c2bbb5b71a | ||
|
|
a2656670f7 | ||
|
|
ae2781b4c8 | ||
|
|
65a81f4fca | ||
|
|
e025b2aa10 | ||
|
|
9399f06db9 | ||
|
|
2e6370084a | ||
|
|
adc478a8dc | ||
|
|
247c9a85e2 | ||
|
|
40fc98d354 | ||
|
|
5797d86c05 | ||
|
|
62de16c56e | ||
|
|
d89f2b0783 | ||
|
|
d6b2131a91 | ||
|
|
b085fc12d0 | ||
|
|
0da431b7a3 | ||
|
|
3e18308301 | ||
|
|
47c7ffba99 | ||
|
|
42b1dffbb9 | ||
|
|
73ebe7e1fb | ||
|
|
c9c3589946 | ||
|
|
62596ab533 | ||
|
|
0be1c661aa | ||
|
|
eb10a80c3c | ||
|
|
3679c79b5c | ||
|
|
a0816d1ec6 | ||
|
|
175ac42b43 | ||
|
|
d39874551c | ||
|
|
16402f75cf | ||
|
|
aacea44d41 | ||
|
|
f2a90520d7 | ||
|
|
34d25006f4 | ||
|
|
e382fb1bec | ||
|
|
ba9e3558a2 | ||
|
|
f6514b4e7d | ||
|
|
fe7ffdd413 | ||
|
|
8d1a4cb40a | ||
|
|
ad3f4842f8 | ||
|
|
944fc5cf38 | ||
|
|
026c065ebc | ||
|
|
00ac784a4d | ||
|
|
7d99223547 | ||
|
|
65a338b5c2 | ||
|
|
b0fd6ac756 | ||
|
|
c268ca1278 | ||
|
|
13e3141dfb | ||
|
|
70fbd61758 | ||
|
|
db638319c7 | ||
|
|
8d36a03f68 | ||
|
|
2b8dc3df18 | ||
|
|
11c5172588 | ||
|
|
43f55f5d3c | ||
|
|
153ebe2b77 | ||
|
|
70d11217de | ||
|
|
82beff5527 | ||
|
|
2e4f0876b0 | ||
|
|
072a72316f | ||
|
|
d199482205 | ||
|
|
eae7953061 | ||
|
|
d88d4e9165 | ||
|
|
cea36bc756 | ||
|
|
c517444258 | ||
|
|
a109274d1f | ||
|
|
490cb9dfdb | ||
|
|
ab748166d5 | ||
|
|
a796df9019 | ||
|
|
85abc98759 | ||
|
|
041540de6b | ||
|
|
72a06ad176 | ||
|
|
eea69630fb | ||
|
|
19846758d8 | ||
|
|
7532fcfd3c | ||
|
|
616575911f | ||
|
|
227a1f6532 | ||
|
|
2c7186a381 | ||
|
|
b4775b9d29 | ||
|
|
ad8d7e3373 | ||
|
|
b5e7443ae3 | ||
|
|
5a33c0d9ba | ||
|
|
7064ac994b | ||
|
|
3c05e660b3 | ||
|
|
ed54c5f7ac | ||
|
|
63d6dd3735 | ||
|
|
02d56fd026 | ||
|
|
d4c9da6475 | ||
|
|
99f126d0b6 | ||
|
|
8110d0eb01 | ||
|
|
90a2021948 | ||
|
|
7bfd0e058b | ||
|
|
6dcfe5b215 | ||
|
|
7daeb0297d | ||
|
|
76597fa080 | ||
|
|
14908f3fc8 | ||
|
|
3269cdfa70 | ||
|
|
5f0e3e3443 | ||
|
|
fcd37dcbb4 | ||
|
|
528759fdaa | ||
|
|
cfe1235b57 | ||
|
|
e5d5f84ae7 | ||
|
|
bbda5c4f44 | ||
|
|
9605192834 | ||
|
|
4c6e526e6c | ||
|
|
e43fa17429 | ||
|
|
c5dd14788a | ||
|
|
334ba32d69 | ||
|
|
8ba1941ab9 | ||
|
|
ea85532cc2 | ||
|
|
d3ee2e66af | ||
|
|
4ac917ef66 | ||
|
|
41660385d7 | ||
|
|
e5ae8e5ac9 | ||
|
|
7fb87660ac | ||
|
|
6ea7b5b1d0 | ||
|
|
b624ad312b | ||
|
|
b64f4081cf | ||
|
|
bd9b153e9b | ||
|
|
32ca66f234 | ||
|
|
753e9181fe | ||
|
|
9546a73182 | ||
|
|
c0ee99c553 | ||
|
|
50976b8dc2 | ||
|
|
6a312461a1 | ||
|
|
3fe09bde12 | ||
|
|
f851b18b80 | ||
|
|
ced29ced1b | ||
|
|
5023b1ab74 | ||
|
|
c2ef78de8d | ||
|
|
6fbe452b55 | ||
|
|
51c4a0d8d0 | ||
|
|
b191a977af | ||
|
|
61858814ee | ||
|
|
365387f092 | ||
|
|
df295d96c2 | ||
|
|
a069f806d9 | ||
|
|
4638a9e6ee | ||
|
|
af790e40f8 | ||
|
|
76fd5d3eb4 | ||
|
|
dc8a8fbc06 | ||
|
|
30e0cc20c8 | ||
|
|
63dcb81384 | ||
|
|
ce391ad328 | ||
|
|
7b908c7adf | ||
|
|
0d26d734b3 | ||
|
|
f836c40fc4 | ||
|
|
21fe7f2ca6 | ||
|
|
da85a57f83 | ||
|
|
e35664b188 | ||
|
|
2fc350b265 | ||
|
|
83bcd6a2d7 | ||
|
|
edcfa4df12 | ||
|
|
12a83e1aec | ||
|
|
7d50a8b28c | ||
|
|
232e112d84 | ||
|
|
5b1ee883b4 | ||
|
|
b07fceec65 | ||
|
|
4c9cf6c773 | ||
|
|
164f37e961 | ||
|
|
093fb303f3 | ||
|
|
f3d5039e33 | ||
|
|
007c307388 | ||
|
|
4079689f32 | ||
|
|
2b3d6926c8 | ||
|
|
14b3414e9d | ||
|
|
73254962f1 | ||
|
|
74f042516b | ||
|
|
8c0853248c | ||
|
|
80ea0a67b5 | ||
|
|
6d2b51203c | ||
|
|
8ac82156b3 | ||
|
|
c1806b099a | ||
|
|
1046c816bf | ||
|
|
cfbb5ecde5 | ||
|
|
afdec02674 | ||
|
|
927e6bc6cc | ||
|
|
e862d3332c | ||
|
|
699144a83d | ||
|
|
1792f44bfa | ||
|
|
64e4095ef1 | ||
|
|
1d1ffcec7c | ||
|
|
e73bff817c | ||
|
|
486779ceb2 | ||
|
|
283a9950f3 | ||
|
|
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 |
53
.travis.yml
Normal file
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
|
||||||
15
AUTHORS
15
AUTHORS
@@ -1,4 +1,7 @@
|
|||||||
Author:
|
Current maintainer:
|
||||||
|
* Sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||||
|
|
||||||
|
Original author:
|
||||||
* Christophe Dumez <chris@qbittorrent.org>
|
* Christophe Dumez <chris@qbittorrent.org>
|
||||||
|
|
||||||
Contributors:
|
Contributors:
|
||||||
@@ -11,6 +14,7 @@ Contributors:
|
|||||||
* Grigis Gaëtan <cipher16@gmail.com>
|
* Grigis Gaëtan <cipher16@gmail.com>
|
||||||
* Christian Kandeler <zambesi@users.sourceforge.net>
|
* Christian Kandeler <zambesi@users.sourceforge.net>
|
||||||
* Silvan Scherrer <silvan.scherrer@aroa.ch>
|
* Silvan Scherrer <silvan.scherrer@aroa.ch>
|
||||||
|
* Nick Tiskov <daymansmail@gmail.com>
|
||||||
|
|
||||||
Code from other projects:
|
Code from other projects:
|
||||||
* files src/qtsingleapp/* src/lineedit/*
|
* files src/qtsingleapp/* src/lineedit/*
|
||||||
@@ -25,6 +29,10 @@ Code from other projects:
|
|||||||
copyright: Dan Haim <negativeiq@users.sourceforge.net>
|
copyright: Dan Haim <negativeiq@users.sourceforge.net>
|
||||||
license: BSD
|
license: BSD
|
||||||
|
|
||||||
|
* file src/stacktrace_win.h
|
||||||
|
copyright: Quassel Project
|
||||||
|
license: GPLv2/3
|
||||||
|
|
||||||
Images Authors:
|
Images Authors:
|
||||||
* files: src/Icons/*.png
|
* files: src/Icons/*.png
|
||||||
copyright: Gnome Icon Theme
|
copyright: Gnome Icon Theme
|
||||||
@@ -92,8 +100,9 @@ Translations authors:
|
|||||||
- Georgian: Beqa Arabuli (arabulibeqa@yahoo.com)
|
- Georgian: Beqa Arabuli (arabulibeqa@yahoo.com)
|
||||||
- German: Niels Hoffmann (zentralmaschine@users.sourceforge.net)
|
- 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) and Stephanos Antaris (santaris@csd.auth.gr)
|
||||||
|
- Hebrew: David Deutsch (d.deffo@gmail.com)
|
||||||
- Hungarian: Majoros Péter (majoros.j.p@t-online.hu)
|
- Hungarian: Majoros Péter (majoros.j.p@t-online.hu)
|
||||||
- Italian: Matteo Sechi (bu17714@gmail.com)
|
- Italian: bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)
|
||||||
- Japanese: Masato Hashimoto (cabezon.hashimoto@gmail.com)
|
- Japanese: Masato Hashimoto (cabezon.hashimoto@gmail.com)
|
||||||
- Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
|
- Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
|
||||||
- Lithuanian: Naglis Jonaitis (njonaitis@gmail.com)
|
- Lithuanian: Naglis Jonaitis (njonaitis@gmail.com)
|
||||||
@@ -107,5 +116,5 @@ Translations authors:
|
|||||||
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
|
||||||
- Swedish: Daniel Nylander (po@danielnylander.se)
|
- Swedish: Daniel Nylander (po@danielnylander.se)
|
||||||
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
|
- 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)
|
||||||
license: GPLv2
|
license: GPLv2
|
||||||
|
|||||||
198
Changelog
198
Changelog
@@ -1,85 +1,125 @@
|
|||||||
* Sun Jul 1 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.11
|
* Mon Jul 29 2013 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.0.11
|
||||||
- BUGFIX: Fix unreversible "Minimize to tray" on some window managers
|
- FEATURE: Allow more fine tuning of upload slots. It should improve speed (sledgehammer999)
|
||||||
- BUGFIX: Fix torrent availability computation (closes #988869)
|
- FEATURE: Enable edit/rename via F2 or double click in various places (Gelmir)
|
||||||
- BUGFIX: Bring window to front after restoring from systray
|
- BUGFIX: Fix Spanish and Basque translations being messed up on Windows (sledgehammer999)
|
||||||
- BUGFIX: Fix keyboard focus problems on main window (closes #1019563)
|
- BUGFIX: Don't allow newlines in rename dialog (Gelmir)
|
||||||
- BUGFIX: Fix ThePirateBay search plugin
|
- BUGFIX: Treat unfinished dates as the newest ones when sorting (sledgehammer999)
|
||||||
|
- BUGFIX: Fix text size problem on Windows with custom DPI (sledgehammer999)
|
||||||
|
- BUGFIX: Respect UI lock when clicking on tray notification (sledgehammer999)
|
||||||
|
- BUGFIX: Fix kickass torrents search plugin (Gelmir)
|
||||||
|
- BUGFIX: Use system language as default language. Closes #780 (sledgehammer999)
|
||||||
|
- BUGFIX: Move completed files to .unwanted folder when they are unselected by the user (constantined)
|
||||||
|
- BUGFIX: Show delete action when multiple feeds are selected (Gelmir)
|
||||||
|
- BUGFIX: Use Unicode for libtorrent alert messages (Gelmir)
|
||||||
|
- OTHER: Update translations
|
||||||
|
- WINDOWS: Shave off ~4MB from the binary size (sledgehammer999)
|
||||||
|
- WINDOWS: Remove wrong dependency on msvc2008 runtime (sledgehammer999)
|
||||||
|
- WINDOWS: Disable stacktrace when building with mingw (Gelmir)
|
||||||
|
- WINDOWS: Updated NSIS script to include/delete .pdb file. (sledgehammer999)
|
||||||
|
|
||||||
* Sun Jun 24 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.10
|
* Tue Jul 9 2013 - Christophe Dumez <chris@qbittorrent.org> and sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.0.10
|
||||||
- BUGFIX: Fix possible crash when showing torrent content (closes #1002586)
|
- BUGFIX: Fix LegitTorrents search plugin
|
||||||
- BUGFIX: Add support for RSS feeds using magnet links (closes #1016379)
|
- BUGFIX: Improve peer host name resolution (closes #360)
|
||||||
- BUGFIX: Remove 100kb limit for torrent file size in Web UI
|
- BUGFIX: Context menu fix in the Web UI
|
||||||
- BUGFIX: Fix ratio limiting bug (closes #835217)
|
- BUGFIX: Respect 'don't show' torrent dialog in Search (sledgehammer999)
|
||||||
- BUGFIX: Do not display .!qB file extensions in Web UI
|
- BUGFIX: Torrent creator can now use files/folders from disk root (Gelmir)
|
||||||
- BUGFIX: Stop using absolute URLs in Web UI ajax requests (closes #1011226)
|
- BUGFIX: Update free disk space when changing drives in the add new torrent dialog (sledgehammer999)
|
||||||
- BUGFIX: Fix torrent association and loading on Mac OS X (closes #1011229)
|
- BUGFIX: Various fixes relating to RSS drag and drop (Gelmir)
|
||||||
- BUGFIX: Fix unreversible "Minimize to tray" on some window managers (closes #917825)
|
- BUGFIX: Properly rename torrent which changes position in filter model (Gelmir)
|
||||||
|
- BUGFIX: Actually show tray notifications when a torrent finishes downloading (sledgehammer999)
|
||||||
|
- BUGFIX: Don't download RSS items based on rules still being edited (Gelmir)
|
||||||
|
- COSMETIC: Native look for the search boxes (Hyperz)
|
||||||
|
- IMPROVEMENT: Use natural sorting where possible (Gelmir and sledgehammer999)
|
||||||
|
- LINUX: Drop Boost.Thread dependency from configure script
|
||||||
|
- OTHER: Update translations.
|
||||||
|
- OTHER: Drop obsolete Boost.Thread dependency from configure script on linux (Dumez)
|
||||||
|
- LIBTORRENT: SOCKS5 fixes (0.16.10)
|
||||||
|
- LIBTORRENT: Fix hanging issue on Windows when closing files (0.16.10)
|
||||||
|
- LIBTORRENT: Cache can now be returned to the OS (0.16.10)
|
||||||
|
- PERFORMANCE: Impove drawing speed of tranferlist when there are many torrents(>100) (sledgehammer999)
|
||||||
|
- PERFORMANCE: Impove drawing speed of peers list when there are many peers (sledgehammer999)
|
||||||
|
|
||||||
* Sun May 20 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.9
|
* Sat Mar 16 2013 - Christophe Dumez <chris@qbittorrent.org> - v3.0.9
|
||||||
- BUGFIX: More reliable RSS feed parsing (closes #1001777)
|
- BUGFIX: Raise qBittorrent windows when another instance is launched
|
||||||
- BUGFIX: Better support for cookies in RSS
|
- BUGFIX: Show human readable names for network interfaces in preferences (Windows)
|
||||||
- BUGFIX: Make sure show/hide text in tray icon menu is correct
|
- BUGFIX: Fix torrent creator bug when saving non-latin path (Windows)
|
||||||
|
- BUGFIX: Enable 'copy magnet uri' for torrents without metadata too
|
||||||
|
- BUGFIX: Fix a few JSON parser issues (Gelmir)
|
||||||
|
- BUGFIX: Add support for gzipped encoded HTTP responses (daimor)
|
||||||
|
- BUGFIX: Fix possibly missing "Add torrent" icon (Driim)
|
||||||
|
- OTHER: Add search plugin for Legit Torrents
|
||||||
|
|
||||||
|
* Sun Jan 20 2013 - Christophe Dumez <chris@qbittorrent.org> - v3.0.8
|
||||||
|
- BUGFIX: Fix support for --no-splash command line argument
|
||||||
|
- BUGFIX: Fix compilation error with libtorrent v0.15
|
||||||
|
- BUGFIX: Fix search issues with Python3
|
||||||
|
- BUGFIX: Fix dead link about certificates in program preferences
|
||||||
|
|
||||||
|
* Sat Jan 19 2013 - Christophe Dumez <chris@qbittorrent.org> - v3.0.7
|
||||||
|
- BUGFIX: Update max write cache size to 2048MB and set it to automatic by default (closes #148)
|
||||||
|
- BUGFIX: Add m4v to the list of previewable file extensions (closes #216)
|
||||||
|
- BUGFIX: Fix "Couldn't set environment variable..." message on start up (closes #245)
|
||||||
|
- BUGFIX: Use right path separator in torrent addition dialog on Windows
|
||||||
|
- BUGFIX: Fix "Set as default save path" setting (closes #254)
|
||||||
|
- BUGFIX: Reenable disk cache on Windows since the memory issue seems to be gone
|
||||||
|
- BUGFIX: Fixed several search engine plugins and removed the dead ones
|
||||||
|
- BUGFIX: Use https links in search plugins when possible
|
||||||
|
- BUGFIX: Bump Mootools to v1.4.5 (Web UI)
|
||||||
|
- BUGFIX: Require password to exit qBittorrent from tray icon when locked (closes #311)
|
||||||
|
- BUGFIX: Fix possible crash in loadPeers() (closes #222)
|
||||||
|
|
||||||
|
* Sun Oct 7 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.6
|
||||||
|
- BUGFIX: Fix unicode support for command-line arguments on Windows (closes #139)
|
||||||
|
- BUGFIX: Do not store created torrent in memory before writing it to a file (closes #133)
|
||||||
|
- BUGFIX: No longer fallback to ANY interface if the user-selected interface cannot be found (closes #143)
|
||||||
|
- BUGFIX: Fix timezone parsing in RSS (closes #136)
|
||||||
|
- BUGFIX: Fix cookie support for RSS feeds (closes #119)
|
||||||
|
|
||||||
|
* Sun Sep 30 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.5
|
||||||
|
- BUGFIX: Disabling systray icon no longer disables file association settings (closes #114)
|
||||||
|
- BUGFIX: Import new trackers from magnet link in case of duplicate torrent (closes #111)
|
||||||
|
- BUGFIX: Fix "Skip hash check" feature in torrent import dialog (closes #128)
|
||||||
|
- BUGFIX: Several Web UI connection fixes
|
||||||
|
- BUGFIX: Add Basque locale to Web UI
|
||||||
|
|
||||||
|
* Tue Sep 18 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.4
|
||||||
|
- BUGFIX: Fix issue with downloads starting from scratch on startup if temporary
|
||||||
|
directory setting is enabled.
|
||||||
|
|
||||||
|
* Sun Sep 16 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.3
|
||||||
|
- BUGFIX: Fix issue with temporary directory not being taken into consideration (closes #94)
|
||||||
|
- BUGFIX: Address encoding issues when using search engine on Windows (closes #29)
|
||||||
|
- BUGFIX: Bypass cache when uploading a torrent file in Web UI (closes #68)
|
||||||
|
- BUGFIX: "Completed On" column is not updated until restart (closes #84)
|
||||||
|
- BUGFIX: Fix possible build error on some systems
|
||||||
|
- I18N: Add hebrew translation
|
||||||
|
|
||||||
|
* Sat Sep 1 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.2
|
||||||
|
- FEATURE: Add "clear" functionality to search field (closes #59)
|
||||||
|
- BUGFIX: Attempt to use qBittorrent icon from theme if available (closes #49)
|
||||||
|
- BUGFIX: Fix crash when a fastresume file is empty (closes #52)
|
||||||
|
- BUGFIX: Fix encoding problem for detected XDG Download folder (closes #53)
|
||||||
|
- BUGFIX: Improve performance when showing torrent content panel (Improves #24)
|
||||||
|
- BUGFIX: Fix label-based filtering of torrents whose label contains special characters
|
||||||
|
- BUGFIX: Fix possible crash due to labels (closes #64)
|
||||||
|
|
||||||
|
* Tue Aug 21 2012 - Christophe Dumez <chris@qbittorrent.org> - v3.0.1
|
||||||
|
- BUGFIX: Fix possible crash when adding a tracker to a magnet torrent without metadata (Closes #1034254)
|
||||||
|
- BUGFIX: Remember queue position for torrents without metadata (closes #17)
|
||||||
|
- BUGFIX: Fix crash when using unauthorized characters in label names (closes #19)
|
||||||
|
- BUGFIX: Fix search plugins updating (closes #25)
|
||||||
|
- BUGFIX: Make uTP connections rate limited by default
|
||||||
|
|
||||||
|
* 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
|
- COSMETIC: Improve style of left panel
|
||||||
- COSMETIC: Never disable properties panel
|
- BUGFIX: Lower panels no longer gets disabled
|
||||||
- COSMETIC: Make sure first tab is initially selected in options dialog
|
- BUGFIX: Major code refactoring and various optimizations.
|
||||||
- COSMETIC: Fix a few focus issues on Mac OS X
|
- BUGFIX: No longer strip root folder from torrent files
|
||||||
|
- OTHER: Drop support for libtorrent v0.14.x
|
||||||
* Sat May 5 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.8
|
- OTHER: Drop support for Qt 4.5
|
||||||
- BUGFIX: Various UI style fixes
|
|
||||||
- BUGFIX: Fix compilation with gcc 4.7
|
|
||||||
- BUGFIX: Fix possible compilation error with msvc (Windows)
|
|
||||||
- BUGFIX: Fix compilation on OS/2
|
|
||||||
- I18N: Update Italian translation
|
|
||||||
|
|
||||||
* Sun Mar 18 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.7
|
|
||||||
- BUGFIX: Fix important HTTP request parsing bug (Web UI)
|
|
||||||
|
|
||||||
* Sat Mar 17 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.6
|
|
||||||
- BUGFIX: Fix download first/last pieces state reporting
|
|
||||||
- BUGFIX: Fix name of progress column in torrent content panel
|
|
||||||
- BUGFIX: Disable system tray icon on Mac OS X
|
|
||||||
- BUGFIX: RSS downloader should not ignore "Do not start automatically" rule (closes #946910)
|
|
||||||
- BUGFIX: Fix DHT port setting in Web UI (Closes #952182)
|
|
||||||
- BUGFIX: Fix possible Web UI authentication problem when using SSL (closes #941343)
|
|
||||||
- BUGFIX: Fix possible issues with folder removal when removing a torrent
|
|
||||||
- I18N: Add Basque translation
|
|
||||||
|
|
||||||
* Sat Feb 18 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.5
|
|
||||||
- BUGFIX: Fix crash when disabling then reenabling RSS
|
|
||||||
- BUGFIX: Fix duplicate torrent detection when adding a magnet link
|
|
||||||
- BUGFIX: Fix import of new trackers when adding a torrent with same hash (Closes #747000)
|
|
||||||
- BUGFIX: Fix possible redownload of torrents marked as read (Closes #927495)
|
|
||||||
- BUGFIX: Properly remove RSS feed settings/history upon feed removal
|
|
||||||
|
|
||||||
* Sat Feb 18 2012 - Christophe Dumez <chris@qbittorrent.org> - v2.9.4
|
|
||||||
- BUGFIX: qBittorrent does not handle redirection to relative URLs correctly (Closes #919905)
|
|
||||||
- BUGFIX: Cmd+M minimizes main window on Mac OS X (Closes #928216)
|
|
||||||
- BUGFIX: Cmd+Del removes torrents on Mac OS X (Closes #928852)
|
|
||||||
- BUGFIX: Fix potential bug when moving single file torrents to tmp folder (closes #932861)
|
|
||||||
- BUGFIX: Fix torrent import dialog layout (Closes #930932)
|
|
||||||
- BUGFIX: Prevent log window buffer from filling up (Closes #929673)
|
|
||||||
- I18N: Add Belarusian translation
|
|
||||||
|
|
||||||
* Thu Dec 29 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.3
|
|
||||||
- BUGFIX: Fix btdigg plugin (Python3 support + torrent name in magnet links)
|
|
||||||
- BUGFIX: Fix banning of IPv6 peers (Closes #885021)
|
|
||||||
- BUGFIX: Fix torrent addition dialog layout problem (Closes #84650522)
|
|
||||||
- BUGFIX: Do not report any progress for disabled files (Closes #56731485)
|
|
||||||
- BUGFIX: Make torrent sorting case insensitive (Closes #857154)
|
|
||||||
- BUGFIX: Improve Web UI usability of small devices
|
|
||||||
- BUGFIX: Program updater: More reliable version detection / comparison
|
|
||||||
- I18N: Add Georgian translation
|
|
||||||
|
|
||||||
* Sat Oct 29 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.2
|
|
||||||
- BUGFIX: Fix mimimum dimensions for torrent addition dialog
|
|
||||||
- BUGFIX: Remove dependency on boost-datetime
|
|
||||||
- BUGFIX: Remove dependency on boost-filesystem (libtorrent v0.16.x)
|
|
||||||
|
|
||||||
* Sun Oct 23 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.1
|
|
||||||
- BUGFIX: Add support for speed limits scheduling (Web UI)
|
|
||||||
- BUGFIX: Fix ratio calculation for purely seeded torrents
|
|
||||||
- I18N: Update Russian translation
|
|
||||||
- COSMETIC: Torrent addition dialog layout fixes
|
|
||||||
|
|
||||||
* Sat Oct 08 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.0
|
* Sat Oct 08 2011 - Christophe Dumez <chris@qbittorrent.org> - v2.9.0
|
||||||
- FEATURE: Add file association settings to program preferences (Windows)
|
- FEATURE: Add file association settings to program preferences (Windows)
|
||||||
|
|||||||
6
INSTALL
6
INSTALL
@@ -10,11 +10,11 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
|||||||
will install and execute qBittorrent hopefully without any problems.
|
will install and execute qBittorrent hopefully without any problems.
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- Qt >= 4.5.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
- Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
||||||
|
|
||||||
- pkg-config executable
|
- pkg-config executable
|
||||||
|
|
||||||
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, compatible with v0.15.x/v0.16.x)
|
- libtorrent-rasterbar by Arvid Norberg (>= 0.15.0)
|
||||||
-> http://www.libtorrent.net
|
-> http://www.libtorrent.net
|
||||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ qBittorrent - A BitTorrent client in C++ / Qt4
|
|||||||
|
|
||||||
- pkg-config executable
|
- 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
|
-> http://www.libtorrent.net
|
||||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||||
|
|
||||||
|
|||||||
15
README.os2
15
README.os2
@@ -42,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.
|
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:
|
Simply type:
|
||||||
$ qmake
|
$ qmake
|
||||||
@@ -50,6 +53,16 @@ $ qmake
|
|||||||
Followed by:
|
Followed by:
|
||||||
$ make
|
$ 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 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:
|
If you have any question regarding the eCS (OS/2) port of qBittorrent you can meet me (_diver) on IRC:
|
||||||
|
|||||||
14
configure
vendored
14
configure
vendored
@@ -325,7 +325,7 @@ cat >$1/modules.cpp <<EOT
|
|||||||
#line 1 "qt4.qcm"
|
#line 1 "qt4.qcm"
|
||||||
/*
|
/*
|
||||||
-----BEGIN QCMOD-----
|
-----BEGIN QCMOD-----
|
||||||
name: Qt >= 4.5
|
name: Qt >= 4.6
|
||||||
arg: enable-debug, Enable debug mode
|
arg: enable-debug, Enable debug mode
|
||||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||||
-----END QCMOD-----
|
-----END QCMOD-----
|
||||||
@@ -334,8 +334,8 @@ class qc_qt4 : public ConfObj
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||||
QString name() const { return "Qt >= 4.5"; }
|
QString name() const { return "Qt >= 4.6"; }
|
||||||
QString shortname() const { return "Qt 4.5"; }
|
QString shortname() const { return "Qt 4.6"; }
|
||||||
bool exec()
|
bool exec()
|
||||||
{
|
{
|
||||||
// NOX mode
|
// NOX mode
|
||||||
@@ -356,7 +356,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
conf->addExtra("MANPREFIX = \$\$PREFIX/share");
|
conf->addExtra("MANPREFIX = \$\$PREFIX/share");
|
||||||
#endif
|
#endif
|
||||||
return(QT_VERSION >= 0x040500);
|
return(QT_VERSION >= 0x040600);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#line 1 "qt-dbus.qcm"
|
#line 1 "qt-dbus.qcm"
|
||||||
@@ -419,11 +419,11 @@ class qc_libtorrent_rasterbar : public ConfObj
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
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"; }
|
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||||
bool exec(){
|
bool exec(){
|
||||||
QStringList incs;
|
QStringList incs;
|
||||||
QString req_ver = "0.14.4";
|
QString req_ver = "0.15.0";
|
||||||
QString version, libs, other;
|
QString version, libs, other;
|
||||||
VersionMode mode = VersionMin;
|
VersionMode mode = VersionMin;
|
||||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||||
@@ -507,7 +507,7 @@ public:
|
|||||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||||
required_libs << "filesystem" ;
|
required_libs << "filesystem" ;
|
||||||
#endif
|
#endif
|
||||||
required_libs << "thread";
|
//required_libs << "thread";
|
||||||
QStringList libDirs;
|
QStringList libDirs;
|
||||||
if (!s.isEmpty())
|
if (!s.isEmpty())
|
||||||
libDirs << s;
|
libDirs << s;
|
||||||
|
|||||||
15
install.os2
15
install.os2
@@ -67,7 +67,7 @@ ZIP Installation:
|
|||||||
klibc
|
klibc
|
||||||
-----
|
-----
|
||||||
|
|
||||||
1. Download klibc 0.6.4 or better (see http://svn.netlabs.org/libc for more information)
|
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
|
2. Install the files to your libpath eg x:\ecs\dll
|
||||||
|
|
||||||
openssl 1.0
|
openssl 1.0
|
||||||
@@ -146,6 +146,19 @@ development, you can do so in one of the following ways:
|
|||||||
7. HISTORY
|
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
|
2012-03-15
|
||||||
|
|
||||||
* updated to 2.9.5 code level of QBittorrent
|
* updated to 2.9.5 code level of QBittorrent
|
||||||
|
|||||||
46
macxconf.pri
46
macxconf.pri
@@ -16,16 +16,52 @@ LIBS += -lssl -lcrypto
|
|||||||
# Boost system lib
|
# Boost system lib
|
||||||
LIBS += -lboost_system-mt
|
LIBS += -lboost_system-mt
|
||||||
# Boost filesystem lib (Not needed for libtorrent >= 0.16.0)
|
# Boost filesystem lib (Not needed for libtorrent >= 0.16.0)
|
||||||
LIBS += -lboost_filesystem-mt
|
#LIBS += -lboost_filesystem-mt
|
||||||
# Carbon
|
# Carbon
|
||||||
LIBS += -framework Carbon -framework IOKit
|
LIBS += -framework Carbon -framework IOKit
|
||||||
|
# Zlib
|
||||||
|
LIBS += -lz
|
||||||
|
|
||||||
document_icon.path = Contents/Resources
|
document_icon.path = Contents/Resources
|
||||||
document_icon.files = Icons/qBitTorrentDocument.icns
|
document_icon.files = mac/qBitTorrentDocument.icns
|
||||||
|
|
||||||
QMAKE_BUNDLE_DATA += document_icon
|
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
|
DEFINES += WITH_GEOIP_EMBEDDED
|
||||||
message("On Mac OS X, GeoIP database must be embedded.")
|
message("On Mac OS X, GeoIP database must be embedded.")
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ LIBS += -ltorrent-rasterbar \
|
|||||||
-lboost_thread \
|
-lboost_thread \
|
||||||
-lboost_system \
|
-lboost_system \
|
||||||
-lboost_filesystem \
|
-lboost_filesystem \
|
||||||
-lssl -lcrypto -lidn -lpthread
|
-lssl -lcrypto -lidn -lpthread -lz
|
||||||
|
|
||||||
RC_FILE = qbittorrent_os2.rc
|
RC_FILE = qbittorrent_os2.rc
|
||||||
|
|
||||||
# LIBTORRENT DEFINES
|
# LIBTORRENT DEFINES
|
||||||
DEFINES += WITH_SHIPPED_GEOIP_H
|
DEFINES += WITH_SHIPPED_GEOIP_H
|
||||||
|
DEFINES += BOOST_ASIO_DYN_LINK
|
||||||
|
|
||||||
DEFINES += WITH_GEOIP_EMBEDDED
|
DEFINES += WITH_GEOIP_EMBEDDED
|
||||||
message("On eCS(OS/2), GeoIP database must be embedded.")
|
message("On eCS(OS/2), GeoIP database must be embedded.")
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
#if LIBTORRENT_VERSION_MAJOR == 0 && LIBTORRENT_VERSION_MINOR < 16
|
||||||
required_libs << "filesystem" ;
|
required_libs << "filesystem" ;
|
||||||
#endif
|
#endif
|
||||||
required_libs << "thread";
|
//required_libs << "thread";
|
||||||
QStringList libDirs;
|
QStringList libDirs;
|
||||||
if (!s.isEmpty())
|
if (!s.isEmpty())
|
||||||
libDirs << s;
|
libDirs << s;
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ class qc_libtorrent_rasterbar : public ConfObj
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
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"; }
|
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||||
bool exec(){
|
bool exec(){
|
||||||
QStringList incs;
|
QStringList incs;
|
||||||
QString req_ver = "0.14.4";
|
QString req_ver = "0.15.0";
|
||||||
QString version, libs, other;
|
QString version, libs, other;
|
||||||
VersionMode mode = VersionMin;
|
VersionMode mode = VersionMin;
|
||||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
-----BEGIN QCMOD-----
|
-----BEGIN QCMOD-----
|
||||||
name: Qt >= 4.5
|
name: Qt >= 4.6
|
||||||
arg: enable-debug, Enable debug mode
|
arg: enable-debug, Enable debug mode
|
||||||
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
arg: disable-gui, Disable qBittorrent Graphical user interface for headless running
|
||||||
-----END QCMOD-----
|
-----END QCMOD-----
|
||||||
@@ -9,8 +9,8 @@ class qc_qt4 : public ConfObj
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||||
QString name() const { return "Qt >= 4.5"; }
|
QString name() const { return "Qt >= 4.6"; }
|
||||||
QString shortname() const { return "Qt 4.5"; }
|
QString shortname() const { return "Qt 4.6"; }
|
||||||
bool exec()
|
bool exec()
|
||||||
{
|
{
|
||||||
// NOX mode
|
// NOX mode
|
||||||
@@ -31,6 +31,6 @@ public:
|
|||||||
#else
|
#else
|
||||||
conf->addExtra("MANPREFIX = $$PREFIX/share");
|
conf->addExtra("MANPREFIX = $$PREFIX/share");
|
||||||
#endif
|
#endif
|
||||||
return(QT_VERSION >= 0x040500);
|
return(QT_VERSION >= 0x040600);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
282
src/about.ui
282
src/about.ui
File diff suppressed because one or more lines are too long
@@ -45,13 +45,13 @@ class about : public QDialog, private Ui::AboutDlg{
|
|||||||
qDebug("Deleting about dlg");
|
qDebug("Deleting about dlg");
|
||||||
}
|
}
|
||||||
|
|
||||||
about(QWidget *parent): QDialog(parent){
|
about(QWidget *parent): QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
// Set icons
|
// Set icons
|
||||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
|
||||||
//Title
|
//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
|
// Thanks
|
||||||
QString thanks_txt;
|
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>");
|
thanks_txt += QString::fromUtf8("<p>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</p>");
|
||||||
@@ -80,8 +80,9 @@ class about : public QDialog, private Ui::AboutDlg{
|
|||||||
<li><u>Georgian:</u> Beqa Arabuli (arabulibeqa@yahoo.com)</li>\
|
<li><u>Georgian:</u> Beqa Arabuli (arabulibeqa@yahoo.com)</li>\
|
||||||
<li><u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)</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)</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>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)</li>\
|
||||||
<li><u>Italian:</u> Matteo Sechi (bu17714@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>Japanese:</u> Masato Hashimoto (cabezon.hashimoto@gmail.com)</li>\
|
||||||
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
|
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
|
||||||
<li><u>Lithuanian:</u> Naglis Jonaitis (njonaitis@gmail.com)</li>\
|
<li><u>Lithuanian:</u> Naglis Jonaitis (njonaitis@gmail.com)</li>\
|
||||||
@@ -92,16 +93,16 @@ class about : public QDialog, private Ui::AboutDlg{
|
|||||||
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
|
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
|
||||||
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
|
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
|
||||||
<li><u>Slovak:</u> helix84</li>\
|
<li><u>Slovak:</u> helix84</li>\
|
||||||
<li><u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
|
<li><u>Spanish:</u> Alfredo Monclús (alfrix), Francisco Luque Contreras (frannoe@ya.com)</li>\
|
||||||
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
|
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
|
||||||
<li><u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)</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></ul>");
|
||||||
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
|
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
|
||||||
te_translation->setHtml(trans_txt);
|
te_translation->setHtml(trans_txt);
|
||||||
// License
|
// License
|
||||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||||
QFile licensefile(":/gpl.html");
|
QFile licensefile(":/gpl.html");
|
||||||
if(licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
if (licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||||
te_license->setHtml(licensefile.readAll());
|
te_license->setHtml(licensefile.readAll());
|
||||||
licensefile.close();
|
licensefile.close();
|
||||||
}
|
}
|
||||||
|
|||||||
608
src/addnewtorrentdialog.cpp
Normal file
608
src/addnewtorrentdialog.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt4 and libtorrent.
|
||||||
* Copyright (C) 2006 Christophe Dumez
|
* Copyright (C) 2012 Christophe Dumez
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@@ -28,70 +28,66 @@
|
|||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TORRENTADDITION_H
|
#ifndef ADDNEWTORRENTDIALOG_H
|
||||||
#define TORRENTADDITION_H
|
#define ADDNEWTORRENTDIALOG_H
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
#include "ui_torrentadditiondlg.h"
|
|
||||||
|
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QUrl>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
class TorrentFilesFilterModel;
|
QT_BEGIN_NAMESPACE
|
||||||
|
namespace Ui {
|
||||||
|
class AddNewTorrentDialog;
|
||||||
|
}
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TorrentContentFilterModel;
|
||||||
class PropListDelegate;
|
class PropListDelegate;
|
||||||
|
|
||||||
class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
|
class AddNewTorrentDialog : public QDialog
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
torrentAdditionDialog(QWidget *parent);
|
~AddNewTorrentDialog();
|
||||||
~torrentAdditionDialog();
|
|
||||||
void showLoadMagnetURI(QString magnet_uri);
|
|
||||||
void showLoad(QString filePath, QString from_url=QString::null);
|
|
||||||
QString getCurrentTruncatedSavePath(QString* root_folder_or_file_name = 0) const;
|
|
||||||
QString getTruncatedSavePath(QString save_path, QString* root_folder_or_file_name = 0) const;
|
|
||||||
bool allFiltered() const;
|
|
||||||
|
|
||||||
public slots:
|
static void showTorrent(const QString& torrent_path, const QString& from_url = QString());
|
||||||
void displayContentListMenu(const QPoint&);
|
static void showMagnet(const QString& torrent_link);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void showAdvancedSettings(bool show);
|
||||||
|
void displayContentTreeMenu(const QPoint&);
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void updateDiskSpaceLabel();
|
||||||
|
void onSavePathChanged(int);
|
||||||
|
void relayout();
|
||||||
void renameSelectedFile();
|
void renameSelectedFile();
|
||||||
void updateDiskSpaceLabels();
|
void setdialogPosition();
|
||||||
void on_browseButton_clicked();
|
|
||||||
void on_CancelButton_clicked();
|
private:
|
||||||
void savePiecesPriorities();
|
explicit AddNewTorrentDialog(QWidget *parent = 0);
|
||||||
void on_OkButton_clicked();
|
bool loadTorrent(const QString& torrent_path, const QString& from_url);
|
||||||
void hideTorrentContent();
|
bool loadMagnet(const QString& magnet_uri);
|
||||||
void limitDialogWidth();
|
|
||||||
void saveTruncatedPathHistory();
|
|
||||||
void loadSavePathHistory();
|
void loadSavePathHistory();
|
||||||
void updateLabelInSavePath(QString label);
|
void saveSavePathHistory() const;
|
||||||
void updateSavePathCurrentText();
|
int indexOfSavePath(const QString& save_path);
|
||||||
void resetComboLabelIndex(QString text);
|
void updateFileNameInSavePaths(const QString& new_filename);
|
||||||
|
void loadState();
|
||||||
protected:
|
void saveState();
|
||||||
void closeEvent(QCloseEvent *event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void readSettings();
|
Ui::AddNewTorrentDialog *ui;
|
||||||
void saveSettings();
|
TorrentContentFilterModel *m_contentModel;
|
||||||
|
PropListDelegate *m_contentDelegate;
|
||||||
private:
|
bool m_isMagnet;
|
||||||
QString fileName;
|
QString m_filePath;
|
||||||
QString hash;
|
QString m_url;
|
||||||
QString filePath;
|
QString m_hash;
|
||||||
QString from_url;
|
boost::intrusive_ptr<libtorrent::torrent_info> m_torrentInfo;
|
||||||
QString defaultSavePath;
|
QStringList m_filesPath;
|
||||||
QString old_label;
|
bool m_hasRenamedFile;
|
||||||
bool appendLabelToSavePath;
|
QShortcut *editHotkey;
|
||||||
TorrentFilesFilterModel *PropListModel;
|
|
||||||
PropListDelegate *PropDelegate;
|
|
||||||
unsigned int nbFiles;
|
|
||||||
boost::intrusive_ptr<libtorrent::torrent_info> t;
|
|
||||||
QStringList files_path;
|
|
||||||
bool is_magnet;
|
|
||||||
int hidden_height;
|
|
||||||
QStringList path_history;
|
|
||||||
bool m_showContentList;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // ADDNEWTORRENTDIALOG_H
|
||||||
271
src/addnewtorrentdialog.ui
Normal file
271
src/addnewtorrentdialog.ui
Normal file
File diff suppressed because it is too large
Load Diff
@@ -59,7 +59,7 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
|
|||||||
|
|
||||||
static bool askForDeletionConfirmation(bool *delete_local_files) {
|
static bool askForDeletionConfirmation(bool *delete_local_files) {
|
||||||
DeletionConfirmationDlg dlg;
|
DeletionConfirmationDlg dlg;
|
||||||
if(dlg.exec() == QDialog::Accepted) {
|
if (dlg.exec() == QDialog::Accepted) {
|
||||||
*delete_local_files = dlg.shouldDeleteLocalFiles();
|
*delete_local_files = dlg.shouldDeleteLocalFiles();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ DNSUpdater::DNSUpdater(QObject *parent) :
|
|||||||
m_ipCheckTimer.start();
|
m_ipCheckTimer.start();
|
||||||
|
|
||||||
// Check lastUpdate to avoid flooding
|
// Check lastUpdate to avoid flooding
|
||||||
if(!m_lastIPCheckTime.isValid() ||
|
if (!m_lastIPCheckTime.isValid() ||
|
||||||
m_lastIPCheckTime.secsTo(QDateTime::currentDateTime())*1000 > IP_CHECK_INTERVAL_MS) {
|
m_lastIPCheckTime.secsTo(QDateTime::currentDateTime())*1000 > IP_CHECK_INTERVAL_MS) {
|
||||||
checkPublicIP();
|
checkPublicIP();
|
||||||
}
|
}
|
||||||
@@ -79,19 +79,19 @@ void DNSUpdater::checkPublicIP()
|
|||||||
void DNSUpdater::ipRequestFinished(QNetworkReply *reply)
|
void DNSUpdater::ipRequestFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
if(reply->error()) {
|
if (reply->error()) {
|
||||||
// Error
|
// Error
|
||||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||||
} else {
|
} else {
|
||||||
// Parse response
|
// Parse response
|
||||||
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
|
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
|
||||||
QString ret = reply->readAll();
|
QString ret = reply->readAll();
|
||||||
if(ipregex.indexIn(ret) >= 0) {
|
if (ipregex.indexIn(ret) >= 0) {
|
||||||
QString ip_str = ipregex.cap(1);
|
QString ip_str = ipregex.cap(1);
|
||||||
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ip_str;
|
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ip_str;
|
||||||
QHostAddress new_ip(ip_str);
|
QHostAddress new_ip(ip_str);
|
||||||
if(!new_ip.isNull()) {
|
if (!new_ip.isNull()) {
|
||||||
if(m_lastIP != new_ip) {
|
if (m_lastIP != new_ip) {
|
||||||
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
|
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
|
||||||
qDebug() << m_lastIP.toString() << "->" << new_ip.toString();
|
qDebug() << m_lastIP.toString() << "->" << new_ip.toString();
|
||||||
m_lastIP = new_ip;
|
m_lastIP = new_ip;
|
||||||
@@ -157,7 +157,7 @@ QUrl DNSUpdater::getUpdateUrl() const
|
|||||||
|
|
||||||
void DNSUpdater::ipUpdateFinished(QNetworkReply *reply)
|
void DNSUpdater::ipUpdateFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
if(reply->error()) {
|
if (reply->error()) {
|
||||||
// Error
|
// Error
|
||||||
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
|
||||||
} else {
|
} else {
|
||||||
@@ -174,11 +174,11 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
|||||||
qDebug() << Q_FUNC_INFO << reply;
|
qDebug() << Q_FUNC_INFO << reply;
|
||||||
QString code = reply.split(" ").first();
|
QString code = reply.split(" ").first();
|
||||||
qDebug() << Q_FUNC_INFO << "Code:" << code;
|
qDebug() << Q_FUNC_INFO << "Code:" << code;
|
||||||
if(code == "good" || code == "nochg") {
|
if (code == "good" || code == "nochg") {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Your dynamic DNS was successfuly updated."), "green");
|
QBtSession::instance()->addConsoleMessage(tr("Your dynamic DNS was successfully updated."), "green");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(code == "911" || code == "dnserr") {
|
if (code == "911" || code == "dnserr") {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."),
|
||||||
"red");
|
"red");
|
||||||
m_lastIP.clear();
|
m_lastIP.clear();
|
||||||
@@ -188,30 +188,30 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
|||||||
// Everything bellow is an error, stop updating until the user updates something
|
// Everything bellow is an error, stop updating until the user updates something
|
||||||
m_ipCheckTimer.stop();
|
m_ipCheckTimer.stop();
|
||||||
m_lastIP.clear();
|
m_lastIP.clear();
|
||||||
if(code == "nohost") {
|
if (code == "nohost") {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: hostname supplied does not exist under specified account."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: hostname supplied does not exist under specified account."),
|
||||||
"red");
|
"red");
|
||||||
m_state = INVALID_CREDS;
|
m_state = INVALID_CREDS;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(code == "badauth") {
|
if (code == "badauth") {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Invalid username/password."), "red");
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Invalid username/password."), "red");
|
||||||
m_state = INVALID_CREDS;
|
m_state = INVALID_CREDS;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(code == "badagent") {
|
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."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."),
|
||||||
"red");
|
"red");
|
||||||
m_state = FATAL;
|
m_state = FATAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(code == "!donator") {
|
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"),
|
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");
|
"red");
|
||||||
m_state = FATAL;
|
m_state = FATAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(code == "abuse") {
|
if (code == "abuse") {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."),
|
||||||
"red");
|
"red");
|
||||||
m_state = FATAL;
|
m_state = FATAL;
|
||||||
@@ -221,18 +221,18 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
|||||||
|
|
||||||
void DNSUpdater::updateCredentials()
|
void DNSUpdater::updateCredentials()
|
||||||
{
|
{
|
||||||
if(m_state == FATAL) return;
|
if (m_state == FATAL) return;
|
||||||
Preferences pref;
|
Preferences pref;
|
||||||
bool change = false;
|
bool change = false;
|
||||||
// Get DNS service information
|
// Get DNS service information
|
||||||
if(m_service != pref.getDynDNSService()) {
|
if (m_service != pref.getDynDNSService()) {
|
||||||
m_service = pref.getDynDNSService();
|
m_service = pref.getDynDNSService();
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
if(m_domain != pref.getDynDomainName()) {
|
if (m_domain != pref.getDynDomainName()) {
|
||||||
m_domain = pref.getDynDomainName();
|
m_domain = pref.getDynDomainName();
|
||||||
QRegExp domain_regex("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$");
|
QRegExp domain_regex("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$");
|
||||||
if(domain_regex.indexIn(m_domain) < 0) {
|
if (domain_regex.indexIn(m_domain) < 0) {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied domain name is invalid."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied domain name is invalid."),
|
||||||
"red");
|
"red");
|
||||||
m_lastIP.clear();
|
m_lastIP.clear();
|
||||||
@@ -242,9 +242,9 @@ void DNSUpdater::updateCredentials()
|
|||||||
}
|
}
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
if(m_username != pref.getDynDNSUsername()) {
|
if (m_username != pref.getDynDNSUsername()) {
|
||||||
m_username = pref.getDynDNSUsername();
|
m_username = pref.getDynDNSUsername();
|
||||||
if(m_username.length() < 4) {
|
if (m_username.length() < 4) {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied username is too short."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied username is too short."),
|
||||||
"red");
|
"red");
|
||||||
m_lastIP.clear();
|
m_lastIP.clear();
|
||||||
@@ -254,9 +254,9 @@ void DNSUpdater::updateCredentials()
|
|||||||
}
|
}
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
if(m_password != pref.getDynDNSPassword()) {
|
if (m_password != pref.getDynDNSPassword()) {
|
||||||
m_password = pref.getDynDNSPassword();
|
m_password = pref.getDynDNSPassword();
|
||||||
if(m_password.length() < 4) {
|
if (m_password.length() < 4) {
|
||||||
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied password is too short."),
|
QBtSession::instance()->addConsoleMessage(tr("Dynamic DNS error: supplied password is too short."),
|
||||||
"red");
|
"red");
|
||||||
m_lastIP.clear();
|
m_lastIP.clear();
|
||||||
@@ -267,7 +267,7 @@ void DNSUpdater::updateCredentials()
|
|||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_state == INVALID_CREDS && change) {
|
if (m_state == INVALID_CREDS && change) {
|
||||||
m_state = OK; // Try again
|
m_state = OK; // Try again
|
||||||
m_ipCheckTimer.start();
|
m_ipCheckTimer.start();
|
||||||
checkPublicIP();
|
checkPublicIP();
|
||||||
|
|||||||
@@ -43,38 +43,38 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
downloadFromURL(QWidget *parent): QDialog(parent){
|
downloadFromURL(QWidget *parent): QDialog(parent) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
setModal(true);
|
setModal(true);
|
||||||
show();
|
show();
|
||||||
// Paste clipboard if there is an URL in it
|
// Paste clipboard if there is an URL in it
|
||||||
QString clip_txt = qApp->clipboard()->text();
|
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)) {
|
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);
|
textUrls->setText(clip_txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~downloadFromURL(){}
|
~downloadFromURL() {}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void urlsReadyToBeDownloaded(const QStringList& torrent_urls);
|
void urlsReadyToBeDownloaded(const QStringList& torrent_urls);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void on_downloadButton_clicked(){
|
void on_downloadButton_clicked() {
|
||||||
QString urls = textUrls->toPlainText();
|
QString urls = textUrls->toPlainText();
|
||||||
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
||||||
QString url;
|
QString url;
|
||||||
QStringList url_list_cleaned;
|
QStringList url_list_cleaned;
|
||||||
foreach(url, url_list){
|
foreach (url, url_list) {
|
||||||
url = url.trimmed();
|
url = url.trimmed();
|
||||||
if(!url.isEmpty()){
|
if (!url.isEmpty()) {
|
||||||
if(url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0){
|
if (url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) {
|
||||||
url_list_cleaned << url;
|
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."));
|
QMessageBox::critical(0, tr("No URL entered"), tr("Please type at least one URL."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_cancelButton_clicked(){
|
void on_cancelButton_clicked() {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,11 +50,61 @@ DownloadThread::DownloadThread(QObject* parent) : QObject(parent) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
||||||
QString url = reply->url().toString();
|
QString url = reply->url().toString();
|
||||||
qDebug("Download finished: %s", qPrintable(url));
|
qDebug("Download finished: %s", qPrintable(url));
|
||||||
// Check if the request was successful
|
// Check if the request was successful
|
||||||
if(reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
// Failure
|
// Failure
|
||||||
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
|
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
|
||||||
emit downloadFailure(url, errorCodeToString(reply->error()));
|
emit downloadFailure(url, errorCodeToString(reply->error()));
|
||||||
@@ -63,7 +113,7 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
|||||||
}
|
}
|
||||||
// Check if the server ask us to redirect somewhere lese
|
// Check if the server ask us to redirect somewhere lese
|
||||||
const QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
const QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||||
if(redirection.isValid()) {
|
if (redirection.isValid()) {
|
||||||
// We should redirect
|
// We should redirect
|
||||||
QUrl newUrl = redirection.toUrl();
|
QUrl newUrl = redirection.toUrl();
|
||||||
// Resolve relative urls
|
// Resolve relative urls
|
||||||
@@ -72,12 +122,13 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
|||||||
const QString newUrlString = newUrl.toString();
|
const QString newUrlString = newUrl.toString();
|
||||||
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString));
|
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(newUrlString));
|
||||||
m_redirectMapping.insert(newUrlString, url);
|
m_redirectMapping.insert(newUrlString, url);
|
||||||
downloadUrl(newUrlString);
|
// redirecting with first cookies
|
||||||
|
downloadUrl(newUrlString, m_networkManager.cookieJar()->cookiesForUrl(url));
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Checking if it was redirected, restoring initial URL
|
// Checking if it was redirected, restoring initial URL
|
||||||
if(m_redirectMapping.contains(url)) {
|
if (m_redirectMapping.contains(url)) {
|
||||||
url = m_redirectMapping.take(url);
|
url = m_redirectMapping.take(url);
|
||||||
}
|
}
|
||||||
// Success
|
// Success
|
||||||
@@ -86,9 +137,13 @@ void DownloadThread::processDlFinished(QNetworkReply* reply) {
|
|||||||
if (tmpfile->open()) {
|
if (tmpfile->open()) {
|
||||||
QString filePath = tmpfile->fileName();
|
QString filePath = tmpfile->fileName();
|
||||||
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
qDebug("Temporary filename is: %s", qPrintable(filePath));
|
||||||
if(reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
|
if (reply->isOpen() || reply->open(QIODevice::ReadOnly)) {
|
||||||
// TODO: Support GZIP compression
|
QByteArray replyData = reply->readAll();
|
||||||
tmpfile->write(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();
|
tmpfile->close();
|
||||||
// XXX: tmpfile needs to be deleted on Windows before using the file
|
// XXX: tmpfile needs to be deleted on Windows before using the file
|
||||||
// or it will complain that the file is used by another process.
|
// or it will complain that the file is used by another process.
|
||||||
@@ -132,19 +187,21 @@ QNetworkReply* DownloadThread::downloadUrl(const QString &url, const QList<QNetw
|
|||||||
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");
|
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("Downloading %s...", request.url().toEncoded().data());
|
||||||
qDebug("%d cookies for this URL", m_networkManager.cookieJar()->cookiesForUrl(url).size());
|
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("%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()));
|
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);
|
return m_networkManager.get(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
|
||||||
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
if(!reply) return;
|
if (!reply) return;
|
||||||
if(bytesTotal > 0) {
|
if (bytesTotal > 0) {
|
||||||
// Total number of bytes is available
|
// Total number of bytes is available
|
||||||
if(bytesTotal > 1048576) {
|
if (bytesTotal > 1048576) {
|
||||||
// More than 1MB, this is probably not a torrent file, aborting...
|
// More than 1MB, this is probably not a torrent file, aborting...
|
||||||
reply->abort();
|
reply->abort();
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -152,7 +209,7 @@ void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
|||||||
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(bytesReceived > 1048576) {
|
if (bytesReceived > 1048576) {
|
||||||
// More than 1MB, this is probably not a torrent file, aborting...
|
// More than 1MB, this is probably not a torrent file, aborting...
|
||||||
reply->abort();
|
reply->abort();
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -163,13 +220,13 @@ void DownloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
|||||||
void DownloadThread::applyProxySettings() {
|
void DownloadThread::applyProxySettings() {
|
||||||
QNetworkProxy proxy;
|
QNetworkProxy proxy;
|
||||||
const Preferences pref;
|
const Preferences pref;
|
||||||
if(pref.isProxyEnabled()) {
|
if (pref.isProxyEnabled()) {
|
||||||
// Proxy enabled
|
// Proxy enabled
|
||||||
proxy.setHostName(pref.getProxyIp());
|
proxy.setHostName(pref.getProxyIp());
|
||||||
proxy.setPort(pref.getProxyPort());
|
proxy.setPort(pref.getProxyPort());
|
||||||
// Default proxy type is HTTP, we must change if it is SOCKS5
|
// Default proxy type is HTTP, we must change if it is SOCKS5
|
||||||
const int proxy_type = pref.getProxyType();
|
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";
|
qDebug() << Q_FUNC_INFO << "using SOCKS proxy";
|
||||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||||
} else {
|
} else {
|
||||||
@@ -177,7 +234,7 @@ void DownloadThread::applyProxySettings() {
|
|||||||
proxy.setType(QNetworkProxy::HttpProxy);
|
proxy.setType(QNetworkProxy::HttpProxy);
|
||||||
}
|
}
|
||||||
// Authentication?
|
// Authentication?
|
||||||
if(pref.isProxyAuthEnabled()) {
|
if (pref.isProxyAuthEnabled()) {
|
||||||
qDebug("Proxy requires authentication, authenticating");
|
qDebug("Proxy requires authentication, authenticating");
|
||||||
proxy.setUser(pref.getProxyUsername());
|
proxy.setUser(pref.getProxyUsername());
|
||||||
proxy.setPassword(pref.getProxyPassword());
|
proxy.setPassword(pref.getProxyPassword());
|
||||||
@@ -189,7 +246,7 @@ void DownloadThread::applyProxySettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString DownloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
QString DownloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
|
||||||
switch(status){
|
switch(status) {
|
||||||
case QNetworkReply::HostNotFoundError:
|
case QNetworkReply::HostNotFoundError:
|
||||||
return tr("The remote host name was not found (invalid hostname)");
|
return tr("The remote host name was not found (invalid hostname)");
|
||||||
case QNetworkReply::OperationCanceledError:
|
case QNetworkReply::OperationCanceledError:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QSslError>
|
#include <QSslError>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
@@ -46,8 +47,8 @@ class DownloadThread : public QObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DownloadThread(QObject* parent = 0);
|
DownloadThread(QObject* parent = 0);
|
||||||
QNetworkReply* downloadUrl(const QString &url, const QList<QNetworkCookie>& raw_cookies = QList<QNetworkCookie>());
|
QNetworkReply* downloadUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||||
void downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& raw_cookies = QList<QNetworkCookie>());
|
void downloadTorrentUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||||
//void setProxy(QString IP, int port, QString username, QString password);
|
//void setProxy(QString IP, int port, QString username, QString password);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -62,6 +63,7 @@ private slots:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static QByteArray gUncompress(Bytef *inData, size_t len);
|
||||||
QString errorCodeToString(QNetworkReply::NetworkError status);
|
QString errorCodeToString(QNetworkReply::NetworkError status);
|
||||||
void applyProxySettings();
|
void applyProxySettings();
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ ExecutionLog::ExecutionLog(QWidget *parent) :
|
|||||||
ui->tabBan->layout()->addWidget(m_banList);
|
ui->tabBan->layout()->addWidget(m_banList);
|
||||||
|
|
||||||
const QStringList log_msgs = QBtSession::instance()->getConsoleMessages();
|
const QStringList log_msgs = QBtSession::instance()->getConsoleMessages();
|
||||||
foreach(const QString& msg, log_msgs)
|
foreach (const QString& msg, log_msgs)
|
||||||
addLogMessage(msg);
|
addLogMessage(msg);
|
||||||
const QStringList ban_msgs = QBtSession::instance()->getPeerBanMessages();
|
const QStringList ban_msgs = QBtSession::instance()->getPeerBanMessages();
|
||||||
foreach(const QString& msg, ban_msgs)
|
foreach (const QString& msg, ban_msgs)
|
||||||
addBanMessage(msg);
|
addBanMessage(msg);
|
||||||
connect(QBtSession::instance(), SIGNAL(newConsoleMessage(QString)), SLOT(addLogMessage(QString)));
|
connect(QBtSession::instance(), SIGNAL(newConsoleMessage(QString)), SLOT(addLogMessage(QString)));
|
||||||
connect(QBtSession::instance(), SIGNAL(newBanMessage(QString)), SLOT(addBanMessage(QString)));
|
connect(QBtSession::instance(), SIGNAL(newBanMessage(QString)), SLOT(addBanMessage(QString)));
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "fs_utils.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
#ifndef CIFS_MAGIC_NUMBER
|
#ifndef CIFS_MAGIC_NUMBER
|
||||||
@@ -59,11 +60,11 @@ private:
|
|||||||
private:
|
private:
|
||||||
static bool isNetworkFileSystem(QString path) {
|
static bool isNetworkFileSystem(QString path) {
|
||||||
QString file = path;
|
QString file = path;
|
||||||
if(!file.endsWith(QDir::separator()))
|
if (!file.endsWith(QDir::separator()))
|
||||||
file += QDir::separator();
|
file += QDir::separator();
|
||||||
file += ".";
|
file += ".";
|
||||||
struct statfs buf;
|
struct statfs buf;
|
||||||
if(!statfs(file.toLocal8Bit().constData(), &buf)) {
|
if (!statfs(file.toLocal8Bit().constData(), &buf)) {
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
// XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined?
|
// 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);
|
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:
|
public:
|
||||||
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
|
||||||
m_filters << "*.torrent";
|
m_filters << "*.torrent" << "*.magnet";
|
||||||
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
~FileSystemWatcher() {
|
~FileSystemWatcher() {
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
if(watch_timer)
|
if (watch_timer)
|
||||||
delete watch_timer;
|
delete watch_timer;
|
||||||
#endif
|
#endif
|
||||||
if(m_partialTorrentTimer)
|
if (m_partialTorrentTimer)
|
||||||
delete m_partialTorrentTimer;
|
delete m_partialTorrentTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList directories() const {
|
QStringList directories() const {
|
||||||
QStringList dirs;
|
QStringList dirs;
|
||||||
#ifndef Q_WS_WIN
|
#ifndef Q_WS_WIN
|
||||||
if(watch_timer) {
|
if (watch_timer) {
|
||||||
foreach (const QDir &dir, watched_folders)
|
foreach (const QDir &dir, watched_folders)
|
||||||
dirs << dir.canonicalPath();
|
dirs << dir.canonicalPath();
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,7 @@ public:
|
|||||||
if (!dir.exists())
|
if (!dir.exists())
|
||||||
return;
|
return;
|
||||||
// Check if the path points to a network file system or not
|
// Check if the path points to a network file system or not
|
||||||
if(isNetworkFileSystem(path)) {
|
if (isNetworkFileSystem(path)) {
|
||||||
// Network mode
|
// Network mode
|
||||||
qDebug("Network folder detected: %s", qPrintable(path));
|
qDebug("Network folder detected: %s", qPrintable(path));
|
||||||
qDebug("Using file polling mode instead of inotify...");
|
qDebug("Using file polling mode instead of inotify...");
|
||||||
@@ -194,7 +195,7 @@ protected slots:
|
|||||||
// Local folders scan
|
// Local folders scan
|
||||||
addTorrentsFromDir(QDir(path), torrents);
|
addTorrentsFromDir(QDir(path), torrents);
|
||||||
// Report detected torrent files
|
// Report detected torrent files
|
||||||
if(!torrents.empty()) {
|
if (!torrents.empty()) {
|
||||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||||
emit torrentsAdded(torrents);
|
emit torrentsAdded(torrents);
|
||||||
}
|
}
|
||||||
@@ -210,7 +211,7 @@ protected slots:
|
|||||||
addTorrentsFromDir(dir, torrents);
|
addTorrentsFromDir(dir, torrents);
|
||||||
}
|
}
|
||||||
// Report detected torrent files
|
// Report detected torrent files
|
||||||
if(!torrents.empty()) {
|
if (!torrents.empty()) {
|
||||||
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
|
||||||
emit torrentsAdded(torrents);
|
emit torrentsAdded(torrents);
|
||||||
}
|
}
|
||||||
@@ -221,16 +222,16 @@ protected slots:
|
|||||||
QStringList no_longer_partial;
|
QStringList no_longer_partial;
|
||||||
|
|
||||||
// Check which torrents are still partial
|
// Check which torrents are still partial
|
||||||
foreach(const QString& torrent_path, m_partialTorrents.keys()) {
|
foreach (const QString& torrent_path, m_partialTorrents.keys()) {
|
||||||
if(!QFile::exists(torrent_path)) {
|
if (!QFile::exists(torrent_path)) {
|
||||||
m_partialTorrents.remove(torrent_path);
|
m_partialTorrents.remove(torrent_path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(misc::isValidTorrentFile(torrent_path)) {
|
if (fsutils::isValidTorrentFile(torrent_path)) {
|
||||||
no_longer_partial << torrent_path;
|
no_longer_partial << torrent_path;
|
||||||
m_partialTorrents.remove(torrent_path);
|
m_partialTorrents.remove(torrent_path);
|
||||||
} else {
|
} else {
|
||||||
if(m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
if (m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
|
||||||
m_partialTorrents.remove(torrent_path);
|
m_partialTorrents.remove(torrent_path);
|
||||||
QFile::rename(torrent_path, torrent_path+".invalid");
|
QFile::rename(torrent_path, torrent_path+".invalid");
|
||||||
} else {
|
} else {
|
||||||
@@ -240,7 +241,7 @@ protected slots:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop the partial timer if necessary
|
// Stop the partial timer if necessary
|
||||||
if(m_partialTorrents.empty()) {
|
if (m_partialTorrents.empty()) {
|
||||||
m_partialTorrentTimer->stop();
|
m_partialTorrentTimer->stop();
|
||||||
m_partialTorrentTimer->deleteLater();
|
m_partialTorrentTimer->deleteLater();
|
||||||
qDebug("No longer any partial torrent.");
|
qDebug("No longer any partial torrent.");
|
||||||
@@ -249,7 +250,7 @@ protected slots:
|
|||||||
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
m_partialTorrentTimer->start(WATCH_INTERVAL);
|
||||||
}
|
}
|
||||||
// Notify of new torrents
|
// Notify of new torrents
|
||||||
if(!no_longer_partial.isEmpty())
|
if (!no_longer_partial.isEmpty())
|
||||||
emit torrentsAdded(no_longer_partial);
|
emit torrentsAdded(no_longer_partial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +260,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
void startPartialTorrentTimer() {
|
void startPartialTorrentTimer() {
|
||||||
Q_ASSERT(!m_partialTorrents.isEmpty());
|
Q_ASSERT(!m_partialTorrents.isEmpty());
|
||||||
if(!m_partialTorrentTimer) {
|
if (!m_partialTorrentTimer) {
|
||||||
m_partialTorrentTimer = new QTimer();
|
m_partialTorrentTimer = new QTimer();
|
||||||
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
|
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
|
||||||
m_partialTorrentTimer->setSingleShot(true);
|
m_partialTorrentTimer->setSingleShot(true);
|
||||||
@@ -269,19 +270,25 @@ private:
|
|||||||
|
|
||||||
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
|
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
|
||||||
const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted);
|
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);
|
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;
|
torrents << file_abspath;
|
||||||
} else {
|
} else {
|
||||||
if(!m_partialTorrents.contains(file_abspath)) {
|
if (!m_partialTorrents.contains(file_abspath)) {
|
||||||
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
|
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
|
||||||
qDebug("Delay the file's processing...");
|
qDebug("Delay the file's processing...");
|
||||||
m_partialTorrents.insert(file_abspath, 0);
|
m_partialTorrents.insert(file_abspath, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!m_partialTorrents.empty())
|
if (!m_partialTorrents.empty())
|
||||||
startPartialTorrentTimer();
|
startPartialTorrentTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
503
src/fs_utils.cpp
Normal file
503
src/fs_utils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
src/fs_utils.h
Normal file
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 <QFile>
|
||||||
#include <QChar>
|
#include <QChar>
|
||||||
|
|
||||||
#include "misc.h"
|
#include "fs_utils.h"
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
QString GeoIPManager::geoipFolder(bool embedded) {
|
QString GeoIPManager::geoipFolder(bool embedded) {
|
||||||
#ifdef WITH_GEOIP_EMBEDDED
|
#ifdef WITH_GEOIP_EMBEDDED
|
||||||
if(embedded)
|
if (embedded)
|
||||||
return ":/geoip/";
|
return ":/geoip/";
|
||||||
return misc::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
return fsutils::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(embedded);
|
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/";
|
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 "/var/lib/GeoIP/";
|
||||||
return "/usr/share/GeoIP/";
|
return "/usr/share/GeoIP/";
|
||||||
#endif
|
#endif
|
||||||
@@ -89,22 +89,22 @@ QString GeoIPManager::geoipDBpath(bool embedded) {
|
|||||||
|
|
||||||
#ifdef WITH_GEOIP_EMBEDDED
|
#ifdef WITH_GEOIP_EMBEDDED
|
||||||
void GeoIPManager::exportEmbeddedDb() {
|
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...");
|
qDebug("A local Geoip database update is required, proceeding...");
|
||||||
// Create geoip folder is necessary
|
// Create geoip folder is necessary
|
||||||
QDir gfolder(geoipFolder(false));
|
QDir gfolder(geoipFolder(false));
|
||||||
if(!gfolder.exists()) {
|
if (!gfolder.exists()) {
|
||||||
if(!gfolder.mkpath(geoipFolder(false))) {
|
if (!gfolder.mkpath(geoipFolder(false))) {
|
||||||
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove destination files
|
// Remove destination files
|
||||||
if(QFile::exists(geoipDBpath(false)))
|
if (QFile::exists(geoipDBpath(false)))
|
||||||
misc::safeRemove(geoipDBpath(false));
|
fsutils::forceRemove(geoipDBpath(false));
|
||||||
// Copy from executable to hard disk
|
// Copy from executable to hard disk
|
||||||
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
|
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;
|
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
|
||||||
}
|
}
|
||||||
qDebug("Local Geoip database was updated");
|
qDebug("Local Geoip database was updated");
|
||||||
@@ -116,7 +116,7 @@ void GeoIPManager::loadDatabase(session *s) {
|
|||||||
#ifdef WITH_GEOIP_EMBEDDED
|
#ifdef WITH_GEOIP_EMBEDDED
|
||||||
exportEmbeddedDb();
|
exportEmbeddedDb();
|
||||||
#endif
|
#endif
|
||||||
if(QFile::exists(geoipDBpath(false))) {
|
if (QFile::exists(geoipDBpath(false))) {
|
||||||
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
|
||||||
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
|
s->load_country_db(geoipDBpath(false).toLocal8Bit().constData());
|
||||||
} else {
|
} else {
|
||||||
@@ -183,9 +183,9 @@ const char * country_name[253] =
|
|||||||
"Saint Barthelemy","Saint Martin"};
|
"Saint Barthelemy","Saint Martin"};
|
||||||
|
|
||||||
QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
QString GeoIPManager::CountryISOCodeToName(const char* iso) {
|
||||||
if(iso[0] == 0) return "N/A";
|
if (iso[0] == 0) return "N/A";
|
||||||
for(uint i = 0; i < num_countries; ++i) {
|
for (uint i = 0; i < num_countries; ++i) {
|
||||||
if(iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
if (iso[0] == country_code[i][0] && iso[1] == country_code[i][1]) {
|
||||||
return QLatin1String(country_name[i]);
|
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
|
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||||
QIcon GeoIPManager::CountryISOCodeToIcon(const char* iso) {
|
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();
|
const QString isoStr = QString(QByteArray(iso, 2)).toLower();
|
||||||
return QIcon(":/Icons/flags/"+isoStr+".png");
|
return QIcon(":/Icons/flags/"+isoStr+".png");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ 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("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;
|
std::cout << qPrintable(tr("The Web UI administrator user name is: %1").arg(pref.getWebUiUsername())) << std::endl;
|
||||||
qDebug() << "Password:" << pref.getWebUiPassword();
|
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("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;
|
std::cout << qPrintable(tr("This is a security risk, please consider changing your password from program preferences.")) << std::endl;
|
||||||
}
|
}
|
||||||
@@ -85,16 +85,16 @@ public slots:
|
|||||||
// the right addTorrent function, considering
|
// the right addTorrent function, considering
|
||||||
// the parameter type.
|
// the parameter type.
|
||||||
void processParams(const QStringList& params) {
|
void processParams(const QStringList& params) {
|
||||||
foreach(QString param, params) {
|
foreach (QString param, params) {
|
||||||
param = param.trimmed();
|
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);
|
QBtSession::instance()->downloadFromUrl(param);
|
||||||
}else{
|
}else{
|
||||||
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
if (param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||||
qDebug("Converting bc link to magnet link");
|
qDebug("Converting bc link to magnet link");
|
||||||
param = misc::bcLinkToMagnet(param);
|
param = misc::bcLinkToMagnet(param);
|
||||||
}
|
}
|
||||||
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
if (param.startsWith("magnet:", Qt::CaseInsensitive)) {
|
||||||
QBtSession::instance()->addMagnetUri(param);
|
QBtSession::instance()->addMagnetUri(param);
|
||||||
} else {
|
} else {
|
||||||
QBtSession::instance()->addTorrent(param);
|
QBtSession::instance()->addTorrent(param);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void tabInserted(int index) {
|
void tabInserted(int index) {
|
||||||
QTabWidget::tabInserted(index);
|
QTabWidget::tabInserted(index);
|
||||||
if(count() == 1) {
|
if (count() == 1) {
|
||||||
showTabBar(false);
|
showTabBar(false);
|
||||||
} else {
|
} else {
|
||||||
showTabBar(true);
|
showTabBar(true);
|
||||||
@@ -53,7 +53,7 @@ protected:
|
|||||||
|
|
||||||
void tabRemoved(int index) {
|
void tabRemoved(int index) {
|
||||||
QTabWidget::tabInserted(index);
|
QTabWidget::tabInserted(index);
|
||||||
if(count() == 1) {
|
if (count() == 1) {
|
||||||
showTabBar(false);
|
showTabBar(false);
|
||||||
} else {
|
} else {
|
||||||
showTabBar(true);
|
showTabBar(true);
|
||||||
|
|||||||
@@ -35,21 +35,21 @@ IconProvider* IconProvider::m_instance = 0;
|
|||||||
|
|
||||||
IconProvider::IconProvider()
|
IconProvider::IconProvider()
|
||||||
{
|
{
|
||||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
#if defined(Q_WS_X11)
|
||||||
m_useSystemTheme = Preferences().useSystemIconTheme();
|
m_useSystemTheme = Preferences().useSystemIconTheme();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
IconProvider * IconProvider::instance()
|
IconProvider * IconProvider::instance()
|
||||||
{
|
{
|
||||||
if(!m_instance)
|
if (!m_instance)
|
||||||
m_instance = new IconProvider;
|
m_instance = new IconProvider;
|
||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconProvider::drop()
|
void IconProvider::drop()
|
||||||
{
|
{
|
||||||
if(m_instance) {
|
if (m_instance) {
|
||||||
delete m_instance;
|
delete m_instance;
|
||||||
m_instance = 0;
|
m_instance = 0;
|
||||||
}
|
}
|
||||||
@@ -57,8 +57,8 @@ void IconProvider::drop()
|
|||||||
|
|
||||||
QIcon IconProvider::getIcon(const QString &iconId)
|
QIcon IconProvider::getIcon(const QString &iconId)
|
||||||
{
|
{
|
||||||
#if defined(Q_WS_X11) && (QT_VERSION >= QT_VERSION_CHECK(4,6,0))
|
#if defined(Q_WS_X11)
|
||||||
if(m_useSystemTheme) {
|
if (m_useSystemTheme) {
|
||||||
QIcon icon = QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
|
QIcon icon = QIcon::fromTheme(iconId, QIcon(":/Icons/oxygen/"+iconId+".png"));
|
||||||
icon = generateDifferentSizes(icon);
|
icon = generateDifferentSizes(icon);
|
||||||
return icon;
|
return icon;
|
||||||
@@ -67,7 +67,7 @@ QIcon IconProvider::getIcon(const QString &iconId)
|
|||||||
return QIcon(":/Icons/oxygen/"+iconId+".png");
|
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)
|
void IconProvider::useSystemIconTheme(bool enable)
|
||||||
{
|
{
|
||||||
m_useSystemTheme = enable;
|
m_useSystemTheme = enable;
|
||||||
@@ -77,21 +77,21 @@ void IconProvider::useSystemIconTheme(bool enable)
|
|||||||
// It scales the icon from the theme if necessary
|
// It scales the icon from the theme if necessary
|
||||||
// Otherwise, the UI looks broken if the icon is not available
|
// Otherwise, the UI looks broken if the icon is not available
|
||||||
// in the correct size.
|
// in the correct size.
|
||||||
QIcon IconProvider::generateDifferentSizes(const QIcon &icon)
|
QIcon IconProvider::generateDifferentSizes(const QIcon& icon)
|
||||||
{
|
{
|
||||||
QIcon new_icon;
|
QIcon new_icon;
|
||||||
QList<QSize> required_sizes;
|
QList<QSize> required_sizes;
|
||||||
required_sizes << QSize(16, 16) << QSize(24, 24);
|
required_sizes << QSize(16, 16) << QSize(24, 24);
|
||||||
QList<QIcon::Mode> modes;
|
QList<QIcon::Mode> modes;
|
||||||
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
|
modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled;
|
||||||
foreach(const QSize& size, required_sizes) {
|
foreach (const QSize& size, required_sizes) {
|
||||||
foreach(QIcon::Mode mode, modes) {
|
foreach (QIcon::Mode mode, modes) {
|
||||||
QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off);
|
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);
|
pixoff = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
new_icon.addPixmap(pixoff, mode, QIcon::Off);
|
new_icon.addPixmap(pixoff, mode, QIcon::Off);
|
||||||
QPixmap pixon = icon.pixmap(size, mode, QIcon::On);
|
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);
|
pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
new_icon.addPixmap(pixon, mode, QIcon::On);
|
new_icon.addPixmap(pixon, mode, QIcon::On);
|
||||||
}
|
}
|
||||||
@@ -100,14 +100,14 @@ QIcon IconProvider::generateDifferentSizes(const QIcon &icon)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 defined(Q_WS_X11)
|
||||||
if(m_useSystemTheme) {
|
if (m_useSystemTheme) {
|
||||||
QString path = QDir::temp().absoluteFilePath(iconId+".png");
|
QString path = QDir::temp().absoluteFilePath(iconId+".png");
|
||||||
if(!QFile::exists(path)) {
|
if (!QFile::exists(path)) {
|
||||||
const QIcon icon = QIcon::fromTheme(iconId);
|
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);
|
QPixmap px = icon.pixmap(32);
|
||||||
px.save(path);
|
px.save(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ public:
|
|||||||
static IconProvider* instance();
|
static IconProvider* instance();
|
||||||
static void drop();
|
static void drop();
|
||||||
QIcon getIcon(const QString& iconId);
|
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:
|
public:
|
||||||
void useSystemIconTheme(bool enable);
|
void useSystemIconTheme(bool enable);
|
||||||
|
|
||||||
|
|||||||
646
src/icons.qrc
646
src/icons.qrc
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user