Compare commits
431 Commits
release-1.
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11276174c1 | ||
|
|
05948e2edf | ||
|
|
c9c4f7001a | ||
|
|
6cd185d0d5 | ||
|
|
063219cbe7 | ||
|
|
e324f3792b | ||
|
|
0267ecc342 | ||
|
|
e53c7aaea6 | ||
|
|
3e90e56266 | ||
|
|
1c1b8acd67 | ||
|
|
811846e5fa | ||
|
|
3ba28885b9 | ||
|
|
8ed1c57c29 | ||
|
|
af5d24c5bc | ||
|
|
9dcd572d60 | ||
|
|
e024a3ff35 | ||
|
|
37342e0f0c | ||
|
|
bfbbc1f497 | ||
|
|
5d31dcdb15 | ||
|
|
6f89b1f131 | ||
|
|
9d35bda43c | ||
|
|
e780d83fd0 | ||
|
|
7a59d5e47c | ||
|
|
f2ea524be9 | ||
|
|
a33094519c | ||
|
|
e313ae808f | ||
|
|
dc9802fe1e | ||
|
|
64f1d306f4 | ||
|
|
f3af4867fd | ||
|
|
4fe22dbc57 | ||
|
|
1d9b524b77 | ||
|
|
63761afd0a | ||
|
|
8da148ffa1 | ||
|
|
e2dc2207d8 | ||
|
|
6e87d6655a | ||
|
|
d72485a955 | ||
|
|
04c6760892 | ||
|
|
382f3e3c86 | ||
|
|
c1378450fc | ||
|
|
4e10a8dbf7 | ||
|
|
4f7b4c2a55 | ||
|
|
f98f076335 | ||
|
|
b148a93a8f | ||
|
|
37cf23fe33 | ||
|
|
87f43123c6 | ||
|
|
11dd2d81b8 | ||
|
|
d18d07efed | ||
|
|
518a120c07 | ||
|
|
290bc8b7a6 | ||
|
|
0ede09efb5 | ||
|
|
15de12f6dd | ||
|
|
ef95d6df81 | ||
|
|
f382ba4fd0 | ||
|
|
01d504d992 | ||
|
|
cdd894a6a1 | ||
|
|
d7b2d3497f | ||
|
|
5dbd5c4326 | ||
|
|
9a14c4c599 | ||
|
|
3fa14cd47f | ||
|
|
941d9b9bd9 | ||
|
|
3d88b7b05c | ||
|
|
8d39e2a776 | ||
|
|
4a1c8a7279 | ||
|
|
b8d8862562 | ||
|
|
40e9105ee5 | ||
|
|
0984b8b8e1 | ||
|
|
3dd7dcc58f | ||
|
|
6ba5df3ec8 | ||
|
|
1560b4ca3b | ||
|
|
68d8a9ed47 | ||
|
|
ca00f3084d | ||
|
|
39c16b20ae | ||
|
|
666d4622b9 | ||
|
|
27388643b1 | ||
|
|
90d17d16a4 | ||
|
|
df0f01cd71 | ||
|
|
480d00d747 | ||
|
|
a0923741a4 | ||
|
|
8e2efc2950 | ||
|
|
91dee6058e | ||
|
|
f5c1343722 | ||
|
|
d4d0a08390 | ||
|
|
d02aca7323 | ||
|
|
fd81567ecd | ||
|
|
8e5f5b5d65 | ||
|
|
215d561b82 | ||
|
|
dc18780a97 | ||
|
|
06fb19e8be | ||
|
|
3550e31871 | ||
|
|
46c6c4fc9a | ||
|
|
e126de8ff5 | ||
|
|
f2d2e70967 | ||
|
|
48b14d1066 | ||
|
|
725700420c | ||
|
|
480df1f5dc | ||
|
|
2fa43dd973 | ||
|
|
b9f1586068 | ||
|
|
07dbe388f4 | ||
|
|
b2af40c95b | ||
|
|
05569a5011 | ||
|
|
73dbce45b2 | ||
|
|
fdaeafc701 | ||
|
|
9ca4e2f1f6 | ||
|
|
2b53aa7e81 | ||
|
|
8e79e918c5 | ||
|
|
687842a949 | ||
|
|
645ee86860 | ||
|
|
f50762dfa8 | ||
|
|
7e252d3fbd | ||
|
|
2dc9f10bf4 | ||
|
|
bca03706a0 | ||
|
|
e7663e7b6b | ||
|
|
2b0e05b453 | ||
|
|
4d67170d3e | ||
|
|
538c028f8a | ||
|
|
2cbbd6ef50 | ||
|
|
955d8069e2 | ||
|
|
25d998f1b5 | ||
|
|
462f6c41cd | ||
|
|
298f1e6a9a | ||
|
|
2926745102 | ||
|
|
c6003c7403 | ||
|
|
66e5a6672a | ||
|
|
c35500dd29 | ||
|
|
f80bd42361 | ||
|
|
0b9c05d41b | ||
|
|
2477dc1fc0 | ||
|
|
706362333d | ||
|
|
6fcf25af52 | ||
|
|
c8e8306e0a | ||
|
|
e429126934 | ||
|
|
7e71de558a | ||
|
|
09d8a4797d | ||
|
|
1bcb8b1ed8 | ||
|
|
d132d50f4d | ||
|
|
e619b6977a | ||
|
|
2742a54d6e | ||
|
|
360a327d7d | ||
|
|
b659303419 | ||
|
|
43108712be | ||
|
|
a038616fe5 | ||
|
|
81e5c295b6 | ||
|
|
08d079a563 | ||
|
|
454c8dc2bc | ||
|
|
337fc72ee6 | ||
|
|
b1e9c1ccf5 | ||
|
|
64806cb199 | ||
|
|
8e8e7cd3e7 | ||
|
|
27a18e01e2 | ||
|
|
fc9e7d74a3 | ||
|
|
037a1875f9 | ||
|
|
66baa4d3dc | ||
|
|
9e522a8a6c | ||
|
|
cfa4edd140 | ||
|
|
9e9134cd44 | ||
|
|
83a798b07e | ||
|
|
baee85684c | ||
|
|
88afb0f0e7 | ||
|
|
6f212f18f5 | ||
|
|
f04e600340 | ||
|
|
5140886567 | ||
|
|
0aa59694fd | ||
|
|
66d31b5ca1 | ||
|
|
47135932a4 | ||
|
|
40d0e44f15 | ||
|
|
16c30a2f10 | ||
|
|
7f2639fcbd | ||
|
|
8ad987a672 | ||
|
|
b24194068a | ||
|
|
f4e9b00ce3 | ||
|
|
5c0a24d58b | ||
|
|
c4aa23c86b | ||
|
|
96911a2c48 | ||
|
|
85abb80f43 | ||
|
|
2372f434cf | ||
|
|
ee6bc3c2e9 | ||
|
|
b6c6637c3b | ||
|
|
d358987316 | ||
|
|
6f28711f9e | ||
|
|
7b4b568859 | ||
|
|
c3aa2906bb | ||
|
|
9509bbaed4 | ||
|
|
b7c7245fb5 | ||
|
|
0153b03160 | ||
|
|
ca83fdecff | ||
|
|
bca898d8b6 | ||
|
|
c877c9c412 | ||
|
|
4dfd1f229b | ||
|
|
0d63f46035 | ||
|
|
106f7cdd32 | ||
|
|
0308825c11 | ||
|
|
8c21ef5c04 | ||
|
|
53c2fe4a60 | ||
|
|
64fef21a86 | ||
|
|
f6f4b5f219 | ||
|
|
f809b8a014 | ||
|
|
cf8dbf22f8 | ||
|
|
00d9f7c36b | ||
|
|
9a314db530 | ||
|
|
7db2ffc09f | ||
|
|
9a02c12ec9 | ||
|
|
2a77de686c | ||
|
|
a79b294885 | ||
|
|
13c670b96d | ||
|
|
65c4da6f0e | ||
|
|
bf9dc052d3 | ||
|
|
0ea6ee32be | ||
|
|
019bd476db | ||
|
|
baf5cb31af | ||
|
|
fc3c123f5b | ||
|
|
7dfdebd593 | ||
|
|
9835af4962 | ||
|
|
04cbd91f04 | ||
|
|
66db20cb47 | ||
|
|
2e0707bc0c | ||
|
|
e9c12cbf78 | ||
|
|
031de096f5 | ||
|
|
b85ed8ff38 | ||
|
|
00c5127ba1 | ||
|
|
714bf4f2ab | ||
|
|
c2244f746e | ||
|
|
8214d87ce5 | ||
|
|
e8454596ea | ||
|
|
1cc039c147 | ||
|
|
fe455970f1 | ||
|
|
36871a34ad | ||
|
|
4ea6ca75ca | ||
|
|
9e46c6c047 | ||
|
|
a2e9210665 | ||
|
|
aaf79add0b | ||
|
|
55743021e8 | ||
|
|
a8d627e1df | ||
|
|
eead11427f | ||
|
|
bec1388ba5 | ||
|
|
1542ff98bc | ||
|
|
0e9fd2dc3f | ||
|
|
cd618150b0 | ||
|
|
a2bcfa9192 | ||
|
|
1421f1450c | ||
|
|
288300d264 | ||
|
|
5e41a64c8b | ||
|
|
f4502367f3 | ||
|
|
273526b414 | ||
|
|
5b7b4b2cf3 | ||
|
|
ee99df0ba9 | ||
|
|
aec32db565 | ||
|
|
3894452840 | ||
|
|
54bfb7cda9 | ||
|
|
aa18f19ab7 | ||
|
|
3ae783e9cb | ||
|
|
83cac18690 | ||
|
|
3b09203937 | ||
|
|
a12621e1c0 | ||
|
|
60c3ccac7f | ||
|
|
1fbf7d42a1 | ||
|
|
4b73172105 | ||
|
|
ada5d2665b | ||
|
|
f1ca41a5c5 | ||
|
|
17e0700a52 | ||
|
|
cc77b2f578 | ||
|
|
85463e3910 | ||
|
|
7bd0dff802 | ||
|
|
4bc043146d | ||
|
|
fd78e0b5ce | ||
|
|
8565f1e61e | ||
|
|
4c6d6a35f3 | ||
|
|
fc79b7dc56 | ||
|
|
da11488ba1 | ||
|
|
968c3e1c3e | ||
|
|
68e30de763 | ||
|
|
573f00c66c | ||
|
|
ae81dbe088 | ||
|
|
2edbe66d91 | ||
|
|
f9f912906e | ||
|
|
7b4eee7a7d | ||
|
|
e799ac57ed | ||
|
|
30c93b9a4a | ||
|
|
03dc617874 | ||
|
|
bc29577a7b | ||
|
|
5509e94778 | ||
|
|
89330e11de | ||
|
|
c016c4bf66 | ||
|
|
3f1081b621 | ||
|
|
e3ae03c8a8 | ||
|
|
fbe292d06e | ||
|
|
1d294e43f1 | ||
|
|
d883ef27be | ||
|
|
be934837e5 | ||
|
|
956f97f6d6 | ||
|
|
de38ca3e23 | ||
|
|
1efaea46e3 | ||
|
|
2694a0947f | ||
|
|
f61d9d23f5 | ||
|
|
60dda258b3 | ||
|
|
c79a4a746f | ||
|
|
942b579d8e | ||
|
|
93bc6dca95 | ||
|
|
f36052351c | ||
|
|
d40c646561 | ||
|
|
9412ced722 | ||
|
|
7037b53ff8 | ||
|
|
adc72fb9a6 | ||
|
|
f0ca99ed6c | ||
|
|
e443aa75b7 | ||
|
|
282d0a4af6 | ||
|
|
25adf6b061 | ||
|
|
88f0ffe86d | ||
|
|
c786c42bb1 | ||
|
|
36bc2e96ba | ||
|
|
f9bf485ed7 | ||
|
|
c18103539c | ||
|
|
727f59f73f | ||
|
|
5d2d1dfa94 | ||
|
|
cf694d14f3 | ||
|
|
ec24fe2f49 | ||
|
|
a0b4e54410 | ||
|
|
c97bce4d61 | ||
|
|
afbfe1a96d | ||
|
|
2651ec5f0b | ||
|
|
330905da5e | ||
|
|
4c6359276c | ||
|
|
ff1fc527e0 | ||
|
|
d79cb6b66e | ||
|
|
0ac2554060 | ||
|
|
1d31e049a4 | ||
|
|
d5a4794610 | ||
|
|
29886acc01 | ||
|
|
f1ed7f06b9 | ||
|
|
a848538d66 | ||
|
|
b58046b1fc | ||
|
|
fe95e90e05 | ||
|
|
1544300616 | ||
|
|
028041f874 | ||
|
|
81f2d7ee4a | ||
|
|
66874fbd2f | ||
|
|
f47b3be0be | ||
|
|
87eee7029d | ||
|
|
713c80451e | ||
|
|
60889cac79 | ||
|
|
d398679c7e | ||
|
|
2e5330e54b | ||
|
|
1499138b9b | ||
|
|
2433a87445 | ||
|
|
d0de11909f | ||
|
|
3f5340523f | ||
|
|
cc5015773b | ||
|
|
cd260198f9 | ||
|
|
71e3061c18 | ||
|
|
6369401150 | ||
|
|
fa05441e74 | ||
|
|
81aac9ebcc | ||
|
|
7a1af536b6 | ||
|
|
45efcfce13 | ||
|
|
cddc3a0a43 | ||
|
|
c38a8a2bec | ||
|
|
1225d16413 | ||
|
|
384f3b23ee | ||
|
|
a3cfa6bba1 | ||
|
|
51638eddcc | ||
|
|
41c6a847b9 | ||
|
|
d57062a45a | ||
|
|
32f478a8c2 | ||
|
|
61dae1444b | ||
|
|
8ed40cc856 | ||
|
|
941b8c8d2a | ||
|
|
4f2a2dfab9 | ||
|
|
4a6ab376af | ||
|
|
1e37858cc4 | ||
|
|
668268b6b5 | ||
|
|
cfcd9b7eaf | ||
|
|
6a3dddd0cc | ||
|
|
dfb2046f82 | ||
|
|
3ae55b6a6f | ||
|
|
7e53d23e33 | ||
|
|
ce2294ee96 | ||
|
|
14646d0f9e | ||
|
|
717a4b00e1 | ||
|
|
fca3b66a25 | ||
|
|
1a861ef240 | ||
|
|
1590d9a98f | ||
|
|
112bcd7255 | ||
|
|
af29228cc9 | ||
|
|
b8c79e0b5f | ||
|
|
0d078f660a | ||
|
|
e7f89f256a | ||
|
|
cb693a0795 | ||
|
|
7b57345c4f | ||
|
|
90879386d5 | ||
|
|
3678aa4d23 | ||
|
|
e497789ec7 | ||
|
|
2134d404a5 | ||
|
|
e0707f6907 | ||
|
|
816f35cbab | ||
|
|
a73d3132df | ||
|
|
368c122dce | ||
|
|
c41d17043c | ||
|
|
3c17a1410b | ||
|
|
078110851d | ||
|
|
70725bdfe2 | ||
|
|
3c0a610a34 | ||
|
|
d5b74eecd0 | ||
|
|
1faf183c73 | ||
|
|
a1773a7cfd | ||
|
|
1af3515b00 | ||
|
|
70e2a5d3b3 | ||
|
|
78409570a9 | ||
|
|
5133931302 | ||
|
|
8326cebf5c | ||
|
|
ab46f11af2 | ||
|
|
91acb1a6ec | ||
|
|
c721fad54b | ||
|
|
2aea2a0032 | ||
|
|
3164337c3c | ||
|
|
b984c309ff | ||
|
|
cfbd06225b | ||
|
|
b0a0abd764 | ||
|
|
9618056b4e | ||
|
|
8b40e43432 | ||
|
|
01bc15d3f4 | ||
|
|
3282e1bcc9 | ||
|
|
e5b6a5605a | ||
|
|
9b67807926 | ||
|
|
f3729fbae6 | ||
|
|
0538c9c3e8 | ||
|
|
53a0e85b8d | ||
|
|
453dd93abf | ||
|
|
669cc2395a | ||
|
|
82706141cf | ||
|
|
c536f24d55 | ||
|
|
764b4e72ca | ||
|
|
19dd21062b |
10
AUTHORS
@@ -6,12 +6,22 @@ Contributors:
|
||||
* Ishan Arora <ishan@qbittorrent.org>
|
||||
* Grigis Gaëtan <cipher16@gmail.com>
|
||||
|
||||
Code from other projects:
|
||||
* files src/ico.cpp src/ico.h
|
||||
copyright: Malte Starostik <malte@kde.org>
|
||||
license: LGPL
|
||||
|
||||
Images Authors:
|
||||
* files: src/Icons/*.png
|
||||
copyright: Gnome Icon Theme
|
||||
license: GPLv2
|
||||
url: http://ftp.acc.umu.se/pub/GNOME/sources/gnome-icon-theme
|
||||
|
||||
* files: src/oxygen/*.png
|
||||
copyright: Oxygen Icon Theme (KDE)
|
||||
license: LGPL
|
||||
url: http://www.oxygen-icons.org
|
||||
|
||||
* files: src/Icons/flags/*.png
|
||||
copyright: Open Clip Art Library
|
||||
license: Creative Commons Public Domain Dedication
|
||||
|
||||
14
COPYING
@@ -1,3 +1,17 @@
|
||||
qBittorrent is licensed under the GNU General Public License version 2 with the
|
||||
addition of the following special exception:
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission to
|
||||
link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
modified versions of it that use the same license as the "OpenSSL" library),
|
||||
and distribute the linked executables. You must obey the GNU General Public
|
||||
License in all respects for all of the code used other than "OpenSSL". If you
|
||||
modify file(s), you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
----------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
117
Changelog
@@ -1,9 +1,124 @@
|
||||
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.5.0
|
||||
- FEATURE: Added Magnet URI support
|
||||
- FEATURE: Search engine supports category-based requests
|
||||
- FEATURE: Make use of torrent enclosure in RSS feeds for direct download
|
||||
- FEATURE: Implemented a RSS feed downloader with filter support
|
||||
- FEATURE: Save old RSS item to hard disk to remember them on start up
|
||||
- FEATURE: Display free disk space in torrent addition dialog
|
||||
- FEATURE: In torrent addition from URL, paste clipboard content if it contains an URL
|
||||
- FEATURE: RSS feeds URLs can now be copied to clipboard
|
||||
- FEATURE: RSS feeds can now be grouped into folders
|
||||
- FEATURE: Added "Unread" item to RSS feed list to display all unread news
|
||||
- FEATURE: If a torrent contains a torrent file, process downloaded torrent file too
|
||||
- FEATURE: A random listening port can be chosen automatically
|
||||
- BUGFIX: torrent resume code rewrited
|
||||
- BUGFIX: Greatly improved column sorting code
|
||||
- BUGFIX: Possibility to create trackerless torrents
|
||||
- BUGFIX: Better item coloring in torrent content filtering dialog
|
||||
- COSMETIC: Redesigned search tab to improve usability
|
||||
- COSMETIC: Redesigned RSS tab to improve usability
|
||||
|
||||
* Sun Aug 21 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.1
|
||||
- BUGFIX: Fix problems when changing save path (if using temporary download folder)
|
||||
- BUGFIX: Display real save path instead of the temporary one in torrent properties
|
||||
- BUGFIX: Catching invalid_handle exception to avoid rare crashes
|
||||
- BUGFIX: Fixed popup menu position in RSS feeds list
|
||||
- BUGFIX: Don't save RSS feed state if it could not be updated
|
||||
|
||||
* Thu Aug 13 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.4.0
|
||||
- FEATURE: Display swarm information in lists
|
||||
- FEATURE: Allow to define temporary download folder
|
||||
- FEATURE: Display total amount of uploaded data in finished list
|
||||
- FEATURE: Resizing a column in a search results tab affects all tabs
|
||||
- FEATURE: Search results tab columns are now remembered upon startup
|
||||
- FEATURE: Added right click menu in search engine to clear completion history
|
||||
- FEATURE: Allow to set a different port for DHT (UDP) than the one used for Bittorrent
|
||||
- FEATURE: Updated spoofing code to avoid trackers ban
|
||||
- BUGFIX: Provide more helpful explanation when an I/O error occured
|
||||
- BUGFIX: Stop enforcing UTF-8 and use system locale instead
|
||||
- COSMETIC: Redesigned program preferences
|
||||
- COSMETIC: Updated icons set
|
||||
|
||||
* Fri Jul 24 2009 - Christophe DUMEZ <chris@qbittorrent.org> - 1.3.5
|
||||
- BUGFIX: Made IP filter parser more robust
|
||||
- BUGFIX: Fixed torrent creation tool
|
||||
- BUGFIX: Fixed possible overflow in progress calculation in arborescence.h
|
||||
- BUGFIX: Save properties window size, position, columns width and restore them
|
||||
- BUGFIX: Set a minimum default width for NAME column in properties
|
||||
- BUGFIX: Remember visual indexes of columns in transfer lists
|
||||
|
||||
* Sun Jul 12 2009 - Christophe DUMEZ <chris@qbittorrent.org> - v1.3.4
|
||||
- BUGFIX: Fixed IP filter file parsing on 64bits
|
||||
- BUGFIX: Suppressed QLayout: Attempting to add QLayout "" to properties "properties" warning message when opening a properties dialog
|
||||
- BUGFIX: Fixed a little bug in search engine plugins helper file
|
||||
- BUGFIX: Fixed compilation problems with Qt 4.3
|
||||
- BUGFIX: Percentages no longer disapear with default cleanlooks style
|
||||
- BUGFIX: Cleanly fixed popup menus position in lists (no more workarounds)
|
||||
- BUGFIX: Fixed memory leak in search engine
|
||||
- BUGFIX: Torrents with an infinite ratio are no longer affected by ratio_limit set in program preferences
|
||||
- BUGFIX: Display a ratio of 0.0 if total_upload and total_download are both 0
|
||||
- BUGFIX: Remove last separator in top tool bar
|
||||
- BUGFIX: Tuned lists properties to make sure display is correct
|
||||
- COSMETIC: Display date as well as time in log window
|
||||
|
||||
* Sun Apr 5 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.3
|
||||
- BUGFIX: Fixed Web UI torrent upload form
|
||||
- BUGFIX: Fixed unicode support in search engine
|
||||
- BUGFIX: Fixed search engine bug that prevented a torrent from appearing more than once among all tabs
|
||||
- LICENSE: Added an exception to the license regarding OpenSSL.
|
||||
- I18N: Updated Finnish translation
|
||||
|
||||
* Sat Mar 7 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.2
|
||||
- BUGFIX: Fix top toolbar disabling
|
||||
- BUGFIX: Fix building with Qt 4.5
|
||||
- BUGFIX: RSS items read status is now remembered upon restart
|
||||
|
||||
* Mon Jan 26 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.1
|
||||
- BUGFIX: Torrents paused due to an I/O error were displayed as queued
|
||||
- BUGFIX: qBittorrent now prints backtrace in terminal when segfaulting
|
||||
- BUGFIX: Fixed files progress display in torrent properties
|
||||
- BUGFIX: Improved torrent ratio calculation
|
||||
- BUGFIX: Fixed possible crash when parsing filter file
|
||||
- BUGFIX: Made some code optimization
|
||||
- BUGFIX: Fixed download/upload speed decrease problems
|
||||
- I18N: Updated Finnish, Bulgarian and Greek translations
|
||||
|
||||
* Fri Jan 9 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.3.0
|
||||
- FEATURE: Based on libtorrent-rasterbar v0.14.2
|
||||
- FEATURE: Improved ratio calculation system
|
||||
- FEATURE: Torrent creation code cleanup
|
||||
- FEATURE: Allow to set maximum number of active seeds (queueing)
|
||||
- FEATURE: Now seeds priorities are handled automatically by libtorrent-rasterbar (queueing)
|
||||
- FEATURE: Code cleanup and optimization (save memory and cpu)
|
||||
- FEATURE: ETA calculation now relies on average speed over all sessions
|
||||
- FEATURE: Allow to force rechecking torrents
|
||||
- FEATURE: Added support for 2 new extensions (uTorrent metadata and smart ban plugin)
|
||||
- FEATURE: Allow to change the save path of torrents after addition
|
||||
- FEATURE: Got rid of libmagick++ dependency
|
||||
- FEATURE: Updated Web interface to MochaUI v0.9.5
|
||||
- FEATURE: Added notification in WebUI when qBittorrent is not reachable
|
||||
- FEATURE: Rewrote folder scanning code (Now uses a filesystem watcher)
|
||||
- FEATURE: Added torrent deletion from hard drive function in Web UI
|
||||
- FEATURE: Added queueing priority actions in Web UI
|
||||
- FEATURE: Display progress using progress bars in Web UI
|
||||
- BUGFIX: Made usage of fastresume data more reliable
|
||||
- BUGFIX: qBittorrent shutdown is now faster
|
||||
- BUGFIX: Fixed several memory leaks
|
||||
- BUGFIX: WebUI is now working with IE7
|
||||
- BUGFIX: Fixed spacing problem in toolbar when toggling its visibility
|
||||
- BUGFIX: Fixed some compilation and Qt4 warnings
|
||||
- BUGFIX: Do not use an addition dialog for torrents from folder scanning
|
||||
- BUGFIX: Catch SIGTERM to exit cleanly (e.g. computer shutdown)
|
||||
- BUGFIX: Improved proxy support code
|
||||
- BUGFIX: Fixed systray icon tooltip on Windows
|
||||
- BUGFIX: Proxy settings are now saved even if disabled
|
||||
|
||||
* Sun Nov 9 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.1
|
||||
- BUGFIX: Fixed possible crash when deleting a torrent permanently
|
||||
- BUGFIX: Queued_for_checking torrents were not displayed as checking in seeding list
|
||||
- BUGFIX: Speed up startup time when having a lot of torrents
|
||||
|
||||
* Wed Oct 29 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.0
|
||||
* Wed Oct 29th 2008 - Christophe Dumez <chris@qbittorrent.org> - v1.2.0
|
||||
- FEATURE: Torrent queueing system (with priorities)
|
||||
- FEATURE: The number of DHT nodes is displayed
|
||||
- FEATURE: RSS can now be disabled from program preferences
|
||||
|
||||
2
INSTALL
@@ -17,7 +17,7 @@ Dependencies:
|
||||
- Qt >= 4.3.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
|
||||
Qt >= 4.4.0 is advised
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= v0.13.1 REQUIRED)
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= v0.14.0 REQUIRED)
|
||||
-> http://www.qbittorrent.org/download.php (advised)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
16
TODO
@@ -1,18 +1,2 @@
|
||||
See https://blueprints.launchpad.net/qbittorrent/
|
||||
|
||||
// translations done
|
||||
- french
|
||||
- chinese traditional
|
||||
- chinese simplified
|
||||
- finish
|
||||
- swedish
|
||||
- slovak
|
||||
- German
|
||||
- Hungarian
|
||||
- Italian
|
||||
- Dutch
|
||||
- Romanian
|
||||
- Korean
|
||||
- Russian
|
||||
- Bulgarian
|
||||
- Greek
|
||||
|
||||
216
configure
vendored
@@ -18,20 +18,12 @@ Main options:
|
||||
--help This help text.
|
||||
|
||||
Dependency options:
|
||||
--with-libtorrent-inc=[path] Path to libtorrent-rasterbar include
|
||||
files
|
||||
--with-libtorrent-lib=[path] Path to libtorrent-rasterbar library
|
||||
files
|
||||
--with-libtorrent-static-lib=[path] Path to libtorrent-rasterbar .a file
|
||||
--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
|
||||
--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
|
||||
--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
|
||||
--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
|
||||
}
|
||||
@@ -148,21 +140,6 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-inc=*)
|
||||
QC_WITH_LIBTORRENT_INC=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-lib=*)
|
||||
QC_WITH_LIBTORRENT_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libtorrent-static-lib=*)
|
||||
QC_WITH_LIBTORRENT_STATIC_LIB=$optarg
|
||||
shift
|
||||
;;
|
||||
|
||||
--with-libboost-inc=*)
|
||||
QC_WITH_LIBBOOST_INC=$optarg
|
||||
shift
|
||||
@@ -178,21 +155,6 @@ while [ $# -gt 0 ]; do
|
||||
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
|
||||
@@ -229,15 +191,9 @@ echo PREFIX=$PREFIX
|
||||
echo BINDIR=$BINDIR
|
||||
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_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
|
||||
@@ -367,70 +323,29 @@ public:
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libtorrent-rasterbar
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.13"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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-rasterbar")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "torrent-rasterbar")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.0";
|
||||
QString adv_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toUtf8().data(), adv_ver.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -553,86 +468,6 @@ public:
|
||||
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(!conf->checkLibrary(s, "Magick++")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "Magick++")) {
|
||||
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-----
|
||||
@@ -720,9 +555,6 @@ cat >$1/modules_new.cpp <<EOT
|
||||
o = new qc_libcurl(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;
|
||||
@@ -1671,15 +1503,9 @@ export PREFIX
|
||||
export BINDIR
|
||||
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_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
|
||||
|
||||
@@ -15,6 +15,5 @@
|
||||
<dep type='libcurl'>
|
||||
<required/>
|
||||
</dep>
|
||||
<dep type='libmagick'/>
|
||||
<dep type='libzzip'/>
|
||||
</qconf>
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
-----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/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -64,14 +64,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
QProcess magickConfig;
|
||||
QString out = "";
|
||||
QStringList params;
|
||||
params << "--libs";
|
||||
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
|
||||
magickConfig.waitForStarted();
|
||||
magickConfig.waitForFinished();
|
||||
QByteArray result = magickConfig.readAll();
|
||||
result = result.replace("\n", "");
|
||||
params << "--libs";
|
||||
qconf->doCommand("Magick++-config", params, &out);
|
||||
out = out.replace("\n", "");
|
||||
conf->addLib(result.data());
|
||||
conf->addDefine("HAVE_MAGICK");
|
||||
return true;
|
||||
|
||||
@@ -1,70 +1,29 @@
|
||||
/*
|
||||
-----BEGIN QCMOD-----
|
||||
name: libtorrent-rasterbar
|
||||
arg: with-libtorrent-inc=[path], Path to libtorrent-rasterbar include files
|
||||
arg: with-libtorrent-lib=[path], Path to libtorrent-rasterbar library files
|
||||
arg: with-libtorrent-static-lib=[path], Path to libtorrent-rasterbar .a file
|
||||
-----END QCMOD-----
|
||||
*/
|
||||
// see Conf::findPkgConfig
|
||||
class qc_libtorrent_rasterbar : public ConfObj
|
||||
{
|
||||
public:
|
||||
qc_libtorrent_rasterbar(Conf *c) : ConfObj(c) {}
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.13"; }
|
||||
QString name() const { return "libtorrent-rasterbar >= 0.14.0 (>= 0.14.4 advised)"; }
|
||||
QString shortname() const { return "libtorrent-rasterbar"; }
|
||||
bool exec(){
|
||||
QString s;
|
||||
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
|
||||
if(!s.isEmpty()) {
|
||||
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/include";
|
||||
sl << "/usr/local/include";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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-rasterbar")) {
|
||||
return false;
|
||||
}
|
||||
conf->addLib(QString("-L") + s);
|
||||
}else{
|
||||
QStringList sl;
|
||||
sl << "/usr/lib/";
|
||||
sl << "/usr/lib64/";
|
||||
sl << "/usr/local/lib/";
|
||||
sl << "/usr/local/lib64/";
|
||||
bool found = false;
|
||||
foreach(s, sl){
|
||||
if(conf->checkLibrary(s, "torrent-rasterbar")){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) return false;
|
||||
conf->addLib(QString("-L") + s);
|
||||
}
|
||||
QStringList incs;
|
||||
QString req_ver = "0.14.0";
|
||||
QString adv_ver = "0.14.4";
|
||||
QString version, libs, other;
|
||||
VersionMode mode = VersionMin;
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
|
||||
return false;
|
||||
for(int n = 0; n < incs.count(); ++n)
|
||||
conf->addIncludePath(incs[n]);
|
||||
if(!libs.isEmpty())
|
||||
conf->addLib(libs);
|
||||
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, adv_ver, &version, &incs, &libs, &other))
|
||||
printf("\nWarning: libtorrent-rasterbar v%s was detected. Although it will compile and run, you will probably experience some bugs. Please consider updating to v%s!\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -72,7 +81,10 @@ class DLListDelegate: public QItemDelegate {
|
||||
case RATIO:{
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
double ratio = index.data().toDouble();
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
if(ratio > 100.)
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::fromUtf8("∞"));
|
||||
else
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
case PROGRESS:{
|
||||
|
||||
480
src/FeedDownloader.h
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FEEDDOWNLOADER_H
|
||||
#define FEEDDOWNLOADER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QSettings>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QRegExp>
|
||||
#include <QMenu>
|
||||
#include <QFile>
|
||||
#include <QDataStream>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "bittorrent.h"
|
||||
#include "ui_FeedDownloader.h"
|
||||
|
||||
class FeedFilter: public QHash<QString, QVariant> {
|
||||
private:
|
||||
bool valid;
|
||||
public:
|
||||
FeedFilter():valid(true) {}
|
||||
FeedFilter(bool valid): valid(valid) {}
|
||||
FeedFilter(QHash<QString, QVariant> filter): QHash<QString, QVariant>(filter), valid(true) {}
|
||||
|
||||
bool matches(QString s) {
|
||||
QStringList match_tokens = getMatchingTokens();
|
||||
foreach(const QString& token, match_tokens) {
|
||||
if(token.isEmpty() || token == "")
|
||||
continue;
|
||||
QRegExp reg(token, Qt::CaseInsensitive);
|
||||
if(reg.indexIn(s) < 0) return false;
|
||||
}
|
||||
// Checking not matching
|
||||
QStringList notmatch_tokens = getNotMatchingTokens();
|
||||
foreach(const QString& token, notmatch_tokens) {
|
||||
if(token.isEmpty()) continue;
|
||||
QRegExp reg(token, Qt::CaseInsensitive);
|
||||
if(reg.indexIn(s) > -1) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return valid;
|
||||
}
|
||||
|
||||
QStringList getMatchingTokens() const {
|
||||
QString matches = this->value("matches", "").toString();
|
||||
return matches.split(" ");
|
||||
}
|
||||
|
||||
QString getMatchingTokens_str() const {
|
||||
return this->value("matches", "").toString();
|
||||
}
|
||||
|
||||
void setMatchingTokens(QString tokens) {
|
||||
tokens = tokens.trimmed();
|
||||
if(tokens.isEmpty())
|
||||
(*this)["matches"] = "";
|
||||
else
|
||||
(*this)["matches"] = tokens;
|
||||
}
|
||||
|
||||
QStringList getNotMatchingTokens() const {
|
||||
QString notmatching = this->value("not", "").toString();
|
||||
return notmatching.split(" ");
|
||||
}
|
||||
|
||||
QString getNotMatchingTokens_str() const {
|
||||
return this->value("not", "").toString();
|
||||
}
|
||||
|
||||
void setNotMatchingTokens(QString tokens) {
|
||||
(*this)["not"] = tokens.trimmed();
|
||||
}
|
||||
|
||||
QString getSavePath() const {
|
||||
return this->value("save_path", "").toString();
|
||||
}
|
||||
|
||||
void setSavePath(QString save_path) {
|
||||
(*this)["save_path"] = save_path;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FeedFilters : public QHash<QString, QVariant> {
|
||||
|
||||
private:
|
||||
QString feed_url;
|
||||
|
||||
public:
|
||||
FeedFilters() {}
|
||||
FeedFilters(QString feed_url, QHash<QString, QVariant> filters): QHash<QString, QVariant>(filters), feed_url(feed_url) {}
|
||||
|
||||
bool hasFilter(QString name) const {
|
||||
return this->contains(name);
|
||||
}
|
||||
|
||||
FeedFilter* matches(QString s) {
|
||||
if(!isDownloadingEnabled()) return 0;
|
||||
if(this->size() == 0) return new FeedFilter(false);
|
||||
foreach(QVariant var_hash_filter, this->values()) {
|
||||
QHash<QString, QVariant> hash_filter = var_hash_filter.toHash();
|
||||
FeedFilter *filter = new FeedFilter(hash_filter);
|
||||
if(filter->matches(s))
|
||||
return filter;
|
||||
else
|
||||
delete filter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList names() const {
|
||||
return this->keys();
|
||||
}
|
||||
|
||||
FeedFilter getFilter(QString name) const {
|
||||
if(this->contains(name))
|
||||
return FeedFilter(this->value(name).toHash());
|
||||
return FeedFilter();
|
||||
}
|
||||
|
||||
void setFilter(QString name, FeedFilter f) {
|
||||
(*this)[name] = f;
|
||||
}
|
||||
|
||||
bool isDownloadingEnabled() const {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
return feeds_w_downloader.value(feed_url, false).toBool();
|
||||
}
|
||||
|
||||
void setDownloadingEnabled(bool enabled) {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> feeds_w_downloader = qBTRSS.value("downloader_on", QHash<QString, QVariant>()).toHash();
|
||||
feeds_w_downloader[feed_url] = enabled;
|
||||
qBTRSS.setValue("downloader_on", feeds_w_downloader);
|
||||
}
|
||||
|
||||
static FeedFilters getFeedFilters(QString url) {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
return FeedFilters(url, all_feeds_filters.value(url, QHash<QString, QVariant>()).toHash());
|
||||
}
|
||||
|
||||
void rename(QString old_name, QString new_name) {
|
||||
Q_ASSERT(this->contains(old_name));
|
||||
(*this)[new_name] = this->take(old_name);
|
||||
}
|
||||
|
||||
bool serialize(QString path) {
|
||||
QFile f(path);
|
||||
if(f.open(QIODevice::WriteOnly)) {
|
||||
QDataStream out(&f);
|
||||
out.setVersion(QDataStream::Qt_4_3);
|
||||
out << (QHash<QString, QVariant>)(*this);
|
||||
f.close();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool unserialize(QString path) {
|
||||
QFile f(path);
|
||||
if(f.open(QIODevice::ReadOnly)) {
|
||||
QDataStream in(&f);
|
||||
in.setVersion(QDataStream::Qt_4_3);
|
||||
QHash<QString, QVariant> tmp;
|
||||
in >> tmp;
|
||||
qDebug("Unserialized %d filters", tmp.size());
|
||||
foreach(const QString& key, tmp.keys()) {
|
||||
(*this)[key] = tmp[key];
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void save() {
|
||||
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
|
||||
QHash<QString, QVariant> all_feeds_filters = qBTRSS.value("feed_filters", QHash<QString, QVariant>()).toHash();
|
||||
qDebug("Saving filters for feed: %s (%d filters)", feed_url.toLocal8Bit().data(), (*this).size());
|
||||
all_feeds_filters[feed_url] = *this;
|
||||
qBTRSS.setValue("feed_filters", all_feeds_filters);
|
||||
}
|
||||
};
|
||||
|
||||
class FeedDownloaderDlg : public QDialog, private Ui_FeedDownloader{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString feed_url;
|
||||
QString feed_name;
|
||||
FeedFilters filters;
|
||||
bittorrent *BTSession;
|
||||
QString selected_filter; // name
|
||||
|
||||
public:
|
||||
FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, bittorrent* BTSession): QDialog(parent), feed_url(feed_url), feed_name(feed_name), BTSession(BTSession), selected_filter(QString::null){
|
||||
setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
Q_ASSERT(!feed_name.isEmpty());
|
||||
rssfeed_lbl->setText(feed_name);
|
||||
filters = FeedFilters::getFeedFilters(feed_url);
|
||||
// Connect Signals/Slots
|
||||
connect(filtersList, SIGNAL(currentItemChanged(QListWidgetItem* , QListWidgetItem *)), this, SLOT(showFilterSettings(QListWidgetItem *)));
|
||||
connect(filtersList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFiltersListMenu(const QPoint&)));
|
||||
connect(actionAdd_filter, SIGNAL(triggered()), this, SLOT(addFilter()));
|
||||
connect(actionRemove_filter, SIGNAL(triggered()), this, SLOT(deleteFilter()));
|
||||
connect(actionRename_filter, SIGNAL(triggered()), this, SLOT(renameFilter()));
|
||||
connect(del_button, SIGNAL(clicked(bool)), this, SLOT(deleteFilter()));
|
||||
connect(add_button, SIGNAL(clicked(bool)), this, SLOT(addFilter()));
|
||||
connect(enableDl_cb, SIGNAL(stateChanged(int)), this, SLOT(enableFilterBox(int)));
|
||||
// Restore saved info
|
||||
enableDl_cb->setChecked(filters.isDownloadingEnabled());
|
||||
fillFiltersList();
|
||||
if(filters.size() > 0) {
|
||||
// Select first filter
|
||||
filtersList->setCurrentItem(filtersList->item(0));
|
||||
//showFilterSettings(filtersList->item(0));
|
||||
}
|
||||
// Show
|
||||
show();
|
||||
}
|
||||
|
||||
~FeedDownloaderDlg() {
|
||||
// Make sure we save everything
|
||||
saveCurrentFilterSettings();
|
||||
filters.save();
|
||||
}
|
||||
|
||||
protected slots:
|
||||
void saveCurrentFilterSettings() {
|
||||
if(!selected_filter.isEmpty()) {
|
||||
FeedFilter filter = filters.getFilter(selected_filter);
|
||||
filter.setMatchingTokens(match_line->text());
|
||||
filter.setNotMatchingTokens(notmatch_line->text());
|
||||
QString save_path = savepath_line->text().trimmed();
|
||||
if(save_path.isEmpty())
|
||||
save_path = BTSession->getDefaultSavePath();
|
||||
filter.setSavePath(save_path);
|
||||
// Save updated filter
|
||||
filters.setFilter(selected_filter, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void fillFiltersList() {
|
||||
// Fill filter list
|
||||
foreach(QString filter_name, filters.names()) {
|
||||
new QListWidgetItem(filter_name, filtersList);
|
||||
}
|
||||
}
|
||||
|
||||
void displayFiltersListMenu(const QPoint&) {
|
||||
QMenu myFiltersListMenu(this);
|
||||
if(filtersList->selectedItems().size() > 0) {
|
||||
myFiltersListMenu.addAction(actionRename_filter);
|
||||
myFiltersListMenu.addAction(actionRemove_filter);
|
||||
} else {
|
||||
myFiltersListMenu.addAction(actionAdd_filter);
|
||||
}
|
||||
// Call menu
|
||||
myFiltersListMenu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void showFilterSettings(QListWidgetItem *item) {
|
||||
// First, save current filter settings
|
||||
saveCurrentFilterSettings();
|
||||
// Clear all fields
|
||||
clearFields();
|
||||
if(!item) {
|
||||
qDebug("No new selected item");
|
||||
return;
|
||||
}
|
||||
// Actually show filter settings
|
||||
QString filter_name = item->text();
|
||||
FeedFilter filter = filters.getFilter(filter_name);
|
||||
filterSettingsBox->setEnabled(true);
|
||||
match_line->setText(filter.getMatchingTokens_str());
|
||||
if(match_line->text().trimmed().isEmpty()) {
|
||||
match_line->setText(filter_name);
|
||||
}
|
||||
notmatch_line->setText(filter.getNotMatchingTokens_str());
|
||||
QString save_path = filter.getSavePath();
|
||||
if(save_path.isEmpty())
|
||||
save_path = BTSession->getDefaultSavePath();
|
||||
savepath_line->setText(save_path);
|
||||
// Update selected filter
|
||||
selected_filter = filter_name;
|
||||
}
|
||||
|
||||
void deleteFilter() {
|
||||
QList<QListWidgetItem *> items = filtersList->selectedItems();
|
||||
if(items.size() == 1) {
|
||||
QListWidgetItem * item = items.first();
|
||||
filters.remove(item->text());
|
||||
selected_filter = QString::null;
|
||||
delete item;
|
||||
// Reset Filter settings view
|
||||
if(filters.size() == 0) {
|
||||
clearFields();
|
||||
filterSettingsBox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renameFilter() {
|
||||
QList<QListWidgetItem *> items = filtersList->selectedItems();
|
||||
if(items.size() == 1) {
|
||||
QListWidgetItem *item = items.first();
|
||||
QString current_name = item->text();
|
||||
QString new_name;
|
||||
bool validated = false;
|
||||
do {
|
||||
new_name = askFilterName(current_name);
|
||||
if(new_name.isNull() || new_name == current_name) return;
|
||||
if(!filters.hasFilter(new_name)) {
|
||||
validated = true;
|
||||
} else {
|
||||
QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use."));
|
||||
}
|
||||
}while(!validated);
|
||||
// Rename the filter
|
||||
filters.rename(current_name, new_name);
|
||||
if(selected_filter == current_name)
|
||||
selected_filter = new_name;
|
||||
item->setText(new_name);
|
||||
}
|
||||
}
|
||||
|
||||
void enableFilterBox(int state) {
|
||||
if(state == Qt::Checked) {
|
||||
filtersBox->setEnabled(true);
|
||||
filters.setDownloadingEnabled(true);
|
||||
} else {
|
||||
filtersBox->setEnabled(false);
|
||||
filters.setDownloadingEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
QString askFilterName(QString name=QString::null) {
|
||||
QString name_prop;
|
||||
if(name.isEmpty())
|
||||
name_prop = tr("New filter");
|
||||
else
|
||||
name_prop = name;
|
||||
QString new_name;
|
||||
bool validated = false;
|
||||
do {
|
||||
bool ok;
|
||||
new_name = QInputDialog::getText(this, tr("Please choose a name for this filter"), tr("Filter name:"), QLineEdit::Normal, name_prop, &ok);
|
||||
if(!ok) {
|
||||
return QString::null;
|
||||
}
|
||||
// Validate filter name
|
||||
new_name = new_name.trimmed();
|
||||
if(new_name.isEmpty()) {
|
||||
// Cannot be left empty
|
||||
QMessageBox::warning(0, tr("Invalid filter name"), tr("The filter name cannot be left empty."));
|
||||
} else {
|
||||
validated = true;
|
||||
}
|
||||
} while(!validated);
|
||||
return new_name;
|
||||
}
|
||||
|
||||
void addFilter() {
|
||||
QString filter_name = QString::null;
|
||||
bool validated = false;
|
||||
do {
|
||||
filter_name = askFilterName();
|
||||
if(filter_name.isNull()) return;
|
||||
if(filters.hasFilter(filter_name)) {
|
||||
// Filter alread exists
|
||||
QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use."));
|
||||
} else {
|
||||
validated = true;
|
||||
}
|
||||
}while(!validated);
|
||||
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
|
||||
filtersList->setCurrentItem(it);
|
||||
//showFilterSettings(it);
|
||||
}
|
||||
|
||||
void clearFields() {
|
||||
match_line->clear();
|
||||
notmatch_line->clear();
|
||||
savepath_line->clear();
|
||||
test_res_lbl->setText("");
|
||||
test_line->clear();
|
||||
}
|
||||
|
||||
void on_testButton_clicked(bool) {
|
||||
if(selected_filter.isEmpty()) return;
|
||||
QString s = test_line->text().trimmed();
|
||||
if(s.isEmpty()) {
|
||||
QMessageBox::warning(0, tr("Filter testing error"), tr("Please specify a test torrent name."));
|
||||
return;
|
||||
}
|
||||
// Get current filter
|
||||
saveCurrentFilterSettings();
|
||||
FeedFilter f = filters.getFilter(selected_filter);
|
||||
if(f.matches(s))
|
||||
test_res_lbl->setText("<b><font color=\"green\">"+tr("matches")+"</font></b>");
|
||||
else
|
||||
test_res_lbl->setText("<b><font color=\"red\">"+tr("does not match")+"</font></b>");
|
||||
}
|
||||
|
||||
void on_importButton_clicked(bool) {
|
||||
QString source = QFileDialog::getOpenFileName(0, tr("Select file to import"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
|
||||
if(source.isEmpty()) return;
|
||||
if(filters.unserialize(source)) {
|
||||
// Clean up first
|
||||
clearFields();
|
||||
filtersList->clear();
|
||||
selected_filter = QString::null;
|
||||
fillFiltersList();
|
||||
if(filters.size() > 0)
|
||||
filtersList->setCurrentItem(filtersList->item(0));
|
||||
QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful."));
|
||||
} else {
|
||||
QMessageBox::warning(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error."));
|
||||
}
|
||||
}
|
||||
|
||||
void on_exportButton_clicked(bool) {
|
||||
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination file"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)"));
|
||||
if(destination.isEmpty()) return;
|
||||
// Append file extension
|
||||
if(!destination.endsWith(".filters"))
|
||||
destination += ".filters";
|
||||
if(QFile::exists(destination)) {
|
||||
int ret = QMessageBox::question(0, tr("Overwriting confirmation"), tr("Are you sure you want to overwrite existing file?"), QMessageBox::Yes|QMessageBox::No);
|
||||
if(ret != QMessageBox::Yes) return;
|
||||
}
|
||||
if(filters.serialize(destination))
|
||||
QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful."));
|
||||
else
|
||||
QMessageBox::warning(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error."));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // FEEDDOWNLOADER_H
|
||||
546
src/FeedDownloader.ui
Normal file
@@ -0,0 +1,546 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FeedDownloader</class>
|
||||
<widget class="QDialog" name="FeedDownloader">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>737</width>
|
||||
<height>415</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>RSS Feed downloader</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>RSS feed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rssfeed_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Feed name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enableDl_cb">
|
||||
<property name="text">
|
||||
<string>Automatically download torrents from this feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filtersBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Download filters</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filters:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="filtersList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="del_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="add_button">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="filterSettingsBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Filter settings</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Matches:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Does not match:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Destination folder:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="match_line">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="notmatch_line"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="savepath_line">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="browse_button">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="testerBox">
|
||||
<property name="title">
|
||||
<string>Filter testing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Torrent title:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Result:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="test_line"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="testButton">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="test_res_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>9</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QPushButton" name="importButton">
|
||||
<property name="text">
|
||||
<string>Import...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportButton">
|
||||
<property name="text">
|
||||
<string>Export...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionRename_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/edit_clear.png</normaloff>:/Icons/oxygen/edit_clear.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rename filter</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Rename filter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRemove_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-remove.png</normaloff>:/Icons/oxygen/list-remove.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove filter</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove filter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_filter">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/list-add.png</normaloff>:/Icons/oxygen/list-add.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add filter</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FeedDownloader</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>FeedDownloader</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -35,10 +44,13 @@
|
||||
#define F_NAME 0
|
||||
#define F_SIZE 1
|
||||
#define F_UPSPEED 2
|
||||
#define F_LEECH 3
|
||||
#define F_RATIO 4
|
||||
#define F_PRIORITY 5
|
||||
#define F_HASH 6
|
||||
#define F_SWARM 3
|
||||
#define F_PEERS 4
|
||||
#define F_UPLOAD 5
|
||||
#define F_RATIO 6
|
||||
#define F_HASH 7
|
||||
|
||||
#define MAX_RATIO 100.
|
||||
|
||||
class FinishedListDelegate: public QItemDelegate {
|
||||
Q_OBJECT
|
||||
@@ -52,6 +64,7 @@ class FinishedListDelegate: public QItemDelegate {
|
||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||
switch(index.column()){
|
||||
case F_SIZE:
|
||||
case F_UPLOAD:
|
||||
QItemDelegate::drawBackground(painter, opt, index);
|
||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||
break;
|
||||
@@ -64,7 +77,10 @@ class FinishedListDelegate: public QItemDelegate {
|
||||
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)));
|
||||
if(ratio > MAX_RATIO)
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString::fromUtf8("∞"));
|
||||
else
|
||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#include "FinishedTorrents.h"
|
||||
@@ -29,6 +38,7 @@
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QStandardItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
@@ -37,63 +47,75 @@ FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : par
|
||||
setupUi(this);
|
||||
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
|
||||
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
|
||||
connect(BTSession, SIGNAL(addedTorrent(QTorrentHandle&)), this, SLOT(torrentAdded(QTorrentHandle&)));
|
||||
finishedListModel = new QStandardItemModel(0,7);
|
||||
finishedListModel = new QStandardItemModel(0,8);
|
||||
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_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
|
||||
finishedListModel->setHeaderData(F_LEECH, Qt::Horizontal, tr("Leechers", "i.e: full/partial sources"));
|
||||
finishedListModel->setHeaderData(F_SWARM, Qt::Horizontal, tr("Seeds / Leechers"));
|
||||
finishedListModel->setHeaderData(F_PEERS, Qt::Horizontal, tr("Connected peers"));
|
||||
finishedListModel->setHeaderData(F_UPLOAD, Qt::Horizontal, tr("Total uploaded", "i.e: Total amount of uploaded data"));
|
||||
finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio"));
|
||||
finishedListModel->setHeaderData(F_PRIORITY, Qt::Horizontal, tr("Priority"));
|
||||
finishedList->setModel(finishedListModel);
|
||||
|
||||
proxyModel = new QSortFilterProxyModel();
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
proxyModel->setSourceModel(finishedListModel);
|
||||
finishedList->setModel(proxyModel);
|
||||
|
||||
finishedList->setRootIsDecorated(false);
|
||||
finishedList->setAllColumnsShowFocus(true);
|
||||
finishedList->setSortingEnabled(true);
|
||||
|
||||
loadHiddenColumns();
|
||||
// Hide priority column
|
||||
finishedList->hideColumn(F_PRIORITY);
|
||||
// Hide hash column
|
||||
finishedList->hideColumn(F_HASH);
|
||||
// Load last columns width for download list
|
||||
if(!loadColWidthFinishedList()){
|
||||
finishedList->header()->resizeSection(0, 200);
|
||||
}
|
||||
// Connect BTSession signals
|
||||
connect(BTSession, SIGNAL(metadataReceived(QTorrentHandle&)), this, SLOT(updateMetadata(QTorrentHandle&)));
|
||||
// Make download list header clickable for sorting
|
||||
finishedList->header()->setClickable(true);
|
||||
finishedList->header()->setSortIndicatorShown(true);
|
||||
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(toggleFinishedListSortOrder(int)));
|
||||
finishedListDelegate = new FinishedListDelegate(finishedList);
|
||||
finishedList->setItemDelegate(finishedListDelegate);
|
||||
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
|
||||
finishedList->header()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(finishedList->header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedHoSMenu(const QPoint&)));
|
||||
connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
|
||||
connect(BTSession, SIGNAL(forceFinishedListUpdate()), this, SLOT(updateFinishedList()));
|
||||
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")));
|
||||
actionCopy_magnet_link->setIcon(QIcon(QString::fromUtf8(":/Icons/magnet.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(actionIncreasePriority, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionIncreasePriority_triggered()));
|
||||
connect(actionDecreasePriority, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDecreasePriority_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(actionOpen_destination_folder, SIGNAL(triggered()), (GUI*)parent, SLOT(openDestinationFolder()));
|
||||
connect(actionBuy_it, SIGNAL(triggered()), (GUI*)parent, SLOT(goBuyPage()));
|
||||
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
|
||||
connect(actionForce_recheck, SIGNAL(triggered()), this, SLOT(forceRecheck()));
|
||||
connect(actionCopy_magnet_link, SIGNAL(triggered()), (GUI*)parent, SLOT(copyMagnetURI()));
|
||||
|
||||
connect(actionHOSColName, SIGNAL(triggered()), this, SLOT(hideOrShowColumnName()));
|
||||
connect(actionHOSColSize, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSize()));
|
||||
connect(actionHOSColUpSpeed, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpSpeed()));
|
||||
connect(actionHOSColLeechers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnLeechers()));
|
||||
connect(actionHOSColSwarm, SIGNAL(triggered()), this, SLOT(hideOrShowColumnSwarm()));
|
||||
connect(actionHOSColPeers, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPeers()));
|
||||
connect(actionHOSColUpload, SIGNAL(triggered()), this, SLOT(hideOrShowColumnUpload()));
|
||||
connect(actionHOSColRatio, SIGNAL(triggered()), this, SLOT(hideOrShowColumnRatio()));
|
||||
connect(actionHOSColPriority, SIGNAL(triggered()), this, SLOT(hideOrShowColumnPriority()));
|
||||
}
|
||||
|
||||
FinishedTorrents::~FinishedTorrents(){
|
||||
saveLastSortedColumn();
|
||||
saveColWidthFinishedList();
|
||||
saveHiddenColumns();
|
||||
delete finishedListDelegate;
|
||||
delete proxyModel;
|
||||
delete finishedListModel;
|
||||
}
|
||||
|
||||
@@ -103,18 +125,7 @@ void FinishedTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
|
||||
emit torrentDoubleClicked(hash, true);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hidePriorityColumn(bool hide) {
|
||||
finishedList->setColumnHidden(F_PRIORITY, hide);
|
||||
if(hide)
|
||||
getActionHoSCol(F_PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
else
|
||||
getActionHoSCol(F_PRIORITY)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
}
|
||||
|
||||
void FinishedTorrents::addTorrent(QString hash){
|
||||
if(!BTSession->isFinished(hash)){
|
||||
BTSession->setFinishedTorrent(hash);
|
||||
}
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) return;
|
||||
row = finishedListModel->rowCount();
|
||||
@@ -124,10 +135,10 @@ void FinishedTorrents::addTorrent(QString hash){
|
||||
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_LEECH), QVariant("0"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SWARM), QVariant("-1/-1"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant("0"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((qlonglong)h.all_time_upload()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString::fromUtf8(misc::toString(BTSession->getRealRatio(hash)).c_str())));
|
||||
if(BTSession->isQueueingEnabled())
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PRIORITY), QVariant((int)BTSession->getUpTorrentPriority(hash)));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
|
||||
if(h.is_paused()) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(":/Icons/skin/paused.png"), Qt::DecorationRole);
|
||||
@@ -139,13 +150,8 @@ void FinishedTorrents::addTorrent(QString hash){
|
||||
// Update the number of finished torrents
|
||||
++nbFinished;
|
||||
emit finishedTorrentsNumberChanged(nbFinished);
|
||||
}
|
||||
|
||||
void FinishedTorrents::torrentAdded(QTorrentHandle& h) {
|
||||
QString hash = h.hash();
|
||||
if(BTSession->isFinished(hash)) {
|
||||
addTorrent(hash);
|
||||
}
|
||||
loadLastSortedColumn();
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
@@ -158,12 +164,11 @@ void FinishedTorrents::setRowColor(int row, QString color){
|
||||
|
||||
QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
|
||||
QStringList res;
|
||||
QModelIndex index;
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(index, selectedIndexes) {
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file hash
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
QString hash = getHashFromRow(index.row());
|
||||
res << hash;
|
||||
if(only_one) break;
|
||||
}
|
||||
@@ -191,10 +196,39 @@ bool FinishedTorrents::loadColWidthFinishedList(){
|
||||
finishedList->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
loadLastSortedColumn();
|
||||
QVariantList visualIndexes = settings.value(QString::fromUtf8("FinishedListVisualIndexes"), QVariantList()).toList();
|
||||
if(visualIndexes.size() != finishedListModel->columnCount()-1) {
|
||||
qDebug("Corrupted values for download list columns sizes");
|
||||
return false;
|
||||
}
|
||||
bool change = false;
|
||||
do {
|
||||
change = false;
|
||||
for(int i=0;i<visualIndexes.size(); ++i) {
|
||||
int new_visual_index = visualIndexes.at(finishedList->header()->logicalIndex(i)).toInt();
|
||||
if(i != new_visual_index) {
|
||||
qDebug("Moving column from %d to %d", finishedList->header()->logicalIndex(i), new_visual_index);
|
||||
finishedList->header()->moveSection(i, new_visual_index);
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}while(change);
|
||||
qDebug("Finished list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
void FinishedTorrents::saveLastSortedColumn() {
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
Qt::SortOrder sortOrder = finishedList->header()->sortIndicatorOrder();
|
||||
QString sortOrderLetter;
|
||||
if(sortOrder == Qt::AscendingOrder)
|
||||
sortOrderLetter = QString::fromUtf8("a");
|
||||
else
|
||||
sortOrderLetter = QString::fromUtf8("d");
|
||||
int index = finishedList->header()->sortIndicatorSection();
|
||||
settings.setValue(QString::fromUtf8("FinishedListSortedCol"), misc::toQString(index)+sortOrderLetter);
|
||||
}
|
||||
|
||||
void FinishedTorrents::loadLastSortedColumn() {
|
||||
// Loading last sorted column
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
@@ -207,7 +241,7 @@ void FinishedTorrents::loadLastSortedColumn() {
|
||||
sortOrder = Qt::AscendingOrder;
|
||||
sortedCol = sortedCol.left(sortedCol.size()-1);
|
||||
int index = sortedCol.toInt();
|
||||
sortFinishedList(index, sortOrder);
|
||||
finishedList->sortByColumn(index, sortOrder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +259,7 @@ void FinishedTorrents::saveColWidthFinishedList() const{
|
||||
width_list = line.split(' ');
|
||||
}
|
||||
for(short i=0; i<nbColumns; ++i){
|
||||
if(finishedList->columnWidth(i)<1 && width_list.size() == finishedListModel->columnCount()-1 && width_list.at(i).toInt()>=1) {
|
||||
if(finishedList->columnWidth(i)<1 && width_list.size() == nbColumns && width_list.at(i).toInt()>=1) {
|
||||
// load the former width
|
||||
new_width_list << width_list.at(i);
|
||||
} else if(finishedList->columnWidth(i)>=1) {
|
||||
@@ -238,31 +272,39 @@ void FinishedTorrents::saveColWidthFinishedList() const{
|
||||
}
|
||||
}
|
||||
settings.setValue("FinishedListColsWidth", new_width_list.join(" "));
|
||||
QVariantList visualIndexes;
|
||||
for(int i=0; i<nbColumns; ++i) {
|
||||
visualIndexes.append(finishedList->header()->visualIndex(i));
|
||||
}
|
||||
settings.setValue(QString::fromUtf8("FinishedListVisualIndexes"), visualIndexes);
|
||||
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){
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
// Get the file hash
|
||||
hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
hashes << getHashFromRow(index.row());
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
void FinishedTorrents::updateMetadata(QTorrentHandle &h) {
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row != -1) {
|
||||
qDebug("Updating torrent metadata in download list");
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::updateTorrent(QTorrentHandle h) {
|
||||
if(!h.is_valid()) return;
|
||||
QString hash = h.hash();
|
||||
int row = getRowFromHash(hash);
|
||||
if(row == -1){
|
||||
qDebug("Cannot find torrent in finished list, adding it");
|
||||
@@ -270,47 +312,42 @@ void FinishedTorrents::updateFinishedList(){
|
||||
row = getRowFromHash(hash);
|
||||
}
|
||||
Q_ASSERT(row != -1);
|
||||
// Update priority
|
||||
if(BTSession->isQueueingEnabled()) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PRIORITY), QVariant((int)BTSession->getUpTorrentPriority(hash)));
|
||||
if(h.is_paused() && BTSession->isUploadQueued(hash)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_SWARM)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_SWARM), misc::toQString(h.num_complete())+QString("/")+misc::toQString(h.num_incomplete()));
|
||||
}
|
||||
if(h.is_paused()) 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!
|
||||
int reponse = QMessageBox::question(this, tr("Incomplete torrent in seeding list"), tr("It appears that the state of '%1' torrent changed from 'seeding' to 'downloading'. Would you like to move it back to download list? (otherwise the torrent will simply be deleted)").arg(h.name()), QMessageBox::Yes | QMessageBox::No);
|
||||
if (reponse == QMessageBox::Yes) {
|
||||
qDebug("Info: a torrent was moved from finished to download tab");
|
||||
deleteTorrent(hash);
|
||||
BTSession->setUnfinishedTorrent(hash);
|
||||
emit torrentMovedFromFinishedList(hash);
|
||||
}
|
||||
else if (reponse == QMessageBox::No) {
|
||||
qDebug("Deleted from the finished");
|
||||
BTSession->deleteTorrent(hash, false);
|
||||
}
|
||||
continue;
|
||||
if(h.is_paused()) return;
|
||||
// Update queued torrent
|
||||
if(BTSession->isQueueingEnabled() && h.is_queued()) {
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
} else {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/queued.png"))), Qt::DecorationRole);
|
||||
}
|
||||
// Reset upload speed and seeds/leech
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), 0.);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), "0");
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
return;
|
||||
}
|
||||
if(h.state() == torrent_status::checking_files || h.state() == torrent_status::queued_for_checking){
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/oxygen/time.png"))), Qt::DecorationRole);
|
||||
setRowColor(row, QString::fromUtf8("grey"));
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
setRowColor(row, QString::fromUtf8("orange"));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
|
||||
if(!finishedList->isColumnHidden(F_UPSPEED)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_LEECH)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_LEECH), misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||
if(!finishedList->isColumnHidden(F_PEERS)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), misc::toQString(h.num_peers() - h.num_seeds(), true));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_UPLOAD)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_UPLOAD), QVariant((double)h.all_time_upload()));
|
||||
}
|
||||
if(!finishedList->isColumnHidden(F_RATIO)) {
|
||||
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FinishedTorrents::getRowFromHash(QString hash) const{
|
||||
@@ -330,20 +367,13 @@ void FinishedTorrents::pauseTorrent(QString hash) {
|
||||
return;
|
||||
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_LEECH), QVariant(QString::fromUtf8("0")));
|
||||
finishedListModel->setData(finishedListModel->index(row, F_PEERS), QVariant(QString::fromUtf8("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();
|
||||
Q_ASSERT(row < (unsigned int)proxyModel->rowCount());
|
||||
return proxyModel->data(proxyModel->index(row, F_HASH)).toString();
|
||||
}
|
||||
|
||||
// Will move it to download tab
|
||||
@@ -360,7 +390,7 @@ void FinishedTorrents::deleteTorrent(QString hash){
|
||||
|
||||
// Show torrent properties dialog
|
||||
void FinishedTorrents::showProperties(const QModelIndex &index){
|
||||
showPropertiesFromHash(finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString());
|
||||
showPropertiesFromHash(getHashFromRow(index.row()));
|
||||
}
|
||||
|
||||
void FinishedTorrents::showPropertiesFromHash(QString hash){
|
||||
@@ -380,24 +410,34 @@ void FinishedTorrents::updateFileSize(QString hash){
|
||||
// display properties of selected items
|
||||
void FinishedTorrents::propertiesSelection(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
QModelIndex index;
|
||||
foreach(index, selectedIndexes){
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
showProperties(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
|
||||
void FinishedTorrents::forceRecheck(){
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
foreach(const QModelIndex &index, selectedIndexes){
|
||||
if(index.column() == F_NAME){
|
||||
QString hash = getHashFromRow(index.row());
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
qDebug("Forcing recheck for torrent %s", hash.toLocal8Bit().data());
|
||||
h.force_recheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinishedTorrents::displayFinishedListMenu(const QPoint&){
|
||||
QMenu myFinishedListMenu(this);
|
||||
QModelIndex index;
|
||||
// Enable/disable pause/start action given the DL state
|
||||
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
|
||||
bool has_pause = false, has_start = false, has_preview = false;
|
||||
foreach(index, selectedIndexes) {
|
||||
foreach(const QModelIndex &index, selectedIndexes) {
|
||||
if(index.column() == F_NAME) {
|
||||
// Get the file name
|
||||
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
|
||||
QString hash = getHashFromRow(index.row());
|
||||
// Get handle and pause the torrent
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(!h.is_valid()) continue;
|
||||
@@ -425,19 +465,16 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionSet_upload_limit);
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionForce_recheck);
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionOpen_destination_folder);
|
||||
myFinishedListMenu.addAction(actionTorrent_Properties);
|
||||
if(BTSession->isQueueingEnabled()) {
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionIncreasePriority);
|
||||
myFinishedListMenu.addAction(actionDecreasePriority);
|
||||
}
|
||||
myFinishedListMenu.addSeparator();
|
||||
myFinishedListMenu.addAction(actionCopy_magnet_link);
|
||||
myFinishedListMenu.addAction(actionBuy_it);
|
||||
|
||||
// Call menu
|
||||
// XXX: why mapToGlobal() is not enough?
|
||||
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,58));
|
||||
myFinishedListMenu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
|
||||
@@ -446,20 +483,15 @@ void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
|
||||
*/
|
||||
|
||||
// hide/show columns menu
|
||||
void FinishedTorrents::displayFinishedHoSMenu(const QPoint& pos){
|
||||
void FinishedTorrents::displayFinishedHoSMenu(const QPoint&){
|
||||
QMenu hideshowColumn(this);
|
||||
hideshowColumn.setTitle(tr("Hide or Show Column"));
|
||||
int lastCol;
|
||||
if(BTSession->isQueueingEnabled()) {
|
||||
lastCol = F_PRIORITY;
|
||||
} else {
|
||||
lastCol = F_RATIO;
|
||||
}
|
||||
int lastCol = F_RATIO;
|
||||
for(int i=0; i<=lastCol; i++) {
|
||||
hideshowColumn.addAction(getActionHoSCol(i));
|
||||
}
|
||||
// Call menu
|
||||
hideshowColumn.exec(mapToGlobal(pos)+QPoint(10,34));
|
||||
hideshowColumn.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
// toggle hide/show a column
|
||||
@@ -477,12 +509,12 @@ void FinishedTorrents::hideOrShowColumn(int index) {
|
||||
if(nbVisibleColumns <= 1) return;
|
||||
// User can hide the column, do it.
|
||||
finishedList->setColumnHidden(index, true);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
--nbVisibleColumns;
|
||||
} else {
|
||||
// User want to display the column
|
||||
finishedList->setColumnHidden(index, false);
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
getActionHoSCol(index)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
++nbVisibleColumns;
|
||||
}
|
||||
//resize all others non-hidden columns
|
||||
@@ -505,18 +537,22 @@ void FinishedTorrents::hideOrShowColumnUpSpeed() {
|
||||
hideOrShowColumn(F_UPSPEED);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnLeechers() {
|
||||
hideOrShowColumn(F_LEECH);
|
||||
void FinishedTorrents::hideOrShowColumnSwarm() {
|
||||
hideOrShowColumn(F_SWARM);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnPeers() {
|
||||
hideOrShowColumn(F_PEERS);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnUpload() {
|
||||
hideOrShowColumn(F_UPLOAD);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnRatio() {
|
||||
hideOrShowColumn(F_RATIO);
|
||||
}
|
||||
|
||||
void FinishedTorrents::hideOrShowColumnPriority() {
|
||||
hideOrShowColumn(F_PRIORITY);
|
||||
}
|
||||
|
||||
// load the previous settings, and hide the columns
|
||||
bool FinishedTorrents::loadHiddenColumns() {
|
||||
bool loaded = false;
|
||||
@@ -536,9 +572,9 @@ bool FinishedTorrents::loadHiddenColumns() {
|
||||
for(int i=0; i<finishedListModel->columnCount()-1; i++) {
|
||||
if(loaded && ishidden_list.at(i) == "0") {
|
||||
finishedList->setColumnHidden(i, true);
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_cancel.png")));
|
||||
} else {
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
|
||||
getActionHoSCol(i)->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/button_ok.png")));
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
@@ -572,108 +608,19 @@ QAction* FinishedTorrents::getActionHoSCol(int index) {
|
||||
case F_UPSPEED :
|
||||
return actionHOSColUpSpeed;
|
||||
break;
|
||||
case F_LEECH :
|
||||
return actionHOSColLeechers;
|
||||
case F_SWARM :
|
||||
return actionHOSColSwarm;
|
||||
break;
|
||||
case F_PEERS :
|
||||
return actionHOSColPeers;
|
||||
break;
|
||||
case F_UPLOAD :
|
||||
return actionHOSColUpload;
|
||||
break;
|
||||
case F_RATIO :
|
||||
return actionHOSColRatio;
|
||||
break;
|
||||
case F_PRIORITY :
|
||||
return actionHOSColPriority;
|
||||
break;
|
||||
default :
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sorting functions
|
||||
*/
|
||||
|
||||
void FinishedTorrents::toggleFinishedListSortOrder(int index) {
|
||||
Qt::SortOrder sortOrder = Qt::AscendingOrder;
|
||||
if(finishedList->header()->sortIndicatorSection() == index){
|
||||
sortOrder = (Qt::SortOrder)!(bool)finishedList->header()->sortIndicatorOrder();
|
||||
}
|
||||
switch(index) {
|
||||
case F_SIZE:
|
||||
case F_UPSPEED:
|
||||
case F_PRIORITY:
|
||||
sortFinishedListFloat(index, sortOrder);
|
||||
break;
|
||||
default:
|
||||
sortFinishedListString(index, sortOrder);
|
||||
}
|
||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
|
||||
QString sortOrderLetter;
|
||||
if(sortOrder == Qt::AscendingOrder)
|
||||
sortOrderLetter = QString::fromUtf8("a");
|
||||
else
|
||||
sortOrderLetter = QString::fromUtf8("d");
|
||||
settings.setValue(QString::fromUtf8("FinishedListSortedCol"), misc::toQString(index)+sortOrderLetter);
|
||||
}
|
||||
|
||||
void FinishedTorrents::sortFinishedList(int index, Qt::SortOrder sortOrder){
|
||||
if(index == -1) {
|
||||
index = finishedList->header()->sortIndicatorSection();
|
||||
sortOrder = finishedList->header()->sortIndicatorOrder();
|
||||
} else {
|
||||
finishedList->header()->setSortIndicator(index, sortOrder);
|
||||
}
|
||||
switch(index) {
|
||||
case F_SIZE:
|
||||
case F_UPSPEED:
|
||||
case F_PRIORITY:
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -26,6 +35,7 @@
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
class QStandardItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
class bittorrent;
|
||||
class FinishedListDelegate;
|
||||
|
||||
@@ -38,6 +48,7 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
|
||||
bittorrent *BTSession;
|
||||
FinishedListDelegate *finishedListDelegate;
|
||||
QStandardItemModel *finishedListModel;
|
||||
QSortFilterProxyModel *proxyModel;
|
||||
unsigned int nbFinished;
|
||||
void hideOrShowColumn(int index);
|
||||
bool loadHiddenColumns();
|
||||
@@ -60,31 +71,28 @@ class FinishedTorrents : public QWidget, public Ui::seeding {
|
||||
void displayFinishedHoSMenu(const QPoint&);
|
||||
void setRowColor(int row, QString color);
|
||||
void saveColWidthFinishedList() const;
|
||||
void toggleFinishedListSortOrder(int index);
|
||||
void sortFinishedList(int index=-1, Qt::SortOrder sortOrder=Qt::AscendingOrder);
|
||||
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
|
||||
void sortFinishedListString(int index, Qt::SortOrder sortOrder);
|
||||
void updateFileSize(QString hash);
|
||||
void torrentAdded(QTorrentHandle& h);
|
||||
void on_actionSet_upload_limit_triggered();
|
||||
void notifyTorrentDoubleClicked(const QModelIndex& index);
|
||||
void hideOrShowColumnName();
|
||||
void hideOrShowColumnSize();
|
||||
void hideOrShowColumnUpSpeed();
|
||||
void hideOrShowColumnLeechers();
|
||||
void hideOrShowColumnSwarm();
|
||||
void hideOrShowColumnPeers();
|
||||
void hideOrShowColumnUpload();
|
||||
void hideOrShowColumnRatio();
|
||||
void hideOrShowColumnPriority();
|
||||
void forceRecheck();
|
||||
|
||||
public slots:
|
||||
void addTorrent(QString hash);
|
||||
void updateFinishedList();
|
||||
void updateTorrent(QTorrentHandle h);
|
||||
void pauseTorrent(QString hash);
|
||||
void resumeTorrent(QString hash);
|
||||
void propertiesSelection();
|
||||
void deleteTorrent(QString hash);
|
||||
void showPropertiesFromHash(QString hash);
|
||||
void hidePriorityColumn(bool hide);
|
||||
void loadLastSortedColumn();
|
||||
void saveLastSortedColumn();
|
||||
void updateMetadata(QTorrentHandle &h);
|
||||
|
||||
signals:
|
||||
void torrentMovedFromFinishedList(QString);
|
||||
|
||||
2529
src/GUI.cpp
28
src/GUI.h
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -61,10 +70,11 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
// Bittorrent
|
||||
bittorrent *BTSession;
|
||||
QTimer *checkConnect;
|
||||
QTimer *scrapeTimer;
|
||||
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
|
||||
// GUI related
|
||||
QTabWidget *tabs;
|
||||
options_imp *options;
|
||||
QPointer<options_imp> options;
|
||||
QSystemTrayIcon *myTrayIcon;
|
||||
QPointer<QTimer> systrayCreator;
|
||||
QMenu *myTrayIconMenu;
|
||||
@@ -128,13 +138,12 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void readSettings();
|
||||
void on_actionExit_triggered();
|
||||
void createTrayIcon();
|
||||
void updateUnfinishedTorrentNumberCalc();
|
||||
void updateFinishedTorrentNumberCalc();
|
||||
void updateUnfinishedTorrentNumber(unsigned int nb);
|
||||
void updateFinishedTorrentNumber(unsigned int nb);
|
||||
void fullDiskError(QTorrentHandle& h) const;
|
||||
void fullDiskError(QTorrentHandle& h, QString msg) const;
|
||||
void handleDownloadFromUrlFailure(QString, QString) const;
|
||||
void createSystrayDelayed();
|
||||
void setPaused(QTorrentHandle &h) const;
|
||||
// Keyboard shortcuts
|
||||
void createKeyboardShortcuts();
|
||||
void displayDownTab() const;
|
||||
@@ -158,16 +167,19 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void processParams(const QStringList& params);
|
||||
void addTorrent(QString path);
|
||||
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
|
||||
void processScannedFiles(const QStringList& params);
|
||||
void processDownloadedFiles(QString path, QString url);
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
void deleteTorrent(QString hash);
|
||||
void finishedTorrent(QTorrentHandle& h) const;
|
||||
void updateLists();
|
||||
void addedTorrent(QTorrentHandle& h) const;
|
||||
void checkedTorrent(QTorrentHandle& h) const;
|
||||
void pausedTorrent(QTorrentHandle& h) const;
|
||||
void resumedTorrent(QTorrentHandle& h) const;
|
||||
void updateLists(bool force=false);
|
||||
bool initWebUi(QString username, QString password, int port);
|
||||
void pauseTorrent(QString hash);
|
||||
void on_actionIncreasePriority_triggered();
|
||||
void on_actionDecreasePriority_triggered();
|
||||
void scrapeTrackers();
|
||||
// Options slots
|
||||
void on_actionOptions_triggered();
|
||||
void OptionsSaved(bool deleteOptions);
|
||||
@@ -180,10 +192,12 @@ class GUI : public QMainWindow, private Ui::MainWindow{
|
||||
void setTabText(int index, QString text) const;
|
||||
void openDestinationFolder() const;
|
||||
void goBuyPage() const;
|
||||
void copyMagnetURI() const;
|
||||
void updateRatio();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
void showEvent(QShowEvent *);
|
||||
bool event(QEvent * event);
|
||||
void displayRSSTab(bool enable);
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1005 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 820 B |
|
Before Width: | Height: | Size: 821 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 998 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 846 B |
BIN
src/Icons/magnet.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 532 B |
BIN
src/Icons/oxygen/application-x-kgetlist-no.png
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
src/Icons/oxygen/application-x-kgetlist.png
Normal file
|
After Width: | Height: | Size: 659 B |
BIN
src/Icons/oxygen/browse.png
Normal file
|
After Width: | Height: | Size: 796 B |
BIN
src/Icons/oxygen/bt_settings.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/Icons/oxygen/bug.png
Normal file
|
After Width: | Height: | Size: 733 B |
BIN
src/Icons/oxygen/button_cancel.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Icons/oxygen/button_ok.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/Icons/oxygen/connection.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/oxygen/document-new.png
Normal file
|
After Width: | Height: | Size: 873 B |
BIN
src/Icons/oxygen/download.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/Icons/oxygen/edit-clear.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/Icons/oxygen/edit-copy.png
Normal file
|
After Width: | Height: | Size: 860 B |
BIN
src/Icons/oxygen/edit-cut.png
Normal file
|
After Width: | Height: | Size: 892 B |
BIN
src/Icons/oxygen/edit-find.png
Normal file
|
After Width: | Height: | Size: 627 B |
BIN
src/Icons/oxygen/edit-paste.png
Normal file
|
After Width: | Height: | Size: 937 B |
|
Before Width: | Height: | Size: 575 B After Width: | Height: | Size: 575 B |
|
Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 750 B |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 704 B |
BIN
src/Icons/oxygen/filter.png
Normal file
|
After Width: | Height: | Size: 885 B |
BIN
src/Icons/oxygen/folder-new.png
Normal file
|
After Width: | Height: | Size: 923 B |
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
BIN
src/Icons/oxygen/gear.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/Icons/oxygen/list-add.png
Normal file
|
After Width: | Height: | Size: 907 B |
BIN
src/Icons/oxygen/list-remove.png
Normal file
|
After Width: | Height: | Size: 498 B |
BIN
src/Icons/oxygen/log.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
src/Icons/oxygen/mail-folder-inbox.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
src/Icons/oxygen/preferences-desktop.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/Icons/oxygen/proxy.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
0
src/Icons/skin/remove.png → src/Icons/oxygen/remove.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/oxygen/subscribe.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Icons/oxygen/subscribe16.png
Normal file
|
After Width: | Height: | Size: 752 B |
BIN
src/Icons/oxygen/tab-close.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 856 B After Width: | Height: | Size: 856 B |
BIN
src/Icons/oxygen/unavailable.png
Normal file
|
After Width: | Height: | Size: 813 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 765 B |
BIN
src/Icons/oxygen/view-refresh.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/Icons/oxygen/wallet.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Icons/oxygen/webui.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,19 +1,26 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P
|
||||
Comment=V1.2.1
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V1.5.0
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[bg]=Торент клиент
|
||||
GenericName[cs]=Bittorrent klient
|
||||
GenericName[de]=Bittorren Client
|
||||
GenericName[el]=Τορεντ πελάτης
|
||||
GenericName[el]=Bittorrent πελάτης
|
||||
GenericName[es]=Cliente Bittorrent
|
||||
GenericName[fi]=Bittorrent-ohjelma
|
||||
GenericName[fr]=Client Bittorrent
|
||||
GenericName[hu]=Bittorrent kliens
|
||||
GenericName[it]=Client Bittorrent
|
||||
GenericName[ja]=Bittorrent クライアント
|
||||
GenericName[ko]=비토렌트 클라이언트
|
||||
GenericName[nl]=Bittorrent client
|
||||
GenericName[pl]=Klient Bittorrent
|
||||
GenericName[pt]=Cliente Bittorrent
|
||||
GenericName[pt_BR]=Cliente Bittorrent
|
||||
GenericName[ro]=Client Bittorrent
|
||||
GenericName[ru]=клиент Bittorrent
|
||||
GenericName[sk]=Klient siete Bittorrent
|
||||
GenericName[sv]=Bittorrent-klient
|
||||
GenericName[tr]=Bittorrent istemcisi
|
||||
GenericName[uk]=Bittorrent-клієнт
|
||||
|
||||
|
Before Width: | Height: | Size: 948 B |
|
Before Width: | Height: | Size: 842 B |
|
Before Width: | Height: | Size: 576 B |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 965 B After Width: | Height: | Size: 965 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 739 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +1,8 @@
|
||||
<ui version="4.0" >
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
<property name="geometry" >
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
@@ -9,264 +10,266 @@
|
||||
<height>563</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<layout class="QVBoxLayout" />
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout"/>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
<property name="geometry" >
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>914</width>
|
||||
<height>26</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_Edit" >
|
||||
<property name="title" >
|
||||
<widget class="QMenu" name="menu_Edit">
|
||||
<property name="title">
|
||||
<string>&Edit</string>
|
||||
</property>
|
||||
<addaction name="actionStart_All" />
|
||||
<addaction name="actionPause_All" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionStart" />
|
||||
<addaction name="actionPause" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionTorrent_Properties" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionDelete" />
|
||||
<addaction name="actionDelete_Permanently" />
|
||||
<addaction name="actionDecreasePriority" />
|
||||
<addaction name="actionIncreasePriority" />
|
||||
<addaction name="actionStart_All"/>
|
||||
<addaction name="actionPause_All"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionStart"/>
|
||||
<addaction name="actionPause"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTorrent_Properties"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="actionDelete_Permanently"/>
|
||||
<addaction name="actionDecreasePriority"/>
|
||||
<addaction name="actionIncreasePriority"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help" >
|
||||
<property name="title" >
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionBugReport" />
|
||||
<addaction name="actionWebsite" />
|
||||
<addaction name="actionDocumentation" />
|
||||
<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" >
|
||||
<widget class="QMenu" name="menu_Options">
|
||||
<property name="title">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<addaction name="actionOptions" />
|
||||
<addaction name="actionShow_console" />
|
||||
<addaction name="actionOptions"/>
|
||||
<addaction name="actionShow_console"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_File" >
|
||||
<property name="title" >
|
||||
<widget class="QMenu" name="menu_File">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen" />
|
||||
<addaction name="actionDownload_from_URL" />
|
||||
<addaction name="actionCreate_torrent" />
|
||||
<addaction name="actionExit" />
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionDownload_from_URL"/>
|
||||
<addaction name="actionCreate_torrent"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<addaction name="menu_File" />
|
||||
<addaction name="menu_Edit" />
|
||||
<addaction name="menu_Options" />
|
||||
<addaction name="menu_Help" />
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_Edit"/>
|
||||
<addaction name="menu_Options"/>
|
||||
<addaction name="menu_Help"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar" >
|
||||
<property name="enabled" >
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="contextMenuPolicy" >
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::NoContextMenu</enum>
|
||||
</property>
|
||||
<property name="movable" >
|
||||
<property name="movable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="iconSize" >
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable" >
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea" >
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak" >
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionOpen" />
|
||||
<addaction name="actionDownload_from_URL" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionDelete" />
|
||||
<addaction name="actionDelete_Permanently" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionTorrent_Properties" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionStart" />
|
||||
<addaction name="actionPause" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionStart_All" />
|
||||
<addaction name="actionPause_All" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionOptions" />
|
||||
<addaction name="actionDecreasePriority" />
|
||||
<addaction name="actionIncreasePriority" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionExit" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionDownload_from_URL"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="actionDelete_Permanently"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTorrent_Properties"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionStart"/>
|
||||
<addaction name="actionPause"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionStart_All"/>
|
||||
<addaction name="actionPause_All"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionOptions"/>
|
||||
<addaction name="actionDecreasePriority"/>
|
||||
<addaction name="actionIncreasePriority"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar" />
|
||||
<action name="actionOpen" >
|
||||
<property name="text" >
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit" >
|
||||
<property name="text" >
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOptions" >
|
||||
<property name="text" >
|
||||
<action name="actionOptions">
|
||||
<property name="text">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout" >
|
||||
<property name="text" >
|
||||
<action name="actionAbout">
|
||||
<property name="text">
|
||||
<string>About</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStart" >
|
||||
<property name="text" >
|
||||
<action name="actionStart">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPause" >
|
||||
<property name="text" >
|
||||
<action name="actionPause">
|
||||
<property name="text">
|
||||
<string>Pause</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete" >
|
||||
<property name="text" >
|
||||
<action name="actionDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPause_All" >
|
||||
<property name="text" >
|
||||
<action name="actionPause_All">
|
||||
<property name="text">
|
||||
<string>Pause All</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStart_All" >
|
||||
<property name="text" >
|
||||
<action name="actionStart_All">
|
||||
<property name="text">
|
||||
<string>Start All</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionWebsite" >
|
||||
<property name="text" >
|
||||
<action name="actionWebsite">
|
||||
<property name="text">
|
||||
<string>Visit website</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete_Permanently" >
|
||||
<property name="text" >
|
||||
<action name="actionDelete_Permanently">
|
||||
<property name="text">
|
||||
<string>Delete Permanently</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTorrent_Properties" >
|
||||
<property name="text" >
|
||||
<action name="actionTorrent_Properties">
|
||||
<property name="text">
|
||||
<string>Torrent Properties</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDownload_from_URL" >
|
||||
<property name="text" >
|
||||
<action name="actionDownload_from_URL">
|
||||
<property name="text">
|
||||
<string>Download from URL</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCreate_torrent" >
|
||||
<property name="text" >
|
||||
<action name="actionCreate_torrent">
|
||||
<property name="text">
|
||||
<string>Create torrent</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPreview_file" >
|
||||
<property name="text" >
|
||||
<action name="actionPreview_file">
|
||||
<property name="text">
|
||||
<string>Preview file</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClearLog" >
|
||||
<property name="text" >
|
||||
<action name="actionClearLog">
|
||||
<property name="text">
|
||||
<string>Clear log</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBugReport" >
|
||||
<property name="text" >
|
||||
<action name="actionBugReport">
|
||||
<property name="text">
|
||||
<string>Report a bug</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_upload_limit" >
|
||||
<property name="text" >
|
||||
<action name="actionSet_upload_limit">
|
||||
<property name="text">
|
||||
<string>Set upload limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_download_limit" >
|
||||
<property name="text" >
|
||||
<action name="actionSet_download_limit">
|
||||
<property name="text">
|
||||
<string>Set download limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDocumentation" >
|
||||
<property name="text" >
|
||||
<action name="actionDocumentation">
|
||||
<property name="text">
|
||||
<string>Documentation</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSet_global_download_limit" >
|
||||
<property name="text" >
|
||||
<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" >
|
||||
<action name="actionSet_global_upload_limit">
|
||||
<property name="text">
|
||||
<string>Set global upload limit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDecreasePriority" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/decrease.png</iconset>
|
||||
<action name="actionDecreasePriority">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/skin/decrease.png</normaloff>:/Icons/skin/decrease.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Decrease priority</string>
|
||||
</property>
|
||||
<property name="visible" >
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionIncreasePriority" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/skin/increase.png</iconset>
|
||||
<action name="actionIncreasePriority">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/skin/increase.png</normaloff>:/Icons/skin/increase.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Increase priority</string>
|
||||
</property>
|
||||
<property name="visible" >
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_console" >
|
||||
<property name="icon" >
|
||||
<iconset resource="icons.qrc" >:/Icons/log.png</iconset>
|
||||
<action name="actionShow_console">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/Icons/oxygen/log.png</normaloff>:/Icons/oxygen/log.png</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<property name="text">
|
||||
<string>Console</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc" />
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -24,6 +33,7 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
#include <QSettings>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "SearchTab.h"
|
||||
#include "SearchListDelegate.h"
|
||||
@@ -36,154 +46,104 @@
|
||||
#define SEARCH_LEECHERS 3
|
||||
#define SEARCH_ENGINE 4
|
||||
|
||||
SearchTab::SearchTab(SearchEngine *parent) : QWidget()
|
||||
SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||
{
|
||||
box=new QVBoxLayout();
|
||||
results_lbl=new QLabel();
|
||||
resultsBrowser = new QTreeView();
|
||||
resultsBrowser->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
box->addWidget(results_lbl);
|
||||
box->addWidget(resultsBrowser);
|
||||
|
||||
setLayout(box);
|
||||
// Set Search results list model
|
||||
SearchListModel = new QStandardItemModel(0,5);
|
||||
SearchListModel->setHeaderData(SEARCH_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
SearchListModel->setHeaderData(SEARCH_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_LEECHERS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
|
||||
resultsBrowser->setModel(SearchListModel);
|
||||
SearchDelegate = new SearchListDelegate();
|
||||
resultsBrowser->setItemDelegate(SearchDelegate);
|
||||
// Make search list header clickable for sorting
|
||||
resultsBrowser->header()->setClickable(true);
|
||||
resultsBrowser->header()->setSortIndicatorShown(true);
|
||||
|
||||
// Connect signals to slots (search part)
|
||||
connect(resultsBrowser, SIGNAL(doubleClicked(const QModelIndex&)), parent, SLOT(downloadSelectedItem(const QModelIndex&)));
|
||||
connect(resultsBrowser->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortSearchList(int)));
|
||||
|
||||
// Load last columns width for search results list
|
||||
if(!loadColWidthSearchList()){
|
||||
resultsBrowser->header()->resizeSection(0, 275);
|
||||
}
|
||||
box=new QVBoxLayout();
|
||||
results_lbl=new QLabel();
|
||||
resultsBrowser = new QTreeView();
|
||||
resultsBrowser->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
box->addWidget(results_lbl);
|
||||
box->addWidget(resultsBrowser);
|
||||
|
||||
setLayout(box);
|
||||
// Set Search results list model
|
||||
SearchListModel = new QStandardItemModel(0,6);
|
||||
SearchListModel->setHeaderData(SEARCH_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||
SearchListModel->setHeaderData(SEARCH_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_LEECHERS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
|
||||
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
|
||||
|
||||
proxyModel = new QSortFilterProxyModel();
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
proxyModel->setSourceModel(SearchListModel);
|
||||
resultsBrowser->setModel(proxyModel);
|
||||
|
||||
SearchDelegate = new SearchListDelegate();
|
||||
resultsBrowser->setItemDelegate(SearchDelegate);
|
||||
|
||||
resultsBrowser->setRootIsDecorated(false);
|
||||
resultsBrowser->setAllColumnsShowFocus(true);
|
||||
resultsBrowser->setSortingEnabled(true);
|
||||
|
||||
// Connect signals to slots (search part)
|
||||
connect(resultsBrowser, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(downloadSelectedItem(const QModelIndex&)));
|
||||
|
||||
// Load last columns width for search results list
|
||||
if(!loadColWidthResultsList()){
|
||||
resultsBrowser->header()->resizeSection(0, 275);
|
||||
}
|
||||
|
||||
// Sort by Seeds
|
||||
resultsBrowser->sortByColumn(SEEDERS, Qt::DescendingOrder);
|
||||
}
|
||||
|
||||
SearchTab::~SearchTab()
|
||||
{
|
||||
saveColWidthSearchList();
|
||||
delete resultsBrowser;
|
||||
delete SearchListModel;
|
||||
delete SearchDelegate;
|
||||
void SearchTab::downloadSelectedItem(const QModelIndex& index) {
|
||||
QString engine_url = proxyModel->data(proxyModel->index(index.row(), ENGINE_URL_COLUMN)).toString();
|
||||
QString torrent_url = proxyModel->data(proxyModel->index(index.row(), URL_COLUMN)).toString();
|
||||
setRowColor(index.row(), "red");
|
||||
parent->downloadTorrent(engine_url, torrent_url);
|
||||
}
|
||||
|
||||
SearchTab::~SearchTab() {
|
||||
delete box;
|
||||
delete results_lbl;
|
||||
delete resultsBrowser;
|
||||
delete SearchListModel;
|
||||
delete proxyModel;
|
||||
delete SearchDelegate;
|
||||
}
|
||||
|
||||
QHeaderView* SearchTab::header() const {
|
||||
return resultsBrowser->header();
|
||||
}
|
||||
|
||||
bool SearchTab::loadColWidthResultsList() {
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString line = settings.value("SearchResultsColsWidth", QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(' ');
|
||||
if(width_list.size() < SearchListModel->columnCount())
|
||||
return false;
|
||||
unsigned int listSize = width_list.size();
|
||||
for(unsigned int i=0; i<listSize; ++i){
|
||||
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QLabel* SearchTab::getCurrentLabel()
|
||||
{
|
||||
return results_lbl;
|
||||
return results_lbl;
|
||||
}
|
||||
|
||||
QTreeView* SearchTab::getCurrentTreeView()
|
||||
{
|
||||
return resultsBrowser;
|
||||
return resultsBrowser;
|
||||
}
|
||||
|
||||
QStandardItemModel* SearchTab::getCurrentSearchListModel()
|
||||
{
|
||||
return SearchListModel;
|
||||
return SearchListModel;
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
void SearchTab::setRowColor(int row, QString color){
|
||||
for(int i=0; i<SearchListModel->columnCount(); ++i){
|
||||
SearchListModel->setData(SearchListModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
for(int i=0; i<proxyModel->columnCount(); ++i){
|
||||
proxyModel->setData(proxyModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchTab::sortSearchList(int index){
|
||||
static Qt::SortOrder sortOrder = Qt::AscendingOrder;
|
||||
if(resultsBrowser->header()->sortIndicatorSection() == index){
|
||||
sortOrder = (sortOrder == Qt::DescendingOrder) ? Qt::AscendingOrder : Qt::DescendingOrder; ;
|
||||
}
|
||||
resultsBrowser->header()->setSortIndicator(index, sortOrder);
|
||||
switch(index){
|
||||
case SEEDERS:
|
||||
case LEECHERS:
|
||||
case SIZE:
|
||||
sortSearchListInt(index, sortOrder);
|
||||
break;
|
||||
default:
|
||||
sortSearchListString(index, sortOrder);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchTab::sortSearchListInt(int index, Qt::SortOrder sortOrder){
|
||||
QList<QPair<int, qlonglong> > lines;
|
||||
// Insertion sorting
|
||||
for(int i=0; i<SearchListModel->rowCount(); ++i){
|
||||
misc::insertSort(lines, QPair<int,qlonglong>(i, SearchListModel->data(SearchListModel->index(i, index)).toLongLong()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
int nbRows_old = lines.size();
|
||||
for(int row=0; row<lines.size(); ++row){
|
||||
SearchListModel->insertRow(SearchListModel->rowCount());
|
||||
int sourceRow = lines[row].first;
|
||||
for(int col=0; col<5; ++col){
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
SearchListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
void SearchTab::sortSearchListString(int index, Qt::SortOrder sortOrder){
|
||||
QList<QPair<int, QString> > lines;
|
||||
// Insetion sorting
|
||||
for(int i=0; i<SearchListModel->rowCount(); ++i){
|
||||
misc::insertSortString(lines, QPair<int, QString>(i, SearchListModel->data(SearchListModel->index(i, index)).toString()), sortOrder);
|
||||
}
|
||||
// Insert items in new model, in correct order
|
||||
int nbRows_old = lines.size();
|
||||
for(int row=0; row<nbRows_old; ++row){
|
||||
SearchListModel->insertRow(SearchListModel->rowCount());
|
||||
int sourceRow = lines[row].first;
|
||||
for(int col=0; col<5; ++col){
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col)));
|
||||
SearchListModel->setData(SearchListModel->index(nbRows_old+row, col), SearchListModel->data(SearchListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
|
||||
}
|
||||
}
|
||||
// Remove old rows
|
||||
SearchListModel->removeRows(0, nbRows_old);
|
||||
}
|
||||
|
||||
// Save columns width in a file to remember them
|
||||
// (download list)
|
||||
void SearchTab::saveColWidthSearchList() const{
|
||||
qDebug("Saving columns width in search list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QStringList width_list;
|
||||
for(int i=0; i<SearchListModel->columnCount(); ++i){
|
||||
width_list << misc::toQString(resultsBrowser->columnWidth(i));
|
||||
}
|
||||
settings.setValue("SearchListColsWidth", width_list.join(" "));
|
||||
qDebug("Search list columns width saved");
|
||||
}
|
||||
|
||||
// Load columns width in a file that were saved previously
|
||||
// (search list)
|
||||
bool SearchTab::loadColWidthSearchList(){
|
||||
qDebug("Loading columns width for search list");
|
||||
QSettings settings("qBittorrent", "qBittorrent");
|
||||
QString line = settings.value("SearchListColsWidth", QString()).toString();
|
||||
if(line.isEmpty())
|
||||
return false;
|
||||
QStringList width_list = line.split(' ');
|
||||
if(width_list.size() != SearchListModel->columnCount())
|
||||
return false;
|
||||
for(int i=0; i<width_list.size(); ++i){
|
||||
resultsBrowser->header()->resizeSection(i, width_list.at(i).toInt());
|
||||
}
|
||||
qDebug("Search list columns width loaded");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
@@ -24,35 +33,42 @@
|
||||
|
||||
#include "ui_search.h"
|
||||
|
||||
#define ENGINE_URL_COLUMN 4
|
||||
#define URL_COLUMN 5
|
||||
|
||||
class SearchListDelegate;
|
||||
class SearchEngine;
|
||||
class QTreeView;
|
||||
class QHeaderView;
|
||||
class QStandardItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
|
||||
class SearchTab: public QWidget, public Ui::search_engine {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QVBoxLayout *box;
|
||||
QLabel *results_lbl;
|
||||
QTreeView *resultsBrowser;
|
||||
QStandardItemModel *SearchListModel;
|
||||
QSortFilterProxyModel *proxyModel;
|
||||
SearchListDelegate *SearchDelegate;
|
||||
SearchEngine *parent;
|
||||
|
||||
protected slots:
|
||||
void downloadSelectedItem(const QModelIndex& index);
|
||||
|
||||
public:
|
||||
SearchTab(SearchEngine *parent);
|
||||
~SearchTab();
|
||||
bool loadColWidthResultsList();
|
||||
QLabel * getCurrentLabel();
|
||||
QStandardItemModel * getCurrentSearchListModel();
|
||||
QTreeView * getCurrentTreeView();
|
||||
void setRowColor(int row, QString color);
|
||||
QHeaderView* header() const;
|
||||
|
||||
|
||||
class SearchTab : public QWidget, public Ui::search_engine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QVBoxLayout *box;
|
||||
QLabel *results_lbl;
|
||||
QTreeView *resultsBrowser;
|
||||
QStandardItemModel *SearchListModel;
|
||||
SearchListDelegate *SearchDelegate;
|
||||
public:
|
||||
SearchTab(SearchEngine *parent);
|
||||
~SearchTab();
|
||||
bool loadColWidthSearchList();
|
||||
QLabel * getCurrentLabel();
|
||||
QStandardItemModel * getCurrentSearchListModel();
|
||||
QTreeView * getCurrentTreeView();
|
||||
void setRowColor(int row, QString color);
|
||||
protected slots:
|
||||
void sortSearchList(int index);
|
||||
void sortSearchListInt(int index, Qt::SortOrder sortOrder);
|
||||
void sortSearchListString(int index, Qt::SortOrder sortOrder);
|
||||
void saveColWidthSearchList() const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||