Compare commits
541 Commits
release-0.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ffb4c7c5 | ||
|
|
b7fd7d9837 | ||
|
|
89670af7c9 | ||
|
|
10a13195b3 | ||
|
|
0f34a98350 | ||
|
|
59279aa43a | ||
|
|
11198208eb | ||
|
|
4a2c7efb27 | ||
|
|
3ea344cb2e | ||
|
|
dff33dbfb1 | ||
|
|
ed6cad6d1b | ||
|
|
b582ec9480 | ||
|
|
b5ccf05541 | ||
|
|
b3c5e6cfa2 | ||
|
|
229927bbe9 | ||
|
|
495d6f2bab | ||
|
|
a9f1bd4f74 | ||
|
|
73c247fe10 | ||
|
|
bd84cb197f | ||
|
|
57309c7d82 | ||
|
|
27e76962d1 | ||
|
|
db6180b737 | ||
|
|
6918aba90c | ||
|
|
17b8f76dda | ||
|
|
ea3a635d49 | ||
|
|
2ddcaf008b | ||
|
|
99268bfc06 | ||
|
|
19c606e067 | ||
|
|
057029787a | ||
|
|
06cb5ff4c6 | ||
|
|
f67eb47f8c | ||
|
|
7921adbcf9 | ||
|
|
63334ea6fb | ||
|
|
cdfaed4fb4 | ||
|
|
21908e0a03 | ||
|
|
105563ac5a | ||
|
|
c064e5877c | ||
|
|
29a290264e | ||
|
|
08a57d267b | ||
|
|
01df4d3c81 | ||
|
|
6ecb45d661 | ||
|
|
c6b25e5f79 | ||
|
|
39feb335a4 | ||
|
|
b90012e431 | ||
|
|
71599c0f9f | ||
|
|
20a8b3f418 | ||
|
|
3b03b385f3 | ||
|
|
c7592a6dc8 | ||
|
|
8f7de730cc | ||
|
|
e4795cd64b | ||
|
|
fd2ee35e92 | ||
|
|
8404eec301 | ||
|
|
cc252fc70a | ||
|
|
89ecdca5e7 | ||
|
|
1bfc181cb2 | ||
|
|
124fa3c8ed | ||
|
|
28294efadf | ||
|
|
829c358f10 | ||
|
|
35a9fab3b4 | ||
|
|
4e2ebe5a69 | ||
|
|
366d5108c4 | ||
|
|
7dc7cea31b | ||
|
|
32c330092a | ||
|
|
36e2cb6f68 | ||
|
|
cebb5fc1fe | ||
|
|
1ad2495896 | ||
|
|
e82cb2188e | ||
|
|
680f6409d8 | ||
|
|
cfacac7dbf | ||
|
|
8ce1a4c3df | ||
|
|
6ee9152b21 | ||
|
|
d8dd509a7b | ||
|
|
4c5c1d49c2 | ||
|
|
8ba1cb329d | ||
|
|
a28160bcaa | ||
|
|
c9925eddb6 | ||
|
|
5946f20783 | ||
|
|
a4a98e3ada | ||
|
|
a01c7e2c60 | ||
|
|
2bf0aba48a | ||
|
|
7030f85826 | ||
|
|
5066819c58 | ||
|
|
5231f5a22b | ||
|
|
de8c3158fe | ||
|
|
04352cce3c | ||
|
|
5315ba7894 | ||
|
|
2ce097ec77 | ||
|
|
d025a2ea36 | ||
|
|
a4d24fd4a7 | ||
|
|
b2867e97bf | ||
|
|
98159eaa1b | ||
|
|
b4fbaaa47c | ||
|
|
df8c591edd | ||
|
|
13f21ef6cd | ||
|
|
55834ba5db | ||
|
|
417d8a777b | ||
|
|
38b008a2ac | ||
|
|
38283882e9 | ||
|
|
85055c1ef9 | ||
|
|
36e87952fa | ||
|
|
d5fa6cefe4 | ||
|
|
12fd87ab85 | ||
|
|
47b42c1c90 | ||
|
|
31abae33a1 | ||
|
|
7b8722df34 | ||
|
|
eda115249a | ||
|
|
aa4c53ec43 | ||
|
|
44d61e0b9d | ||
|
|
c51abd9096 | ||
|
|
320c125d17 | ||
|
|
8b26b7fd48 | ||
|
|
f9c357b52d | ||
|
|
3494702437 | ||
|
|
3100c4afc9 | ||
|
|
60923e81c6 | ||
|
|
06a2f2ad1f | ||
|
|
d02edebb58 | ||
|
|
a9692dbe60 | ||
|
|
bee1dbeea4 | ||
|
|
9ba0c7ebba | ||
|
|
b702bea806 | ||
|
|
ff756a2b1f | ||
|
|
8e6b1be322 | ||
|
|
d74a095186 | ||
|
|
037fc69c34 | ||
|
|
969d9d5f69 | ||
|
|
db9bc24b5f | ||
|
|
86d38efcb2 | ||
|
|
533aeb3f8b | ||
|
|
dcb6642394 | ||
|
|
2589d4e682 | ||
|
|
b2eec9a765 | ||
|
|
e569fdd2c0 | ||
|
|
fff4ad529c | ||
|
|
ab63fa62ea | ||
|
|
30fef7d1fc | ||
|
|
6d7c15aa33 | ||
|
|
be11acb31b | ||
|
|
a9cd4fd3f4 | ||
|
|
1c0e890252 | ||
|
|
190dc793ac | ||
|
|
0c18f44a34 | ||
|
|
0280158138 | ||
|
|
265458ae98 | ||
|
|
a98a21196f | ||
|
|
66c8a21a66 | ||
|
|
4ce1a7eda2 | ||
|
|
83b0cd5706 | ||
|
|
1a1219448a | ||
|
|
f4465dcea2 | ||
|
|
fc0a41e7f8 | ||
|
|
7469f97953 | ||
|
|
80fa44f8bb | ||
|
|
6eae7bd201 | ||
|
|
5879df7d5f | ||
|
|
57b4a7150a | ||
|
|
58dc75fbcf | ||
|
|
d04b9a7f02 | ||
|
|
c2450cd41e | ||
|
|
4922eb3dc5 | ||
|
|
34d94cd2bb | ||
|
|
9bd3647f36 | ||
|
|
79e2d253d4 | ||
|
|
9b08b0ff8c | ||
|
|
b0f3cdad5d | ||
|
|
0561206d91 | ||
|
|
99530728c5 | ||
|
|
99a58b9208 | ||
|
|
816a3c8784 | ||
|
|
570296c29e | ||
|
|
5518144b26 | ||
|
|
e66af5b271 | ||
|
|
7b9da8d941 | ||
|
|
05a7ba4e38 | ||
|
|
f07b0eed61 | ||
|
|
8fdc59c37c | ||
|
|
58b5d4378d | ||
|
|
bd8ec01add | ||
|
|
c0e4b0bbff | ||
|
|
b0bbbf0305 | ||
|
|
6dd78d33ab | ||
|
|
d2983fa5aa | ||
|
|
d680be3626 | ||
|
|
0043edc85f | ||
|
|
a00ea9af99 | ||
|
|
57376ae875 | ||
|
|
7f89b30190 | ||
|
|
6951619c04 | ||
|
|
c19937cf98 | ||
|
|
dbc084dd66 | ||
|
|
3cb0612cc6 | ||
|
|
c6285d8f67 | ||
|
|
0a144708d8 | ||
|
|
410bbcf003 | ||
|
|
c4a1f30b70 | ||
|
|
269b59f8a2 | ||
|
|
ffc1479b1f | ||
|
|
9683916d88 | ||
|
|
74b2b955c9 | ||
|
|
620deb3b6a | ||
|
|
e4fbf2107d | ||
|
|
1db4af50dd | ||
|
|
a5ac742c1f | ||
|
|
183544b959 | ||
|
|
897ab4d782 | ||
|
|
3e36cd3c46 | ||
|
|
f839d6fe41 | ||
|
|
ff9b9d7148 | ||
|
|
b4537c52c1 | ||
|
|
9cbab8d63e | ||
|
|
676f30d9a1 | ||
|
|
d3f917b408 | ||
|
|
faf6f155ca | ||
|
|
4e4b0ed9ff | ||
|
|
95fc9e3a72 | ||
|
|
3ba3e12f93 | ||
|
|
2ab7f6f923 | ||
|
|
d43d68122b | ||
|
|
03fae3953f | ||
|
|
102c5ee81e | ||
|
|
f27e913f67 | ||
|
|
4ef72c6c8f | ||
|
|
a370503eb3 | ||
|
|
e9126aedc3 | ||
|
|
e493776a73 | ||
|
|
a0e32fefd7 | ||
|
|
e606d04098 | ||
|
|
5713af7375 | ||
|
|
1e64d0a3e4 | ||
|
|
e4ab5ceb43 | ||
|
|
ce5baa93b7 | ||
|
|
042323a1a8 | ||
|
|
93938d8597 | ||
|
|
0db60065c0 | ||
|
|
c8c53e2812 | ||
|
|
737bdadbd0 | ||
|
|
53d2bc34fc | ||
|
|
5cc6e6e8f4 | ||
|
|
a27e7e1b9e | ||
|
|
2ba45ef9ad | ||
|
|
59d35b9f8a | ||
|
|
cf6a91e850 | ||
|
|
4e0ed1ec4c | ||
|
|
2ad1c56933 | ||
|
|
4f17339820 | ||
|
|
c019b0d72c | ||
|
|
0fb78727d5 | ||
|
|
2c48968a31 | ||
|
|
f4adf173a2 | ||
|
|
c086558597 | ||
|
|
7c48afd6eb | ||
|
|
e6554db498 | ||
|
|
d25776ddda | ||
|
|
325a588526 | ||
|
|
8c05caba3a | ||
|
|
d3793d180c | ||
|
|
e1e28fa9ff | ||
|
|
e3e559d857 | ||
|
|
708e802570 | ||
|
|
a74dc5ee35 | ||
|
|
7edc89638f | ||
|
|
e4915260e7 | ||
|
|
92ae8de58e | ||
|
|
f81e431032 | ||
|
|
2789316e38 | ||
|
|
f4250d812f | ||
|
|
1fb848e9ed | ||
|
|
2fd0de082c | ||
|
|
7c8677d787 | ||
|
|
347b03d699 | ||
|
|
4c9d1db9d5 | ||
|
|
8fdd614673 | ||
|
|
0bdb10cdbe | ||
|
|
60c0049bef | ||
|
|
a40c2bfc8f | ||
|
|
a6b037d663 | ||
|
|
e079c87f5c | ||
|
|
22a80fe1c3 | ||
|
|
d762f094f2 | ||
|
|
e916300a6e | ||
|
|
99959b1aa3 | ||
|
|
38c6c63924 | ||
|
|
3d7540dafe | ||
|
|
86a0e68f46 | ||
|
|
eb3db365e7 | ||
|
|
2dea5f2ff8 | ||
|
|
766be4b381 | ||
|
|
d0bf8b5b04 | ||
|
|
8df61db644 | ||
|
|
f0353e50b2 | ||
|
|
28ea505088 | ||
|
|
8c5d38400a | ||
|
|
eed49c10ce | ||
|
|
0a2ab16e4c | ||
|
|
dda4ffed08 | ||
|
|
54f9375b32 | ||
|
|
8d667310e3 | ||
|
|
a4371e7f55 | ||
|
|
a5b8d3c730 | ||
|
|
09c97decb6 | ||
|
|
c2fc03b0d7 | ||
|
|
5622fd0991 | ||
|
|
1712a7c776 | ||
|
|
9f3b9da24a | ||
|
|
18ec98c3fb | ||
|
|
c8e4894d85 | ||
|
|
4657ee9087 | ||
|
|
97aed61fc8 | ||
|
|
c11e5e8b12 | ||
|
|
3a727dea28 | ||
|
|
107d2c8e7b | ||
|
|
b1ed521d6b | ||
|
|
e2427a4ce2 | ||
|
|
d12e510fad | ||
|
|
9bde00b7de | ||
|
|
611b9424ee | ||
|
|
0ec6af03c0 | ||
|
|
80f61880b7 | ||
|
|
92541b779c | ||
|
|
f5a4190e4b | ||
|
|
6ae1564136 | ||
|
|
e361ef5543 | ||
|
|
dfa9965ed3 | ||
|
|
dcc54a7f35 | ||
|
|
478a275bb5 | ||
|
|
8c30ee3403 | ||
|
|
cf002e5ab2 | ||
|
|
09ca6e97b8 | ||
|
|
dfa58f909b | ||
|
|
d925efb928 | ||
|
|
1910ee20dd | ||
|
|
faaa700270 | ||
|
|
d0e2e9c85f | ||
|
|
55538934e0 | ||
|
|
ee4a4c81bf | ||
|
|
568b2ddf75 | ||
|
|
8755ebba01 | ||
|
|
18b41d07bd | ||
|
|
614606e3be | ||
|
|
0aa4651657 | ||
|
|
841e6549c0 | ||
|
|
3ec647cfda | ||
|
|
e6fca96d0d | ||
|
|
5e73539393 | ||
|
|
68b867e480 | ||
|
|
4a671dba9e | ||
|
|
ef1f030076 | ||
|
|
341225aff4 | ||
|
|
2d9f688d56 | ||
|
|
3b63d34f34 | ||
|
|
c39da36cca | ||
|
|
c4b49a6d96 | ||
|
|
68e78a7d24 | ||
|
|
8b9a15d4f2 | ||
|
|
71dd59f5bc | ||
|
|
4b03220064 | ||
|
|
7fad742e99 | ||
|
|
fe70d5ecaa | ||
|
|
89022a5065 | ||
|
|
a0d107a0e8 | ||
|
|
e71252306a | ||
|
|
f86037865d | ||
|
|
1cff97f65d | ||
|
|
e3228a9699 | ||
|
|
407ae8d01b | ||
|
|
b3b1bcc60c | ||
|
|
2196fcc911 | ||
|
|
2985fa921a | ||
|
|
9808e5a37a | ||
|
|
ff70dc7c83 | ||
|
|
9093f8e44a | ||
|
|
f8eea3b779 | ||
|
|
85fa92ca12 | ||
|
|
44bfb1e376 | ||
|
|
06378e09be | ||
|
|
2c6b66a834 | ||
|
|
9a4466e74f | ||
|
|
f482496a61 | ||
|
|
6802e22f7e | ||
|
|
79253c76f1 | ||
|
|
5fc754520a | ||
|
|
43bced2e04 | ||
|
|
65468d7826 | ||
|
|
1a553b00b0 | ||
|
|
79a3d2e81b | ||
|
|
4ed6f12374 | ||
|
|
4d6afaacfd | ||
|
|
7d8d4e7ee5 | ||
|
|
3fa88436c3 | ||
|
|
191ac5eeac | ||
|
|
2ce51400aa | ||
|
|
d5aea98f80 | ||
|
|
85fd33a619 | ||
|
|
ada614a956 | ||
|
|
45d51e1d44 | ||
|
|
9c83c195e3 | ||
|
|
ec3f878372 | ||
|
|
9885169baf | ||
|
|
00afd6b635 | ||
|
|
ff3575c7ac | ||
|
|
66201a2853 | ||
|
|
eb85389c0a | ||
|
|
f7c4411c9a | ||
|
|
36d073d597 | ||
|
|
658771612a | ||
|
|
7f7fb2354f | ||
|
|
c146f6d0d9 | ||
|
|
923bba95b4 | ||
|
|
ee594400dc | ||
|
|
77b998c438 | ||
|
|
cf2bc1e980 | ||
|
|
ab4ad0b114 | ||
|
|
dc4acc83a5 | ||
|
|
7263867f14 | ||
|
|
cfe979c8dd | ||
|
|
762df4b914 | ||
|
|
4a57037c47 | ||
|
|
bfe7010350 | ||
|
|
76708c96df | ||
|
|
e0261295db | ||
|
|
953a99ee90 | ||
|
|
e3f3293461 | ||
|
|
8e8ffae57a | ||
|
|
30d328774f | ||
|
|
e1660e592b | ||
|
|
6428fd4ae0 | ||
|
|
b08d08512f | ||
|
|
a25cc14af4 | ||
|
|
30aa59f582 | ||
|
|
3933d78da2 | ||
|
|
a9ed013ca3 | ||
|
|
b198494900 | ||
|
|
216e9a9785 | ||
|
|
c627c9b540 | ||
|
|
359dcd3b99 | ||
|
|
0eaa592086 | ||
|
|
62b61750d1 | ||
|
|
3e1f7d2193 | ||
|
|
8980905c24 | ||
|
|
f3f71e5d14 | ||
|
|
2a9d2a4910 | ||
|
|
59c6f469a0 | ||
|
|
4473b7917b | ||
|
|
3dbb958bde | ||
|
|
f81481c50f | ||
|
|
485c6b80af | ||
|
|
b8d5793ab7 | ||
|
|
933957282b | ||
|
|
381ae195b9 | ||
|
|
d323dcd4e0 | ||
|
|
1ae635a8b5 | ||
|
|
d3eda2e8be | ||
|
|
adf91c95d3 | ||
|
|
eddee2a0d5 | ||
|
|
ff0dd88ee1 | ||
|
|
81d05a67b3 | ||
|
|
a0743c0713 | ||
|
|
8c9ce5dd45 | ||
|
|
4727cd57ed | ||
|
|
775afd6ac2 | ||
|
|
a615038498 | ||
|
|
cd70dcc3ba | ||
|
|
5c53c457e5 | ||
|
|
6d0b550f5d | ||
|
|
37027c0480 | ||
|
|
13aa2cfa6e | ||
|
|
c832d91f79 | ||
|
|
c6c4bc1277 | ||
|
|
2ab2e5a40f | ||
|
|
732cc41be4 | ||
|
|
2f0bee3b19 | ||
|
|
ab1d664f07 | ||
|
|
95bc8e513a | ||
|
|
da2602a632 | ||
|
|
178a2046dc | ||
|
|
d90e4286e3 | ||
|
|
5d0e466d6d | ||
|
|
622fb85f60 | ||
|
|
0ebdd34df3 | ||
|
|
81eee7bba2 | ||
|
|
5ddc3467f8 | ||
|
|
76d9a230c0 | ||
|
|
b3e6f341ff | ||
|
|
6c8f0bff13 | ||
|
|
456f57e32f | ||
|
|
4ca852c2b3 | ||
|
|
3ff075c048 | ||
|
|
ebc9d62f69 | ||
|
|
fd3e60bce1 | ||
|
|
3f01be8d6e | ||
|
|
3ea7685405 | ||
|
|
fa2815df49 | ||
|
|
01dd57a5fb | ||
|
|
a5ebc85bdb | ||
|
|
04a716ac91 | ||
|
|
fc10f3c4cd | ||
|
|
682196543f | ||
|
|
2772a41917 | ||
|
|
0dc4bdd646 | ||
|
|
78916bba41 | ||
|
|
e8e40c7bcf | ||
|
|
47db3386aa | ||
|
|
92f840519c | ||
|
|
e0a0a0beb1 | ||
|
|
d778766e29 | ||
|
|
371dcb0a45 | ||
|
|
9408e8006d | ||
|
|
2e4b7b375b | ||
|
|
868d7cee4a | ||
|
|
e8cc751f22 | ||
|
|
26e0c5d4ea | ||
|
|
ef71b122df | ||
|
|
98ecb97790 | ||
|
|
86cfe82b89 | ||
|
|
1502bcb5d4 | ||
|
|
d2d3968b8b | ||
|
|
1256da9bd5 | ||
|
|
1f6948d260 | ||
|
|
ab18594e00 | ||
|
|
3467d68020 | ||
|
|
db7c7bd21a | ||
|
|
f785888213 | ||
|
|
a346d49b60 | ||
|
|
5dacf4755e | ||
|
|
3e5f36dc97 | ||
|
|
db55b72d87 | ||
|
|
95844ce045 | ||
|
|
4bf4ed0f00 | ||
|
|
1d2d91d091 | ||
|
|
40239f5cb2 | ||
|
|
488e9d77b8 | ||
|
|
85a5041a35 | ||
|
|
fd2d2ddc0b | ||
|
|
f8e7687551 | ||
|
|
5140f42cb1 | ||
|
|
59e1e0bbf0 | ||
|
|
d53e85a232 | ||
|
|
cf36db16ba | ||
|
|
5adf3f023d | ||
|
|
a0e49f8162 | ||
|
|
92eed29ded |
6
AUTHORS
@@ -1 +1,5 @@
|
||||
Christophe Dumez <chris@qbittorrent.org>
|
||||
Author:
|
||||
* Christophe Dumez <chris@qbittorrent.org>
|
||||
|
||||
Contributors:
|
||||
* Arnaud Demaizière <arnaud@qbittorrent.org>
|
||||
|
||||
98
Changelog
@@ -1,18 +1,92 @@
|
||||
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.0.0
|
||||
- FEATURE: Based on new libtorrent v0.13
|
||||
- FEATURE: Added UPnP / NAT-PMP port forwarding support
|
||||
- FEATURE: Added encryption support (compatible with Azureus)
|
||||
- FEATURE: Bittorrent FAST extension support
|
||||
- FEATURE: Added RSS support
|
||||
- FEATURE: Support files prioritizing in a torrent
|
||||
- FEATURE: Brand new search engine plugins system
|
||||
- FEATURE: Filtered files don't appear on hard disk anymore
|
||||
- FEATURE: Finished torrents are now moved to another tab for seeding
|
||||
- FEATURE: Display more infos about the torrent in its properties
|
||||
- FEATURE: Allow the user to edit torrents' trackers
|
||||
- FEATURE: Allow user to change qBT's style (Plastique, Cleanlooks, Motif, CDE, MacOSX, WinXP)
|
||||
- FEATURE: Allow the user to disable system tray integration
|
||||
- FEATURE: Search engine is now using one thread per website for faster results
|
||||
- FEATURE: Improved a lot the torrent creation module
|
||||
- FEATURE: Allow to set upload/download limit per torrent (right click)
|
||||
- FEATURE: Ask for exit confirmation only if download list is not empty
|
||||
- FEATURE: Allow to use a proxy for trackers / web seeds / peers / DHT connections
|
||||
- FEATURE: Supports SOCKS5 proxies as well as HTTP ones
|
||||
- FEATURE: Better systems integration (buttons, dialogs...)
|
||||
- FEATURE: Filtered files are not allocated on the hard-drive anymore (sparse file support)
|
||||
- FEATURE: IPs blocked by filter are now logged in GUI
|
||||
- FEATURE: Added a way to link against static libtorrent (useful for deb packages)
|
||||
- FEATURE: Allow to set global upload/download limits from tray icon menu
|
||||
- FEATURE: IPv6 is now fully supported
|
||||
- FEATURE: Real torrent share ratio is now displayed in transfer list
|
||||
- FEATURE: Added keyboard shortcuts for main actions (see wiki)
|
||||
- FEATURE: Added a popup menu to set priority for multiple files at once
|
||||
- FEATURE: Improved a lot downloading from urls (using libcommoncpp2 instead of libcurl)
|
||||
- FEATURE: A search request can now be terminated by another
|
||||
- FEATURE: User is now warned when fast resume data was rejected
|
||||
- FEATURE: Url seeds are now displayed in torrent properties and are editable
|
||||
- FEATURE: Allow to drag 'n drop urls on the main window
|
||||
- FEATURE: Improved search engine (multipage support in all plugins)
|
||||
- FEATURE: Added BTJunkie search engine plugin
|
||||
- FEATURE: Added an option to force full disk allocation for all torrents
|
||||
- FEATURE: Added an option to add torrents in paused state
|
||||
- FEATURE: Added an option to set the max number of connections per torrent
|
||||
- FEATURE: Added an option to set the max number of uploads per torrent
|
||||
- FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0)
|
||||
- FEATURE: Added an option to display current transfer speeds in title bar
|
||||
- FEATURE: Torrent content is now displayed as a tree
|
||||
- I18N: Added Hungarian translation
|
||||
- I18N: Added Brazilian translation
|
||||
- BUGFIX: Progress of paused torrents is now correct on restart
|
||||
- BUGFIX: Progress column gets sorted on restart it is was during last execution
|
||||
- BUGFIX: Made ETA more reliable using stats instead of instant values
|
||||
- BUGFIX: Remove torrent from hard drive used to delete parent folder if empty
|
||||
- BUGFIX: Fixed a crash when filtering all the files in a torrent
|
||||
- BUGFIX: Reload torrent only when necessary (properties)
|
||||
- BUGFIX: qBittorrent is not exiting anymore when a dialog is closed and main window is hidden
|
||||
- BUGFIX: Search plugin update is not making the GUI freeze anymore (moved to a thread)
|
||||
- BUGFIX: DHT settings were not saved correctly
|
||||
- BUGFIX: Workaround to build on Fedora system (pkg-config problem)
|
||||
- BUGFIX: search plugin update - do not display only last version changelog
|
||||
- BUGFIX: Search plugin update - fixed missing new lines in changelog
|
||||
- BUGFIX: The number of search results was not reset when clicking on 'Clear' button
|
||||
- BUGFIX: Update torrent progress when its content changed (filtered files)
|
||||
- BUGFIX: Improved the way menu icons are installed to avoid problems on some systems
|
||||
- BUGFIX: Improved incremental download
|
||||
- BUGFIX: Improved unicode support
|
||||
- BUGFIX: Made torrent deletion from hard-drive safer
|
||||
- BUGFIX: Prevent downloadFromUrl flooding
|
||||
- BUGFIX: ETA was wrong for torrents with filtered files
|
||||
- BUGFIX: Fixed drag'n drop on non-KDE systems
|
||||
- COSMETIC: Redesigned torrent properties a little
|
||||
- COSMETIC: Totally redesigned program preferences
|
||||
- COSMETIC: Display more logs messages concerning features
|
||||
- COSMETIC: Improved lists renderers
|
||||
- COSMETIC: Use a different icon for torrents being checked and for connecting ones
|
||||
- COSMETIC: Improved some icons
|
||||
- COSMETIC: Improved systray tooltip style
|
||||
|
||||
* Mon May 07 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.3
|
||||
- BUGFIX: Fixed pause toggle on double-click in download list
|
||||
- BUGFIX: The torrent size displayed now only takes unfiltered files into account
|
||||
- BUGFIX: Fixed compiling errors with libtorrent svn (future v0.13 with UPnP enabled)
|
||||
- BUGFIX: Remember sorted column in download list on restart
|
||||
- BUGFIX: Small fix in the german translation
|
||||
- BUGFIX: Some fixes in slovak translation
|
||||
- BUGFIX: Fixed pause toggle on double-click in download list
|
||||
- BUGFIX: The torrent size displayed now only takes unfiltered files into account
|
||||
- BUGFIX: Fixed compiling errors with libtorrent svn (future v0.13 with UPnP enabled)
|
||||
- BUGFIX: Remember sorted column in download list on restart
|
||||
- BUGFIX: Small fix in the german translation
|
||||
- BUGFIX: Some fixes in slovak translation
|
||||
|
||||
* Tue Apr 10 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.2
|
||||
- BUGFIX: Window can now stay maximized on exit
|
||||
- BUGFIX: Use PKGCONFIG again for configuring libtorrent
|
||||
- BUGFIX: Allow to compile with libtorrent v0.11
|
||||
- BUGFIX: Disabled main window context menu (annoying)
|
||||
- I18N: Added Japanese translation
|
||||
- I18N: Updated Turkish translation
|
||||
- BUGFIX: Window can now stay maximized on exit
|
||||
- BUGFIX: Use PKGCONFIG again for configuring libtorrent
|
||||
- BUGFIX: Allow to compile with libtorrent v0.11
|
||||
- BUGFIX: Disabled main window context menu (annoying)
|
||||
- I18N: Added Japanese translation
|
||||
- I18N: Updated Turkish translation
|
||||
|
||||
* Wed Apr 04 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.1
|
||||
- BUGFIX: A lot of fixes in configure file
|
||||
|
||||
28
INSTALL
@@ -1,4 +1,4 @@
|
||||
qBittorrent - A BitTorrent client in C++ / Qt4.2
|
||||
qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
------------------------------------------
|
||||
|
||||
*** Necessary if qt3 is default on your system ***
|
||||
@@ -14,23 +14,33 @@ qbittorrent
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
|
||||
Dependencies:
|
||||
- Qt >= 4.2 (libqt-devel, libqtgui, libqtcore, libqtnetwork)
|
||||
- Qt >= 4.3.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
|
||||
|
||||
- libtorrent by Arvid Norberg (>= v0.11 REQUIRED, >= 0.12 ADVISED)
|
||||
-> http://libtorrent.sf.net
|
||||
Be carefull: another library (the one used by rtorrent) use the same name.
|
||||
- rblibtorrent by Arvid Norberg (>= v0.13 REQUIRED)
|
||||
-> http://www.qbittorrent.org/download.php (advised)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) use the same name.
|
||||
These are TWO different libraries and qBittorrent will only work with the one provided
|
||||
on sourceforge (created by Arvid Norberg). The two libraries conflicts with each other.
|
||||
|
||||
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
||||
|
||||
- libcurl
|
||||
- libcommoncpp2
|
||||
|
||||
- python >= 2.3 (previous might work - not tested): needed by search engine.
|
||||
- python >= 2.3 (needed by search engine)
|
||||
|
||||
NOTE FOR GNOME USERS:
|
||||
- qt4-qtconfig package is advised or qBittorrent interface will be ugly
|
||||
- libmagick++ (advised, not required)
|
||||
* Needed for favicons support (RSS / Search plugins)
|
||||
|
||||
- libzzip (advised, not required)
|
||||
* Needed for zip support (Search plugins)
|
||||
|
||||
NOTE FOR NON-KDE USERS:
|
||||
- qt4-qtconfig package is advised when using other systems than KDE.
|
||||
You can also change qBittorrent style to Cleanlooks (GNOME like)
|
||||
|
||||
DOCUMENTATION:
|
||||
Please note that there is a documentation with a "compiling howto" at http://wiki.qbittorrent.org.
|
||||
|
||||
------------------------------------------
|
||||
Christophe Dumez <chris@qbittorrent.org>
|
||||
|
||||
16
README
@@ -1,32 +1,32 @@
|
||||
qBittorrent - A BitTorrent client in Qt4.2
|
||||
qBittorrent - A BitTorrent client in Qt4
|
||||
------------------------------------------
|
||||
|
||||
Description:
|
||||
********************************
|
||||
qBittorrent is a bittorrent client programmed in C++ / Qt4.2 that use
|
||||
libtorrent (sometimes called rb_libtorrent) by Arvid Norberg.
|
||||
qBittorrent is a bittorrent client programmed in C++ / Qt4 that uses
|
||||
libtorrent (sometimes called rblibtorrent) by Arvid Norberg.
|
||||
|
||||
It aims to be a good alternative to all other bittorrent clients
|
||||
out there. qBittorrent is fast, stable and provides unicode
|
||||
support.
|
||||
support as well as many features.
|
||||
|
||||
Installation:
|
||||
********************************
|
||||
For installation follow the instructions from INSTALL file, but simple
|
||||
For installation, follow the instructions from INSTALL file, but simple:
|
||||
|
||||
./configure
|
||||
make && make install
|
||||
qbittorrent
|
||||
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
will install and execute qBittorrent hopefully without any problem.
|
||||
|
||||
For more information please visit:
|
||||
http://www.qbittorrent.org
|
||||
|
||||
Please report any bug (or feature requests) to:
|
||||
Please report any bug (or feature request) to:
|
||||
http://bugs.qbittorrent.org
|
||||
|
||||
You can also meet me on IRC:
|
||||
You can also meet me (chris-qBT) on IRC:
|
||||
#qbittorrent on irc.freenode.net
|
||||
|
||||
------------------------------------------
|
||||
|
||||
75
TODO
@@ -1,38 +1,67 @@
|
||||
// Easy
|
||||
- Write documentation
|
||||
- Translations into as many languages as possible
|
||||
- Improve man page
|
||||
- Add more keyboard shortcuts
|
||||
- Use Launchpad/Rosetta for translations once it supports TS files
|
||||
|
||||
// Intermediate
|
||||
- Port on MacOS, Windows (and create an installer for Windows) - Progressing
|
||||
- Add some transparency (menus,...)
|
||||
- Add upnp port forwarding support
|
||||
- Port on MacOS, Windows (and create an installer for Windows) - Slow progress
|
||||
- Add some transparency (menus,...), improve look / usabilty
|
||||
- Skins support? (contact Mateusz)
|
||||
|
||||
// Harder
|
||||
- Allow user to organize the downloads into categories/folders
|
||||
- Display new searches in new tabs
|
||||
- Display a progress bar that really displays the pieces we have (like in eMule)
|
||||
- Display a progress bar that really represents the pieces we have (like in eMule)
|
||||
- Torrent scheduler ala µtorrent/Bitcomet
|
||||
|
||||
// Waiting for libtorrent
|
||||
- Encryption support (v0.13?)
|
||||
- File selection in a torrent in compact mode
|
||||
- Allow to prioritize files within a torrent
|
||||
- Allow to prioritize torrents
|
||||
- Allow to prioritize torrents (may code this in qBittorrent?)
|
||||
|
||||
// Unsure
|
||||
- Display the peers we are connected to for each torrent with infos (like flag, dl/up speeds, ...)
|
||||
- Azureus spoofing to prevent ban from trackers?
|
||||
- Web interface?
|
||||
- Use downloader class to download search plugin updates
|
||||
- Allow to set upload limit for each torrent
|
||||
- Option to shutdown computer when downloads are finished
|
||||
- Add a torrent scheduler
|
||||
- NAT checker/Tester
|
||||
- Display hard drive space left?
|
||||
- Make use of dbus on Linux for the single instance instead of socket communication?
|
||||
(http://techbase.kde.org/Development/Tutorials/D-Bus/Accessing_Interfaces)
|
||||
- When favicon can't be downloaded, try to parse the webpage for:
|
||||
<link rel="icon" href="http://example.com/favicon.ico" type="image/vnd.microsoft.icon">
|
||||
* Be carefull, the link can be relative
|
||||
|
||||
// in v1.0.0 (partial)
|
||||
- Download from RSS feeds (WIP by gtsoul)
|
||||
- Move finished torrent to another tab and keep on seeding them even after restart
|
||||
- Allow to edit the trackers for a torrent
|
||||
- Improve torrent creation dialog (look & features)
|
||||
- Add IPv6 support (at least start working on it)
|
||||
- UPnP support?
|
||||
// in v1.2.0
|
||||
- Allow user to organize the downloads into categories/folders?
|
||||
|
||||
// in v1.1.0
|
||||
- Tabs support in search
|
||||
- Allow to hide columns?
|
||||
- Allow to scan multiple directories? (useful?)
|
||||
- Web interface (turbogears? php? python?)
|
||||
* Webserver? Try to write a webserver as a plugin for qBittorrent in Python
|
||||
* http://fragments.turtlemeat.com/pythonwebserver.php
|
||||
- improve and test tracker authentication code (remember login/pass) (need a tracker to test this)
|
||||
- support zipped torrents? (useful?)
|
||||
- Allow to limit the number of downloading torrents simultaneously (other are paused until a download finishes)
|
||||
- Improve search plugin install (choose in a list taken from plugins.qbittorrent.org)
|
||||
- Display the number of DHT node if possible
|
||||
- When adding a duplicate torrent, check if the trackers are different from the existing one and ask the user if he wants to add them
|
||||
- Display in torrent addition dialog:
|
||||
* free disk space on selected drive
|
||||
* free disk space after torrent download (and/or torrent size)
|
||||
- Allow to change action on double-click
|
||||
-> in download list
|
||||
-> in seeding list
|
||||
|
||||
// in v1.0.0 - FEATURE FREEZE
|
||||
- Fix all (or almost all) opened bugs in bug tracker
|
||||
- Recheck doc
|
||||
- Translations update (IN PROGRESS)
|
||||
- add qt4-qtconfig as package dependency
|
||||
|
||||
rc4->rc5 changelog:
|
||||
- BUGFIX: Now filtered don't appear on hard drive anymore (libtorrent >= r1659)
|
||||
- BUGFIX: AddInPause setting doesn't pause downloads on startup anymore
|
||||
- BUGFIX: Fixed an ETA calculation problem when the torrent has filtered files
|
||||
- BUGFIX: Fixed possible overflow in ETA calculation
|
||||
- BUGFIX: Fixed "Missing Input path" error when creating a torrent
|
||||
- BUGFIX: Fixed some notification messages for torrent addition dialog
|
||||
- BUGFIX: Fixed "Automatically start seeding" feature in torrent creation tool
|
||||
- COSMETIC: Improved progress bar text rendering
|
||||
474
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Generated by qconf 1.3 ( http://delta.affinix.com/qconf/ )
|
||||
# Generated by qconf 1.4 ( http://delta.affinix.com/qconf/ )
|
||||
#
|
||||
|
||||
show_usage() {
|
||||
@@ -18,11 +18,18 @@ Main options:
|
||||
--help This help text.
|
||||
|
||||
Dependency options:
|
||||
--with-libtorrent-inc=[path] Path to libtorrent include files
|
||||
--with-libtorrent-lib=[path] Path to libtorrent library files
|
||||
--with-libboost-inc=[path] Path to libboost include files
|
||||
--with-libcurl-inc=[path] Path to libcurl include files
|
||||
--with-libcurl-lib=[path] Path to libcurl library files
|
||||
--with-libtorrent-inc=[path] Path to libtorrent include files
|
||||
--with-libtorrent-lib=[path] Path to libtorrent library files
|
||||
--with-libtorrent-static-lib=[path] Path to libtorrent .a file
|
||||
--with-libboost-inc=[path] Path to libboost include files
|
||||
--with-libcommoncpp2-inc=[path] Path to libcommoncpp2 include files
|
||||
--with-libcommoncpp2-lib=[path] Path to libcommoncpp2 library files
|
||||
--disable-libmagick Disable use of libmagick
|
||||
--with-libmagick-inc=[path] Path to libmagick++ include files
|
||||
--with-libmagick-lib=[path] Path to libmagick++ library files
|
||||
--disable-libzzip Disable use of libzzip
|
||||
--with-libzzip-inc=[path] Path to libzzip++ include files
|
||||
--with-libzzip-lib=[path] Path to libzzip++ library files
|
||||
|
||||
EOT
|
||||
}
|
||||
@@ -149,23 +156,58 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-static-lib=*)
|
||||
QC_WITH_LIBTORRENT_STATIC_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libboost-inc=*)
|
||||
QC_WITH_LIBBOOST_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libcurl-inc=*)
|
||||
QC_WITH_LIBCURL_INC=$optarg
|
||||
--with-libcommoncpp2-inc=*)
|
||||
QC_WITH_LIBCOMMONCPP2_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libcurl-lib=*)
|
||||
QC_WITH_LIBCURL_LIB=$optarg
|
||||
--with-libcommoncpp2-lib=*)
|
||||
QC_WITH_LIBCOMMONCPP2_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-libmagick)
|
||||
QC_DISABLE_libmagick="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libmagick-inc=*)
|
||||
QC_WITH_LIBMAGICK_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libmagick-lib=*)
|
||||
QC_WITH_LIBMAGICK_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--disable-libzzip)
|
||||
QC_DISABLE_libzzip="Y"
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libzzip-inc=*)
|
||||
QC_WITH_LIBZZIP_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libzzip-lib=*)
|
||||
QC_WITH_LIBZZIP_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--verbose)
|
||||
QC_DEBUG="Y"
|
||||
QC_VERBOSE="Y"
|
||||
shift
|
||||
;;
|
||||
--help) show_usage; exit ;;
|
||||
@@ -179,7 +221,7 @@ DATADIR=${DATADIR:-$PREFIX/share}
|
||||
|
||||
echo "Configuring qbittorrent ..."
|
||||
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo
|
||||
echo PREFIX=$PREFIX
|
||||
echo BINDIR=$BINDIR
|
||||
@@ -187,39 +229,65 @@ echo DATADIR=$DATADIR
|
||||
echo EX_QTDIR=$EX_QTDIR
|
||||
echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
|
||||
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
|
||||
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
|
||||
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
|
||||
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
|
||||
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
|
||||
echo QC_WITH_LIBCOMMONCPP2_INC=$QC_WITH_LIBCOMMONCPP2_INC
|
||||
echo QC_WITH_LIBCOMMONCPP2_LIB=$QC_WITH_LIBCOMMONCPP2_LIB
|
||||
echo QC_DISABLE_libmagick=$QC_DISABLE_libmagick
|
||||
echo QC_WITH_LIBMAGICK_INC=$QC_WITH_LIBMAGICK_INC
|
||||
echo QC_WITH_LIBMAGICK_LIB=$QC_WITH_LIBMAGICK_LIB
|
||||
echo QC_DISABLE_libzzip=$QC_DISABLE_libzzip
|
||||
echo QC_WITH_LIBZZIP_INC=$QC_WITH_LIBZZIP_INC
|
||||
echo QC_WITH_LIBZZIP_LIB=$QC_WITH_LIBZZIP_LIB
|
||||
echo
|
||||
fi
|
||||
|
||||
printf "Verifying Qt 4 build environment ... "
|
||||
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
# run qmake -v and check version
|
||||
qmake_check_v4() {
|
||||
if [ -x "$1" ]; then
|
||||
if echo `$1 -v 2>&1` | grep "Qt version 4\." >/dev/null 2>&1; then
|
||||
return 0
|
||||
elif [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "Warning: $1 not for Qt 4"
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
qm=""
|
||||
names="qmake-qt4 qmake4 qmake"
|
||||
|
||||
# qt4 check: --qtdir
|
||||
if [ -z "$qm" ]; then
|
||||
qstr=$EX_QTDIR/bin/qmake
|
||||
if [ -x "$qstr" ]; then
|
||||
qm=$qstr
|
||||
fi
|
||||
if [ -z "$qm" ] && [ ! -z "$EX_QTDIR" ]; then
|
||||
for n in $names; do
|
||||
qstr=$EX_QTDIR/bin/$n
|
||||
if qmake_check_v4 "$qstr"; then
|
||||
qm=$qstr
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "Warning: qmake not found via --qtdir"
|
||||
fi
|
||||
|
||||
# qt4 check: QTDIR
|
||||
if [ -z "$qm" ]; then
|
||||
qstr=$QTDIR/bin/qmake
|
||||
if [ -x "$qstr" ]; then
|
||||
qm=$qstr
|
||||
fi
|
||||
if [ -z "$qm" ] && [ ! -z "$QTDIR" ]; then
|
||||
for n in $names; do
|
||||
qstr=$QTDIR/bin/$n
|
||||
if qmake_check_v4 "$qstr"; then
|
||||
qm=$qstr
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "Warning: qmake not found via \$QTDIR"
|
||||
fi
|
||||
|
||||
@@ -227,60 +295,66 @@ fi
|
||||
if [ -z "$qm" ]; then
|
||||
str=`pkg-config QtCore --variable=exec_prefix 2>/dev/null`
|
||||
if [ ! -z "$str" ]; then
|
||||
qstr=$str/bin/qmake
|
||||
if [ -x "$qstr" ]; then
|
||||
qm=$qstr
|
||||
fi
|
||||
for n in $names; do
|
||||
qstr=$str/bin/$n
|
||||
if qmake_check_v4 "$qstr"; then
|
||||
qm=$qstr
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "Warning: qmake not found via pkg-config"
|
||||
fi
|
||||
|
||||
# qt4 check: PATH
|
||||
if [ -z "$qm" ]; then
|
||||
qstr=`$WHICH qmake 2>/dev/null`
|
||||
if [ -x "$qstr" ]; then
|
||||
qm=$qstr
|
||||
fi
|
||||
for n in $names; do
|
||||
qstr=`$WHICH $n 2>/dev/null`
|
||||
if qmake_check_v4 "$qstr"; then
|
||||
qm=$qstr
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "Warning: qmake not found via \$PATH"
|
||||
fi
|
||||
|
||||
if [ -z "$qm" ]; then
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo " -> fail"
|
||||
else
|
||||
echo "fail"
|
||||
fi
|
||||
printf "\n"
|
||||
printf "Reason: Unable to find the 'qmake' tool.\n"
|
||||
printf "Reason: Unable to find the 'qmake' tool for Qt 4.\n"
|
||||
printf "\n"
|
||||
show_qt_info
|
||||
exit 1;
|
||||
fi
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo qmake found in $qm
|
||||
fi
|
||||
|
||||
gen_files() {
|
||||
cat >$1/modules.cpp <<EOT
|
||||
#line 1 "qt42.qcm"
|
||||
#line 1 "qt4.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.2
|
||||
name: Qt >= 4.3
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_qt42 : public ConfObj
|
||||
class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt42(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.2"; }
|
||||
QString shortname() const { return "qt42"; }
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.3"; }
|
||||
QString shortname() const { return "Qt 4.3"; }
|
||||
bool exec()
|
||||
{
|
||||
return(QT_VERSION >= 0x040200);
|
||||
return(QT_VERSION >= 0x040300);
|
||||
}
|
||||
};
|
||||
#line 1 "libtorrent.qcm"
|
||||
@@ -289,51 +363,46 @@ public:
|
||||
name: libtorrent
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libtorrent : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent >= 0.11 (>= 0.12 ADVISED)"; }
|
||||
QString name() const { return "libtorrent >= 0.13"; }
|
||||
QString shortname() const { return "libtorrent"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
|
||||
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")) {
|
||||
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
|
||||
conf->addDefine("NO_PEX");
|
||||
}
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
conf->addDefine("V_0_13");
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")){
|
||||
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
|
||||
conf->addDefine("NO_PEX");
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
conf->addDefine("V_0_13");
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
conf->addIncludePath(s+QDir::separator()+"libtorrent");
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
|
||||
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
|
||||
conf->addLib(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "torrent")) {
|
||||
@@ -354,7 +423,16 @@ public:
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
//conf->addLib("-ltorrent");
|
||||
// BUGFIX for Fedora (doesn't support pkg-config?)
|
||||
QFile issue_file("/etc/issue");
|
||||
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
QString content = issue_file.readAll();
|
||||
issue_file.close();
|
||||
if(content.indexOf("Fedora") != -1){
|
||||
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
|
||||
conf->addLib("-lssl -lcrypto -lboost_date_time -lboost_filesystem -lboost_thread -lz -ltorrent");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -415,65 +493,225 @@ public:
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "libcurl.qcm"
|
||||
#line 1 "libcommoncpp2.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libcurl
|
||||
arg: with-libcurl-inc=[path], Path to libcurl include files
|
||||
arg: with-libcurl-lib=[path], Path to libcurl library files
|
||||
name: libcommoncpp2
|
||||
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
|
||||
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libcurl : public ConfObj
|
||||
class qc_libcommoncpp2 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libcurl(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libcurl"; }
|
||||
QString shortname() const { return "libcurl"; }
|
||||
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
|
||||
QString shortname() const { return "libcommoncpp2"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBCURL_INC");
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "curl/curl.h")) {
|
||||
if(!conf->checkHeader(s, "cc++/url.h")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "curl/curl.h")){
|
||||
if(conf->checkHeader(s, "cc++/url.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBCURL_LIB");
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "curl")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
if(!QFile::exists(s+QString("libccext2.so")))
|
||||
return false;
|
||||
if(!QFile::exists(s+QString("libccgnu2.so")))
|
||||
return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "curl")){
|
||||
found = true;
|
||||
break;
|
||||
if(QFile::exists(s+QString("libccext2.so"))){
|
||||
if(QFile::exists(s+QString("libccgnu2.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
conf->addLib("-lcurl");
|
||||
// BUGFIX for Fedora (doesn't support pkg-config?)
|
||||
QFile issue_file("/etc/issue");
|
||||
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
QString content = issue_file.readAll();
|
||||
issue_file.close();
|
||||
if(content.indexOf("Fedora") != -1){
|
||||
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
|
||||
conf->addLib("-pthread -lccext2 -lz -lccgnu2 -ldl -lrt");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "libmagick.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libmagick
|
||||
arg: with-libmagick-inc=[path], Path to libmagick++ include files
|
||||
arg: with-libmagick-lib=[path], Path to libmagick++ library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <QProcess>
|
||||
class qc_libmagick : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libmagick(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "ImageMagick library (libmagick++)"; }
|
||||
QString shortname() const { return "libmagick++"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
|
||||
return false;
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBMAGICK_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "Magick++.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "Magick++.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("libMagick++.so"))){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libMagick++.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
QProcess magickConfig;
|
||||
QStringList params;
|
||||
params << "--libs";
|
||||
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
|
||||
magickConfig.waitForStarted();
|
||||
magickConfig.waitForFinished();
|
||||
QByteArray result = magickConfig.readAll();
|
||||
result = result.replace("\n", "");
|
||||
conf->addLib(result.data());
|
||||
conf->addDefine("HAVE_MAGICK");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#line 1 "libzzip.qcm"
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libzzip
|
||||
arg: with-libzzip-inc=[path], Path to libzzip++ include files
|
||||
arg: with-libzzip-lib=[path], Path to libzzip++ library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <QProcess>
|
||||
class qc_libzzip : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libzzip(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Zzip library (libzzip)"; }
|
||||
QString shortname() const { return "libzzip"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
|
||||
return false;
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBZZIP_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "zzip/zzip.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "zzip/zzip.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBZZIP_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("libzzip.so"))){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libzzip.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
conf->addLib("-lzzip");
|
||||
conf->addDefine("HAVE_ZZIP");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -500,7 +738,7 @@ public:
|
||||
|
||||
EOT
|
||||
cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_qt42(conf);
|
||||
o = new qc_qt4(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_libtorrent(conf);
|
||||
@@ -509,15 +747,23 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_libboost(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_libcurl(conf);
|
||||
o = new qc_libcommoncpp2(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
o = new qc_libmagick(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_libzzip(conf);
|
||||
o->required = false;
|
||||
o->disabled = false;
|
||||
o = new qc_python(conf);
|
||||
o->required = true;
|
||||
o->disabled = false;
|
||||
|
||||
EOT
|
||||
cat >$1/conf4.h <<EOT
|
||||
// For license information, see the COPYING file in the qconf base directory.
|
||||
|
||||
#ifndef QC_CONF4_H
|
||||
#define QC_CONF4_H
|
||||
|
||||
@@ -622,6 +868,8 @@ private:
|
||||
|
||||
EOT
|
||||
cat >$1/conf4.cpp <<EOT
|
||||
// For license information, see the COPYING file in the qconf base directory.
|
||||
|
||||
#include "conf4.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -772,6 +1020,18 @@ void qc_splitcflags(const QString &cflags, QStringList *incs, QStringList *other
|
||||
}
|
||||
}
|
||||
|
||||
QString qc_escapeArg(const QString &str)
|
||||
{
|
||||
QString out;
|
||||
for(int n = 0; n < (int)str.length(); ++n) {
|
||||
if(str[n] == '-')
|
||||
out += '_';
|
||||
else
|
||||
out += str[n];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ConfObj
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -888,14 +1148,14 @@ bool Conf::exec()
|
||||
// if this was a disabled-by-default option, check if it was enabled
|
||||
if(o->disabled)
|
||||
{
|
||||
QString v = QString("QC_ENABLE_") + o->shortname();
|
||||
QString v = QString("QC_ENABLE_") + qc_escapeArg(o->shortname());
|
||||
if(getenv(v) != "Y")
|
||||
continue;
|
||||
}
|
||||
// and the opposite?
|
||||
else
|
||||
{
|
||||
QString v = QString("QC_DISABLE_") + o->shortname();
|
||||
QString v = QString("QC_DISABLE_") + qc_escapeArg(o->shortname());
|
||||
if(getenv(v) == "Y")
|
||||
continue;
|
||||
}
|
||||
@@ -1322,7 +1582,7 @@ int main()
|
||||
# include"modules_new.cpp"
|
||||
#endif
|
||||
|
||||
conf->debug_enabled = (qc_getenv("QC_DEBUG") == "Y") ? true: false;
|
||||
conf->debug_enabled = (qc_getenv("QC_VERBOSE") == "Y") ? true: false;
|
||||
if(conf->debug_enabled)
|
||||
printf(" -> ok\n");
|
||||
else
|
||||
@@ -1378,6 +1638,9 @@ int main()
|
||||
var = qc_getenv("BINDIR");
|
||||
if(!var.isEmpty())
|
||||
str += QString("BINDIR = %1\n").arg(var);
|
||||
var = qc_getenv("INCDIR");
|
||||
if(!var.isEmpty())
|
||||
str += QString("INCDIR = %1\n").arg(var);
|
||||
var = qc_getenv("LIBDIR");
|
||||
if(!var.isEmpty())
|
||||
str += QString("LIBDIR = %1\n").arg(var);
|
||||
@@ -1443,10 +1706,17 @@ export DATADIR
|
||||
export EX_QTDIR
|
||||
export QC_WITH_LIBTORRENT_INC
|
||||
export QC_WITH_LIBTORRENT_LIB
|
||||
export QC_WITH_LIBTORRENT_STATIC_LIB
|
||||
export QC_WITH_LIBBOOST_INC
|
||||
export QC_WITH_LIBCURL_INC
|
||||
export QC_WITH_LIBCURL_LIB
|
||||
export QC_DEBUG
|
||||
export QC_WITH_LIBCOMMONCPP2_INC
|
||||
export QC_WITH_LIBCOMMONCPP2_LIB
|
||||
export QC_DISABLE_libmagick
|
||||
export QC_WITH_LIBMAGICK_INC
|
||||
export QC_WITH_LIBMAGICK_LIB
|
||||
export QC_DISABLE_libzzip
|
||||
export QC_WITH_LIBZZIP_INC
|
||||
export QC_WITH_LIBZZIP_LIB
|
||||
export QC_VERBOSE
|
||||
rm -rf .qconftemp
|
||||
(
|
||||
mkdir .qconftemp
|
||||
@@ -1459,7 +1729,7 @@ rm -rf .qconftemp
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
rm -rf .qconftemp
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo " -> fail"
|
||||
else
|
||||
echo "fail"
|
||||
@@ -1468,7 +1738,7 @@ if [ "$?" != "0" ]; then
|
||||
printf "Reason: There was an error compiling 'conf'. See conf.log for details.\n"
|
||||
printf "\n"
|
||||
show_qt_info
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo "conf.log:"
|
||||
cat conf.log
|
||||
fi
|
||||
@@ -1492,7 +1762,7 @@ if [ "$ret" = "1" ]; then
|
||||
else
|
||||
if [ "$ret" != "0" ]; then
|
||||
rm -rf .qconftemp
|
||||
if [ "$QC_DEBUG" = "Y" ]; then
|
||||
if [ "$QC_VERBOSE" = "Y" ]; then
|
||||
echo " -> fail"
|
||||
else
|
||||
echo "fail"
|
||||
|
||||
200
qBittorrent.kdevelop
Normal file
@@ -0,0 +1,200 @@
|
||||
<?xml version = '1.0'?>
|
||||
<kdevelop>
|
||||
<general>
|
||||
<author>Christophe Dumez</author>
|
||||
<email>chris@qbittorrent.org</email>
|
||||
<version>1.0.0</version>
|
||||
<projectmanagement>KDevTrollProject</projectmanagement>
|
||||
<primarylanguage>C++</primarylanguage>
|
||||
<keywords>
|
||||
<keyword>Qt</keyword>
|
||||
</keywords>
|
||||
<projectname>qBittorrent</projectname>
|
||||
<ignoreparts/>
|
||||
<projectdirectory>.</projectdirectory>
|
||||
<absoluteprojectpath>false</absoluteprojectpath>
|
||||
<description/>
|
||||
<defaultencoding/>
|
||||
<versioncontrol>kdevsubversion</versioncontrol>
|
||||
</general>
|
||||
<kdevfileview>
|
||||
<groups>
|
||||
<group pattern="*.cpp;*.cxx;*.h" name="Sources" />
|
||||
<group pattern="*.ui" name="User Interface" />
|
||||
<group pattern="*.png" name="Icons" />
|
||||
<group pattern="*" name="Others" />
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
<hidenonlocation>false</hidenonlocation>
|
||||
</groups>
|
||||
<tree>
|
||||
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
<showvcsfields>false</showvcsfields>
|
||||
</tree>
|
||||
</kdevfileview>
|
||||
<kdevdoctreeview>
|
||||
<ignoretocs>
|
||||
<toc>bash</toc>
|
||||
<toc>bash_bugs</toc>
|
||||
<toc>clanlib</toc>
|
||||
<toc>w3c-dom-level2-html</toc>
|
||||
<toc>fortran_bugs_gcc</toc>
|
||||
<toc>gnome1</toc>
|
||||
<toc>gnustep</toc>
|
||||
<toc>gtk</toc>
|
||||
<toc>gtk_bugs</toc>
|
||||
<toc>haskell</toc>
|
||||
<toc>haskell_bugs_ghc</toc>
|
||||
<toc>java_bugs_gcc</toc>
|
||||
<toc>java_bugs_sun</toc>
|
||||
<toc>kde2book</toc>
|
||||
<toc>opengl</toc>
|
||||
<toc>pascal_bugs_fp</toc>
|
||||
<toc>php</toc>
|
||||
<toc>php_bugs</toc>
|
||||
<toc>perl</toc>
|
||||
<toc>perl_bugs</toc>
|
||||
<toc>python</toc>
|
||||
<toc>python_bugs</toc>
|
||||
<toc>qt-kdev3</toc>
|
||||
<toc>ruby</toc>
|
||||
<toc>ruby_bugs</toc>
|
||||
<toc>sdl</toc>
|
||||
<toc>stl</toc>
|
||||
<toc>w3c-svg</toc>
|
||||
<toc>sw</toc>
|
||||
<toc>w3c-uaag10</toc>
|
||||
<toc>wxwidgets_bugs</toc>
|
||||
</ignoretocs>
|
||||
<ignoredoxygen>
|
||||
<toc>KDE Libraries (Doxygen)</toc>
|
||||
</ignoredoxygen>
|
||||
</kdevdoctreeview>
|
||||
<kdevdebugger>
|
||||
<general>
|
||||
<dbgshell/>
|
||||
<gdbpath/>
|
||||
<configGdbScript/>
|
||||
<runShellScript/>
|
||||
<runGdbScript/>
|
||||
<breakonloadinglibs>true</breakonloadinglibs>
|
||||
<separatetty>false</separatetty>
|
||||
<floatingtoolbar>false</floatingtoolbar>
|
||||
</general>
|
||||
<display>
|
||||
<staticmembers>false</staticmembers>
|
||||
<demanglenames>true</demanglenames>
|
||||
<outputradix>10</outputradix>
|
||||
</display>
|
||||
</kdevdebugger>
|
||||
<kdevcppsupport>
|
||||
<qt>
|
||||
<version>4</version>
|
||||
<used>true</used>
|
||||
<includestyle>4</includestyle>
|
||||
<designerintegration>ExternalDesigner</designerintegration>
|
||||
<root>/usr/lib/qt4</root>
|
||||
<qmake>/usr/bin/qmake-qt4</qmake>
|
||||
<designer>/usr/bin/designer-qt4</designer>
|
||||
<designerpluginpaths/>
|
||||
</qt>
|
||||
<references>
|
||||
<pcs>automatic_%2Fhome%2Fchris%2Fqbittorrent_svn%2Ftrunk</pcs>
|
||||
<pcs>Qt4</pcs>
|
||||
</references>
|
||||
<codecompletion>
|
||||
<automaticCodeCompletion>true</automaticCodeCompletion>
|
||||
<automaticArgumentsHint>true</automaticArgumentsHint>
|
||||
<automaticHeaderCompletion>true</automaticHeaderCompletion>
|
||||
<codeCompletionDelay>250</codeCompletionDelay>
|
||||
<argumentsHintDelay>400</argumentsHintDelay>
|
||||
<headerCompletionDelay>250</headerCompletionDelay>
|
||||
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
|
||||
<completionBoxItemOrder>0</completionBoxItemOrder>
|
||||
<howEvaluationContextMenu>true</howEvaluationContextMenu>
|
||||
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
|
||||
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
|
||||
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
|
||||
<processPrimaryTypes>true</processPrimaryTypes>
|
||||
<processFunctionArguments>true</processFunctionArguments>
|
||||
<preProcessAllHeaders>true</preProcessAllHeaders>
|
||||
<parseMissingHeadersExperimental>true</parseMissingHeadersExperimental>
|
||||
<resolveIncludePathsUsingMakeExperimental>true</resolveIncludePathsUsingMakeExperimental>
|
||||
<alwaysParseInBackground>true</alwaysParseInBackground>
|
||||
<usePermanentCaching>true</usePermanentCaching>
|
||||
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
|
||||
<includePaths>.;</includePaths>
|
||||
</codecompletion>
|
||||
<creategettersetter>
|
||||
<prefixGet>get</prefixGet>
|
||||
<prefixSet>set</prefixSet>
|
||||
<prefixVariable>m_,_</prefixVariable>
|
||||
<parameterName>theValue</parameterName>
|
||||
<inlineGet>true</inlineGet>
|
||||
<inlineSet>true</inlineSet>
|
||||
</creategettersetter>
|
||||
<splitheadersource>
|
||||
<enabled>false</enabled>
|
||||
<synchronize>true</synchronize>
|
||||
<orientation>Vertical</orientation>
|
||||
</splitheadersource>
|
||||
</kdevcppsupport>
|
||||
<kdevfilecreate>
|
||||
<filetypes/>
|
||||
<useglobaltypes>
|
||||
<type ext="ui" />
|
||||
<type ext="cpp" />
|
||||
<type ext="h" />
|
||||
</useglobaltypes>
|
||||
</kdevfilecreate>
|
||||
<kdevtrollproject>
|
||||
<general>
|
||||
<activedir></activedir>
|
||||
</general>
|
||||
<run>
|
||||
<directoryradio>executable</directoryradio>
|
||||
<mainprogram>/home/chris/qbittorrent_svn/trunk/src/qbittorrent</mainprogram>
|
||||
<programargs/>
|
||||
<globaldebugarguments/>
|
||||
<globalcwd>/home/chris/qbittorrent_svn/trunk</globalcwd>
|
||||
<useglobalprogram>true</useglobalprogram>
|
||||
<terminal>false</terminal>
|
||||
<autocompile>true</autocompile>
|
||||
<autoinstall>false</autoinstall>
|
||||
<autokdesu>false</autokdesu>
|
||||
<envvars/>
|
||||
</run>
|
||||
<make>
|
||||
<abortonerror>true</abortonerror>
|
||||
<runmultiplejobs>false</runmultiplejobs>
|
||||
<numberofjobs>1</numberofjobs>
|
||||
<dontact>false</dontact>
|
||||
<makebin/>
|
||||
<prio>0</prio>
|
||||
<envvars/>
|
||||
</make>
|
||||
<qmake>
|
||||
<savebehaviour>2</savebehaviour>
|
||||
<replacePaths>false</replacePaths>
|
||||
<disableDefaultOpts>true</disableDefaultOpts>
|
||||
</qmake>
|
||||
</kdevtrollproject>
|
||||
<cppsupportpart>
|
||||
<filetemplates>
|
||||
<interfacesuffix>.h</interfacesuffix>
|
||||
<implementationsuffix>.cpp</implementationsuffix>
|
||||
</filetemplates>
|
||||
</cppsupportpart>
|
||||
<ctagspart>
|
||||
<customArguments/>
|
||||
<customTagfilePath>/home/chris/qbittorrent_svn/trunk/tags</customTagfilePath>
|
||||
<activeTagsFiles/>
|
||||
</ctagspart>
|
||||
<kdevdocumentation>
|
||||
<projectdoc>
|
||||
<docsystem/>
|
||||
<docurl/>
|
||||
<usermanualurl/>
|
||||
</projectdoc>
|
||||
</kdevdocumentation>
|
||||
</kdevelop>
|
||||
@@ -2,7 +2,8 @@
|
||||
<name>qbittorrent</name>
|
||||
<profile>qbittorrent.pro</profile>
|
||||
<moddir>qcm</moddir>
|
||||
<dep type='qt42'>
|
||||
<datadir/>
|
||||
<dep type='qt4'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libtorrent'>
|
||||
@@ -11,9 +12,11 @@
|
||||
<dep type='libboost'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libcurl'>
|
||||
<dep type='libcommoncpp2'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libmagick'/>
|
||||
<dep type='libzzip'/>
|
||||
<dep type='python'>
|
||||
<required/>
|
||||
</dep>
|
||||
|
||||
73
qcm/libcommoncpp2.qcm
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libcommoncpp2
|
||||
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
|
||||
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libcommoncpp2 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
|
||||
QString shortname() const { return "libcommoncpp2"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "cc++/url.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "cc++/url.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("libccext2.so")))
|
||||
return false;
|
||||
if(!QFile::exists(s+QString("libccgnu2.so")))
|
||||
return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libccext2.so"))){
|
||||
if(QFile::exists(s+QString("libccgnu2.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
// BUGFIX for Fedora (doesn't support pkg-config?)
|
||||
QFile issue_file("/etc/issue");
|
||||
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
QString content = issue_file.readAll();
|
||||
issue_file.close();
|
||||
if(content.indexOf("Fedora") != -1){
|
||||
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
|
||||
conf->addLib("-pthread -lccext2 -lz -lccgnu2 -ldl -lrt");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libcurl
|
||||
arg: with-libcurl-inc=[path], Path to libcurl include files
|
||||
arg: with-libcurl-lib=[path], Path to libcurl library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libcurl : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libcurl(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libcurl"; }
|
||||
QString shortname() const { return "libcurl"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBCURL_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "curl/curl.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "curl/curl.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBCURL_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "curl")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "curl")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
conf->addLib("-lcurl");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
77
qcm/libmagick.qcm
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libmagick
|
||||
arg: with-libmagick-inc=[path], Path to libmagick++ include files
|
||||
arg: with-libmagick-lib=[path], Path to libmagick++ library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <QProcess>
|
||||
class qc_libmagick : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libmagick(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "ImageMagick library (libmagick++)"; }
|
||||
QString shortname() const { return "libmagick++"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
|
||||
return false;
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBMAGICK_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "Magick++.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "Magick++.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("libMagick++.so"))){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libMagick++.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
QProcess magickConfig;
|
||||
QStringList params;
|
||||
params << "--libs";
|
||||
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
|
||||
magickConfig.waitForStarted();
|
||||
magickConfig.waitForFinished();
|
||||
QByteArray result = magickConfig.readAll();
|
||||
result = result.replace("\n", "");
|
||||
conf->addLib(result.data());
|
||||
conf->addDefine("HAVE_MAGICK");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -3,51 +3,46 @@
|
||||
name: libtorrent
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_libtorrent : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent >= 0.11 (>= 0.12 ADVISED)"; }
|
||||
QString name() const { return "libtorrent >= 0.13"; }
|
||||
QString shortname() const { return "libtorrent"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
|
||||
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
|
||||
return false;
|
||||
}
|
||||
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")) {
|
||||
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
|
||||
conf->addDefine("NO_PEX");
|
||||
}
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
conf->addDefine("V_0_13");
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")){
|
||||
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
|
||||
conf->addDefine("NO_PEX");
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
conf->addDefine("V_0_13");
|
||||
}
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
conf->addIncludePath(s+QDir::separator()+"libtorrent");
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
|
||||
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
|
||||
conf->addLib(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkLibrary(s, "torrent")) {
|
||||
@@ -68,7 +63,16 @@ public:
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
//conf->addLib("-ltorrent");
|
||||
// BUGFIX for Fedora (doesn't support pkg-config?)
|
||||
QFile issue_file("/etc/issue");
|
||||
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
QString content = issue_file.readAll();
|
||||
issue_file.close();
|
||||
if(content.indexOf("Fedora") != -1){
|
||||
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
|
||||
conf->addLib("-lssl -lcrypto -lboost_date_time -lboost_filesystem -lboost_thread -lz -ltorrent");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
69
qcm/libzzip.qcm
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libzzip
|
||||
arg: with-libzzip-inc=[path], Path to libzzip++ include files
|
||||
arg: with-libzzip-lib=[path], Path to libzzip++ library files
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
#include <QProcess>
|
||||
class qc_libzzip : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libzzip(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Zzip library (libzzip)"; }
|
||||
QString shortname() const { return "libzzip"; }
|
||||
QString checkString() const {
|
||||
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
|
||||
return "";
|
||||
return ConfObj::checkString();
|
||||
}
|
||||
bool exec(){
|
||||
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
|
||||
return false;
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBZZIP_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "zzip/zzip.h")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "zzip/zzip.h")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addIncludePath(s);
|
||||
|
||||
s = conf->getenv("QC_WITH_LIBZZIP_LIB");
|
||||
if(!s.isEmpty()) {
|
||||
if(!QFile::exists(s+QString("libzzip.so"))){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/local/lib/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(QFile::exists(s+QString("libzzip.so"))){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
conf->addLib("-lzzip");
|
||||
conf->addDefine("HAVE_ZZIP");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
16
qcm/qt4.qcm
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.3
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_qt4 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt4(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.3"; }
|
||||
QString shortname() const { return "Qt 4.3"; }
|
||||
bool exec()
|
||||
{
|
||||
return(QT_VERSION >= 0x040300);
|
||||
}
|
||||
};
|
||||
16
qcm/qt42.qcm
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: Qt >= 4.2
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
class qc_qt42 : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_qt42(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "Qt >= 4.2"; }
|
||||
QString shortname() const { return "qt42"; }
|
||||
bool exec()
|
||||
{
|
||||
return(QT_VERSION >= 0x040200);
|
||||
}
|
||||
};
|
||||
@@ -22,10 +22,11 @@
|
||||
#ifndef DLLISTDELEGATE_H
|
||||
#define DLLISTDELEGATE_H
|
||||
|
||||
#include <QAbstractItemDelegate>
|
||||
#include <QItemDelegate>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QStyleOptionViewItemV2>
|
||||
#include <QProgressBar>
|
||||
#include <QApplication>
|
||||
#include "misc.h"
|
||||
@@ -37,128 +38,66 @@
|
||||
#define DLSPEED 3
|
||||
#define UPSPEED 4
|
||||
#define SEEDSLEECH 5
|
||||
#define STATUS 6
|
||||
#define RATIO 6
|
||||
#define ETA 7
|
||||
#define HASH 8
|
||||
|
||||
class DLListDelegate: public QAbstractItemDelegate {
|
||||
class DLListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DLListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
|
||||
DLListDelegate(QObject *parent) : QItemDelegate(parent){}
|
||||
|
||||
~DLListDelegate(){}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QStyleOptionViewItem opt = option;
|
||||
char tmp[MAX_CHAR_TMP];
|
||||
// set text color
|
||||
QVariant value = index.data(Qt::TextColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
|
||||
}
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
if (option.state & QStyle::State_Selected){
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}else{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
// draw the background color
|
||||
if(index.column() != PROGRESS){
|
||||
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
|
||||
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
|
||||
cg = QPalette::Inactive;
|
||||
}
|
||||
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
|
||||
}else{
|
||||
value = index.data(Qt::BackgroundColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
switch(index.column()){
|
||||
case SIZE:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case ETA:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, misc::userFriendlyDuration(index.data().toLongLong()));
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::userFriendlyDuration(index.data().toLongLong()));
|
||||
break;
|
||||
case UPSPEED:
|
||||
case DLSPEED:{
|
||||
float speed = index.data().toDouble();
|
||||
snprintf(tmp, MAX_CHAR_TMP, "%.1f", speed/1024.);
|
||||
painter->drawText(option.rect, Qt::AlignCenter, QString(tmp)+" "+tr("KiB/s"));
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double speed = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(speed/1024., 'f', 1))+QString::fromUtf8(" ")+tr("KiB/s"));
|
||||
break;
|
||||
}
|
||||
case RATIO:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double ratio = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
case PROGRESS:{
|
||||
QStyleOptionProgressBarV2 newopt;
|
||||
float progress;
|
||||
progress = index.data().toDouble()*100.;
|
||||
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
|
||||
double progress = index.data().toDouble()*100.;
|
||||
newopt.rect = opt.rect;
|
||||
newopt.text = QString(tmp)+"%";
|
||||
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
|
||||
newopt.progress = (int)progress;
|
||||
newopt.maximum = 100;
|
||||
newopt.minimum = 0;
|
||||
newopt.state |= QStyle::State_Enabled;
|
||||
newopt.textVisible = false;
|
||||
newopt.textVisible = true;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
|
||||
painter);
|
||||
//We prefer to display text manually to control color/font/boldness
|
||||
if (option.state & QStyle::State_Selected){
|
||||
opt.palette.setColor(QPalette::Text, QColor("grey"));
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
|
||||
break;
|
||||
}
|
||||
case NAME:{
|
||||
// decoration
|
||||
value = index.data(Qt::DecorationRole);
|
||||
QPixmap pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off);
|
||||
QRect pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
|
||||
if (pixmapRect.isValid()){
|
||||
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
|
||||
painter->drawPixmap(p, pixmap);
|
||||
}
|
||||
painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QVariant value = index.data(Qt::FontRole);
|
||||
QFont fnt = value.isValid() ? qvariant_cast<QFont>(value) : option.font;
|
||||
QFontMetrics fontMetrics(fnt);
|
||||
const QString text = index.data(Qt::DisplayRole).toString();
|
||||
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
|
||||
return textRect.size();
|
||||
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
// No editor here
|
||||
return 0;
|
||||
}
|
||||
|
||||
// QWidget* createEditor(QWidget * parent, const QStyleOptionViewItem& /*option*/, const QModelIndex & index) const{
|
||||
// if(index.column() == PROGRESS){
|
||||
// QProgressBar *progressBar = new QProgressBar(parent);
|
||||
// progressBar->setRange(0,100);
|
||||
// progressBar->installEventFilter(const_cast<DLListDelegate*>(this));
|
||||
// return progressBar;
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
// void setEditorData(QWidget *editor, const QModelIndex &index) const{
|
||||
// QProgressBar *progressBar = static_cast<QProgressBar*>(editor);
|
||||
// float progress = index.data().toDouble();
|
||||
// progressBar->setValue((int)(progress*100.));
|
||||
// }
|
||||
// void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & index) const{
|
||||
// if(index.column() == PROGRESS){
|
||||
// editor->setGeometry(option.rect);
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
96
src/FinishedListDelegate.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FINISHEDLISTDELEGATE_H
|
||||
#define FINISHEDLISTDELEGATE_H
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QStyleOptionViewItemV2>
|
||||
#include <QProgressBar>
|
||||
#include <QApplication>
|
||||
#include "misc.h"
|
||||
|
||||
// Defines for download list list columns
|
||||
#define F_NAME 0
|
||||
#define F_SIZE 1
|
||||
#define F_PROGRESS 2
|
||||
#define F_UPSPEED 3
|
||||
#define F_SEEDSLEECH 4
|
||||
#define F_RATIO 5
|
||||
#define F_HASH 6
|
||||
|
||||
class FinishedListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FinishedListDelegate(QObject *parent) : QItemDelegate(parent){}
|
||||
|
||||
~FinishedListDelegate(){}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
switch(index.column()){
|
||||
case F_SIZE:
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case F_UPSPEED:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double speed = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(speed/1024., 'f', 1))+QString::fromUtf8(" ")+tr("KiB/s"));
|
||||
break;
|
||||
}
|
||||
case F_RATIO:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double ratio = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
case F_PROGRESS:{
|
||||
QStyleOptionProgressBarV2 newopt;
|
||||
double progress = index.data().toDouble()*100.;
|
||||
newopt.rect = opt.rect;
|
||||
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
|
||||
newopt.progress = (int)progress;
|
||||
newopt.maximum = 100;
|
||||
newopt.minimum = 0;
|
||||
newopt.state |= QStyle::State_Enabled;
|
||||
newopt.textVisible = true;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
|
||||
painter);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
// No editor here
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
425
src/FinishedTorrents.cpp
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include "FinishedTorrents.h"
|
||||
#include "misc.h"
|
||||
#include "properties_imp.h"
|
||||
#include "bittorrent.h"
|
||||
#include "allocationDlg.h"
|
||||
#include "FinishedListDelegate.h"
|
||||
#include "GUI.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
|
||||
FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), nbFinished(0){
|
||||
setupUi(this);
|
||||
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
|
||||
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
|
||||
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
|
||||
finishedListModel = new QStandardItemModel(0,7);
|
||||
finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
finishedListModel->setHeaderData(F_PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
|
||||
finishedListModel->setHeaderData(F_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
|
||||
finishedListModel->setHeaderData(F_SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources"));
|
||||
finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio"));
|
||||
finishedList->setModel(finishedListModel);
|
||||
// Hide ETA & hash column
|
||||
finishedList->hideColumn(F_HASH);
|
||||
// Load last columns width for download list
|
||||
if(!loadColWidthFinishedList()){
|
||||
finishedList->header()->resizeSection(0, 200);
|
||||
}
|
||||
// Make download list header clickable for sorting
|
||||
finishedList->header()->setClickable(true);
|
||||
finishedList->header()->setSortIndicatorShown(true);
|
||||
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int)));
|
||||
finishedListDelegate = new FinishedListDelegate(finishedList);
|
||||
finishedList->setItemDelegate(finishedListDelegate);
|
||||
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
|
||||
connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
|
||||
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
|
||||
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
|
||||
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
|
||||
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
|
||||
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
|
||||
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
|
||||
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
|
||||
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
|
||||
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
|
||||
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
|
||||
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
|
||||
}
|
||||
|
||||
FinishedTorrents::~FinishedTorrents(){
|
||||
saveColWidthFinishedList();
|
||||
delete finishedListDelegate;
|
||||
delete finishedListModel;
|
||||
}
|
||||
|
||||
void FinishedTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
|
||||
unsigned int row = index.row();
|
||||
QString hash = getHashFromRow(row);
|
||||
emit torrentDoubleClicked(hash);
|
||||
}
|
||||
|
||||
void FinishedTorrents::addTorrent(QString hash){
|
||||
if(!BTSession->isFinished(hash)){
|
||||
BTSession->setFinishedTorrent(hash);
|
||||
}
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) return;
|
||||
row = finishedListModel->rowCount();
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
// Adding torrent to download list
|
||||
finishedListModel->insertRow(row);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant("0/0"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString::fromUtf8(misc::toString(BTSession->getRealRatio(hash)).c_str())));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)1.));
|
||||
if(h.is_paused()) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(":/Icons/skin/paused.png"), Qt::DecorationRole);
|
||||
setRowColor(row, "red");
|
||||
}else{
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(":/Icons/skin/seeding.png")), Qt::DecorationRole);
|
||||
setRowColor(row, "orange");
|
||||
}
|
||||
// Update the number of finished torrents
|
||||
++nbFinished;
|
||||
emit finishedTorrentsNumberChanged(nbFinished);
|
||||
}
|
||||
|
||||
void FinishedTorrents::torrentAdded(QString, QTorrentHandle& h, bool) {
|
||||
QString hash = h.hash();
|
||||
if(BTSession->isFinished(hash)) {
|
||||
addTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
void FinishedTorrents::setRowColor(int row, QString color){
|
||||
unsigned int nbColumns = finishedListModel->columnCount()-1;
|
||||
for(unsigned int i=0; i<nbColumns; ++i){
|
||||
finishedListModel->setData(finishedListModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
|
||||
QStringList res;
|
||||
QModelIndex index;
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file hash
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
res << hash;
|
||||
if(only_one) break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int FinishedTorrents::getNbTorrentsInList() const {
|
||||
return nbFinished;
|
||||
}
|
||||
|
||||
// Load columns width in a file that were saved previously
|
||||
// (finished list)
|
||||
bool FinishedTorrents::loadColWidthFinishedList(){
|
||||
qDebug("Loading columns width for finished list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString line = settings.value("FinishedListColsWidth", QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(' ');
|
||||
if(width_list.size() != finishedListModel->columnCount()-1)
|
||||
return false;
|
||||
unsigned int listSize = width_list.size();
|
||||
for(unsigned int i=0; i<listSize; ++i){
|
||||
finishedList->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
qDebug("Finished list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Save columns width in a file to remember them
|
||||
// (finished list)
|
||||
void FinishedTorrents::saveColWidthFinishedList() const{
|
||||
qDebug("Saving columns width in finished list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QStringList width_list;
|
||||
unsigned int nbColumns = finishedListModel->columnCount()-1;
|
||||
for(unsigned int i=0; i<nbColumns; ++i){
|
||||
width_list << QString::fromUtf8(misc::toString(finishedList->columnWidth(i)).c_str());
|
||||
}
|
||||
settings.setValue("FinishedListColsWidth", width_list.join(" "));
|
||||
qDebug("Finished list columns width saved");
|
||||
}
|
||||
|
||||
void FinishedTorrents::on_actionSet_upload_limit_triggered(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
// Get the file hash
|
||||
hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
}
|
||||
}
|
||||
new BandwidthAllocationDialog(this, true, BTSession, hashes);
|
||||
}
|
||||
|
||||
void FinishedTorrents::updateFinishedList(){
|
||||
QString hash;
|
||||
QStringList finishedSHAs = BTSession->getFinishedTorrents();
|
||||
foreach(hash, finishedSHAs){
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()){
|
||||
qDebug("Problem: This torrent is not valid in finished list");
|
||||
continue;
|
||||
}
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1){
|
||||
qDebug("Cannot find torrent in finished list, adding it");
|
||||
addTorrent(hash);
|
||||
row = getRowFromHash(hash);
|
||||
}
|
||||
Q_ASSERT(row != -1);
|
||||
if(h.is_paused()) continue;
|
||||
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)h.progress()));
|
||||
continue;
|
||||
}
|
||||
if(h.state() == torrent_status::downloading || (h.state() != torrent_status::checking_files && h.state() != torrent_status::queued_for_checking && h.progress() < 1.)) {
|
||||
// What are you doing here? go back to download tab!
|
||||
qDebug("Info: a torrent was moved from finished to download tab");
|
||||
deleteTorrent(hash);
|
||||
BTSession->setFinishedTorrent(hash);
|
||||
emit torrentMovedFromFinishedList(hash);
|
||||
continue;
|
||||
}
|
||||
if(h.state() == torrent_status::checking_files){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)h.progress()));
|
||||
continue;
|
||||
}
|
||||
setRowColor(row, QString::fromUtf8("orange"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+"/"+misc::toQString(h.num_peers() - h.num_seeds(), true)));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)1.));
|
||||
}
|
||||
}
|
||||
|
||||
int FinishedTorrents::getRowFromHash(QString hash) const{
|
||||
unsigned int nbRows = finishedListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
if(finishedListModel->data(finishedListModel->index(i, F_HASH)) == hash){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note: does not actually pause the torrent in BT Session
|
||||
void FinishedTorrents::pauseTorrent(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.0));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
|
||||
setRowColor(row, QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
void FinishedTorrents::resumeTorrent(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("orange"));
|
||||
}
|
||||
|
||||
QString FinishedTorrents::getHashFromRow(unsigned int row) const {
|
||||
Q_ASSERT(row < (unsigned int)finishedListModel->rowCount());
|
||||
return finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
|
||||
}
|
||||
|
||||
// Will move it to download tab
|
||||
void FinishedTorrents::deleteTorrent(QString hash){
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1){
|
||||
qDebug("Torrent is not in finished list, nothing to delete");
|
||||
return;
|
||||
}
|
||||
finishedListModel->removeRow(row);
|
||||
--nbFinished;
|
||||
emit finishedTorrentsNumberChanged(nbFinished);
|
||||
}
|
||||
|
||||
// Show torrent properties dialog
|
||||
void FinishedTorrents::showProperties(const QModelIndex &index){
|
||||
int row = index.row();
|
||||
QString hash = finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
properties *prop = new properties(this, BTSession, h);
|
||||
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSize(QString)));
|
||||
prop->show();
|
||||
}
|
||||
|
||||
void FinishedTorrents::updateFileSize(QString hash){
|
||||
int row = getRowFromHash(hash);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
}
|
||||
|
||||
// display properties of selected items
|
||||
void FinishedTorrents::propertiesSelection(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
showProperties(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
|
||||
QMenu myFinishedListMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString previewProgram = settings.value("Preferences/general/MediaPlayer", QString()).toString();
|
||||
bool has_pause = false, has_start = false, has_preview = false;
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file name
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
// Get handle and pause the torrent
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) continue;
|
||||
if(h.is_paused()) {
|
||||
if(!has_start) {
|
||||
myFinishedListMenu.addAction(actionStart);
|
||||
has_start = true;
|
||||
}
|
||||
}else{
|
||||
if(!has_pause) {
|
||||
myFinishedListMenu.addAction(actionPause);
|
||||
has_pause = true;
|
||||
}
|
||||
}
|
||||
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
|
||||
myFinishedListMenu.addAction(actionPreview_file);
|
||||
has_preview = true;
|
||||
}
|
||||
if(has_pause && has_start && has_preview) break;
|
||||
}
|
||||
}
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionDelete);
|
||||
myFinishedListMenu.addAction(actionDelete_Permanently);
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionSet_upload_limit);
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionTorrent_Properties);
|
||||
// Call menu
|
||||
// XXX: why mapToGlobal() is not enough?
|
||||
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,55));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorting functions
|
||||
*/
|
||||
|
||||
void FinishedTorrents::sortFinishedList(int index){
|
||||
static Qt::SortOrder sortOrder = Qt::AscendingOrder;
|
||||
if(finishedList->header()->sortIndicatorSection() == index){
|
||||
if(sortOrder == Qt::AscendingOrder){
|
||||
sortOrder = Qt::DescendingOrder;
|
||||
}else{
|
||||
sortOrder = Qt::AscendingOrder;
|
||||
}
|
||||
}
|
||||
finishedList->header()->setSortIndicator(index, sortOrder);
|
||||
switch(index){
|
||||
case F_SIZE:
|
||||
case F_UPSPEED:
|
||||
case F_PROGRESS:
|
||||
sortFinishedListFloat(index, sortOrder);
|
||||
break;
|
||||
default:
|
||||
sortFinishedListString(index, sortOrder);
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::sortFinishedListFloat(int index, Qt::SortOrder sortOrder){
|
||||
QList<QPair<int, double> > lines;
|
||||
// insertion sorting
|
||||
unsigned int nbRows = finishedListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
misc::insertSort(lines, QPair<int,double>(i, finishedListModel->data(finishedListModel->index(i, index)).toDouble()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
unsigned int nbRows_old = lines.size();
|
||||
for(unsigned int row=0; row<nbRows_old; ++row){
|
||||
finishedListModel->insertRow(finishedListModel->rowCount());
|
||||
unsigned int sourceRow = lines[row].first;
|
||||
unsigned int nbColumns = finishedListModel->columnCount();
|
||||
for(unsigned int col=0; col<nbColumns; ++col){
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
finishedListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
void FinishedTorrents::sortFinishedListString(int index, Qt::SortOrder sortOrder){
|
||||
QList<QPair<int, QString> > lines;
|
||||
// Insertion sorting
|
||||
unsigned int nbRows = finishedListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i){
|
||||
misc::insertSortString(lines, QPair<int, QString>(i, finishedListModel->data(finishedListModel->index(i, index)).toString()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
unsigned int nbRows_old = lines.size();
|
||||
for(unsigned int row=0; row<nbRows_old; ++row){
|
||||
finishedListModel->insertRow(finishedListModel->rowCount());
|
||||
unsigned int sourceRow = lines[row].first;
|
||||
unsigned int nbColumns = finishedListModel->columnCount();
|
||||
for(unsigned int col=0; col<nbColumns; ++col){
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
finishedListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
81
src/FinishedTorrents.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef SEEDING_H
|
||||
#define SEEDING_H
|
||||
|
||||
#include "ui_seeding.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
class QStandardItemModel;
|
||||
class bittorrent;
|
||||
class FinishedListDelegate;
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class FinishedTorrents : public QWidget, public Ui::seeding {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QObject *parent;
|
||||
bittorrent *BTSession;
|
||||
FinishedListDelegate *finishedListDelegate;
|
||||
QStandardItemModel *finishedListModel;
|
||||
unsigned int nbFinished;
|
||||
|
||||
public:
|
||||
FinishedTorrents(QObject *parent, bittorrent *BTSession);
|
||||
~FinishedTorrents();
|
||||
// Methods
|
||||
bool loadColWidthFinishedList();
|
||||
int getRowFromHash(QString hash) const;
|
||||
QStringList getSelectedTorrents(bool only_one=false) const;
|
||||
unsigned int getNbTorrentsInList() const;
|
||||
QString getHashFromRow(unsigned int row) const;
|
||||
|
||||
protected slots:
|
||||
void showProperties(const QModelIndex &index);
|
||||
void displayFinishedListMenu(const QPoint&);
|
||||
void setRowColor(int row, QString color);
|
||||
void saveColWidthFinishedList() const;
|
||||
void sortFinishedList(int index);
|
||||
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
|
||||
void sortFinishedListString(int index, Qt::SortOrder sortOrder);
|
||||
void updateFileSize(QString hash);
|
||||
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
|
||||
void on_actionSet_upload_limit_triggered();
|
||||
void notifyTorrentDoubleClicked(const QModelIndex& index);
|
||||
|
||||
public slots:
|
||||
void addTorrent(QString hash);
|
||||
void updateFinishedList();
|
||||
void pauseTorrent(QString hash);
|
||||
void resumeTorrent(QString hash);
|
||||
void propertiesSelection();
|
||||
void deleteTorrent(QString hash);
|
||||
|
||||
signals:
|
||||
void torrentMovedFromFinishedList(QString);
|
||||
void torrentDoubleClicked(QString hash);
|
||||
void finishedTorrentsNumberChanged(unsigned int);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
2461
src/GUI.cpp
202
src/GUI.h
@@ -22,169 +22,132 @@
|
||||
#ifndef GUI_H
|
||||
#define GUI_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QProcess>
|
||||
#include <QTcpServer>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/fingerprint.hpp>
|
||||
#include <libtorrent/session_settings.hpp>
|
||||
#include <libtorrent/identify_client.hpp>
|
||||
#include <libtorrent/alert_types.hpp>
|
||||
|
||||
#include "ui_MainWindow.h"
|
||||
#include "options_imp.h"
|
||||
#include "about_imp.h"
|
||||
#include "previewSelect.h"
|
||||
#include "trackerLogin.h"
|
||||
#include "bittorrent.h"
|
||||
|
||||
|
||||
#define TIME_TRAY_BALLOON 5000
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
class bittorrent;
|
||||
class createtorrent;
|
||||
class QTimer;
|
||||
class QCompleter;
|
||||
class DLListDelegate;
|
||||
class SearchListDelegate;
|
||||
class downloadThread;
|
||||
class DownloadingTorrents;
|
||||
class FinishedTorrents;
|
||||
class downloadFromURL;
|
||||
class SearchEngine;
|
||||
class QTcpServer;
|
||||
class QTcpSocket;
|
||||
class QCloseEvent;
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace fs = boost::filesystem;
|
||||
class RSSImp;
|
||||
class QShortcut;
|
||||
class about;
|
||||
class previewSelect;
|
||||
class options_imp;
|
||||
class QTabWidget;
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
|
||||
class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
// Bittorrent
|
||||
bittorrent BTSession;
|
||||
bittorrent *BTSession;
|
||||
QTimer *checkConnect;
|
||||
QHash<QString, QStringList> trackerErrors;
|
||||
QList<QPair<torrent_handle,std::string> > unauthenticated_trackers;
|
||||
downloadFromURL *downloadFromURLDialog;
|
||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
|
||||
// GUI related
|
||||
QTabWidget *tabs;
|
||||
options_imp *options;
|
||||
createtorrent *createWindow;
|
||||
QTimer *refresher;
|
||||
QSystemTrayIcon *myTrayIcon;
|
||||
QMenu *myTrayIconMenu;
|
||||
about *aboutdlg;
|
||||
QStandardItemModel *DLListModel;
|
||||
DLListDelegate *DLDelegate;
|
||||
QStandardItemModel *SearchListModel;
|
||||
SearchListDelegate *SearchDelegate;
|
||||
unsigned int nbTorrents;
|
||||
DownloadingTorrents *downloadingTorrentTab;
|
||||
FinishedTorrents *finishedTorrentTab;
|
||||
QLabel *connecStatusLblIcon;
|
||||
bool systrayIntegration;
|
||||
bool displaySpeedInTitle;
|
||||
bool force_exit;
|
||||
unsigned int refreshInterval;
|
||||
QTimer *refresher;
|
||||
// Keyboard shortcuts
|
||||
QShortcut *switchSearchShortcut;
|
||||
QShortcut *switchSearchShortcut2;
|
||||
QShortcut *switchDownShortcut;
|
||||
QShortcut *switchUpShortcut;
|
||||
QShortcut *switchRSSShortcut;
|
||||
// Preview
|
||||
previewSelect *previewSelection;
|
||||
QProcess *previewProcess;
|
||||
// Search related
|
||||
QHash<QString, QString> searchResultsUrls;
|
||||
QProcess *searchProcess;
|
||||
bool search_stopped;
|
||||
bool no_search_results;
|
||||
QByteArray search_result_line_truncated;
|
||||
unsigned long nb_search_results;
|
||||
QTcpServer tcpServer;
|
||||
// Search
|
||||
SearchEngine *searchEngine;
|
||||
// RSS
|
||||
RSSImp *rssWidget;
|
||||
// Misc
|
||||
QTcpServer *tcpServer;
|
||||
QTcpSocket *clientConnection;
|
||||
QCompleter *searchCompleter;
|
||||
QStringList searchHistory;
|
||||
|
||||
protected slots:
|
||||
// GUI related slots
|
||||
void dropEvent(QDropEvent *event);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void toggleVisibility(QSystemTrayIcon::ActivationReason e);
|
||||
void showAbout();
|
||||
void setInfoBar(const QString& info, const QString& color="black");
|
||||
void updateDlList(bool force=false);
|
||||
void showCreateWindow();
|
||||
void clearLog();
|
||||
void openqBTHomepage();
|
||||
void openqBTBugTracker();
|
||||
void on_actionAbout_triggered();
|
||||
void on_actionCreate_torrent_triggered();
|
||||
void on_actionWebsite_triggered() const;
|
||||
void on_actionBugReport_triggered() const;
|
||||
void readParamsOnSocket();
|
||||
void acceptConnection();
|
||||
void saveCheckedSearchEngines(int) const;
|
||||
void saveColWidthDLList() const;
|
||||
void saveColWidthSearchList() const;
|
||||
void loadCheckedSearchEngines();
|
||||
bool loadColWidthDLList();
|
||||
bool loadColWidthSearchList();
|
||||
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
|
||||
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
|
||||
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
|
||||
void sortSearchList(int index);
|
||||
void sortSearchListInt(int index, Qt::SortOrder sortOrder);
|
||||
void sortSearchListString(int index, Qt::SortOrder sortOrder);
|
||||
void displayDLListMenu(const QPoint& pos);
|
||||
void selectGivenRow(const QModelIndex& index);
|
||||
void togglePausedState(const QModelIndex& index);
|
||||
void displayInfoBarMenu(const QPoint& pos);
|
||||
void displayGUIMenu(const QPoint& pos);
|
||||
void previewFileSelection();
|
||||
void previewFile(const QString& filePath);
|
||||
void cleanTempPreviewFile(int, QProcess::ExitStatus);
|
||||
void togglePausedState(QString hash);
|
||||
void on_actionPreview_file_triggered();
|
||||
void previewFile(QString filePath);
|
||||
void cleanTempPreviewFile(int, QProcess::ExitStatus) const;
|
||||
void balloonClicked();
|
||||
void writeSettings();
|
||||
void readSettings();
|
||||
void forceExit();
|
||||
void on_actionExit_triggered();
|
||||
void createTrayIcon();
|
||||
void updateUnfinishedTorrentNumber(unsigned int nb);
|
||||
void updateFinishedTorrentNumber(unsigned int nb);
|
||||
void fullDiskError(QTorrentHandle& h) const;
|
||||
void handleDownloadFromUrlFailure(QString, QString) const;
|
||||
// Keyboard shortcuts
|
||||
void createKeyboardShortcuts();
|
||||
void displayDownTab() const;
|
||||
void displayUpTab() const;
|
||||
void displaySearchTab() const;
|
||||
void displayRSSTab() const;
|
||||
// Torrent actions
|
||||
size_type torrentEffectiveSize(QString hash) const;
|
||||
void showProperties(const QModelIndex &index);
|
||||
void propertiesSelection();
|
||||
void pauseSelection();
|
||||
void pauseAll();
|
||||
void startSelection();
|
||||
void resumeAll();
|
||||
void askForTorrents();
|
||||
void deletePermanently();
|
||||
void deleteSelection();
|
||||
void on_actionTorrent_Properties_triggered();
|
||||
void on_actionPause_triggered();
|
||||
void on_actionPause_All_triggered();
|
||||
void on_actionStart_triggered();
|
||||
void on_actionStart_All_triggered();
|
||||
void on_actionOpen_triggered();
|
||||
void on_actionDelete_Permanently_triggered();
|
||||
void on_actionDelete_triggered();
|
||||
void on_actionSet_global_upload_limit_triggered();
|
||||
void on_actionSet_global_download_limit_triggered();
|
||||
void on_actionDocumentation_triggered() const;
|
||||
void checkConnectionStatus();
|
||||
void configureSession(bool deleteOptions);
|
||||
void processParams(const QStringList& params);
|
||||
void addUnauthenticatedTracker(QPair<torrent_handle,std::string> tracker);
|
||||
void addTorrent(QString path);
|
||||
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
|
||||
void processScannedFiles(const QStringList& params);
|
||||
void processDownloadedFiles(const QString& path, const QString& url);
|
||||
void processDownloadedFiles(QString path, QString url);
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
void displayDownloadingUrlInfos(const QString& url);
|
||||
// Search slots
|
||||
void on_search_button_clicked();
|
||||
void on_stop_search_button_clicked();
|
||||
void on_clear_button_clicked();
|
||||
void on_download_button_clicked();
|
||||
void on_update_nova_button_clicked();
|
||||
void appendSearchResult(const QString& line);
|
||||
void searchFinished(int exitcode,QProcess::ExitStatus);
|
||||
void readSearchOutput();
|
||||
void searchStarted();
|
||||
void downloadSelectedItem(const QModelIndex& index);
|
||||
void startSearchHistory();
|
||||
void saveSearchHistory();
|
||||
// Utils slots
|
||||
void setRowColor(int row, const QString& color, bool inDLList=true);
|
||||
void deleteTorrent(QString hash, QString fileName, bool finished);
|
||||
void finishedTorrent(QTorrentHandle& h) const;
|
||||
void torrentChecked(QString hash) const;
|
||||
void updateLists();
|
||||
// Options slots
|
||||
void showOptions();
|
||||
void OptionsSaved(const QString& info, bool deleteOptions);
|
||||
void on_actionOptions_triggered();
|
||||
void OptionsSaved(QString info, bool deleteOptions);
|
||||
// HTTP slots
|
||||
void askForTorrentUrl();
|
||||
void on_actionDownload_from_URL_triggered();
|
||||
|
||||
|
||||
public slots:
|
||||
void torrentAdded(const QString& path, torrent_handle& h, bool fastResume);
|
||||
void torrentDuplicate(const QString& path);
|
||||
void torrentCorrupted(const QString& path);
|
||||
void finishedTorrent(torrent_handle& h);
|
||||
void fullDiskError(torrent_handle& h);
|
||||
void portListeningFailure();
|
||||
void trackerError(const QString& hash, const QString& time, const QString& msg);
|
||||
void trackerAuthenticationRequired(torrent_handle& h);
|
||||
void updateFileSize(QString hash);
|
||||
void trackerAuthenticationRequired(QTorrentHandle& h);
|
||||
void setTabText(int index, QString text) const;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
@@ -195,11 +158,8 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
|
||||
~GUI();
|
||||
// Methods
|
||||
int getRowFromHash(const QString& hash) const;
|
||||
float getNovaVersion(const QString& novaPath) const;
|
||||
QByteArray getNovaChangelog(const QString& novaPath) const;
|
||||
void updateNova() const;
|
||||
QPoint screenCenter();
|
||||
unsigned int getCurrentTabIndex() const;
|
||||
QPoint screenCenter() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
BIN
src/Icons/add_file.png
Normal file
|
After Width: | Height: | Size: 1005 B |
BIN
src/Icons/add_folder.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Icons/bt_settings.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/configure.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Icons/connection.png
Normal file
|
After Width: | Height: | Size: 820 B |
BIN
src/Icons/description.png
Normal file
|
After Width: | Height: | Size: 821 B |
BIN
src/Icons/downarrow.png
Normal file
|
After Width: | Height: | Size: 722 B |
BIN
src/Icons/download.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/file.png
Normal file
|
After Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 998 B |
BIN
src/Icons/flags/brazil.png
Normal file
|
After Width: | Height: | Size: 799 B |
|
Before Width: | Height: | Size: 558 B |
BIN
src/Icons/flags/hungary.png
Normal file
|
After Width: | Height: | Size: 172 B |
BIN
src/Icons/folder.png
Normal file
|
After Width: | Height: | Size: 449 B |
BIN
src/Icons/gear.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Icons/loading.png
Normal file
|
After Width: | Height: | Size: 248 B |
BIN
src/Icons/mascot.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 532 B |
BIN
src/Icons/password.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
@@ -1,22 +1,23 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Application;Network;P2P
|
||||
Comment=V0.9.2
|
||||
Comment=V1.0.0
|
||||
Encoding=UTF-8
|
||||
Exec=qbittorrent
|
||||
GenericName=Bittorrent client
|
||||
GenericName[fr]=Client Bittorrent
|
||||
GenericName[nl]=Bittorrent client
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[de]=Bittorren Client
|
||||
GenericName[el]=Τορεντ πελάτης
|
||||
GenericName[es]=Cliente Bittorrent
|
||||
GenericName[fr]=Client Bittorrent
|
||||
GenericName[ja]=Bittorrent クライアント
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
GenericName[nl]=Bittorrent client
|
||||
GenericName[pl]=Klient Bittorrent
|
||||
GenericName[ru]=клиент Bittorrent
|
||||
GenericName[sv]=Bittorrent-klient
|
||||
GenericName[tr]=Bittorrent istemcisi
|
||||
GenericName[de]=Bittorren Client
|
||||
GenericName[pl]=Klient Bittorrent
|
||||
GenericName[zh]=Bittorrent之用户
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
GenericName[el]=Τορεντ πελάτης
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[uk]=Bittorrent-клієнт
|
||||
GenericName[ru]=клиент Bittorrent
|
||||
GenericName[zh]=Bittorrent之用户
|
||||
Icon=qbittorrent
|
||||
MimeType=application/x-bittorrent
|
||||
Name=qBittorrent
|
||||
|
||||
BIN
src/Icons/refresh.png
Normal file
|
After Width: | Height: | Size: 948 B |
BIN
src/Icons/rss16.png
Normal file
|
After Width: | Height: | Size: 607 B |
BIN
src/Icons/rss32.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 842 B |
BIN
src/Icons/skin/qb_question.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 770 B After Width: | Height: | Size: 1.3 KiB |
BIN
src/Icons/sphere.png
Normal file
|
After Width: | Height: | Size: 337 B |
BIN
src/Icons/sphere2.png
Normal file
|
After Width: | Height: | Size: 379 B |
|
Before Width: | Height: | Size: 49 KiB |
BIN
src/Icons/splash.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
src/Icons/star.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 766 B After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/subscribe.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Icons/subscribe16.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
src/Icons/time.png
Normal file
|
After Width: | Height: | Size: 856 B |
BIN
src/Icons/unavailable.png
Normal file
|
After Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/unsubscribe.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/Icons/unsubscribe16.png
Normal file
|
After Width: | Height: | Size: 765 B |
BIN
src/Icons/uparrow.png
Normal file
|
After Width: | Height: | Size: 787 B |
BIN
src/Icons/url.png
Normal file
|
After Width: | Height: | Size: 629 B |
@@ -6,7 +6,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>849</width>
|
||||
<height>576</height>
|
||||
<height>563</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
@@ -17,713 +17,12 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabs" >
|
||||
<property name="tabPosition" >
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab" >
|
||||
<attribute name="title" >
|
||||
<string>Transfers</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_DLSpeed" >
|
||||
<property name="text" >
|
||||
<string>Total DL Speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_DownSpeed" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="smallDecimalPoint" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="intValue" stdset="0" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="unitDL" >
|
||||
<property name="text" >
|
||||
<string>KiB/s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Session ratio: </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_Ratio" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_ratio_icon" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_UPSpeed" >
|
||||
<property name="text" >
|
||||
<string>Total UP Speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_UpSpeed" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="smallDecimalPoint" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="unitUP" >
|
||||
<property name="text" >
|
||||
<string>KiB/s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="downloadList" >
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="autoScroll" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="itemsExpandable" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="info_icon" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_info" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Log:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>661</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="infoBar" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>0</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>123</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2" >
|
||||
<attribute name="title" >
|
||||
<string>Search</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupEngines" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>131</width>
|
||||
<height>132</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>132</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title" >
|
||||
<string>Search Engines</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mininova" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="piratebay" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="isohunt" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="meganova" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="search_lbl" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Search Pattern:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search_pattern" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="search_button" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>29</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stop_search_button" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>29</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="status_lbl" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Status:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="search_status" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>true</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Stopped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="results_lbl" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Results:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>721</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="resultsBrowser" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="autoScroll" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="itemsExpandable" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="download_button" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Download</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear_button" >
|
||||
<property name="enabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>601</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="update_nova_button" >
|
||||
<property name="text" >
|
||||
<string>Update search plugin</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
@@ -735,12 +34,6 @@
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_Options" >
|
||||
<property name="title" >
|
||||
<string>&Options</string>
|
||||
</property>
|
||||
<addaction name="actionOptions" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Edit" >
|
||||
<property name="title" >
|
||||
<string>&Edit</string>
|
||||
@@ -760,9 +53,16 @@
|
||||
<property name="title" >
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionAbout" />
|
||||
<addaction name="actionBugReport" />
|
||||
<addaction name="actionWebsite" />
|
||||
<addaction name="actionDocumentation" />
|
||||
<addaction name="actionAbout" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Options" >
|
||||
<property name="title" >
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<addaction name="actionOptions" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_File" >
|
||||
<property name="title" >
|
||||
@@ -800,6 +100,9 @@
|
||||
<attribute name="toolBarArea" >
|
||||
<number>4</number>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak" >
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionOpen" />
|
||||
<addaction name="actionDownload_from_URL" />
|
||||
<addaction name="separator" />
|
||||
@@ -903,24 +206,32 @@
|
||||
<string>Report a bug</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_upload_limit" >
|
||||
<property name="text" >
|
||||
<string>Set upload limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_download_limit" >
|
||||
<property name="text" >
|
||||
<string>Set download limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDocumentation" >
|
||||
<property name="text" >
|
||||
<string>Documentation</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_global_download_limit" >
|
||||
<property name="text" >
|
||||
<string>Set global download limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_global_upload_limit" >
|
||||
<property name="text" >
|
||||
<string>Set global upload limit</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>search_pattern</sender>
|
||||
<signal>returnPressed()</signal>
|
||||
<receiver>search_button</receiver>
|
||||
<slot>click()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>405</x>
|
||||
<y>125</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>543</x>
|
||||
<y>123</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QStyleOptionViewItemV2>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QProgressBar>
|
||||
@@ -35,80 +36,43 @@
|
||||
#define SIZE 1
|
||||
#define PROGRESS 2
|
||||
|
||||
class PreviewListDelegate: public QAbstractItemDelegate {
|
||||
class PreviewListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PreviewListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
|
||||
PreviewListDelegate(QObject *parent=0) : QItemDelegate(parent){}
|
||||
|
||||
~PreviewListDelegate(){}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QItemDelegate delegate;
|
||||
QStyleOptionViewItem opt = option;
|
||||
QStyleOptionProgressBarV2 newopt;
|
||||
char tmp[MAX_CHAR_TMP];
|
||||
float progress;
|
||||
// set text color
|
||||
QVariant value = index.data(Qt::TextColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
|
||||
}
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
if (option.state & QStyle::State_Selected){
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}else{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
// draw the background color
|
||||
if(index.column() != PROGRESS){
|
||||
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
|
||||
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
|
||||
cg = QPalette::Inactive;
|
||||
}
|
||||
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
|
||||
}else{
|
||||
value = index.data(Qt::BackgroundColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
|
||||
switch(index.column()){
|
||||
case SIZE:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case NAME:
|
||||
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
|
||||
break;
|
||||
case PROGRESS:
|
||||
progress = index.data().toDouble()*100.;
|
||||
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
|
||||
case PROGRESS:{
|
||||
float progress = index.data().toDouble()*100.;
|
||||
QStyleOptionProgressBarV2 newopt;
|
||||
newopt.rect = opt.rect;
|
||||
newopt.text = QString(tmp)+"%";
|
||||
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
|
||||
newopt.progress = (int)progress;
|
||||
newopt.maximum = 100;
|
||||
newopt.minimum = 0;
|
||||
newopt.state |= QStyle::State_Enabled;
|
||||
newopt.textVisible = false;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
|
||||
painter);
|
||||
//We prefer to display text manually to control color/font/boldness
|
||||
if (option.state & QStyle::State_Selected){
|
||||
opt.palette.setColor(QPalette::Text, QColor("grey"));
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
|
||||
newopt.textVisible = true;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QItemDelegate delegate;
|
||||
return delegate.sizeHint(option, index);
|
||||
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
// No editor here
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
#ifndef PROPLISTDELEGATE_H
|
||||
#define PROPLISTDELEGATE_H
|
||||
|
||||
#include <QAbstractItemDelegate>
|
||||
#include <QItemDelegate>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QStyleOptionViewItemV2>
|
||||
#include <QStyleOptionComboBox>
|
||||
#include <QComboBox>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QProgressBar>
|
||||
@@ -34,82 +37,112 @@
|
||||
#define NAME 0
|
||||
#define SIZE 1
|
||||
#define PROGRESS 2
|
||||
#define SELECTED 3
|
||||
#define PRIORITY 3
|
||||
#define INDEX 4
|
||||
|
||||
class PropListDelegate: public QAbstractItemDelegate {
|
||||
#define IGNORED 0
|
||||
#define NORMAL 1
|
||||
#define HIGH 2
|
||||
#define MAXIMUM 7
|
||||
|
||||
class PropListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
bool* filteredFilesChanged;
|
||||
|
||||
public:
|
||||
PropListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
|
||||
PropListDelegate(QObject *parent=0, bool* filteredFilesChanged=0) : QItemDelegate(parent){
|
||||
this->filteredFilesChanged = filteredFilesChanged;
|
||||
}
|
||||
|
||||
~PropListDelegate(){}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QStyleOptionViewItem opt = option;
|
||||
char tmp[MAX_CHAR_TMP];
|
||||
// set text color
|
||||
QVariant value = index.data(Qt::TextColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
|
||||
}
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
if (option.state & QStyle::State_Selected){
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}else{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
// draw the background color
|
||||
if(index.column() != PROGRESS){
|
||||
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
|
||||
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
|
||||
cg = QPalette::Inactive;
|
||||
}
|
||||
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
|
||||
}else{
|
||||
value = index.data(Qt::BackgroundColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
switch(index.column()){
|
||||
case SIZE:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case NAME:
|
||||
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case PROGRESS:{
|
||||
QStyleOptionProgressBarV2 newopt;
|
||||
float progress = index.data().toDouble()*100.;
|
||||
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
|
||||
newopt.rect = opt.rect;
|
||||
newopt.text = QString(tmp)+"%";
|
||||
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
|
||||
newopt.progress = (int)progress;
|
||||
newopt.maximum = 100;
|
||||
newopt.minimum = 0;
|
||||
newopt.state |= QStyle::State_Enabled;
|
||||
newopt.textVisible = false;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
|
||||
painter);
|
||||
//We prefer to display text manually to control color/font/boldness
|
||||
if (option.state & QStyle::State_Selected){
|
||||
opt.palette.setColor(QPalette::Text, QColor("grey"));
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
|
||||
newopt.textVisible = true;
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
|
||||
break;
|
||||
}
|
||||
case SELECTED:
|
||||
if(index.data().toBool()){
|
||||
painter->drawText(option.rect, Qt::AlignCenter, tr("True"));
|
||||
}else{
|
||||
painter->drawText(option.rect, Qt::AlignCenter, tr("False"));
|
||||
case PRIORITY:{
|
||||
QStyleOptionComboBox newopt;
|
||||
newopt.rect = opt.rect;
|
||||
switch(index.data().toInt()){
|
||||
case IGNORED:
|
||||
newopt.currentText = tr("Ignored");
|
||||
break;
|
||||
case NORMAL:
|
||||
newopt.currentText = tr("Normal", "Normal (priority)");
|
||||
break;
|
||||
case HIGH:
|
||||
newopt.currentText = tr("High", "High (priority)");
|
||||
break;
|
||||
case MAXIMUM:
|
||||
newopt.currentText = tr("Maximum", "Maximum (priority)");
|
||||
break;
|
||||
default:
|
||||
qDebug("Unhandled priority, setting NORMAL");
|
||||
newopt.currentText = tr("Normal", "Normal (priority)");
|
||||
}
|
||||
newopt.state |= QStyle::State_Enabled;
|
||||
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &newopt,
|
||||
painter);
|
||||
opt.palette.setColor(QPalette::Text, QColor("black"));
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
painter->drawText(option.rect, Qt::AlignLeft, QString::fromUtf8(" ")+newopt.currentText);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const {
|
||||
if(index.column() != PRIORITY) return 0;
|
||||
QComboBox* editor = new QComboBox(parent);
|
||||
editor->setFocusPolicy(Qt::StrongFocus);
|
||||
editor->addItem(tr("Ignored"));
|
||||
editor->addItem(tr("Normal", "Normal (priority)"));
|
||||
editor->addItem(tr("High", "High (priority)"));
|
||||
editor->addItem(tr("Maximum", "Maximum (priority)"));
|
||||
return editor;
|
||||
}
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const {
|
||||
unsigned short val = index.model()->data(index, Qt::DisplayRole).toInt();
|
||||
QComboBox *combobox = static_cast<QComboBox*>(editor);
|
||||
qDebug("Set Editor data: Prio is %d", val);
|
||||
switch(val){
|
||||
case IGNORED:
|
||||
combobox->setCurrentIndex(0);
|
||||
break;
|
||||
case NORMAL:
|
||||
combobox->setCurrentIndex(1);
|
||||
break;
|
||||
case HIGH:
|
||||
combobox->setCurrentIndex(2);
|
||||
break;
|
||||
case MAXIMUM:
|
||||
combobox->setCurrentIndex(3);
|
||||
break;
|
||||
default:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
|
||||
qDebug("Unhandled priority, setting to NORMAL");
|
||||
combobox->setCurrentIndex(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +154,71 @@ class PropListDelegate: public QAbstractItemDelegate {
|
||||
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
|
||||
return textRect.size();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
||||
QComboBox *combobox = static_cast<QComboBox*>(editor);
|
||||
int value = combobox->currentIndex();
|
||||
qDebug("Setting combobox value in index: %d", value);
|
||||
unsigned short old_val = index.model()->data(index, Qt::DisplayRole).toInt();
|
||||
switch(value){
|
||||
case 0:
|
||||
if(old_val != IGNORED){
|
||||
model->setData(index, QVariant(IGNORED));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
} else {
|
||||
// XXX: hack to force the model to send the itemChanged() signal
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
model->setData(index, QVariant(IGNORED));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(old_val != NORMAL){
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
} else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(old_val != HIGH){
|
||||
model->setData(index, QVariant(HIGH));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
} else {
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
model->setData(index, QVariant(HIGH));
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(old_val != MAXIMUM){
|
||||
model->setData(index, QVariant(MAXIMUM));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
} else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(MAXIMUM));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(old_val != NORMAL){
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
if(filteredFilesChanged != 0)
|
||||
*filteredFilesChanged = true;
|
||||
} else {
|
||||
model->setData(index, QVariant(HIGH));
|
||||
model->setData(index, QVariant(NORMAL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const {
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
#ifndef SEARCHLISTDELEGATE_H
|
||||
#define SEARCHLISTDELEGATE_H
|
||||
|
||||
#include <QAbstractItemDelegate>
|
||||
#include <QItemDelegate>
|
||||
#include <QStyleOptionProgressBarV2>
|
||||
#include <QStyleOptionViewItemV2>
|
||||
#include <QModelIndex>
|
||||
#include <QPainter>
|
||||
#include <QProgressBar>
|
||||
@@ -36,59 +37,29 @@
|
||||
#define LEECHERS 3
|
||||
#define ENGINE 4
|
||||
|
||||
class SearchListDelegate: public QAbstractItemDelegate {
|
||||
class SearchListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SearchListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
|
||||
SearchListDelegate(QObject *parent=0) : QItemDelegate(parent){}
|
||||
|
||||
~SearchListDelegate(){}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QStyleOptionViewItem opt = option;
|
||||
// set text color
|
||||
QVariant value = index.data(Qt::TextColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
|
||||
}
|
||||
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
if (option.state & QStyle::State_Selected){
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}else{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
// draw the background color
|
||||
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
|
||||
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
|
||||
cg = QPalette::Inactive;
|
||||
}
|
||||
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
|
||||
}else{
|
||||
value = index.data(Qt::BackgroundColorRole);
|
||||
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
|
||||
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
|
||||
}
|
||||
}
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
switch(index.column()){
|
||||
case SIZE:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
case NAME:
|
||||
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
default:
|
||||
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
|
||||
QVariant value = index.data(Qt::FontRole);
|
||||
QFont fnt = value.isValid() ? qvariant_cast<QFont>(value) : option.font;
|
||||
QFontMetrics fontMetrics(fnt);
|
||||
const QString text = index.data(Qt::DisplayRole).toString();
|
||||
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
|
||||
return textRect.size();
|
||||
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
// No editor here
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
549
src/about.ui
@@ -1,7 +1,5 @@
|
||||
<ui version="4.0" >
|
||||
<author>Christophe Dumez</author>
|
||||
<comment></comment>
|
||||
<exportmacro></exportmacro>
|
||||
<class>AboutDlg</class>
|
||||
<widget class="QDialog" name="AboutDlg" >
|
||||
<property name="geometry" >
|
||||
@@ -12,26 +10,38 @@
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>504</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>504</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>About qBittorrent</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="logo" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
@@ -40,9 +50,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="lb_name" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>5</vsizetype>
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@@ -55,6 +63,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -66,289 +87,257 @@
|
||||
<attribute name="title" >
|
||||
<string>About</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
<widget class="QLabel" name="mascot_lbl" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>380</x>
|
||||
<y>50</y>
|
||||
<width>94</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget1" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lb_about" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.<br>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lb_about" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>40</y>
|
||||
<width>481</width>
|
||||
<height>102</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.<br>
|
||||
<br>
|
||||
Copyright © 2006 by Christophe Dumez<br>
|
||||
<br> <u>Home Page:</u> <i>http://www.qbittorrent.org</i><br></string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab3" >
|
||||
<attribute name="title" >
|
||||
<string>Author</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="te_authors" >
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" >
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
<property name="text" >
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_birthday" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Birthday:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_occupation" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Occupation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Home page:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>03/05/1985</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Student in computer science</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>http://www.dchris.eu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Country:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_birthday" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Birthday:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_occupation" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Occupation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>E-mail:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>true</underline>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Home page:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType" >
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Christophe Dumez</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>France</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>03/05/1985</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Student in computer science</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>chris@qbittorrent.org</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>http://www.dchris.eu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
@@ -370,12 +359,9 @@ Copyright © 2006 by Christophe Dumez<br>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab4" >
|
||||
<attribute name="title" >
|
||||
<string>Thanks To</string>
|
||||
<string>Thanks to</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
@@ -389,9 +375,6 @@ Copyright © 2006 by Christophe Dumez<br>
|
||||
<string>Translation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
@@ -409,9 +392,6 @@ Copyright © 2006 by Christophe Dumez<br>
|
||||
<string>License</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
@@ -425,7 +405,6 @@ Copyright © 2006 by Christophe Dumez<br>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11" />
|
||||
<pixmapfunction></pixmapfunction>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -23,51 +23,64 @@
|
||||
#define ABOUT_H
|
||||
|
||||
#include "ui_about.h"
|
||||
#include <QScrollBar>
|
||||
|
||||
class about : public QDialog, private Ui::AboutDlg{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
about(QWidget *parent = 0): QDialog(parent){
|
||||
~about() {
|
||||
qDebug("Deleting about dlg");
|
||||
}
|
||||
|
||||
about(QWidget *parent): QDialog(parent){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
// Set icons
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent32.png")));
|
||||
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent22.png")));
|
||||
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/mascot.png")));
|
||||
//Title
|
||||
lb_name->setText("<b><h1>"+tr("qBittorrent")+" "VERSION"</h1></b>");
|
||||
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
|
||||
// Thanks
|
||||
te_thanks->append("<ul><li>I would like to thank sourceforge.net for hosting qBittorrent project.</li>");
|
||||
te_thanks->append("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, webdevelopper and RPM packager, for his help.</li>");
|
||||
te_thanks->append("<li>I am gratefull to Peter Koeleman (peter@qbittorrent.org) and Johnny Mast (rave@qbittorrent.org) who helped me port qBittorrent to Windows.</li>");
|
||||
te_thanks->append("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul>");
|
||||
te_thanks->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
te_thanks->append(QString::fromUtf8("<ul><li>I would like to thank sourceforge.net for hosting qBittorrent project.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I am happy that Arnaud Demaizière is contributing to the project as a developer. His help is greatly appreciated</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, RPM packager, for his help and support.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>I am grateful to Peter Koeleman (peter@qbittorrent.org) who is helping port qBittorrent to Windows.</li>"));
|
||||
te_thanks->append(QString::fromUtf8("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul><br><br>"));
|
||||
te_thanks->scrollToAnchor(QString::fromUtf8("top"));
|
||||
// Translation
|
||||
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"<br>");
|
||||
te_translation->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+QString::fromUtf8("<br>"));
|
||||
te_translation->append(QString::fromUtf8(
|
||||
"<i>- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
||||
- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Catalan:</u> Gekko Dam Beer (gekko04@users.sourceforge.net)<br>\
|
||||
- <u>Chinese (Simplified):</u> Guo Yue (guoyue0418@hotmail.com)<br>\
|
||||
- <u>Chinese (Traditional):</u> Jeff Chen (jeff.cn.chen@gmail.com)<br>\
|
||||
- <u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)<br>\
|
||||
- <u>Dutch:</u> Luke Niesink (luke@lukeniesink.net)<br>\
|
||||
- <u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net)<br>\
|
||||
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net)<br>\
|
||||
- <u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)<br>\
|
||||
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Italian:</u> Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
|
||||
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
|
||||
- <u>Hungarian:</u> Majoros Péter (majoros.j.p@t-online.hu)<br>\
|
||||
- <u>Italian:</u> Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
|
||||
- <u>Japanese:</u> Nardog (nardog@e2umail.com)<br>\
|
||||
- <u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)<br>\
|
||||
- <u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)<br>\
|
||||
- <u>Polish:</u> Adam Babol (a-b@users.sourceforge.net)<br>\
|
||||
- <u>Polish:</u> Jarek Smieja (ajep9691@wp.pl)<br>\
|
||||
- <u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
|
||||
- <u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)<br>\
|
||||
- <u>Russian:</u> Nick Khazov (m2k3d0n at users.sourceforge.net)<br>\
|
||||
- <u>Slovak:</u> helix84<br>\
|
||||
- <u>Spanish:</u> Vicente Raul Plata Fonseca (silverxnt@users.sourceforge.net)<br>\
|
||||
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
|
||||
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
|
||||
- <u>Turkish:</u> Erdem Bingöl (erdem84@gmail.com)<br>\
|
||||
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net)<br><br>"));
|
||||
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
|
||||
te_translation->scrollToAnchor(QString::fromUtf8("top"));
|
||||
// License
|
||||
te_license->append("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
te_license->append(QString::fromUtf8("<a name='top'></a>"));
|
||||
te_license->append(QString::fromUtf8("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
|
||||
<center>Version 2, June 1991</center><br>\
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
|
||||
@@ -400,7 +413,8 @@ class about : public QDialog, private Ui::AboutDlg{
|
||||
proprietary programs. If your program is a subroutine library, you may<br>\
|
||||
consider it more useful to permit linking proprietary applications with the<br>\
|
||||
library. If this is what you want to do, use the GNU Library General<br>\
|
||||
Public License instead of this License.<br>");
|
||||
Public License instead of this License.<br>"));
|
||||
te_license->scrollToAnchor(QString::fromUtf8("top"));
|
||||
show();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,20 +5,29 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>440</width>
|
||||
<height>389</height>
|
||||
<width>511</width>
|
||||
<height>441</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Torrent addition dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="fileNameLbl" >
|
||||
<property name="text" >
|
||||
@@ -48,12 +57,21 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="savePathTxt" />
|
||||
</item>
|
||||
@@ -80,31 +98,16 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="torrentContentList" >
|
||||
<widget class="QTreeView" name="torrentContentList" >
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>File name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>File size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Selected</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -123,12 +126,21 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
@@ -172,20 +184,24 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionSelect" >
|
||||
<action name="actionIgnored" >
|
||||
<property name="text" >
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="iconText" >
|
||||
<string>Select</string>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>Select</string>
|
||||
<string>Ignored</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUnselect" >
|
||||
<action name="actionNormal" >
|
||||
<property name="text" >
|
||||
<string>Unselect</string>
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHigh" >
|
||||
<property name="text" >
|
||||
<string>High</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMaximum" >
|
||||
<property name="text" >
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
|
||||
179
src/allocationDlg.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef BANDWIDTH_ALLOCATION_H
|
||||
#define BANDWIDTH_ALLOCATION_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QList>
|
||||
#include <QSettings>
|
||||
#include "ui_bandwidth_limit.h"
|
||||
#include "misc.h"
|
||||
#include "bittorrent.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class BandwidthAllocationDialog : public QDialog, private Ui_bandwidth_dlg {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BandwidthAllocationDialog(QWidget *parent, bool uploadMode, bittorrent *BTSession, QStringList hashes): QDialog(parent), uploadMode(uploadMode), hashes(hashes){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
qDebug("Bandwidth allocation dialog creation");
|
||||
this->BTSession = BTSession;
|
||||
if(hashes.size() == 0)
|
||||
global = true;
|
||||
else
|
||||
global = false;
|
||||
if(uploadMode)
|
||||
lblTitle->setText(tr("Upload limit:"));
|
||||
else
|
||||
lblTitle->setText(tr("Download limit:"));
|
||||
connect(bandwidthSlider, SIGNAL(valueChanged(int)), this, SLOT(updateBandwidthLabel(int)));
|
||||
if(!global){
|
||||
unsigned int nbTorrents = hashes.size();
|
||||
if(!nbTorrents) close();
|
||||
int val = 0;
|
||||
int max = -1;
|
||||
if(nbTorrents == 1){
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hashes.at(0));
|
||||
if(uploadMode){
|
||||
if(h.upload_limit() > 0)
|
||||
val = (int)(h.upload_limit() / 1024.);
|
||||
if(BTSession->getSession()->upload_rate_limit() > 0)
|
||||
max = (int)(BTSession->getSession()->upload_rate_limit() / 1024.);
|
||||
}else{
|
||||
if(h.download_limit() > 0)
|
||||
val = (int)(h.download_limit() / 1024.);
|
||||
if(BTSession->getSession()->download_rate_limit() > 0){
|
||||
qDebug("there is a global download rate limit at: %d kb/s", (int)(BTSession->getSession()->download_rate_limit() / 1024.));
|
||||
max = (int)(BTSession->getSession()->download_rate_limit() / 1024.);
|
||||
}
|
||||
}
|
||||
if(max != -1)
|
||||
bandwidthSlider->setMaximum(max);
|
||||
qDebug("Bandwidth limit: %d", val);
|
||||
if(val > bandwidthSlider->maximum())
|
||||
val = bandwidthSlider->maximum();
|
||||
else if(val < bandwidthSlider->minimum())
|
||||
val = 0;
|
||||
bandwidthSlider->setValue(val);
|
||||
if(val == 0) {
|
||||
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
|
||||
kb_lbl->setText(QString::fromUtf8(""));
|
||||
} else {
|
||||
limit_lbl->setText(misc::toQString(val));
|
||||
}
|
||||
}else{
|
||||
qDebug("More than one torrent selected, no initilization");
|
||||
bandwidthSlider->setValue(0);
|
||||
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
|
||||
kb_lbl->setText(QString::fromUtf8(""));
|
||||
}
|
||||
}else{
|
||||
// Global limit
|
||||
int val = 0;
|
||||
session *s = BTSession->getSession();
|
||||
if(uploadMode){
|
||||
if(s->upload_rate_limit() > 0)
|
||||
val = (int)(s->upload_rate_limit()/1024.);
|
||||
}else{
|
||||
if(s->download_rate_limit() > 0)
|
||||
val = (int)(s->download_rate_limit()/1024.);
|
||||
}
|
||||
if(val == 0){
|
||||
bandwidthSlider->setValue(0);
|
||||
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
|
||||
kb_lbl->setText(QString::fromUtf8(""));
|
||||
}else{
|
||||
bandwidthSlider->setValue(val);
|
||||
}
|
||||
}
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(setBandwidth()));
|
||||
show();
|
||||
}
|
||||
|
||||
~BandwidthAllocationDialog(){
|
||||
qDebug("Deleting bandwidth allocation dialog");
|
||||
}
|
||||
|
||||
protected slots:
|
||||
void updateBandwidthLabel(int val){
|
||||
if(val == 0){
|
||||
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
|
||||
kb_lbl->setText(QString::fromUtf8(""));
|
||||
}else{
|
||||
limit_lbl->setText(misc::toQString(val));
|
||||
kb_lbl->setText(tr("KiB/s"));
|
||||
}
|
||||
}
|
||||
|
||||
void setBandwidth(){
|
||||
qDebug("setBandwidth called");
|
||||
int val = bandwidthSlider->value();
|
||||
if(!global){
|
||||
QString hash;
|
||||
if(uploadMode) {
|
||||
foreach(hash, hashes) {
|
||||
if(!val)
|
||||
BTSession->setUploadLimit(hash, -1);
|
||||
else
|
||||
BTSession->setUploadLimit(hash, val*1024);
|
||||
qDebug("Setting upload limit");
|
||||
}
|
||||
} else {
|
||||
foreach(hash, hashes) {
|
||||
if(!val)
|
||||
BTSession->setDownloadLimit(hash, -1);
|
||||
else
|
||||
BTSession->setDownloadLimit(hash, val*1024);
|
||||
qDebug("Setting download limit");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
session *s = BTSession->getSession();
|
||||
if(uploadMode){
|
||||
if(!val)
|
||||
s->set_upload_rate_limit(-1);
|
||||
else
|
||||
s->set_upload_rate_limit(val*1024);
|
||||
settings.setValue(QString::fromUtf8("Preferences/Connection/GlobalUPLimit"), val);
|
||||
}else{
|
||||
if(!val)
|
||||
s->set_download_rate_limit(-1);
|
||||
else
|
||||
s->set_download_rate_limit(val*1024);
|
||||
settings.setValue(QString::fromUtf8("Preferences/Connection/GlobalDLLimit"), val);
|
||||
}
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
private:
|
||||
bool uploadMode;
|
||||
bool global;
|
||||
bittorrent *BTSession;
|
||||
QStringList hashes;
|
||||
};
|
||||
|
||||
#endif
|
||||
256
src/arborescence.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef ARBORESCENCE_H
|
||||
#define ARBORESCENCE_H
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
#include "misc.h"
|
||||
|
||||
class file {
|
||||
private:
|
||||
file *parent;
|
||||
bool is_dir;
|
||||
QString rel_path;
|
||||
QList<file*> children;
|
||||
size_type size;
|
||||
float progress;
|
||||
int priority;
|
||||
int index; // Index in torrent_info
|
||||
|
||||
public:
|
||||
file(file *parent, QString path, bool dir, size_type size=0, int index=-1, float progress=0., int priority=1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
|
||||
qDebug("created a file with index %d", index);
|
||||
rel_path = QDir::cleanPath(path);
|
||||
if(parent) {
|
||||
parent->updateProgress();
|
||||
parent->updatePriority(priority);
|
||||
}
|
||||
}
|
||||
|
||||
~file() {
|
||||
qDeleteAll(children);
|
||||
}
|
||||
|
||||
QString path() const {
|
||||
return rel_path;
|
||||
}
|
||||
|
||||
QString name() const {
|
||||
return rel_path.split(QDir::separator()).last();
|
||||
}
|
||||
|
||||
void updateProgress() {
|
||||
Q_ASSERT(is_dir);
|
||||
float sum = 0;
|
||||
file *child;
|
||||
foreach(child, children) {
|
||||
sum += child->getProgress();
|
||||
}
|
||||
progress = sum / (float)children.size();
|
||||
}
|
||||
|
||||
void updatePriority(int prio) {
|
||||
Q_ASSERT(is_dir);
|
||||
file *child;
|
||||
foreach(child, children) {
|
||||
if(child->getPriority() != prio) return;
|
||||
}
|
||||
priority = prio;
|
||||
}
|
||||
|
||||
int getPriority() const {
|
||||
return priority;
|
||||
}
|
||||
|
||||
size_type getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
float getProgress() const {
|
||||
return progress;
|
||||
}
|
||||
|
||||
int getIndex() const {
|
||||
return index;
|
||||
}
|
||||
|
||||
bool isDir() const {
|
||||
return is_dir;
|
||||
}
|
||||
|
||||
bool hasChildren() const {
|
||||
return (!children.isEmpty());
|
||||
}
|
||||
|
||||
QList<file*> getChildren() const {
|
||||
return children;
|
||||
}
|
||||
|
||||
file* getChild(QString fileName) const {
|
||||
Q_ASSERT(is_dir);
|
||||
file* f;
|
||||
foreach(f, children) {
|
||||
if(f->name() == fileName) return f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void addBytes(size_type b) {
|
||||
size += b;
|
||||
if(parent)
|
||||
parent->addBytes(b);
|
||||
}
|
||||
|
||||
file* addChild(QString fileName, bool dir, size_type size=0, int index = -1, float progress=0., int priority=1) {
|
||||
Q_ASSERT(is_dir);
|
||||
qDebug("Adding a new child of size: %ld", (long)size);
|
||||
file *f = new file(this, QDir::cleanPath(rel_path+QDir::separator()+fileName), dir, size, index, progress, priority);
|
||||
children << f;
|
||||
if(size) {
|
||||
addBytes(size);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
bool removeFromFS(QString saveDir) {
|
||||
QString full_path = saveDir + QDir::separator() + rel_path;
|
||||
if(!QFile::exists(full_path)) {
|
||||
qDebug("%s does not exist, no need to remove it", full_path.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
bool success = true;
|
||||
file *f;
|
||||
qDebug("We have %d children", children.size());
|
||||
foreach(f, children) {
|
||||
bool s = f->removeFromFS(saveDir);
|
||||
success = s && success;
|
||||
}
|
||||
if(is_dir) {
|
||||
qDebug("trying to remove directory: %s", full_path.toUtf8().data());
|
||||
QDir dir(full_path);
|
||||
dir.rmdir(full_path);
|
||||
} else {
|
||||
qDebug("trying to remove file: %s", full_path.toUtf8().data());
|
||||
bool s = QFile::remove(full_path);
|
||||
success = s && success;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
};
|
||||
|
||||
class arborescence {
|
||||
private:
|
||||
file *root;
|
||||
|
||||
public:
|
||||
arborescence(torrent_info t) {
|
||||
torrent_info::file_iterator fi = t.begin_files();
|
||||
if(t.num_files() > 1) {
|
||||
root = new file(0, misc::toQString(t.name()), true);
|
||||
} else {
|
||||
// XXX: Will crash if there is no file in torrent
|
||||
root = new file(0, misc::toQString(t.name()), false, fi->size, 0);
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while(fi != t.end_files()) {
|
||||
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
|
||||
addFile(path, fi->size, i);
|
||||
fi++;
|
||||
++i;
|
||||
}
|
||||
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
|
||||
Q_ASSERT(root->getSize() == t.total_size());
|
||||
}
|
||||
|
||||
arborescence(torrent_info t, std::vector<float> fp, int *prioritiesTab) {
|
||||
torrent_info::file_iterator fi = t.begin_files();
|
||||
if(t.num_files() > 1) {
|
||||
qDebug("More than one file in the torrent, setting a folder as root");
|
||||
root = new file(0, misc::toQString(t.name()), true);
|
||||
} else {
|
||||
// XXX: Will crash if there is no file in torrent
|
||||
qDebug("one file in the torrent, setting it as root with index 0");
|
||||
root = new file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0], prioritiesTab[0]);
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while(fi != t.end_files()) {
|
||||
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
|
||||
addFile(path, fi->size, i, fp[i], prioritiesTab[i]);
|
||||
fi++;
|
||||
++i;
|
||||
}
|
||||
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
|
||||
Q_ASSERT(root->getSize() == t.total_size());
|
||||
}
|
||||
|
||||
~arborescence() {
|
||||
delete root;
|
||||
}
|
||||
|
||||
file* getRoot() const {
|
||||
return root;
|
||||
}
|
||||
|
||||
bool removeFromFS(QString saveDir) {
|
||||
if(!QFile::exists(saveDir+QDir::separator()+root->path())) return true;
|
||||
bool success = root->removeFromFS(saveDir);
|
||||
QDir root_dir(root->path());
|
||||
root_dir.rmdir(saveDir+QDir::separator()+root->path());
|
||||
return success;
|
||||
}
|
||||
|
||||
protected:
|
||||
void addFile(QString path, size_type file_size, int index, float progress=0., int priority=1) {
|
||||
Q_ASSERT(root->isDir());
|
||||
path = QDir::cleanPath(path);
|
||||
Q_ASSERT(path.startsWith(root->path()));
|
||||
QString relative_path = path.remove(0, root->path().size());
|
||||
if(relative_path.at(0) ==QDir::separator())
|
||||
relative_path.remove(0, 1);
|
||||
QStringList fileNames = relative_path.split(QDir::separator());
|
||||
QString fileName;
|
||||
file *dad = root;
|
||||
unsigned int nb_i = 0;
|
||||
unsigned int size = fileNames.size();
|
||||
foreach(fileName, fileNames) {
|
||||
++nb_i;
|
||||
if(fileName == ".") continue;
|
||||
file* child = dad->getChild(fileName);
|
||||
if(!child) {
|
||||
if(nb_i != size) {
|
||||
// Folder
|
||||
child = dad->addChild(fileName, true);
|
||||
} else {
|
||||
// File
|
||||
child = dad->addChild(fileName, false, file_size, index, progress, priority);
|
||||
}
|
||||
}
|
||||
dad = child;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
113
src/bandwidth_limit.ui
Normal file
@@ -0,0 +1,113 @@
|
||||
<ui version="4.0" >
|
||||
<class>bandwidth_dlg</class>
|
||||
<widget class="QDialog" name="bandwidth_dlg" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>222</width>
|
||||
<height>129</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Bandwidth allocation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTitle" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="limit_lbl" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="kb_lbl" >
|
||||
<property name="text" >
|
||||
<string>KiB/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="bandwidthSlider" >
|
||||
<property name="minimum" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="sliderPosition" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>bandwidth_dlg</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>212</x>
|
||||
<y>83</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>221</x>
|
||||
<y>98</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
1314
src/bittorrent.cpp
164
src/bittorrent.h
@@ -21,133 +21,149 @@
|
||||
#ifndef __BITTORRENT_H__
|
||||
#define __BITTORRENT_H__
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/fingerprint.hpp>
|
||||
#include <libtorrent/session_settings.hpp>
|
||||
#include <libtorrent/identify_client.hpp>
|
||||
#include <libtorrent/alert_types.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
|
||||
#ifndef NO_PEX
|
||||
#include <libtorrent/extensions/metadata_transfer.hpp>
|
||||
#include <libtorrent/extensions/ut_pex.hpp>
|
||||
#endif
|
||||
#ifdef NO_PEX
|
||||
#include <QHash>
|
||||
#endif
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem/exception.hpp>
|
||||
|
||||
#include "deleteThread.h"
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
class downloadThread;
|
||||
class QTimer;
|
||||
|
||||
class bittorrent : public QObject{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
session *s;
|
||||
bool DHTEnabled;
|
||||
QString scan_dir;
|
||||
QTimer *timerScan;
|
||||
QTimer *timerAlerts;
|
||||
bool DHTEnabled;
|
||||
downloadThread *downloader;
|
||||
QStringList supported_preview_extensions;
|
||||
QString defaultSavePath;
|
||||
#ifdef NO_PEX
|
||||
QHash<QString, torrent_handle> torrent_list;
|
||||
#endif
|
||||
QStringList torrentsToPauseAfterChecking;
|
||||
QHash<QString, bool> reloadingTorrents;
|
||||
QHash<QString, QList<qlonglong> > ETAstats;
|
||||
QHash<QString, qlonglong> ETAs;
|
||||
QHash<QString, QPair<size_type,size_type> > ratioData;
|
||||
QTimer *ETARefresher;
|
||||
QHash<QString, QList<QPair<QString, QString> > > trackersErrors;
|
||||
QStringList waitingForPause;
|
||||
QStringList finishedTorrents;
|
||||
QStringList unfinishedTorrents;
|
||||
bool preAllocateAll;
|
||||
bool addInPause;
|
||||
int maxConnecsPerTorrent;
|
||||
int maxUploadsPerTorrent;
|
||||
float max_ratio;
|
||||
|
||||
protected:
|
||||
QString getSavePath(const QString& hash);
|
||||
QString getSavePath(QString hash);
|
||||
|
||||
public:
|
||||
// Constructor / Destructor
|
||||
bittorrent();
|
||||
~bittorrent();
|
||||
torrent_handle getTorrentHandle(const QString& hash) const;
|
||||
#ifndef NO_PEX
|
||||
std::vector<torrent_handle> getTorrentHandles() const;
|
||||
#endif
|
||||
#ifdef NO_PEX
|
||||
QList<torrent_handle> getTorrentHandles() const;
|
||||
#endif
|
||||
bool isPaused(const QString& hash) const;
|
||||
bool hasFilteredFiles(const QString& fileHash) const;
|
||||
bool isFilePreviewPossible(const QString& fileHash) const;
|
||||
QTorrentHandle getTorrentHandle(QString hash) const;
|
||||
bool isPaused(QString hash) const;
|
||||
bool isFilePreviewPossible(QString fileHash) const;
|
||||
bool isDHTEnabled() const;
|
||||
float getPayloadDownloadRate() const;
|
||||
float getPayloadUploadRate() const;
|
||||
QList<torrent_handle> getFinishedTorrentHandles() const;
|
||||
session_status getSessionStatus() const;
|
||||
int getListenPort() const;
|
||||
QStringList getTorrentsToPauseAfterChecking() const;
|
||||
long getETA(QString hash) const;
|
||||
float getRealRatio(QString hash) const;
|
||||
session* getSession() const;
|
||||
QList<QPair<QString, QString> > getTrackersErrors(QString hash) const;
|
||||
QStringList getFinishedTorrents() const;
|
||||
QStringList getUnfinishedTorrents() const;
|
||||
bool isFinished(QString hash) const;
|
||||
bool has_filtered_files(QString hash) const;
|
||||
|
||||
public slots:
|
||||
void addTorrent(const QString& path, bool fromScanDir = false, const QString& from_url = QString());
|
||||
void downloadFromUrl(const QString& url);
|
||||
void addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
|
||||
void downloadFromUrl(QString url);
|
||||
void downloadFromURLList(const QStringList& url_list);
|
||||
void deleteTorrent(const QString& hash, bool permanent = false);
|
||||
void pauseTorrent(const QString& hash);
|
||||
void pauseAllTorrents();
|
||||
void resumeAllTorrents();
|
||||
void resumeTorrent(const QString& hash);
|
||||
void enableDHT();
|
||||
void disableDHT();
|
||||
void deleteTorrent(QString hash, bool permanent = false);
|
||||
bool pauseTorrent(QString hash);
|
||||
bool resumeTorrent(QString hash);
|
||||
void saveDHTEntry();
|
||||
void saveFastResumeData();
|
||||
void enableDirectoryScanning(const QString& scan_dir);
|
||||
void preAllocateAllFiles(bool b);
|
||||
void saveFastResumeAndRatioData();
|
||||
void enableDirectoryScanning(QString scan_dir);
|
||||
void disableDirectoryScanning();
|
||||
#ifndef NO_PEX
|
||||
void enablePeerExchange();
|
||||
#endif
|
||||
void enableIPFilter(ip_filter filter);
|
||||
void disableIPFilter();
|
||||
void reloadTorrent(const torrent_handle &h, bool compact_mode = true);
|
||||
void resumeUnfinishedTorrents();
|
||||
void updateETAs();
|
||||
void saveTorrentSpeedLimits(QString hash);
|
||||
void loadTorrentSpeedLimits(QString hash);
|
||||
void saveDownloadUploadForTorrent(QString hash);
|
||||
void loadDownloadUploadForTorrent(QString hash);
|
||||
void handleDownloadFailure(QString url, QString reason);
|
||||
void loadWebSeeds(QString fileHash);
|
||||
// Session configuration - Setters
|
||||
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
|
||||
void setMaxConnections(int maxConnec);
|
||||
void setDownloadRateLimit(int rate);
|
||||
void setUploadRateLimit(int rate);
|
||||
void setMaxConnectionsPerTorrent(int max);
|
||||
void setMaxUploadsPerTorrent(int max);
|
||||
void setDownloadRateLimit(long rate);
|
||||
void setUploadRateLimit(long rate);
|
||||
void setGlobalRatio(float ratio);
|
||||
void setDeleteRatio(float ratio);
|
||||
void setDHTPort(int dht_port);
|
||||
void setProxySettings(proxy_settings proxySettings, bool trackers=true, bool peers=true, bool web_seeds=true, bool dht=true);
|
||||
void setSessionSettings(session_settings sessionSettings);
|
||||
#ifdef V_0_13
|
||||
void setProxySettings(proxy_settings proxySettings);
|
||||
#endif
|
||||
void setDefaultSavePath(const QString& savepath);
|
||||
void startTorrentsInPause(bool b);
|
||||
void setDefaultSavePath(QString savepath);
|
||||
void applyEncryptionSettings(pe_settings se);
|
||||
void loadFilesPriorities(QTorrentHandle& h);
|
||||
void setDownloadLimit(QString hash, long val);
|
||||
void setUploadLimit(QString hash, long val);
|
||||
void setUnfinishedTorrent(QString hash);
|
||||
void setFinishedTorrent(QString hash);
|
||||
void enableUPnP(bool b);
|
||||
void enableNATPMP(bool b);
|
||||
void enableLSD(bool b);
|
||||
void enableDHT(bool b);
|
||||
|
||||
protected slots:
|
||||
void cleanDeleter(deleteThread* deleter);
|
||||
void loadFilteredFiles(torrent_handle& h);
|
||||
void scanDirectory();
|
||||
void readAlerts();
|
||||
void processDownloadedFile(const QString&, const QString&, int, const QString&);
|
||||
void resumeUnfinished();
|
||||
void processDownloadedFile(QString, QString);
|
||||
bool loadTrackerFile(QString hash);
|
||||
void saveTrackerFile(QString hash);
|
||||
void pauseAndReloadTorrent(QTorrentHandle h, bool full_alloc);
|
||||
void reloadTorrent(const QTorrentHandle &h, bool full_alloc); // This is protected now, call pauseAndReloadTorrent() instead
|
||||
void deleteBigRatios();
|
||||
|
||||
signals:
|
||||
void invalidTorrent(const QString& path);
|
||||
void duplicateTorrent(const QString& path);
|
||||
void addedTorrent(const QString& path, torrent_handle& h, bool fastResume);
|
||||
void finishedTorrent(torrent_handle& h);
|
||||
void fullDiskError(torrent_handle& h);
|
||||
void trackerError(const QString& hash, const QString& time, const QString& msg);
|
||||
void invalidTorrent(QString path);
|
||||
void duplicateTorrent(QString path);
|
||||
void addedTorrent(QString path, QTorrentHandle& h, bool fastResume);
|
||||
void finishedTorrent(QTorrentHandle& h);
|
||||
void fullDiskError(QTorrentHandle& h);
|
||||
void trackerError(QString hash, QString time, QString msg);
|
||||
void portListeningFailure();
|
||||
void trackerAuthenticationRequired(torrent_handle& h);
|
||||
void downloadFromUrlFailure(const QString& url, const QString& error);
|
||||
void trackerAuthenticationRequired(QTorrentHandle& h);
|
||||
void scanDirFoundTorrents(const QStringList& pathList);
|
||||
void newDownloadedTorrent(const QString& path, const QString& url);
|
||||
void aboutToDownloadFromUrl(const QString& url);
|
||||
void newDownloadedTorrent(QString path, QString url);
|
||||
void aboutToDownloadFromUrl(QString url);
|
||||
void updateFileSize(QString hash);
|
||||
void peerBlocked(QString);
|
||||
void downloadFromUrlFailure(QString url, QString reason);
|
||||
void fastResumeDataRejected(QString name);
|
||||
void urlSeedProblem(QString url, QString msg);
|
||||
void torrentFinishedChecking(QString hash);
|
||||
void torrent_deleted(QString hash, QString fileName, bool finished);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
19
src/convertPOtoTS.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
|
||||
LANG_FOLDER = "lang/"
|
||||
PO_FOLDER = 'po_files'
|
||||
|
||||
if __name__ == '__main__':
|
||||
po_files = os.listdir(os.path.join(LANG_FOLDER, PO_FOLDER))
|
||||
po_files = [x for x in po_files if os.path.splitext(x)[-1] == ".po"]
|
||||
for file in po_files:
|
||||
# First clean up the ts file
|
||||
ts_file = os.path.join(LANG_FOLDER, os.path.splitext(file)[0]+'.ts')
|
||||
po_file = os.path.join(LANG_FOLDER, PO_FOLDER, file)
|
||||
if os.path.exists(ts_file):
|
||||
os.remove(ts_file)
|
||||
# Convert to PO
|
||||
print "Converting %s..." % (po_file,)
|
||||
os.system("po2ts %s -o %s" % (po_file, ts_file))
|
||||
24
src/convertTStoPO.py
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
|
||||
LANG_FOLDER = 'lang/'
|
||||
PO_FOLDER = 'po_files'
|
||||
|
||||
if __name__ == '__main__':
|
||||
ts_files = os.listdir(LANG_FOLDER)
|
||||
ts_files = [x for x in ts_files if os.path.splitext(x)[-1] == ".ts"]
|
||||
for file in ts_files:
|
||||
# First clean up the po file
|
||||
po_file = os.path.join(LANG_FOLDER, PO_FOLDER, os.path.splitext(file)[0]+'.po')
|
||||
ts_file = os.path.join(LANG_FOLDER, file)
|
||||
if os.path.exists(po_file):
|
||||
os.remove(po_file)
|
||||
# create po folder if it doesn't exist
|
||||
if not os.path.exists(os.path.join(LANG_FOLDER, PO_FOLDER)):
|
||||
os.mkdir(os.path.join(LANG_FOLDER, PO_FOLDER))
|
||||
# Convert to PO
|
||||
print "Converting %s..." % (ts_file,)
|
||||
os.system("ts2po %s -o %s" % (ts_file, po_file))
|
||||
# Making an archive
|
||||
os.system("tar czf %s %s" % (os.path.join(LANG_FOLDER, PO_FOLDER)+'.tar.gz', os.path.join(LANG_FOLDER, PO_FOLDER)))
|
||||
@@ -1,27 +1,18 @@
|
||||
<ui version="4.0" >
|
||||
<author></author>
|
||||
<comment></comment>
|
||||
<exportmacro></exportmacro>
|
||||
<class>createTorrentDialog</class>
|
||||
<widget class="QDialog" name="createTorrentDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>560</width>
|
||||
<height>307</height>
|
||||
<width>592</width>
|
||||
<height>590</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Torrent Creation Tool</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="createTorrent_title" >
|
||||
<property name="minimumSize" >
|
||||
@@ -48,63 +39,59 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Create Torrent file</string>
|
||||
<string>Torrent file creation</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_input" >
|
||||
<property name="text" >
|
||||
<string>File or folder to add to the torrent:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textInputPath" />
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QPushButton" name="addFile_button" >
|
||||
<property name="text" >
|
||||
<string>Add a file</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/add_file.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addFolder_button" >
|
||||
<property name="text" >
|
||||
<string>Add a folder</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/add_folder.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_destination" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><center>Destination torrent file:</center></string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>txt_destination</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_input" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><center>Input file or directory:</center></string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>txt_input</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_announce_url" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>102</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
@@ -112,7 +99,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><center>Announce url:<br>(One per line)</center></string>
|
||||
<string>Announce urls (trackers):</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring></cstring>
|
||||
@@ -120,9 +107,34 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_comment" >
|
||||
<widget class="QLabel" name="urlSeeds_lbl" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>101</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string><center>Comment:</center></string>
|
||||
<string>Web seeds urls (optional):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_comment" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>102</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>102</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Comment (optional):</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>txt_comment</cstring>
|
||||
@@ -133,64 +145,244 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txt_destination" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browse_destination" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
<widget class="QListWidget" name="trackers_list" >
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addTracker_button" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeTracker_button" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txt_input" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkDirectory" >
|
||||
<property name="text" >
|
||||
<string>Directory</string>
|
||||
<widget class="QListWidget" name="URLSeeds_list" >
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::MultiSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browse_input" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addURLSeed_button" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeURLSeed_button" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="txt_announce" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="txt_comment" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>421</width>
|
||||
<height>102</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="acceptRichText" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -202,12 +394,106 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
<item>
|
||||
<widget class="QLabel" name="txtPieceSize" >
|
||||
<property name="text" >
|
||||
<string>Piece size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboPieceSize" >
|
||||
<property name="currentIndex" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>32 KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>64 KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>128 KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>256 KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>512 KiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>1 MiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>2 MiB</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>4 MiB</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="check_private" >
|
||||
<property name="text" >
|
||||
<string>Private (won't be distributed on DHT network if enabled)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkStartSeeding" >
|
||||
<property name="text" >
|
||||
<string>Start seeding after creation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
@@ -224,7 +510,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="createButton" >
|
||||
<property name="text" >
|
||||
<string>Create</string>
|
||||
<string>Create and save...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -252,8 +538,9 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<pixmapfunction></pixmapfunction>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="icons.qrc" />
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cancelButton</sender>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -32,10 +33,7 @@
|
||||
#include <libtorrent/file.hpp>
|
||||
#include <libtorrent/storage.hpp>
|
||||
#include <libtorrent/hasher.hpp>
|
||||
|
||||
#ifndef NO_PEX
|
||||
#include <libtorrent/file_pool.hpp>
|
||||
#endif
|
||||
|
||||
#include "createtorrent_imp.h"
|
||||
|
||||
@@ -48,26 +46,74 @@ createtorrent::createtorrent(QWidget *parent): QDialog(parent){
|
||||
show();
|
||||
}
|
||||
|
||||
void createtorrent::on_browse_destination_clicked(){
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+" (*.torrent)");
|
||||
if(!destination.isEmpty()){
|
||||
txt_destination->setText(destination);
|
||||
void createtorrent::on_addFolder_button_clicked(){
|
||||
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
|
||||
if(!dir.isEmpty())
|
||||
textInputPath->setText(dir);
|
||||
}
|
||||
|
||||
void createtorrent::on_addFile_button_clicked(){
|
||||
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath(), QString(), 0, QFileDialog::ShowDirsOnly);
|
||||
if(!file.isEmpty())
|
||||
textInputPath->setText(file);
|
||||
}
|
||||
|
||||
void createtorrent::on_removeTracker_button_clicked() {
|
||||
QModelIndexList selectedIndexes = trackers_list->selectionModel()->selectedIndexes();
|
||||
for(int i=selectedIndexes.size()-1; i>=0; --i){
|
||||
QListWidgetItem *item = trackers_list->takeItem(selectedIndexes.at(i).row());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void createtorrent::on_browse_input_clicked(){
|
||||
// Can't use QFileDialog static functions for this because
|
||||
// user can select a file or a directory
|
||||
QFileDialog *fd = new QFileDialog(this, tr("Select input directory or file"), QDir::homePath());
|
||||
if(checkDirectory->isChecked()){
|
||||
fd->setFileMode(QFileDialog::DirectoryOnly);
|
||||
}else{
|
||||
fd->setFileMode(QFileDialog::ExistingFile);
|
||||
int createtorrent::getPieceSize() const {
|
||||
switch(comboPieceSize->currentIndex()) {
|
||||
case 0:
|
||||
return 32*1024;
|
||||
case 1:
|
||||
return 64*1024;
|
||||
case 2:
|
||||
return 128*1024;
|
||||
case 3:
|
||||
return 256*1024;
|
||||
case 4:
|
||||
return 512*1024;
|
||||
case 5:
|
||||
return 1024*1024;
|
||||
case 6:
|
||||
return 2048*1024;
|
||||
default:
|
||||
return 256*1024;
|
||||
}
|
||||
QStringList fileNames;
|
||||
if (fd->exec()){
|
||||
fileNames = fd->selectedFiles();
|
||||
txt_input->setText(fileNames.first());
|
||||
}
|
||||
|
||||
void createtorrent::on_addTracker_button_clicked() {
|
||||
bool ok;
|
||||
QString URL = QInputDialog::getText(this, tr("Please type an announce URL"),
|
||||
tr("Announce URL:", "Tracker URL"), QLineEdit::Normal,
|
||||
"http://", &ok);
|
||||
if(ok){
|
||||
if(trackers_list->findItems(URL, Qt::MatchFixedString).size() == 0)
|
||||
trackers_list->addItem(URL);
|
||||
}
|
||||
}
|
||||
|
||||
void createtorrent::on_removeURLSeed_button_clicked(){
|
||||
QModelIndexList selectedIndexes = URLSeeds_list->selectionModel()->selectedIndexes();
|
||||
for(int i=selectedIndexes.size()-1; i>=0; --i){
|
||||
QListWidgetItem *item = URLSeeds_list->takeItem(selectedIndexes.at(i).row());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void createtorrent::on_addURLSeed_button_clicked(){
|
||||
bool ok;
|
||||
QString URL = QInputDialog::getText(this, tr("Please type a web seed url"),
|
||||
tr("Web seed URL:"), QLineEdit::Normal,
|
||||
"http://", &ok);
|
||||
if(ok){
|
||||
if(URLSeeds_list->findItems(URL, Qt::MatchFixedString).size() == 0)
|
||||
URLSeeds_list->addItem(URL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,72 +129,85 @@ void add_files(torrent_info& t, path const& p, path const& l){
|
||||
}
|
||||
}
|
||||
|
||||
QStringList createtorrent::allItems(QListWidget *list){
|
||||
QStringList res;
|
||||
unsigned int nbItems = list->count();
|
||||
for(unsigned int i=0; i< nbItems; ++i){
|
||||
res << list->item(i)->text();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Main function that create a .torrent file
|
||||
void createtorrent::on_createButton_clicked(){
|
||||
QString destination = txt_destination->text();
|
||||
if(destination.isEmpty()){
|
||||
QMessageBox::critical(0, tr("No destination path set"), tr("Please type a destination path first"));
|
||||
return;
|
||||
}
|
||||
QString input = txt_input->text();
|
||||
QString input = textInputPath->text().trimmed();
|
||||
if(input.isEmpty()){
|
||||
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
|
||||
return;
|
||||
}
|
||||
if(!QFile::exists(input)){
|
||||
QMessageBox::critical(0, tr("Input path does not exist"), tr("Please type a valid input path first"));
|
||||
QStringList trackers = allItems(trackers_list);
|
||||
if(!trackers.size()){
|
||||
QMessageBox::critical(0, tr("No tracker path set"), tr("Please set at least one tracker"));
|
||||
return;
|
||||
}
|
||||
char const* creator_str = "qBittorrent";
|
||||
int piece_size = 256 * 1024;
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
|
||||
if(!destination.isEmpty()) {
|
||||
if(!destination.endsWith(QString::fromUtf8(".torrent")))
|
||||
destination += QString::fromUtf8(".torrent");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
char const* creator_str = "qBittorrent "VERSION;
|
||||
try {
|
||||
torrent_info t;
|
||||
path full_path = complete(path((const char*)input.toUtf8()));
|
||||
boost::intrusive_ptr<torrent_info> t(new torrent_info);
|
||||
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
|
||||
|
||||
add_files(t, full_path.branch_path(), full_path.leaf());
|
||||
t.set_piece_size(piece_size);
|
||||
#ifndef NO_PEX
|
||||
file_pool fp;
|
||||
#ifndef V_0_13
|
||||
storage st(t, full_path.branch_path(), fp);
|
||||
#endif
|
||||
#ifdef V_0_13
|
||||
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NO_PEX
|
||||
storage st(t, full_path.branch_path());
|
||||
#endif
|
||||
QStringList trackers = txt_announce->toPlainText().split('\n');
|
||||
path full_path;
|
||||
// Adding files to the torrent
|
||||
full_path = complete(path(input.toUtf8().data()));
|
||||
add_files(*t, full_path.branch_path(), full_path.leaf());
|
||||
// Set piece size
|
||||
int piece_size = getPieceSize();
|
||||
t->set_piece_size(piece_size);
|
||||
// Add url seeds
|
||||
QStringList urlSeeds = allItems(URLSeeds_list);
|
||||
QString seed;
|
||||
foreach(seed, urlSeeds){
|
||||
t->add_url_seed(seed.toUtf8().data());
|
||||
}
|
||||
for(int i=0; i<trackers.size(); ++i){
|
||||
t.add_tracker((const char*)trackers.at(i).toUtf8());
|
||||
t->add_tracker(trackers.at(i).toUtf8().data());
|
||||
}
|
||||
|
||||
// calculate the hash for all pieces
|
||||
int num = t.num_pieces();
|
||||
file_pool fp;
|
||||
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
|
||||
int num = t->num_pieces();
|
||||
std::vector<char> buf(piece_size);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
#ifndef V_0_13
|
||||
st.read(&buf[0], i, 0, t.piece_size(i));
|
||||
#endif
|
||||
#ifdef V_0_13
|
||||
st->read(&buf[0], i, 0, t.piece_size(i));
|
||||
#endif
|
||||
hasher h(&buf[0], t.piece_size(i));
|
||||
t.set_hash(i, h.final());
|
||||
for (int i = 0; i < num; ++i) {
|
||||
st->read(&buf[0], i, 0, t->piece_size(i));
|
||||
hasher h(&buf[0], t->piece_size(i));
|
||||
t->set_hash(i, h.final());
|
||||
}
|
||||
// Set qBittorrent as creator and add user comment to
|
||||
// torrent_info structure
|
||||
t.set_creator(creator_str);
|
||||
t.set_comment((const char*)txt_comment->toPlainText().toUtf8());
|
||||
t->set_creator(creator_str);
|
||||
t->set_comment((const char*)txt_comment->toPlainText().toUtf8());
|
||||
// Is private ?
|
||||
if(check_private->isChecked()){
|
||||
t->set_priv(true);
|
||||
}
|
||||
// create the torrent and print it to out
|
||||
entry e = t.create_torrent();
|
||||
entry e = t->create_torrent();
|
||||
libtorrent::bencode(std::ostream_iterator<char>(out), e);
|
||||
out.flush();
|
||||
if(checkStartSeeding->isChecked())
|
||||
emit torrent_to_seed(destination);
|
||||
}
|
||||
catch (std::exception& e){
|
||||
std::cerr << e.what() << "\n";
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(QString::fromUtf8(e.what())));
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
hide();
|
||||
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+destination);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#ifndef CREATE_TORRENT_IMP_H
|
||||
#define CREATE_TORRENT_IMP_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "ui_createtorrent.h"
|
||||
|
||||
class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||
@@ -30,11 +29,20 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
|
||||
|
||||
public:
|
||||
createtorrent(QWidget *parent = 0);
|
||||
QStringList allItems(QListWidget *list);
|
||||
int getPieceSize() const;
|
||||
|
||||
signals:
|
||||
void torrent_to_seed(QString path);
|
||||
|
||||
protected slots:
|
||||
void on_browse_destination_clicked();
|
||||
void on_browse_input_clicked();
|
||||
void on_createButton_clicked();
|
||||
void on_addFile_button_clicked();
|
||||
void on_addFolder_button_clicked();
|
||||
void on_addTracker_button_clicked();
|
||||
void on_removeTracker_button_clicked();
|
||||
void on_addURLSeed_button_clicked();
|
||||
void on_removeURLSeed_button_clicked();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,31 +23,102 @@
|
||||
#define DELETETHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QMutexLocker>
|
||||
#include <QPair>
|
||||
|
||||
#include "misc.h"
|
||||
#include "arborescence.h"
|
||||
|
||||
class subDeleteThread : public QThread {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString save_path;
|
||||
arborescence *arb;
|
||||
bool abort;
|
||||
|
||||
public:
|
||||
subDeleteThread(QObject *parent, QString saveDir, arborescence *arb) : QThread(parent), save_path(saveDir), arb(arb), abort(false){}
|
||||
|
||||
~subDeleteThread(){
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
signals:
|
||||
// For subthreads
|
||||
void deletionSuccessST(subDeleteThread* st);
|
||||
void deletionFailureST(subDeleteThread* st);
|
||||
|
||||
protected:
|
||||
void run(){
|
||||
if(arb->removeFromFS(save_path))
|
||||
emit deletionSuccessST(this);
|
||||
else
|
||||
emit deletionFailureST(this);
|
||||
delete arb;
|
||||
}
|
||||
};
|
||||
|
||||
class deleteThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString path;
|
||||
QList<QPair<QString, arborescence*> > torrents_list;
|
||||
QMutex mutex;
|
||||
QWaitCondition condition;
|
||||
bool abort;
|
||||
QList<subDeleteThread*> subThreads;
|
||||
|
||||
public :
|
||||
deleteThread(QString _path): path(_path){
|
||||
start();
|
||||
}
|
||||
public:
|
||||
deleteThread(QObject* parent) : QThread(parent), abort(false){}
|
||||
|
||||
~deleteThread(){
|
||||
mutex.lock();
|
||||
abort = true;
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
qDeleteAll(subThreads);
|
||||
wait();
|
||||
}
|
||||
|
||||
signals:
|
||||
void deletionFinished(deleteThread*) const;
|
||||
void deleteTorrent(QString saveDir, arborescence *arb){
|
||||
qDebug("deleteThread called");
|
||||
QMutexLocker locker(&mutex);
|
||||
torrents_list << QPair<QString, arborescence*>(saveDir, arb);
|
||||
if(!isRunning()){
|
||||
start();
|
||||
}else{
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
void run(){
|
||||
misc::removePath(path);
|
||||
emit deletionFinished(this);
|
||||
forever{
|
||||
if(abort)
|
||||
return;
|
||||
mutex.lock();
|
||||
if(torrents_list.size() != 0){
|
||||
QPair<QString, arborescence *> torrent = torrents_list.takeFirst();
|
||||
mutex.unlock();
|
||||
subDeleteThread *st = new subDeleteThread(0, torrent.first, torrent.second);
|
||||
subThreads << st;
|
||||
connect(st, SIGNAL(deletionSuccessST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
|
||||
connect(st, SIGNAL(deletionFailureST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
|
||||
st->start();
|
||||
}else{
|
||||
condition.wait(&mutex);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
protected slots:
|
||||
void deleteSubThread(subDeleteThread* st){
|
||||
int index = subThreads.indexOf(st);
|
||||
Q_ASSERT(index != -1);
|
||||
subThreads.removeAt(index);
|
||||
delete st;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
352
src/download.ui
Normal file
@@ -0,0 +1,352 @@
|
||||
<ui version="4.0" >
|
||||
<class>downloading</class>
|
||||
<widget class="QWidget" name="downloading" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>811</width>
|
||||
<height>453</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_DLSpeed" >
|
||||
<property name="text" >
|
||||
<string>Total DL Speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_DownSpeed" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="smallDecimalPoint" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="intValue" stdset="0" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="unitDL" >
|
||||
<property name="text" >
|
||||
<string>KiB/s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Session ratio: </string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_Ratio" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_ratio_icon" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_UPSpeed" >
|
||||
<property name="text" >
|
||||
<string>Total UP Speed:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLCDNumber" name="LCD_UpSpeed" >
|
||||
<property name="autoFillBackground" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="smallDecimalPoint" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="numDigits" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="segmentStyle" >
|
||||
<enum>QLCDNumber::Flat</enum>
|
||||
</property>
|
||||
<property name="value" stdset="0" >
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="unitUP" >
|
||||
<property name="text" >
|
||||
<string>KiB/s</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="downloadList" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="autoScroll" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="indentation" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="itemsExpandable" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabBottom" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>142</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabPosition" >
|
||||
<enum>QTabWidget::West</enum>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="log_tab" >
|
||||
<attribute name="title" >
|
||||
<string>Log</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="infoBar" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy>
|
||||
<hsizetype>7</hsizetype>
|
||||
<vsizetype>7</vsizetype>
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="filter_tab" >
|
||||
<attribute name="title" >
|
||||
<string>IP filter</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBlockedUsers" >
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>123</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionStart" >
|
||||
<property name="text" >
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPause" >
|
||||
<property name="text" >
|
||||
<string>Pause</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete" >
|
||||
<property name="text" >
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClearLog" >
|
||||
<property name="text" >
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPreview_file" >
|
||||
<property name="text" >
|
||||
<string>Preview file</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_upload_limit" >
|
||||
<property name="text" >
|
||||
<string>Set upload limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_download_limit" >
|
||||
<property name="text" >
|
||||
<string>Set download limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete_Permanently" >
|
||||
<property name="text" >
|
||||
<string>Delete Permanently</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTorrent_Properties" >
|
||||
<property name="text" >
|
||||
<string>Torrent Properties</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -37,7 +37,6 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
|
||||
connect(this, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), parent, SLOT(downloadFromURLList(const QStringList&)));
|
||||
show();
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
public slots:
|
||||
void on_downloadButton_clicked(){
|
||||
QString urls = textUrls->toPlainText();
|
||||
QStringList url_list = urls.split("\n");
|
||||
QStringList url_list = urls.split(QString::fromUtf8("\n"));
|
||||
QString url;
|
||||
QStringList url_list_cleaned;
|
||||
foreach(url, url_list){
|
||||
@@ -65,6 +64,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
|
||||
return;
|
||||
}
|
||||
emit urlsReadyToBeDownloaded(url_list_cleaned);
|
||||
qDebug("Emitted urlsReadytobedownloaded signal");
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
174
src/downloadThread.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "downloadThread.h"
|
||||
#include <iostream>
|
||||
#include <cc++/common.h>
|
||||
|
||||
QString subDownloadThread::errorCodeToString(int status) {
|
||||
switch(status){
|
||||
case 1://ost::URLStream::errUnreachable:
|
||||
return tr("Host is unreachable");
|
||||
case 2://ost::URLStream::errMissing:
|
||||
return tr("File was not found (404)");
|
||||
case 3://ost::URLStream::errDenied:
|
||||
return tr("Connection was denied");
|
||||
case 4://ost::URLStream::errInvalid:
|
||||
return tr("Url is invalid");
|
||||
case 5://ost::URLStream::errForbidden:
|
||||
return tr("Connection forbidden (403)");
|
||||
case 6://ost::URLStream::errUnauthorized:
|
||||
return tr("Connection was not authorized (401)");
|
||||
case 7://ost::URLStream::errRelocated:
|
||||
return tr("Content has moved (301)");
|
||||
case 8://ost::URLStream::errFailure:
|
||||
return tr("Connection failure");
|
||||
case 9://ost::URLStream::errTimeout:
|
||||
return tr("Connection was timed out");
|
||||
case 10://ost::URLStream::errInterface:
|
||||
return tr("Incorrect network interface");
|
||||
default:
|
||||
return tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
subDownloadThread::subDownloadThread(QObject *parent, QString url) : QThread(parent), url(url), abort(false){
|
||||
url_stream = new ost::URLStream();
|
||||
}
|
||||
|
||||
subDownloadThread::~subDownloadThread(){
|
||||
abort = true;
|
||||
wait();
|
||||
delete url_stream;
|
||||
}
|
||||
|
||||
void subDownloadThread::run(){
|
||||
// XXX: Trick to get a unique filename
|
||||
QString filePath;
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile();
|
||||
if (tmpfile->open()) {
|
||||
filePath = tmpfile->fileName();
|
||||
}
|
||||
delete tmpfile;
|
||||
QFile dest_file(filePath);
|
||||
if(!dest_file.open(QIODevice::WriteOnly | QIODevice::Text)){
|
||||
std::cerr << "Error: could't create temporary file: " << (const char*)filePath.toUtf8() << '\n';
|
||||
return;
|
||||
}
|
||||
ost::URLStream::Error status = url_stream->get((const char*)url.toUtf8());
|
||||
if(status){
|
||||
// Failure
|
||||
QString error_msg = errorCodeToString((int)status);
|
||||
qDebug("Download failed for %s, reason: %s", (const char*)url.toUtf8(), (const char*)error_msg.toUtf8());
|
||||
url_stream->close();
|
||||
emit downloadFailureST(this, url, error_msg);
|
||||
return;
|
||||
}
|
||||
qDebug("Downloading %s...", (const char*)url.toUtf8());
|
||||
char cbuf[1024];
|
||||
int len;
|
||||
while(!url_stream->eof()) {
|
||||
url_stream->read(cbuf, sizeof(cbuf));
|
||||
len = url_stream->gcount();
|
||||
if(len > 0)
|
||||
dest_file.write(cbuf, len);
|
||||
if(abort){
|
||||
dest_file.close();
|
||||
url_stream->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
dest_file.close();
|
||||
url_stream->close();
|
||||
emit downloadFinishedST(this, url, filePath);
|
||||
qDebug("download completed here: %s", (const char*)filePath.toUtf8());
|
||||
}
|
||||
|
||||
/** Download Thread **/
|
||||
|
||||
downloadThread::downloadThread(QObject* parent) : QThread(parent), abort(false){}
|
||||
|
||||
downloadThread::~downloadThread(){
|
||||
mutex.lock();
|
||||
abort = true;
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
qDeleteAll(subThreads);
|
||||
wait();
|
||||
}
|
||||
|
||||
void downloadThread::downloadUrl(QString url){
|
||||
QMutexLocker locker(&mutex);
|
||||
if(downloading_list.contains(url)) return;
|
||||
url_list << url;
|
||||
downloading_list << url;
|
||||
if(!isRunning()){
|
||||
start();
|
||||
}else{
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
void downloadThread::run(){
|
||||
forever{
|
||||
if(abort)
|
||||
return;
|
||||
mutex.lock();
|
||||
if(url_list.size() != 0){
|
||||
QString url = url_list.takeFirst();
|
||||
mutex.unlock();
|
||||
subDownloadThread *st = new subDownloadThread(0, url);
|
||||
subThreads << st;
|
||||
connect(st, SIGNAL(downloadFinishedST(subDownloadThread*, QString, QString)), this, SLOT(propagateDownloadedFile(subDownloadThread*, QString, QString)));
|
||||
connect(st, SIGNAL(downloadFailureST(subDownloadThread*, QString, QString)), this, SLOT(propagateDownloadFailure(subDownloadThread*, QString, QString)));
|
||||
st->start();
|
||||
}else{
|
||||
condition.wait(&mutex);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void downloadThread::propagateDownloadedFile(subDownloadThread* st, QString url, QString path){
|
||||
int index = subThreads.indexOf(st);
|
||||
Q_ASSERT(index != -1);
|
||||
subThreads.removeAt(index);
|
||||
delete st;
|
||||
emit downloadFinished(url, path);
|
||||
mutex.lock();
|
||||
index = downloading_list.indexOf(url);
|
||||
Q_ASSERT(index != -1);
|
||||
downloading_list.removeAt(index);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void downloadThread::propagateDownloadFailure(subDownloadThread* st, QString url, QString reason){
|
||||
int index = subThreads.indexOf(st);
|
||||
Q_ASSERT(index != -1);
|
||||
subThreads.removeAt(index);
|
||||
delete st;
|
||||
emit downloadFailure(url, reason);
|
||||
mutex.lock();
|
||||
index = downloading_list.indexOf(url);
|
||||
Q_ASSERT(index != -1);
|
||||
downloading_list.removeAt(index);
|
||||
mutex.unlock();
|
||||
}
|
||||
@@ -28,144 +28,62 @@
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QWaitCondition>
|
||||
#include <curl/curl.h>
|
||||
#include <iostream>
|
||||
#include <QStringList>
|
||||
|
||||
#include "misc.h"
|
||||
namespace ost {
|
||||
class URLStream;
|
||||
}
|
||||
|
||||
class subDownloadThread : public QThread {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString url;
|
||||
ost::URLStream *url_stream;
|
||||
bool abort;
|
||||
|
||||
public:
|
||||
subDownloadThread(QObject *parent, QString url);
|
||||
~subDownloadThread();
|
||||
QString errorCodeToString(int status);
|
||||
|
||||
signals:
|
||||
// For subthreads
|
||||
void downloadFinishedST(subDownloadThread* st, QString url, QString file_path);
|
||||
void downloadFailureST(subDownloadThread* st, QString url, QString reason);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
};
|
||||
|
||||
class downloadThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QStringList url_list;
|
||||
QStringList downloading_list;
|
||||
QMutex mutex;
|
||||
QWaitCondition condition;
|
||||
bool abort;
|
||||
QList<subDownloadThread*> subThreads;
|
||||
|
||||
signals:
|
||||
void downloadFinished(const QString& url, const QString& file_path, int return_code, const QString& errorBuffer);
|
||||
void downloadFinished(QString url, QString file_path);
|
||||
void downloadFailure(QString url, QString reason);
|
||||
|
||||
public:
|
||||
downloadThread(QObject* parent) : QThread(parent){
|
||||
mutex.lock();
|
||||
abort = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
downloadThread(QObject* parent);
|
||||
|
||||
~downloadThread(){
|
||||
mutex.lock();
|
||||
abort = true;
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
wait();
|
||||
}
|
||||
~downloadThread();
|
||||
|
||||
void downloadUrl(const QString& url){
|
||||
QMutexLocker locker(&mutex);
|
||||
qDebug("In Download thread function, mutex locked");
|
||||
url_list << url;
|
||||
qDebug("In Download thread function, mutex unlocked (url added)");
|
||||
if(!isRunning()){
|
||||
qDebug("In Download thread function, Launching thread (was stopped)");
|
||||
start();
|
||||
}else{
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
void downloadUrl(QString url);
|
||||
|
||||
protected:
|
||||
void run(){
|
||||
forever{
|
||||
if(abort)
|
||||
return;
|
||||
mutex.lock();
|
||||
qDebug("In Download thread RUN, mutex locked");
|
||||
if(url_list.size() != 0){
|
||||
QString url = url_list.takeFirst();
|
||||
mutex.unlock();
|
||||
qDebug("In Download thread RUN, mutex unlocked (got url)");
|
||||
CURL *curl;
|
||||
QString filePath;
|
||||
int return_code, response;
|
||||
// XXX: Trick to get a unique filename
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile;
|
||||
if (tmpfile->open()) {
|
||||
filePath = tmpfile->fileName();
|
||||
}
|
||||
delete tmpfile;
|
||||
if(abort)
|
||||
return;
|
||||
FILE *file = fopen((const char*)filePath.toUtf8(), "w");
|
||||
if(!file){
|
||||
std::cerr << "Error: could not open temporary file...\n";
|
||||
return;
|
||||
}
|
||||
// Initilization required by libcurl
|
||||
curl = curl_easy_init();
|
||||
if(!curl){
|
||||
std::cerr << "Error: Failed to init curl...\n";
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
// Set url to download
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.toLocal8Bit().constData());
|
||||
qDebug("Url: %s", url.toLocal8Bit().constData());
|
||||
// Define our callback to get called when there's data to be written
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, misc::my_fwrite);
|
||||
// Set destination file
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
|
||||
// Some SSL mambo jambo
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
// Disable progress meter
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
||||
// Any kind of authentication
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
// Auto referrer
|
||||
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
|
||||
// Follow redirections
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
// Enable cookies
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
|
||||
// We want error message:
|
||||
char errorBuffer[CURL_ERROR_SIZE];
|
||||
errorBuffer[0]=0; /* prevent junk from being output */
|
||||
return_code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
|
||||
if(return_code){
|
||||
std::cerr << "Error: failed to set error buffer in curl\n";
|
||||
fclose(file);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
unsigned short retries = 0;
|
||||
bool to_many_users = false;
|
||||
do{
|
||||
// Perform Download
|
||||
return_code = curl_easy_perform(curl);
|
||||
// We want HTTP response code
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
qDebug("HTTP response code: %d", response);
|
||||
if(response/100 == 5){
|
||||
to_many_users = true;
|
||||
++retries;
|
||||
SleeperThread::msleep(1000);
|
||||
}
|
||||
}while(to_many_users && retries < 10);
|
||||
// Cleanup
|
||||
curl_easy_cleanup(curl);
|
||||
// Close tmp file
|
||||
fclose(file);
|
||||
emit downloadFinished(url, filePath, return_code, QString(errorBuffer));
|
||||
qDebug("In Download thread RUN, signal emitted, ErrorBuffer: %s", errorBuffer);
|
||||
}else{
|
||||
qDebug("In Download thread RUN, mutex still locked (no urls) -> sleeping");
|
||||
condition.wait(&mutex);
|
||||
mutex.unlock();
|
||||
qDebug("In Download thread RUN, woke up, mutex unlocked");
|
||||
}
|
||||
}
|
||||
}
|
||||
void run();
|
||||
|
||||
protected slots:
|
||||
void propagateDownloadedFile(subDownloadThread* st, QString url, QString path);
|
||||
|
||||
void propagateDownloadFailure(subDownloadThread* st, QString url, QString reason);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
688
src/downloadingTorrents.cpp
Normal file
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include "downloadingTorrents.h"
|
||||
#include "misc.h"
|
||||
#include "properties_imp.h"
|
||||
#include "bittorrent.h"
|
||||
#include "allocationDlg.h"
|
||||
#include "DLListDelegate.h"
|
||||
#include "GUI.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
#include <QTime>
|
||||
#include <QMenu>
|
||||
|
||||
DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), delayedSorting(false), nbTorrents(0) {
|
||||
setupUi(this);
|
||||
// Setting icons
|
||||
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
|
||||
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
|
||||
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
|
||||
actionClearLog->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
|
||||
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
|
||||
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
|
||||
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png")));
|
||||
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
|
||||
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
|
||||
// tabBottom->setTabIcon(0, QIcon(QString::fromUtf8(":/Icons/log.png")));
|
||||
// tabBottom->setTabIcon(1, QIcon(QString::fromUtf8(":/Icons/filter.png")));
|
||||
// Set default ratio
|
||||
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
|
||||
|
||||
// Set Download list model
|
||||
DLListModel = new QStandardItemModel(0,9);
|
||||
DLListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
DLListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
DLListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
|
||||
DLListModel->setHeaderData(DLSPEED, Qt::Horizontal, tr("DL Speed", "i.e: Download speed"));
|
||||
DLListModel->setHeaderData(UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
|
||||
DLListModel->setHeaderData(SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources"));
|
||||
DLListModel->setHeaderData(RATIO, Qt::Horizontal, tr("Ratio"));
|
||||
DLListModel->setHeaderData(ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left"));
|
||||
downloadList->setModel(DLListModel);
|
||||
DLDelegate = new DLListDelegate(downloadList);
|
||||
downloadList->setItemDelegate(DLDelegate);
|
||||
// Hide hash column
|
||||
downloadList->hideColumn(HASH);
|
||||
|
||||
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
|
||||
connect(BTSession, SIGNAL(duplicateTorrent(QString)), this, SLOT(torrentDuplicate(QString)));
|
||||
connect(BTSession, SIGNAL(invalidTorrent(QString)), this, SLOT(torrentCorrupted(QString)));
|
||||
connect(BTSession, SIGNAL(portListeningFailure()), this, SLOT(portListeningFailure()));
|
||||
connect(BTSession, SIGNAL(peerBlocked(QString)), this, SLOT(addLogPeerBlocked(const QString)));
|
||||
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
|
||||
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
|
||||
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
|
||||
|
||||
// Load last columns width for download list
|
||||
if(!loadColWidthDLList()) {
|
||||
downloadList->header()->resizeSection(0, 200);
|
||||
}
|
||||
// Make download list header clickable for sorting
|
||||
downloadList->header()->setClickable(true);
|
||||
downloadList->header()->setSortIndicatorShown(true);
|
||||
// Connecting Actions to slots
|
||||
connect(downloadList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
|
||||
connect(downloadList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortDownloadList(int)));
|
||||
connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&)));
|
||||
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
|
||||
// Actions
|
||||
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
|
||||
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
|
||||
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
|
||||
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
|
||||
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
|
||||
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
|
||||
// Set info Bar infos
|
||||
setInfoBar(tr("qBittorrent %1 started.", "e.g: qBittorrent v0.x started.").arg(QString::fromUtf8(""VERSION)));
|
||||
setInfoBar(tr("Be careful, sharing copyrighted material without permission is against the law."), QString::fromUtf8("red"));
|
||||
qDebug("Download tab built");
|
||||
}
|
||||
|
||||
DownloadingTorrents::~DownloadingTorrents() {
|
||||
saveColWidthDLList();
|
||||
delete DLDelegate;
|
||||
delete DLListModel;
|
||||
}
|
||||
|
||||
|
||||
void DownloadingTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
|
||||
unsigned int row = index.row();
|
||||
QString hash = getHashFromRow(row);
|
||||
emit torrentDoubleClicked(hash);
|
||||
}
|
||||
|
||||
void DownloadingTorrents::addLogPeerBlocked(QString ip) {
|
||||
static unsigned int nbLines = 0;
|
||||
++nbLines;
|
||||
if(nbLines > 200) {
|
||||
textBlockedUsers->clear();
|
||||
nbLines = 1;
|
||||
}
|
||||
textBlockedUsers->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was blocked</i>", "x.y.z.w was blocked").arg(ip));
|
||||
}
|
||||
|
||||
unsigned int DownloadingTorrents::getNbTorrentsInList() const {
|
||||
return nbTorrents;
|
||||
}
|
||||
|
||||
// Note: do not actually pause the torrent in BT session
|
||||
void DownloadingTorrents::pauseTorrent(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.0));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.0));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
setRowColor(row, QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
QString DownloadingTorrents::getHashFromRow(unsigned int row) const {
|
||||
Q_ASSERT(row < (unsigned int)DLListModel->rowCount());
|
||||
return DLListModel->data(DLListModel->index(row, HASH)).toString();
|
||||
}
|
||||
|
||||
void DownloadingTorrents::setBottomTabEnabled(unsigned int index, bool b){
|
||||
if(index and !b)
|
||||
tabBottom->setCurrentIndex(0);
|
||||
tabBottom->setTabEnabled(index, b);
|
||||
}
|
||||
|
||||
// Show torrent properties dialog
|
||||
void DownloadingTorrents::showProperties(const QModelIndex &index) {
|
||||
int row = index.row();
|
||||
QString hash = DLListModel->data(DLListModel->index(row, HASH)).toString();
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
properties *prop = new properties(this, BTSession, h);
|
||||
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSizeAndProgress(QString)));
|
||||
prop->show();
|
||||
}
|
||||
|
||||
void DownloadingTorrents::resumeTorrent(QString hash){
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
}
|
||||
|
||||
// Remove a torrent from the download list but NOT from the BT Session
|
||||
void DownloadingTorrents::deleteTorrent(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1){
|
||||
qDebug("torrent is not in download list, nothing to delete");
|
||||
return;
|
||||
}
|
||||
DLListModel->removeRow(row);
|
||||
--nbTorrents;
|
||||
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
||||
}
|
||||
|
||||
// Update Info Bar information
|
||||
void DownloadingTorrents::setInfoBar(QString info, QColor color) {
|
||||
static unsigned int nbLines = 0;
|
||||
++nbLines;
|
||||
// Check log size, clear it if too big
|
||||
if(nbLines > 200) {
|
||||
infoBar->clear();
|
||||
nbLines = 1;
|
||||
}
|
||||
qDebug("Color is %s", color.name().toUtf8().data());
|
||||
infoBar->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + info + QString::fromUtf8("</i></font>"));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::addFastResumeRejectedAlert(QString name) {
|
||||
setInfoBar(tr("Fast resume data was rejected for torrent %1, checking again...").arg(name), QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::addUrlSeedError(QString url, QString msg) {
|
||||
setInfoBar(tr("Url seed lookup failed for url: %1, message: %2").arg(url).arg(msg), QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::on_actionSet_download_limit_triggered() {
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
}
|
||||
}
|
||||
Q_ASSERT(hashes.size() > 0);
|
||||
new BandwidthAllocationDialog(this, false, BTSession, hashes);
|
||||
}
|
||||
|
||||
void DownloadingTorrents::on_actionSet_upload_limit_triggered() {
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
QStringList hashes;
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
}
|
||||
}
|
||||
Q_ASSERT(hashes.size() > 0);
|
||||
new BandwidthAllocationDialog(this, true, BTSession, hashes);
|
||||
}
|
||||
|
||||
// display properties of selected items
|
||||
void DownloadingTorrents::propertiesSelection(){
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
if(index.column() == NAME){
|
||||
showProperties(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
|
||||
QMenu myDLLlistMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QString previewProgram = settings.value(QString::fromUtf8("Preferences/general/MediaPlayer"), QString()).toString();
|
||||
bool has_pause = false, has_start = false, has_preview = false;
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file name
|
||||
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
// Get handle and pause the torrent
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) continue;
|
||||
if(h.is_paused()) {
|
||||
if(!has_start) {
|
||||
myDLLlistMenu.addAction(actionStart);
|
||||
has_start = true;
|
||||
}
|
||||
}else{
|
||||
if(!has_pause) {
|
||||
myDLLlistMenu.addAction(actionPause);
|
||||
has_pause = true;
|
||||
}
|
||||
}
|
||||
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
|
||||
myDLLlistMenu.addAction(actionPreview_file);
|
||||
has_preview = true;
|
||||
}
|
||||
if(has_pause && has_start && has_preview) break;
|
||||
}
|
||||
}
|
||||
myDLLlistMenu.addSeparator();
|
||||
myDLLlistMenu.addAction(actionDelete);
|
||||
myDLLlistMenu.addAction(actionDelete_Permanently);
|
||||
myDLLlistMenu.addSeparator();
|
||||
myDLLlistMenu.addAction(actionSet_download_limit);
|
||||
myDLLlistMenu.addAction(actionSet_upload_limit);
|
||||
myDLLlistMenu.addSeparator();
|
||||
myDLLlistMenu.addAction(actionTorrent_Properties);
|
||||
// Call menu
|
||||
// XXX: why mapToGlobal() is not enough?
|
||||
myDLLlistMenu.exec(mapToGlobal(pos)+QPoint(10,60));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::on_actionClearLog_triggered() {
|
||||
infoBar->clear();
|
||||
}
|
||||
|
||||
QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
|
||||
QStringList res;
|
||||
QModelIndex index;
|
||||
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
|
||||
foreach(index, selectedIndexes) {
|
||||
if(index.column() == NAME) {
|
||||
// Get the file hash
|
||||
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
|
||||
res << hash;
|
||||
if(only_one) break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void DownloadingTorrents::updateRatio() {
|
||||
// Update ratio info
|
||||
float ratio = 1.;
|
||||
session_status sessionStatus = BTSession->getSessionStatus();
|
||||
if(sessionStatus.total_payload_download == 0) {
|
||||
if(sessionStatus.total_payload_upload == 0)
|
||||
ratio = 1.;
|
||||
else
|
||||
ratio = 10.;
|
||||
}else{
|
||||
ratio = (double)sessionStatus.total_payload_upload / (double)sessionStatus.total_payload_download;
|
||||
if(ratio > 10.)
|
||||
ratio = 10.;
|
||||
}
|
||||
LCD_Ratio->display(QString(QByteArray::number(ratio, 'f', 1)));
|
||||
if(ratio < 0.5) {
|
||||
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/unhappy.png")));
|
||||
}else{
|
||||
if(ratio > 1.0) {
|
||||
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/smile.png")));
|
||||
}else{
|
||||
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadingTorrents::displayInfoBarMenu(const QPoint& pos) {
|
||||
// Log Menu
|
||||
QMenu myLogMenu(this);
|
||||
myLogMenu.addAction(actionClearLog);
|
||||
// XXX: Why mapToGlobal() is not enough?
|
||||
myLogMenu.exec(mapToGlobal(pos)+QPoint(44,305));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::sortProgressColumnDelayed() {
|
||||
if(delayedSorting) {
|
||||
sortDownloadListFloat(PROGRESS, delayedSortingOrder);
|
||||
qDebug("Delayed sorting of progress column");
|
||||
}
|
||||
}
|
||||
|
||||
// get information from torrent handles and
|
||||
// update download list accordingly
|
||||
void DownloadingTorrents::updateDlList() {
|
||||
// update global informations
|
||||
LCD_UpSpeed->display(QString(QByteArray::number(BTSession->getPayloadUploadRate()/1024., 'f', 1))); // UP LCD
|
||||
LCD_DownSpeed->display(QString(QByteArray::number(BTSession->getPayloadDownloadRate()/1024., 'f', 1))); // DL LCD
|
||||
// browse handles
|
||||
QStringList unfinishedTorrents = BTSession->getUnfinishedTorrents();
|
||||
QString hash;
|
||||
foreach(hash, unfinishedTorrents) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()){
|
||||
qDebug("We have an invalid handle for: %s", qPrintable(hash));
|
||||
continue;
|
||||
}
|
||||
try{
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1) {
|
||||
qDebug("Info: Could not find filename in download list, adding it...");
|
||||
addTorrent(hash);
|
||||
row = getRowFromHash(hash);
|
||||
}
|
||||
Q_ASSERT(row != -1);
|
||||
// No need to update a paused torrent
|
||||
if(h.is_paused()) continue;
|
||||
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
continue;
|
||||
}
|
||||
// Parse download state
|
||||
// Setting download state
|
||||
switch(h.state()) {
|
||||
case torrent_status::finished:
|
||||
case torrent_status::seeding:
|
||||
qDebug("A torrent that was in download tab just finished, moving it to finished tab");
|
||||
BTSession->setUnfinishedTorrent(hash);
|
||||
emit torrentFinished(hash);
|
||||
deleteTorrent(hash);
|
||||
continue;
|
||||
case torrent_status::checking_files:
|
||||
case torrent_status::queued_for_checking:
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
break;
|
||||
case torrent_status::connecting_to_tracker:
|
||||
if(h.download_payload_rate() > 0) {
|
||||
// Display "Downloading" status when connecting if download speed > 0
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("green"));
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
}
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
|
||||
break;
|
||||
case torrent_status::downloading:
|
||||
case torrent_status::downloading_metadata:
|
||||
if(h.download_payload_rate() > 0) {
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
|
||||
setRowColor(row, QString::fromUtf8("green"));
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/stalled.png"))), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
setRowColor(row, QPalette::WindowText);
|
||||
}
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
|
||||
break;
|
||||
default:
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
}
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+QString::fromUtf8("/")+misc::toQString(h.num_peers() - h.num_seeds(), true)));
|
||||
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
}catch(invalid_handle e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadingTorrents::addTorrent(QString hash) {
|
||||
if(BTSession->isFinished(hash)){
|
||||
BTSession->setUnfinishedTorrent(hash);
|
||||
}
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) return;
|
||||
row = DLListModel->rowCount();
|
||||
// Adding torrent to download list
|
||||
DLListModel->insertRow(row);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
|
||||
// Pause torrent if it was paused last time
|
||||
if(BTSession->isPaused(hash)) {
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("red"));
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
}
|
||||
++nbTorrents;
|
||||
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
||||
}
|
||||
|
||||
void DownloadingTorrents::sortDownloadListFloat(int index, Qt::SortOrder sortOrder) {
|
||||
QList<QPair<int, double> > lines;
|
||||
// insertion sorting
|
||||
unsigned int nbRows = DLListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i) {
|
||||
misc::insertSort(lines, QPair<int,double>(i, DLListModel->data(DLListModel->index(i, index)).toDouble()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
unsigned int nbRows_old = lines.size();
|
||||
for(unsigned int row=0; row<nbRows_old; ++row) {
|
||||
DLListModel->insertRow(DLListModel->rowCount());
|
||||
unsigned int sourceRow = lines[row].first;
|
||||
unsigned int nbColumns = DLListModel->columnCount();
|
||||
for(unsigned int col=0; col<nbColumns; ++col) {
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
DLListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
void DownloadingTorrents::sortDownloadListString(int index, Qt::SortOrder sortOrder) {
|
||||
QList<QPair<int, QString> > lines;
|
||||
// Insertion sorting
|
||||
unsigned int nbRows = DLListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i) {
|
||||
misc::insertSortString(lines, QPair<int, QString>(i, DLListModel->data(DLListModel->index(i, index)).toString()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
unsigned int nbRows_old = lines.size();
|
||||
for(unsigned int row=0; row<nbRows_old; ++row) {
|
||||
DLListModel->insertRow(DLListModel->rowCount());
|
||||
unsigned int sourceRow = lines[row].first;
|
||||
unsigned int nbColumns = DLListModel->columnCount();
|
||||
for(unsigned int col=0; col<nbColumns; ++col) {
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
|
||||
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
DLListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth) {
|
||||
qDebug("Called sort download list");
|
||||
static Qt::SortOrder sortOrder = startSortOrder;
|
||||
if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index) {
|
||||
if(sortOrder == Qt::AscendingOrder) {
|
||||
sortOrder = Qt::DescendingOrder;
|
||||
}else{
|
||||
sortOrder = Qt::AscendingOrder;
|
||||
}
|
||||
}
|
||||
QString sortOrderLetter;
|
||||
if(sortOrder == Qt::AscendingOrder)
|
||||
sortOrderLetter = QString::fromUtf8("a");
|
||||
else
|
||||
sortOrderLetter = QString::fromUtf8("d");
|
||||
if(fromLoadColWidth) {
|
||||
// XXX: Why is this needed?
|
||||
if(sortOrder == Qt::DescendingOrder)
|
||||
downloadList->header()->setSortIndicator(index, Qt::AscendingOrder);
|
||||
else
|
||||
downloadList->header()->setSortIndicator(index, Qt::DescendingOrder);
|
||||
} else {
|
||||
downloadList->header()->setSortIndicator(index, sortOrder);
|
||||
}
|
||||
switch(index) {
|
||||
case SIZE:
|
||||
case ETA:
|
||||
case UPSPEED:
|
||||
case DLSPEED:
|
||||
sortDownloadListFloat(index, sortOrder);
|
||||
break;
|
||||
case PROGRESS:
|
||||
if(fromLoadColWidth) {
|
||||
// Progress sorting must be delayed until files are checked (on startup)
|
||||
delayedSorting = true;
|
||||
qDebug("Delayed sorting of the progress column");
|
||||
delayedSortingOrder = sortOrder;
|
||||
}else{
|
||||
sortDownloadListFloat(index, sortOrder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sortDownloadListString(index, sortOrder);
|
||||
}
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.setValue(QString::fromUtf8("DownloadListSortedCol"), misc::toQString(index)+sortOrderLetter);
|
||||
}
|
||||
|
||||
// Save columns width in a file to remember them
|
||||
// (download list)
|
||||
void DownloadingTorrents::saveColWidthDLList() const{
|
||||
qDebug("Saving columns width in download list");
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QStringList width_list;
|
||||
unsigned int nbColumns = DLListModel->columnCount()-1;
|
||||
for(unsigned int i=0; i<nbColumns; ++i) {
|
||||
width_list << misc::toQString(downloadList->columnWidth(i));
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("DownloadListColsWidth"), width_list.join(QString::fromUtf8(" ")));
|
||||
qDebug("Download list columns width saved");
|
||||
}
|
||||
|
||||
// Load columns width in a file that were saved previously
|
||||
// (download list)
|
||||
bool DownloadingTorrents::loadColWidthDLList() {
|
||||
qDebug("Loading columns width for download list");
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QString line = settings.value(QString::fromUtf8("DownloadListColsWidth"), QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(QString::fromUtf8(" "));
|
||||
if(width_list.size() != DLListModel->columnCount()-1) {
|
||||
qDebug("Corrupted values for download list columns sizes");
|
||||
return false;
|
||||
}
|
||||
unsigned int listSize = width_list.size();
|
||||
for(unsigned int i=0; i<listSize; ++i) {
|
||||
downloadList->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
// Loading last sorted column
|
||||
QString sortedCol = settings.value(QString::fromUtf8("DownloadListSortedCol"), QString()).toString();
|
||||
if(!sortedCol.isEmpty()) {
|
||||
Qt::SortOrder sortOrder;
|
||||
if(sortedCol.endsWith(QString::fromUtf8("d")))
|
||||
sortOrder = Qt::DescendingOrder;
|
||||
else
|
||||
sortOrder = Qt::AscendingOrder;
|
||||
sortedCol = sortedCol.left(sortedCol.size()-1);
|
||||
int index = sortedCol.toInt();
|
||||
sortDownloadList(index, sortOrder, true);
|
||||
}
|
||||
qDebug("Download list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when a torrent is added
|
||||
void DownloadingTorrents::torrentAdded(QString path, QTorrentHandle& h, bool fastResume) {
|
||||
QString hash = h.hash();
|
||||
if(BTSession->isFinished(hash)) {
|
||||
return;
|
||||
}
|
||||
int row = DLListModel->rowCount();
|
||||
// Adding torrent to download list
|
||||
DLListModel->insertRow(row);
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
|
||||
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
|
||||
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
|
||||
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
|
||||
// Pause torrent if it was paused last time
|
||||
// Not using isPaused function because torrents are paused after checking now
|
||||
if(QFile::exists(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".paused"))) {
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("red"));
|
||||
}else{
|
||||
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
}
|
||||
if(!fastResume) {
|
||||
setInfoBar(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(path));
|
||||
}else{
|
||||
setInfoBar(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(path));
|
||||
}
|
||||
++nbTorrents;
|
||||
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
||||
}
|
||||
|
||||
// Called when trying to add a duplicate torrent
|
||||
void DownloadingTorrents::torrentDuplicate(QString path) {
|
||||
setInfoBar(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(path));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::torrentCorrupted(QString path) {
|
||||
setInfoBar(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(path), QString::fromUtf8("red"));
|
||||
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
void DownloadingTorrents::updateFileSizeAndProgress(QString hash) {
|
||||
int row = getRowFromHash(hash);
|
||||
Q_ASSERT(row != -1);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
|
||||
}
|
||||
|
||||
// Called when we couldn't listen on any port
|
||||
// in the given range.
|
||||
void DownloadingTorrents::portListeningFailure() {
|
||||
setInfoBar(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
void DownloadingTorrents::setRowColor(int row, QColor color) {
|
||||
unsigned int nbColumns = DLListModel->columnCount()-1;
|
||||
for(unsigned int i=0; i<nbColumns; ++i) {
|
||||
DLListModel->setData(DLListModel->index(row, i), QVariant(color), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
|
||||
// return the row of in data model
|
||||
// corresponding to the given the hash
|
||||
int DownloadingTorrents::getRowFromHash(QString hash) const{
|
||||
unsigned int nbRows = DLListModel->rowCount();
|
||||
for(unsigned int i=0; i<nbRows; ++i) {
|
||||
if(DLListModel->data(DLListModel->index(i, HASH)) == hash) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DownloadingTorrents::displayDownloadingUrlInfos(QString url) {
|
||||
setInfoBar(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url), QPalette::WindowText);
|
||||
}
|
||||
97
src/downloadingTorrents.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef DOWNLOADINGTORRENTS_H
|
||||
#define DOWNLOADINGTORRENTS_H
|
||||
|
||||
#include "ui_download.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
class QStandardItemModel;
|
||||
class bittorrent;
|
||||
class DLListDelegate;
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
class DownloadingTorrents : public QWidget, public Ui::downloading{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QObject *parent;
|
||||
bittorrent *BTSession;
|
||||
DLListDelegate *DLDelegate;
|
||||
QStandardItemModel *DLListModel;
|
||||
bool delayedSorting;
|
||||
unsigned int nbTorrents;
|
||||
Qt::SortOrder delayedSortingOrder;
|
||||
|
||||
public:
|
||||
DownloadingTorrents(QObject *parent, bittorrent *BTSession);
|
||||
~DownloadingTorrents();
|
||||
// Methods
|
||||
bool loadColWidthDLList();
|
||||
int getRowFromHash(QString hash) const;
|
||||
QString getHashFromRow(unsigned int row) const;
|
||||
QStringList getSelectedTorrents(bool only_one=false) const;
|
||||
unsigned int getNbTorrentsInList() const;
|
||||
|
||||
signals:
|
||||
void unfinishedTorrentsNumberChanged(unsigned int);
|
||||
void torrentDoubleClicked(QString hash);
|
||||
void torrentFinished(QString hash);
|
||||
|
||||
protected slots:
|
||||
void addLogPeerBlocked(QString);
|
||||
void addFastResumeRejectedAlert(QString);
|
||||
void addUrlSeedError(QString url, QString msg);
|
||||
void on_actionSet_download_limit_triggered();
|
||||
void notifyTorrentDoubleClicked(const QModelIndex& index);
|
||||
void on_actionSet_upload_limit_triggered();
|
||||
void displayDLListMenu(const QPoint& pos);
|
||||
void on_actionClearLog_triggered();
|
||||
void displayInfoBarMenu(const QPoint& pos);
|
||||
void addTorrent(QString hash);
|
||||
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
|
||||
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
|
||||
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
|
||||
void saveColWidthDLList() const;
|
||||
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
|
||||
void torrentDuplicate(QString path);
|
||||
void torrentCorrupted(QString path);
|
||||
void portListeningFailure();
|
||||
void setRowColor(int row, QColor color);
|
||||
void displayDownloadingUrlInfos(QString url);
|
||||
void showProperties(const QModelIndex &index);
|
||||
|
||||
public slots:
|
||||
void updateDlList();
|
||||
void setInfoBar(QString info, QColor color=QPalette::WindowText);
|
||||
void pauseTorrent(QString hash);
|
||||
void resumeTorrent(QString hash);
|
||||
void updateRatio();
|
||||
void deleteTorrent(QString hash);
|
||||
void setBottomTabEnabled(unsigned int index, bool b);
|
||||
void propertiesSelection();
|
||||
void sortProgressColumnDelayed();
|
||||
void updateFileSizeAndProgress(QString hash);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
125
src/engineSelect.ui
Normal file
@@ -0,0 +1,125 @@
|
||||
<ui version="4.0" >
|
||||
<class>engineSelect</class>
|
||||
<widget class="QDialog" name="engineSelect" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>541</width>
|
||||
<height>254</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="acceptDrops" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Search plugins</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_engines" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Installed search engines:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="pluginsTree" >
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="uniformRowHeights" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Url</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="getNewEngine_lbl" >
|
||||
<property name="font" >
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>You can get new search engine plugins here: <a href="http:plugins.qbittorrent.org">http://plugins.qbittorrent.org</a></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QPushButton" name="installButton" >
|
||||
<property name="text" >
|
||||
<string>Install a new one</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="updateButton" >
|
||||
<property name="text" >
|
||||
<string>Check for updates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton" >
|
||||
<property name="text" >
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionEnable" >
|
||||
<property name="text" >
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisable" >
|
||||
<property name="text" >
|
||||
<string>Disable</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUninstall" >
|
||||
<property name="text" >
|
||||
<string>Uninstall</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
697
src/engineSelectDlg.cpp
Normal file
@@ -0,0 +1,697 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "engineSelectDlg.h"
|
||||
#include "downloadThread.h"
|
||||
#include "misc.h"
|
||||
#include "pluginSource.h"
|
||||
#include <QProcess>
|
||||
#include <QHeaderView>
|
||||
#include <QSettings>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QDropEvent>
|
||||
#include <QInputDialog>
|
||||
|
||||
#ifdef HAVE_MAGICK
|
||||
#include <Magick++.h>
|
||||
using namespace Magick;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ZZIP
|
||||
#include <zzip/zzip.h>
|
||||
#endif
|
||||
|
||||
#define ENGINE_NAME 0
|
||||
#define ENGINE_URL 1
|
||||
#define ENGINE_STATE 2
|
||||
#define ENGINE_ID 3
|
||||
|
||||
engineSelectDlg::engineSelectDlg(QWidget *parent) : QDialog(parent) {
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
pluginsTree->header()->resizeSection(0, 170);
|
||||
pluginsTree->header()->resizeSection(1, 220);
|
||||
pluginsTree->hideColumn(ENGINE_ID);
|
||||
actionEnable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
actionDisable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
actionUninstall->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
|
||||
connect(actionEnable, SIGNAL(triggered()), this, SLOT(enableSelection()));
|
||||
connect(actionDisable, SIGNAL(triggered()), this, SLOT(disableSelection()));
|
||||
connect(pluginsTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContextMenu(const QPoint&)));
|
||||
downloader = new downloadThread(this);
|
||||
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
|
||||
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
|
||||
loadSupportedSearchEngines(true);
|
||||
connect(pluginsTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(toggleEngineState(QTreeWidgetItem*, int)));
|
||||
show();
|
||||
}
|
||||
|
||||
engineSelectDlg::~engineSelectDlg() {
|
||||
qDebug("Destroying engineSelectDlg");
|
||||
saveSettings();
|
||||
emit enginesChanged();
|
||||
qDebug("Before deleting downloader");
|
||||
delete downloader;
|
||||
qDebug("Engine plugins dialog destroyed");
|
||||
}
|
||||
|
||||
void engineSelectDlg::dropEvent(QDropEvent *event) {
|
||||
event->acceptProposedAction();
|
||||
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
|
||||
QString file;
|
||||
foreach(file, files) {
|
||||
qDebug("dropped %s", file.toUtf8().data());
|
||||
file = file.replace("file://", "");
|
||||
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
|
||||
downloader->downloadUrl(file);
|
||||
continue;
|
||||
}
|
||||
if(file.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
QString plugin_name = file.split(QDir::separator()).last();
|
||||
plugin_name.replace(".py", "");
|
||||
installPlugin(file, plugin_name);
|
||||
}
|
||||
#ifdef HAVE_ZZIP
|
||||
if(file.endsWith(".zip", Qt::CaseInsensitive)) {
|
||||
installZipPlugin(file);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Decode if we accept drag 'n drop or not
|
||||
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
|
||||
QString mime;
|
||||
foreach(mime, event->mimeData()->formats()){
|
||||
qDebug("mimeData: %s", mime.toUtf8().data());
|
||||
}
|
||||
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void engineSelectDlg::saveSettings() {
|
||||
qDebug("Saving engines settings");
|
||||
QStringList known_engines;
|
||||
QVariantList known_enginesEnabled;
|
||||
QString engine;
|
||||
foreach(engine, installed_engines.keys()) {
|
||||
known_engines << engine;
|
||||
known_enginesEnabled << QVariant(installed_engines.value(engine, true));
|
||||
qDebug("Engine %s has state: %d", engine.toUtf8().data(), installed_engines.value(engine, true));
|
||||
}
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
settings.setValue(QString::fromUtf8("SearchEngines/knownEngines"), known_engines);
|
||||
settings.setValue(QString::fromUtf8("SearchEngines/knownEnginesEnabled"), known_enginesEnabled);
|
||||
}
|
||||
|
||||
void engineSelectDlg::on_updateButton_clicked() {
|
||||
// Download version file from primary server
|
||||
downloader->downloadUrl("http://www.dchris.eu/search_engine/versions.txt");
|
||||
}
|
||||
|
||||
void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
|
||||
int index = pluginsTree->indexOfTopLevelItem(item);
|
||||
QString id = item->text(ENGINE_ID);
|
||||
bool new_val = !installed_engines.value(id, true);
|
||||
installed_engines[id] = new_val;
|
||||
QString enabledTxt;
|
||||
if(new_val){
|
||||
enabledTxt = tr("True");
|
||||
setRowColor(index, "green");
|
||||
}else{
|
||||
enabledTxt = tr("False");
|
||||
setRowColor(index, "red");
|
||||
}
|
||||
item->setText(ENGINE_STATE, enabledTxt);
|
||||
}
|
||||
|
||||
void engineSelectDlg::displayContextMenu(const QPoint& pos) {
|
||||
QMenu myContextMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
|
||||
bool has_enable = false, has_disable = false;
|
||||
QTreeWidgetItem *item;
|
||||
foreach(item, items) {
|
||||
QString id = item->text(ENGINE_ID);
|
||||
if(installed_engines.value(id, true) and !has_disable) {
|
||||
myContextMenu.addAction(actionDisable);
|
||||
has_disable = true;
|
||||
}
|
||||
if(!installed_engines.value(id, true) and !has_enable) {
|
||||
myContextMenu.addAction(actionEnable);
|
||||
has_enable = true;
|
||||
}
|
||||
if(has_enable && has_disable) break;
|
||||
}
|
||||
myContextMenu.addSeparator();
|
||||
myContextMenu.addAction(actionUninstall);
|
||||
myContextMenu.exec(mapToGlobal(pos)+QPoint(12, 58));
|
||||
}
|
||||
|
||||
void engineSelectDlg::on_closeButton_clicked() {
|
||||
close();
|
||||
}
|
||||
|
||||
void engineSelectDlg::on_actionUninstall_triggered() {
|
||||
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
|
||||
QTreeWidgetItem *item;
|
||||
bool change = false;
|
||||
bool error = false;
|
||||
foreach(item, items) {
|
||||
int index = pluginsTree->indexOfTopLevelItem(item);
|
||||
Q_ASSERT(index != -1);
|
||||
QString id = item->text(ENGINE_ID);
|
||||
if(QFile::exists(":/search_engine/engines/"+id+".py")) {
|
||||
error = true;
|
||||
// Disable it instead
|
||||
installed_engines.insert(id, false);
|
||||
item->setText(ENGINE_STATE, tr("False"));
|
||||
setRowColor(index, "red");
|
||||
continue;
|
||||
}else {
|
||||
// Proceed with uninstall
|
||||
// remove it from hard drive
|
||||
QDir enginesFolder(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines");
|
||||
QStringList filters;
|
||||
filters << id+".*";
|
||||
QStringList files = enginesFolder.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
QString file;
|
||||
foreach(file, files) {
|
||||
enginesFolder.remove(file);
|
||||
}
|
||||
// Remove it from lists
|
||||
installed_engines.remove(id);
|
||||
delete item;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
if(error)
|
||||
QMessageBox::warning(0, tr("Uninstall warning"), tr("Some plugins could not be uninstalled because they are included in qBittorrent.\n Only the ones you added yourself can be uninstalled.\nHowever, those plugins were disabled."));
|
||||
else
|
||||
QMessageBox::information(0, tr("Uninstall success"), tr("All selected plugins were uninstalled successfully"));
|
||||
}
|
||||
|
||||
void engineSelectDlg::enableSelection() {
|
||||
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
|
||||
QTreeWidgetItem *item;
|
||||
foreach(item, items) {
|
||||
int index = pluginsTree->indexOfTopLevelItem(item);
|
||||
Q_ASSERT(index != -1);
|
||||
QString id = item->text(ENGINE_ID);
|
||||
installed_engines.insert(id, true);
|
||||
item->setText(ENGINE_STATE, tr("True"));
|
||||
setRowColor(index, "green");
|
||||
}
|
||||
}
|
||||
|
||||
void engineSelectDlg::disableSelection() {
|
||||
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
|
||||
QTreeWidgetItem *item;
|
||||
foreach(item, items) {
|
||||
int index = pluginsTree->indexOfTopLevelItem(item);
|
||||
Q_ASSERT(index != -1);
|
||||
QString id = item->text(ENGINE_ID);
|
||||
installed_engines.insert(id, false);
|
||||
item->setText(ENGINE_STATE, tr("False"));
|
||||
setRowColor(index, "red");
|
||||
}
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
void engineSelectDlg::setRowColor(int row, QString color){
|
||||
QTreeWidgetItem *item = pluginsTree->topLevelItem(row);
|
||||
for(int i=0; i<pluginsTree->columnCount()-1; ++i){
|
||||
item->setData(i, Qt::ForegroundRole, QVariant(QColor(color)));
|
||||
}
|
||||
}
|
||||
|
||||
bool engineSelectDlg::checkInstalled(QString plugin_name) const {
|
||||
QProcess nova;
|
||||
QStringList params;
|
||||
params << "--supported_engines";
|
||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
||||
nova.waitForStarted();
|
||||
nova.waitForFinished();
|
||||
QByteArray result = nova.readAll();
|
||||
result = result.replace("\n", "");
|
||||
QList<QByteArray> plugins_list = result.split(',');
|
||||
return plugins_list.contains(plugin_name.toUtf8());
|
||||
}
|
||||
|
||||
void engineSelectDlg::loadSupportedSearchEngines(bool first) {
|
||||
// Some clean up first
|
||||
pluginsTree->clear();
|
||||
QHash<QString, bool> old_engines;
|
||||
if(first) {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QStringList known_engines = settings.value(QString::fromUtf8("SearchEngines/knownEngines"), QStringList()).toStringList();
|
||||
QVariantList enabled = settings.value(QString::fromUtf8("SearchEngines/knownEnginesEnabled"), QList<QVariant>()).toList();
|
||||
Q_ASSERT(known_engines.size() == enabled.size());
|
||||
unsigned int nbKnownEngines = known_engines.size();
|
||||
for(unsigned int i=0; i<nbKnownEngines; ++i) {
|
||||
old_engines[known_engines.at(i)] = enabled.at(i).toBool();
|
||||
}
|
||||
} else {
|
||||
old_engines = installed_engines;
|
||||
}
|
||||
installed_engines.clear();
|
||||
QStringList params;
|
||||
// Ask nova core for the supported search engines
|
||||
QProcess nova;
|
||||
params << "--supported_engines";
|
||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
||||
nova.waitForStarted();
|
||||
nova.waitForFinished();
|
||||
QByteArray result = nova.readAll();
|
||||
result = result.replace("\n", "");
|
||||
qDebug("read: %s", result.data());
|
||||
QByteArray e;
|
||||
QStringList supported_engines_ids;
|
||||
foreach(e, result.split(',')) {
|
||||
QString en = QString(e);
|
||||
supported_engines_ids << en;
|
||||
installed_engines[en] = old_engines.value(en, true);
|
||||
}
|
||||
params.clear();
|
||||
params << "--supported_engines_infos";
|
||||
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
|
||||
nova.waitForStarted();
|
||||
nova.waitForFinished();
|
||||
result = nova.readAll();
|
||||
result = result.replace("\n", "");
|
||||
qDebug("read: %s", result.data());
|
||||
unsigned int i = 0;
|
||||
foreach(e, result.split(',')) {
|
||||
QString id = supported_engines_ids.at(i);
|
||||
QString nameUrlCouple(e);
|
||||
QStringList line = nameUrlCouple.split('|');
|
||||
if(line.size() != 2) continue;
|
||||
QString enabledTxt;
|
||||
if(installed_engines.value(id, true)) {
|
||||
enabledTxt = tr("True");
|
||||
} else {
|
||||
enabledTxt = tr("False");
|
||||
}
|
||||
line << enabledTxt;
|
||||
line << id;
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(pluginsTree, line);
|
||||
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
|
||||
if(QFile::exists(iconPath)) {
|
||||
// Good, we already have the icon
|
||||
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
|
||||
} else {
|
||||
// Icon is missing, we must download it
|
||||
downloader->downloadUrl(line.at(1)+"/favicon.ico");
|
||||
}
|
||||
if(installed_engines.value(id, true))
|
||||
setRowColor(i, "green");
|
||||
else
|
||||
setRowColor(i, "red");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QTreeWidgetItem*> engineSelectDlg::findItemsWithUrl(QString url){
|
||||
QList<QTreeWidgetItem*> res;
|
||||
for(int i=0; i<pluginsTree->topLevelItemCount(); ++i) {
|
||||
QTreeWidgetItem *item = pluginsTree->topLevelItem(i);
|
||||
if(url.startsWith(item->text(ENGINE_URL), Qt::CaseInsensitive))
|
||||
res << item;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* engineSelectDlg::findItemWithID(QString id){
|
||||
QList<QTreeWidgetItem*> res;
|
||||
for(int i=0; i<pluginsTree->topLevelItemCount(); ++i) {
|
||||
QTreeWidgetItem *item = pluginsTree->topLevelItem(i);
|
||||
if(id == item->text(ENGINE_ID))
|
||||
return item;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool engineSelectDlg::isUpdateNeeded(QString plugin_name, float new_version) const {
|
||||
float old_version = misc::getPluginVersion(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py");
|
||||
qDebug("IsUpdate needed? tobeinstalled: %.2f, alreadyinstalled: %.2f", new_version, old_version);
|
||||
return (new_version > old_version);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZZIP
|
||||
void engineSelectDlg::installZipPlugin(QString path) {
|
||||
QStringList plugins;
|
||||
QStringList favicons;
|
||||
ZZIP_DIR* dir = zzip_dir_open(path.toUtf8().data(), 0);
|
||||
if(!dir) {
|
||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("Search engine plugin archive could not be read."));
|
||||
return;
|
||||
}
|
||||
ZZIP_DIRENT dirent;
|
||||
while(zzip_dir_read(dir, &dirent)) {
|
||||
/* show info for first file */
|
||||
QString name(dirent.d_name);
|
||||
if(name.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
plugins << name;
|
||||
} else {
|
||||
if(name.endsWith(".png", Qt::CaseInsensitive)) {
|
||||
favicons << name;
|
||||
}
|
||||
}
|
||||
}
|
||||
QString plugin;
|
||||
std::cout << dirent.d_name << std::endl;
|
||||
ZZIP_FILE* fp = zzip_file_open(dir, dirent.d_name, 0);
|
||||
if (fp) {
|
||||
char buf[10];
|
||||
zzip_ssize_t len = zzip_file_read(fp, buf, 10);
|
||||
if (len) {
|
||||
/* show head of README */
|
||||
std::cout << buf;
|
||||
}
|
||||
zzip_file_close(fp);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
foreach(plugin, plugins) {
|
||||
QString plugin_name = plugin.split(QDir::separator()).last();
|
||||
plugin_name.chop(3); // Remove .py extension
|
||||
qDebug("Detected plugin %s in archive", plugin_name.toUtf8().data());
|
||||
ZZIP_FILE* fp = zzip_file_open(dir, plugin.toUtf8().data(), 0);
|
||||
if(fp) {
|
||||
QTemporaryFile *tmpfile = new QTemporaryFile();
|
||||
QString tmpPath;
|
||||
// Write file
|
||||
if(tmpfile->open()) {
|
||||
tmpPath = tmpfile->fileName();
|
||||
char buf[255];
|
||||
zzip_ssize_t len = zzip_file_read(fp, buf, 255);
|
||||
while(len) {
|
||||
tmpfile->write(buf, len);
|
||||
len = zzip_file_read(fp, buf, 255);
|
||||
}
|
||||
zzip_file_close(fp);
|
||||
tmpfile->close();
|
||||
} else {
|
||||
qDebug("Could not open tmp file");
|
||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
delete tmpfile;
|
||||
continue;
|
||||
}
|
||||
// Install plugin
|
||||
installPlugin(tmpPath, plugin_name);
|
||||
qDebug("installPlugin() finished");
|
||||
delete tmpfile;
|
||||
qDebug("Deleted tmpfile");
|
||||
} else {
|
||||
qDebug("Cannot read file in archive");
|
||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
}
|
||||
}
|
||||
QString favicon;
|
||||
foreach(favicon, favicons) {
|
||||
qDebug("Detected favicon %s in archive", favicon.toUtf8().data());
|
||||
// Ok we have a favicon here
|
||||
QString plugin_name = favicon.split(QDir::separator()).last();
|
||||
plugin_name.chop(4); // Remove .png extension
|
||||
if(!QFile::exists(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py"))
|
||||
continue;
|
||||
// Check if we already have a favicon for this plugin
|
||||
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".png";
|
||||
if(QFile::exists(iconPath)) continue;
|
||||
ZZIP_FILE* fp = zzip_file_open(dir, favicon.toUtf8().data(), 0);
|
||||
if(fp) {
|
||||
QFile dest_icon(iconPath);
|
||||
// Write icon
|
||||
if(dest_icon.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
char buf[255];
|
||||
zzip_ssize_t len = zzip_file_read(fp, buf, 255);
|
||||
while(len) {
|
||||
dest_icon.write(buf, len);
|
||||
len = zzip_file_read(fp, buf, 255);
|
||||
}
|
||||
zzip_file_close(fp);
|
||||
dest_icon.close();
|
||||
// Update icon in list
|
||||
QTreeWidgetItem *item = findItemWithID(plugin_name);
|
||||
Q_ASSERT(item);
|
||||
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
|
||||
}
|
||||
}
|
||||
}
|
||||
zzip_dir_close(dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
|
||||
qDebug("Asked to install plugin at %s", path.toUtf8().data());
|
||||
float new_version = misc::getPluginVersion(path);
|
||||
qDebug("Version to be installed: %.2f", new_version);
|
||||
if(!isUpdateNeeded(plugin_name, new_version)) {
|
||||
qDebug("Apparently update it not needed, we have a more recent version");
|
||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
return;
|
||||
}
|
||||
// Process with install
|
||||
QString dest_path = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py";
|
||||
bool update = false;
|
||||
if(QFile::exists(dest_path)) {
|
||||
// Backup in case install fails
|
||||
QFile::copy(dest_path, dest_path+".bak");
|
||||
QFile::remove(dest_path);
|
||||
update = true;
|
||||
}
|
||||
// Copy the plugin
|
||||
QFile::copy(path, dest_path);
|
||||
// Check if this was correctly installed
|
||||
if(!checkInstalled(plugin_name)) {
|
||||
if(update) {
|
||||
// Remove broken file
|
||||
QFile::remove(dest_path);
|
||||
// restore backup
|
||||
QFile::copy(dest_path+".bak", dest_path);
|
||||
QFile::remove(dest_path+".bak");
|
||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
return;
|
||||
} else {
|
||||
// Remove broken file
|
||||
QFile::remove(dest_path);
|
||||
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Install was successful, remove backup
|
||||
if(update) {
|
||||
QFile::remove(dest_path+".bak");
|
||||
}
|
||||
// Refresh plugin list
|
||||
loadSupportedSearchEngines();
|
||||
if(update) {
|
||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
return;
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void engineSelectDlg::on_installButton_clicked() {
|
||||
pluginSourceDlg *dlg = new pluginSourceDlg(this);
|
||||
connect(dlg, SIGNAL(askForLocalFile()), this, SLOT(askForLocalPlugin()));
|
||||
connect(dlg, SIGNAL(askForUrl()), this, SLOT(askForPluginUrl()));
|
||||
}
|
||||
|
||||
void engineSelectDlg::askForPluginUrl() {
|
||||
bool ok;
|
||||
QString url = QInputDialog::getText(this, tr("New search engine plugin URL"),
|
||||
tr("URL:"), QLineEdit::Normal,
|
||||
"http://", &ok);
|
||||
if (ok && !url.isEmpty())
|
||||
downloader->downloadUrl(url);
|
||||
}
|
||||
|
||||
void engineSelectDlg::askForLocalPlugin() {
|
||||
QStringList pathsList = QFileDialog::getOpenFileNames(0,
|
||||
tr("Select search plugins"), QDir::homePath(),
|
||||
#ifdef HAVE_ZZIP
|
||||
tr("qBittorrent search plugins")+QString::fromUtf8(" (*.py *.zip)"));
|
||||
#else
|
||||
tr("qBittorrent search plugins")+QString::fromUtf8(" (*.py)"));
|
||||
#endif
|
||||
QString path;
|
||||
foreach(path, pathsList) {
|
||||
if(path.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
QString plugin_name = path.split(QDir::separator()).last();
|
||||
plugin_name.replace(".py", "", Qt::CaseInsensitive);
|
||||
installPlugin(path, plugin_name);
|
||||
}
|
||||
#ifdef HAVE_ZZIP
|
||||
else {
|
||||
if(path.endsWith(".zip", Qt::CaseInsensitive)) {
|
||||
installZipPlugin(path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool engineSelectDlg::parseVersionsFile(QString versions_file, QString updateServer) {
|
||||
qDebug("Checking if update is needed");
|
||||
bool file_correct = false;
|
||||
QFile versions(versions_file);
|
||||
if(!versions.open(QIODevice::ReadOnly | QIODevice::Text)){
|
||||
qDebug("* Error: Could not read versions.txt file");
|
||||
return false;
|
||||
}
|
||||
bool updated = false;
|
||||
while(!versions.atEnd()) {
|
||||
QByteArray line = versions.readLine();
|
||||
line.replace("\n", "");
|
||||
line = line.trimmed();
|
||||
if(line.isEmpty()) continue;
|
||||
if(line.startsWith("#")) continue;
|
||||
QList<QByteArray> list = line.split(' ');
|
||||
if(list.size() != 2) continue;
|
||||
QString plugin_name = QString(list.first());
|
||||
if(!plugin_name.endsWith(":")) continue;
|
||||
plugin_name.chop(1); // remove trailing ':'
|
||||
bool ok;
|
||||
float version = list.last().toFloat(&ok);
|
||||
qDebug("read line %s: %.2f", plugin_name.toUtf8().data(), version);
|
||||
if(!ok) continue;
|
||||
file_correct = true;
|
||||
if(isUpdateNeeded(plugin_name, version)) {
|
||||
qDebug("Plugin: %s is outdated", plugin_name.toUtf8().data());
|
||||
// Downloading update
|
||||
downloader->downloadUrl(updateServer+plugin_name+".pyqBT"); // Actually this is really a .py
|
||||
downloader->downloadUrl(updateServer+plugin_name+".png");
|
||||
updated = true;
|
||||
}else {
|
||||
qDebug("Plugin: %s is up to date", plugin_name.toUtf8().data());
|
||||
}
|
||||
}
|
||||
// Close file
|
||||
versions.close();
|
||||
// Clean up tmp file
|
||||
QFile::remove(versions_file);
|
||||
if(file_correct && !updated) {
|
||||
QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date."));
|
||||
}
|
||||
return file_correct;
|
||||
}
|
||||
|
||||
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
|
||||
qDebug("engineSelectDlg received %s", url.toUtf8().data());
|
||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||
// Icon downloaded
|
||||
QImage fileIcon;
|
||||
#ifdef HAVE_MAGICK
|
||||
try{
|
||||
QFile::copy(filePath, filePath+".ico");
|
||||
Image image(QDir::cleanPath(filePath+".ico").toUtf8().data());
|
||||
// Convert to PNG since we can't read ICO format
|
||||
image.magick("PNG");
|
||||
// Resize to 16x16px
|
||||
image.sample(Geometry(16, 16));
|
||||
image.write(filePath.toUtf8().data());
|
||||
QFile::remove(filePath+".ico");
|
||||
}catch(Magick::Exception &error_){
|
||||
qDebug("favicon conversion to PNG failure: %s", error_.what());
|
||||
}
|
||||
#endif
|
||||
if(fileIcon.load(filePath)) {
|
||||
QList<QTreeWidgetItem*> items = findItemsWithUrl(url);
|
||||
QTreeWidgetItem *item;
|
||||
foreach(item, items){
|
||||
QString id = item->text(ENGINE_ID);
|
||||
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
|
||||
QFile::copy(filePath, iconPath);
|
||||
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
|
||||
}
|
||||
}
|
||||
// Delete tmp file
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
|
||||
if(!parseVersionsFile(filePath, "http://www.dchris.eu/search_engine/")) {
|
||||
qDebug("Primary update server failed, try secondary");
|
||||
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
|
||||
}
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
|
||||
if(!parseVersionsFile(filePath, "http://hydr0g3n.free.fr/search_engine/")) {
|
||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
|
||||
}
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
if(url.endsWith(".pyqBT", Qt::CaseInsensitive) || url.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
QString plugin_name = url.split('/').last();
|
||||
plugin_name.replace(".pyqBT", "");
|
||||
plugin_name.replace(".py", "");
|
||||
installPlugin(filePath, plugin_name);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_ZZIP
|
||||
if(url.endsWith(".zip", Qt::CaseInsensitive)) {
|
||||
installZipPlugin(filePath);
|
||||
QFile::remove(filePath);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
|
||||
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
|
||||
qDebug("Could not download favicon: %s, reason: %s", url.toUtf8().data(), reason.toUtf8().data());
|
||||
return;
|
||||
}
|
||||
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
|
||||
// Primary update server failed, try secondary
|
||||
qDebug("Primary update server failed, try secondary");
|
||||
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
|
||||
return;
|
||||
}
|
||||
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
|
||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
|
||||
return;
|
||||
}
|
||||
if(url.endsWith(".pyqBT", Qt::CaseInsensitive) || url.endsWith(".py", Qt::CaseInsensitive)) {
|
||||
// a plugin update download has been failed
|
||||
QString plugin_name = url.split('/').last();
|
||||
plugin_name.replace(".pyqBT", "", Qt::CaseInsensitive);
|
||||
plugin_name.replace(".py", "", Qt::CaseInsensitive);
|
||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
}
|
||||
#ifdef HAVE_ZZIP
|
||||
if(url.endsWith(".zip", Qt::CaseInsensitive)) {
|
||||
QString plugin_name = url.split('/').last();
|
||||
plugin_name.replace(".zip", "", Qt::CaseInsensitive);
|
||||
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
76
src/engineSelectDlg.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_SELECT_DLG_H
|
||||
#define ENGINE_SELECT_DLG_H
|
||||
|
||||
#include "ui_engineSelect.h"
|
||||
|
||||
class downloadThread;
|
||||
class QDropEvent;
|
||||
|
||||
class engineSelectDlg : public QDialog, public Ui::engineSelect{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
// Search related
|
||||
QHash<QString, bool> installed_engines;
|
||||
downloadThread *downloader;
|
||||
|
||||
public:
|
||||
engineSelectDlg(QWidget *parent);
|
||||
~engineSelectDlg();
|
||||
QList<QTreeWidgetItem*> findItemsWithUrl(QString url);
|
||||
QTreeWidgetItem* findItemWithID(QString id);
|
||||
|
||||
protected:
|
||||
bool parseVersionsFile(QString versions_file, QString updateServer);
|
||||
bool isUpdateNeeded(QString plugin_name, float new_version) const;
|
||||
bool checkInstalled(QString plugin_name) const;
|
||||
|
||||
signals:
|
||||
void enginesChanged();
|
||||
|
||||
protected slots:
|
||||
void saveSettings();
|
||||
void on_closeButton_clicked();
|
||||
void loadSupportedSearchEngines(bool first=false);
|
||||
void toggleEngineState(QTreeWidgetItem*, int);
|
||||
void setRowColor(int row, QString color);
|
||||
void processDownloadedFile(QString url, QString filePath);
|
||||
void handleDownloadFailure(QString url, QString reason);
|
||||
void displayContextMenu(const QPoint& pos);
|
||||
void enableSelection();
|
||||
void disableSelection();
|
||||
void on_actionUninstall_triggered();
|
||||
void on_updateButton_clicked();
|
||||
void on_installButton_clicked();
|
||||
void dropEvent(QDropEvent *event);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void installPlugin(QString plugin_path, QString plugin_name);
|
||||
void askForLocalPlugin();
|
||||
void askForPluginUrl();
|
||||
#ifdef HAVE_ZZIP
|
||||
void installZipPlugin(QString path);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,48 +1,77 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>Icons/encrypted.png</file>
|
||||
<file>Icons/time.png</file>
|
||||
<file>Icons/connection.png</file>
|
||||
<file>Icons/locale.png</file>
|
||||
<file>Icons/newmsg.png</file>
|
||||
<file>Icons/style.png</file>
|
||||
<file>Icons/wizard.png</file>
|
||||
<file>Icons/button_cancel.png</file>
|
||||
<file>Icons/url.png</file>
|
||||
<file>Icons/button_ok.png</file>
|
||||
<file>Icons/smile.png</file>
|
||||
<file>Icons/stare.png</file>
|
||||
<file>Icons/qbittorrent22.png</file>
|
||||
<file>Icons/proxy.png</file>
|
||||
<file>Icons/log.png</file>
|
||||
<file>Icons/qbittorrent32.png</file>
|
||||
<file>Icons/downarrow.png</file>
|
||||
<file>Icons/description.png</file>
|
||||
<file>Icons/qbittorrent16.png</file>
|
||||
<file>Icons/file.png</file>
|
||||
<file>Icons/systemtray.png</file>
|
||||
<file>Icons/unhappy.png</file>
|
||||
<file>Icons/filter.png</file>
|
||||
<file>Icons/splash.jpg</file>
|
||||
<file>Icons/sphere.png</file>
|
||||
<file>Icons/mascot.png</file>
|
||||
<file>Icons/encrypted.png</file>
|
||||
<file>Icons/refresh.png</file>
|
||||
<file>Icons/uparrow.png</file>
|
||||
<file>Icons/style.png</file>
|
||||
<file>Icons/wizard.png</file>
|
||||
<file>Icons/password.png</file>
|
||||
<file>Icons/gear.png</file>
|
||||
<file>Icons/sphere2.png</file>
|
||||
<file>Icons/smile.png</file>
|
||||
<file>Icons/loading.png</file>
|
||||
<file>Icons/button_cancel.png</file>
|
||||
<file>Icons/qbittorrent22.png</file>
|
||||
<file>Icons/proxy.png</file>
|
||||
<file>Icons/add_folder.png</file>
|
||||
<file>Icons/unavailable.png</file>
|
||||
<file>Icons/add_file.png</file>
|
||||
<file>Icons/home.png</file>
|
||||
<file>Icons/flags/netherlands.png</file>
|
||||
<file>Icons/splash.png</file>
|
||||
<file>Icons/rss32.png</file>
|
||||
<file>Icons/rss16.png</file>
|
||||
<file>Icons/unsubscribe.png</file>
|
||||
<file>Icons/subscribe.png</file>
|
||||
<file>Icons/unsubscribe16.png</file>
|
||||
<file>Icons/subscribe16.png</file>
|
||||
<file>Icons/bt_settings.png</file>
|
||||
<file>Icons/star.png</file>
|
||||
<file>Icons/configure.png</file>
|
||||
<file>Icons/download.png</file>
|
||||
<file>Icons/folder.png</file>
|
||||
<file>Icons/flags/portugal.png</file>
|
||||
<file>Icons/flags/france.png</file>
|
||||
<file>Icons/flags/ukraine.png</file>
|
||||
<file>Icons/flags/germany.png</file>
|
||||
<file>Icons/flags/united_kingdom.png</file>
|
||||
<file>Icons/flags/germany.png</file>
|
||||
<file>Icons/flags/russia.png</file>
|
||||
<file>Icons/flags/south_korea.png</file>
|
||||
<file>Icons/flags/netherlands.png</file>
|
||||
<file>Icons/flags/slovakia.png</file>
|
||||
<file>Icons/flags/spain.png</file>
|
||||
<file>Icons/flags/finland.png</file>
|
||||
<file>Icons/flags/poland.png</file>
|
||||
<file>Icons/flags/china_hong_kong.png</file>
|
||||
<file>Icons/flags/spain_catalunya.png</file>
|
||||
<file>Icons/flags/poland.png</file>
|
||||
<file>Icons/flags/hungary.png</file>
|
||||
<file>Icons/flags/norway.png</file>
|
||||
<file>Icons/flags/denmark.png</file>
|
||||
<file>Icons/flags/italy.png</file>
|
||||
<file>Icons/flags/china.png</file>
|
||||
<file>Icons/flags/denmark.png</file>
|
||||
<file>Icons/flags/brazil.png</file>
|
||||
<file>Icons/flags/south_korea.png</file>
|
||||
<file>Icons/flags/turkey.png</file>
|
||||
<file>Icons/flags/sweden.png</file>
|
||||
<file>Icons/flags/romania.png</file>
|
||||
<file>Icons/flags/bulgaria.png</file>
|
||||
<file>Icons/flags/greece.png</file>
|
||||
<file>Icons/flags/romania.png</file>
|
||||
<file>Icons/flags/japan.png</file>
|
||||
<file>Icons/flags/greece.png</file>
|
||||
<file>Icons/skin/properties.png</file>
|
||||
<file>Icons/skin/play_all.png</file>
|
||||
<file>Icons/skin/remove.png</file>
|
||||
@@ -67,6 +96,7 @@
|
||||
<file>Icons/skin/add.png</file>
|
||||
<file>Icons/skin/stalled.png</file>
|
||||
<file>Icons/skin/new.png</file>
|
||||
<file>Icons/skin/qb_question.png</file>
|
||||
<file>Icons/skin/delete_all.png</file>
|
||||
<file>Icons/skin/info.png</file>
|
||||
</qresource>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<qresource>
|
||||
<file>lang/qbittorrent_es.qm</file>
|
||||
<file>lang/qbittorrent_ko.qm</file>
|
||||
<file>lang/qbittorrent_hu.qm</file>
|
||||
<file>lang/qbittorrent_sk.qm</file>
|
||||
<file>lang/qbittorrent_uk.qm</file>
|
||||
<file>lang/qbittorrent_ro.qm</file>
|
||||
@@ -9,20 +10,20 @@
|
||||
<file>lang/qbittorrent_nb.qm</file>
|
||||
<file>lang/qbittorrent_el.qm</file>
|
||||
<file>lang/qbittorrent_en.qm</file>
|
||||
<file>lang/qbittorrent_pt_BR.qm</file>
|
||||
<file>lang/qbittorrent_fr.qm</file>
|
||||
<file>lang/qbittorrent_nl.qm</file>
|
||||
<file>lang/qbittorrent_pl.qm</file>
|
||||
<file>lang/qbittorrent_it.qm</file>
|
||||
<file>lang/qbittorrent_zh.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_ca.qm</file>
|
||||
<file>lang/qbittorrent_pt.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_tr.qm</file>
|
||||
<file>lang/qbittorrent_bg.qm</file>
|
||||
<file>lang/qbittorrent_de.qm</file>
|
||||
<file>lang/qbittorrent_sv.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
<file>lang/qbittorrent_zh_HK.qm</file>
|
||||
<file>lang/qbittorrent_da.qm</file>
|
||||
<file>lang/qbittorrent_ja.qm</file>
|
||||
<file>lang/qbittorrent_fi.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||