Compare commits

..

727 Commits

Author SHA1 Message Date
Christophe Dumez
cd29de365a Fix compiling error 2010-10-24 10:19:04 +00:00
Christophe Dumez
de78fc495b Fix compiling error 2010-10-24 10:12:37 +00:00
Christophe Dumez
0b89d9b1e9 Tagged today's releases 2010-10-24 09:55:14 +00:00
Christophe Dumez
93731f1b3f Bump to v2.2.8 2010-10-24 09:40:22 +00:00
Christophe Dumez
2e9e10299c Peers can now be sorted by country 2010-10-24 09:34:31 +00:00
Christophe Dumez
9f627b5ec9 BUGFIX: Better fix for save path editing issues in torrent addition dialog 2010-10-24 08:32:39 +00:00
Christophe Dumez
ad252f432a BUGFIX: Fix issue when altering files priorities of a seeding torrent (closes #665799) 2010-10-24 08:07:17 +00:00
Christophe Dumez
eb1feddea6 BUGFIX: Fix rounding issue in torrent progress display (closes #617733) 2010-10-23 19:14:01 +00:00
Christophe Dumez
1634014dde Fix status list widget height issue on style change (closes #603342) 2010-10-23 17:00:58 +00:00
Christophe Dumez
e863772159 Fix possible string encoding problem 2010-10-23 15:26:08 +00:00
Christophe Dumez
7c34f4e93c Update search plugin update URL 2010-10-22 20:14:21 +00:00
Christophe Dumez
91032056e1 Remember the current property tab on startup 2010-10-22 17:32:04 +00:00
Christophe Dumez
f427d267b6 BUGFIX: Auto-disable the shutdown feature 2010-10-21 16:55:44 +00:00
Christophe Dumez
a7a8265053 BUGFIX: Several search plugins fixed 2010-10-20 20:29:30 +00:00
Christophe Dumez
827fceca83 Fix torrentreactor search plugin 2010-10-20 19:51:47 +00:00
Christophe Dumez
7aaa3e8f51 Fix searching for something with {*} in it 2010-10-20 19:44:23 +00:00
Christophe Dumez
1fe49198d1 Improved hostname resolution code 2010-10-20 17:21:29 +00:00
Christophe Dumez
c582aff563 Updated Changelog 2010-10-20 16:17:49 +00:00
Christophe Dumez
5272f1cba3 Fix possible crash on manual peer ban 2010-10-20 16:17:11 +00:00
Christophe Dumez
b72d356083 Bump to v2.4.7 2010-10-19 17:05:06 +00:00
Christophe Dumez
fbd6533eee Update changelog 2010-10-19 16:54:53 +00:00
Christophe Dumez
2998dbd0a1 Fix possible transfer list refresh problem 2010-10-19 16:47:47 +00:00
Christophe Dumez
cb8da634f4 BUGFIX: Improved "Set Location" and "Change save path" dialogs 2010-10-18 19:25:58 +00:00
Christophe Dumez
e8f229816e BUGFIX: Fix issues when marking a file as 'not downloaded' causes the torrent to complete 2010-10-18 18:21:00 +00:00
Christophe Dumez
fe0fc952e8 - BUGFIX: Fix encoding problem in file renaming
- BUGFIX: Delete uneeded files on torrent "soft" deletion
2010-10-18 17:48:18 +00:00
Christophe Dumez
29a76ae600 BUGFIX: Display the priority column when the queueing system gets enabled 2010-10-18 17:08:25 +00:00
Christophe Dumez
5471600dfb Fix to German translation 2010-10-18 16:25:41 +00:00
Christophe Dumez
df42c4d59f Bump to v2.4.6 2010-10-17 15:27:25 +00:00
Christophe Dumez
8047495b2e BUGFIX: Fix moving of a torrent to an unexisting directory 2010-10-17 15:16:25 +00:00
Christophe Dumez
de04b47c29 BUGFIX: Fix detection of files at final destination when temp dir is used 2010-10-17 14:53:03 +00:00
Christophe Dumez
b709bec24d Fix compilation error with libtorrent v0.14 2010-10-17 11:47:16 +00:00
Christophe Dumez
35f93e8e16 BUGFIX: The properties panel data would sometimes not match the selected torrent 2010-10-17 09:12:24 +00:00
Christophe Dumez
554a84f8b0 Improvement to last commit 2010-10-17 09:01:34 +00:00
Christophe Dumez
f26fcabde1 BUGFIX: Fix "torrent seeding after creation" feature 2010-10-17 08:48:32 +00:00
Christophe Dumez
75b91c204d Forgot to commit this file 2010-10-17 08:42:34 +00:00
Christophe Dumez
0837c25602 Updated Changelog 2010-10-12 16:09:03 +00:00
Christophe Dumez
34f8937b8d Code optimization 2010-10-12 16:08:09 +00:00
Christophe Dumez
4a7f3ee415 Some more code optimization 2010-10-11 21:30:11 +00:00
Christophe Dumez
b218531ff7 BUGFIX: Piece availability/downloaded widgets performance improvement 2010-10-11 21:08:49 +00:00
Christophe Dumez
e96dee2038 Fix possible variable overflow 2010-10-11 20:01:56 +00:00
Christophe Dumez
080105c088 Bump to v2.4.5 2010-10-11 19:43:50 +00:00
Christophe Dumez
5d2535c1c1 BUGFIX: Improved peer hostname resolution with caching 2010-10-10 21:06:07 +00:00
Christophe Dumez
49b21059fa BUGFIX: Fix display of URL seeds in the UI 2010-10-10 15:43:53 +00:00
Christophe Dumez
c1af948649 Fix issues introduced recently related to torrent completion 2010-10-09 15:04:15 +00:00
Christophe Dumez
36ad3df9e7 Fix feature to keep incomplete torrents in a separate folder 2010-10-09 08:57:26 +00:00
Christophe Dumez
e607d721a2 Forgot to commit gpl.html 2010-10-08 17:52:10 +00:00
Christophe Dumez
5bfbfeb665 Fix some cosmetic issues in about dlg 2010-10-08 17:50:45 +00:00
Ishan Arora
1f1eabb1e9 moved windows path configs from src/src.pro to winconf.pri 2010-10-05 01:12:29 +00:00
Christophe Dumez
762050f8fc Remember torrent seeding date correctly 2010-10-02 12:55:39 +00:00
Christophe Dumez
e3c1270205 Code cleanup 2010-10-02 12:14:29 +00:00
Christophe Dumez
414685910b Fix to last commit 2010-10-01 20:52:53 +00:00
Christophe Dumez
d61b9c5d4d Bump to v2.4.4 2010-10-01 20:22:20 +00:00
Christophe Dumez
cf86a1cecd BUGFIX: Fix possible search engine plugin update 2010-10-01 20:19:17 +00:00
Christophe Dumez
a3f3287e24 Clean program exit on system shutdown/log out 2010-10-01 20:05:54 +00:00
Christophe Dumez
6e18d780ba Updated Changelog 2010-09-28 16:57:31 +00:00
Christophe Dumez
7dde763fc6 Fix wrong mapping to source model 2010-09-28 16:56:49 +00:00
Christophe Dumez
8c85ffca5f Fix tiny memory leak 2010-09-27 20:47:26 +00:00
Christophe Dumez
321e568d86 TorrentDownloads performance improvement 2010-09-27 19:48:58 +00:00
Christophe Dumez
e0649a7e78 Bump to v2.4.3 2010-09-27 17:49:33 +00:00
Christophe Dumez
4cd3233cd0 Better fix for encoding issue 2010-09-27 17:36:42 +00:00
Christophe Dumez
c554528afe BUGFIX: Fix possible crash when changing the save path in addition dialog 2010-09-27 17:35:34 +00:00
Christophe Dumez
7ab7f4b0fc BUGFIX: Fix encoding issue in command line parameters processing 2010-09-27 17:19:27 +00:00
Christophe Dumez
58c0ac7638 BUGFIX: Really fix manual editing of save path in torrent addition dialog 2010-09-26 17:10:21 +00:00
Christophe Dumez
2514224a3a Bump to v2.4.2 2010-09-26 16:57:04 +00:00
Christophe Dumez
247f6b4a8e BUGFIX: Fix display of torrent content in addition dialog 2010-09-26 16:53:20 +00:00
Christophe Dumez
3d89864b75 Fix deprecation warning 2010-09-26 11:15:00 +00:00
Christophe Dumez
7ac75ad772 Fix to last commit 2010-09-25 19:41:12 +00:00
Christophe Dumez
caa628371f BUGFIX: Limit torrent addition dialog width to fit the screen 2010-09-25 19:40:29 +00:00
Christophe Dumez
fd31f632d9 BUGFIX: Fix saving to drive root on Windows 2010-09-25 17:38:20 +00:00
Christophe Dumez
a25b6e087b Bump to v2.4.1 (release is nearing) 2010-09-25 17:08:21 +00:00
Christophe Dumez
1626d938d1 Fix save path encoding on non-utf8 systems (e.g. Windows)
Fix progress bar style on Windows
2010-09-25 17:02:40 +00:00
Christophe Dumez
a4c7640499 BUGFIX: Use AND operator for torrentdownloads.net searches 2010-09-25 13:12:02 +00:00
Christophe Dumez
2c1b93a12b BUGFIX: Fix locale switching from Web UI 2010-09-25 12:44:31 +00:00
Christophe Dumez
8f19025c2a Remove obsolete strings from language files 2010-09-25 12:12:08 +00:00
Christophe Dumez
20d41bcff2 Fix Web Ui for spanish users 2010-09-25 11:44:44 +00:00
Christophe Dumez
1ad77e00ff BUGFIX: Added support for | (OR) operator in RSS feed downloader 2010-09-25 11:31:33 +00:00
Christophe Dumez
0b65c02666 BUGFIX: Fix possible issue with temporary download path persistence 2010-09-25 11:05:02 +00:00
Christophe Dumez
294095367a BUGFIX: Add .torrent extension only when missing (torrent creator) 2010-09-25 10:49:13 +00:00
Christophe Dumez
05a6ffd554 Fix download in scan dir persistence (closes #633396) 2010-09-25 10:41:17 +00:00
Christophe Dumez
e0a30dc40c BUGFIX: Save path can now be edited in torrent addition dialog 2010-09-25 09:14:00 +00:00
Christophe Dumez
1940bc4e73 Higher maximum download limit 2010-09-25 08:04:36 +00:00
Christophe Dumez
a7e4e0273a Detect OGV as a previewable format 2010-09-25 07:42:55 +00:00
Christophe Dumez
29a9d57cdc Updated Changelog 2010-09-19 08:40:44 +00:00
Christophe Dumez
9c7a4e4983 Fixes to German translation 2010-09-19 08:39:14 +00:00
Christophe Dumez
35ead5bcf2 Updated Spanish and Catalan translations 2010-08-27 07:43:42 +00:00
Christophe Dumez
645bd58d79 Updated Arabic translation 2010-08-25 06:34:50 +00:00
Christophe Dumez
6c47a552ab Updated release date in Changelog 2010-08-24 18:28:56 +00:00
Christophe Dumez
f54bc8bea4 Branched v2.4.x 2010-08-24 18:27:18 +00:00
Christophe Dumez
eb54d81c5e Bump to rc3 2010-08-23 19:42:33 +00:00
Christophe Dumez
431d2f082c FEATURE: Detect executable updates in order to advise the user to restart 2010-08-23 19:42:15 +00:00
Christophe Dumez
a0ff0cdc7e UI lock related cosmetic changes 2010-08-23 16:12:17 +00:00
Christophe Dumez
fb91558261 Updated Portuguese and Brazilian translations 2010-08-23 15:46:06 +00:00
Christophe Dumez
fc2a47ca31 Updated Spanish and Catalan translation 2010-08-23 06:07:52 +00:00
Christophe Dumez
dcccbaad59 UI Lock also lock the tray icon menu 2010-08-22 19:08:15 +00:00
Christophe Dumez
99d040de3f Updated Serbian translation 2010-08-22 18:52:54 +00:00
Christophe Dumez
ee30a75b57 Fix compilation warning 2010-08-22 18:11:19 +00:00
Christophe Dumez
8c001aa478 Force progress update of paused torrents too 2010-08-22 16:55:57 +00:00
Christophe Dumez
849bc11a01 Updated Simplified Chinese translation 2010-08-22 14:27:47 +00:00
Christophe Dumez
5024e0b092 Updated Traditional Chinese translation 2010-08-22 12:53:16 +00:00
Christophe Dumez
d93447489b Clear search filter before hiding the top toolbar 2010-08-22 08:54:33 +00:00
Christophe Dumez
33988e70ab Updated Czech translation 2010-08-22 08:38:56 +00:00
Christophe Dumez
d2b41d70c8 Safer error detection 2010-08-21 20:22:59 +00:00
Christophe Dumez
8e1e51d268 Bump to rc2 2010-08-21 20:16:26 +00:00
Christophe Dumez
53500ea005 Force progress update on torrent pausing 2010-08-21 20:12:16 +00:00
Christophe Dumez
e048389dea Attempt to improve error detection 2010-08-21 09:08:12 +00:00
Christophe Dumez
fa7b1a205d Updated Slovak translation 2010-08-20 20:39:21 +00:00
Christophe Dumez
7dd6b7e9bb Updated Ukrainian translation 2010-08-20 14:37:30 +00:00
Christophe Dumez
78b96accda Fix "Seed until ratio reaches x.x" feature 2010-08-20 14:17:46 +00:00
Christophe Dumez
73d0e2568a Updated Web UI to reflect the autorun changes 2010-08-20 14:02:40 +00:00
Christophe Dumez
92fc212a0e FEATURE: Run external program on torrent completion 2010-08-20 13:20:23 +00:00
Christophe Dumez
6f4d7b7c1b Clean up 2010-08-20 12:35:13 +00:00
Christophe Dumez
63ee1c36e8 FEATURE: Added torrent filtering by name 2010-08-20 12:27:20 +00:00
Christophe Dumez
7d07debcb5 Cleaner program exit on Auto-shutdown 2010-08-20 09:35:28 +00:00
Christophe Dumez
dd67e1ee9d Code cleanup 2010-08-20 09:33:44 +00:00
Christophe Dumez
493efdbf10 Bump to beta3 2010-08-20 09:31:24 +00:00
Christophe Dumez
e323175275 Fix possible crash when using the new "Auto-shutdown" feature 2010-08-20 09:31:00 +00:00
Christophe Dumez
c1fa7f8645 Code cleanup 2010-08-20 09:02:27 +00:00
Christophe Dumez
275b962363 Added missing include 2010-08-19 20:23:39 +00:00
Christophe Dumez
3847c33017 Updated French translation 2010-08-19 19:37:29 +00:00
Christophe Dumez
9e21f52213 Updated language files 2010-08-19 19:16:44 +00:00
Christophe Dumez
25cf9b33ec Bump to beta2 2010-08-19 19:12:25 +00:00
Christophe Dumez
c7a2d3589f Updated Web UI to reflect the mail notification changes 2010-08-19 19:10:46 +00:00
Christophe Dumez
d8dd3834c3 Email notification on download completion 2010-08-19 18:47:57 +00:00
Christophe Dumez
ee01c2c745 FEATURE: Added button to password-lock the UI 2010-08-19 16:30:13 +00:00
Christophe Dumez
e7e5a2b4e9 Fix "Set location" action 2010-08-18 08:46:04 +00:00
Christophe Dumez
ff16f59be1 Fix per-label pause/resume actions 2010-08-18 08:07:17 +00:00
Christophe Dumez
2cd4937ddc Mac specific changes by Stephanos Antaris 2010-08-17 10:50:14 +00:00
Christophe Dumez
0e9abc1762 Bump to v2.4.0beta1 2010-08-17 08:51:12 +00:00
Christophe Dumez
e24ce87946 FEATURE: Added label-level Pause/Resume/Delete actions 2010-08-17 08:42:30 +00:00
Christophe Dumez
308e358d3f Fix Auto-Shutdown feature on Windows 2010-08-16 18:34:30 +00:00
Christophe Dumez
d15e6a4847 Blind implementation for auto-shutdown on Windows 2010-08-16 17:57:15 +00:00
Christophe Dumez
e311239a28 Blind implementation of auto-shutdown for Mac OS 2010-08-16 17:42:21 +00:00
Christophe Dumez
df677789d2 FEATURE: Added Auto-Shutdown on downloads completion feature (Linux Only for now) 2010-08-16 17:35:32 +00:00
Christophe Dumez
0af44eadb6 Fix possible folder watching issues on Windows 2010-08-16 11:51:50 +00:00
Christophe Dumez
85cafe530e Fix to last commit 2010-08-16 09:20:49 +00:00
Christophe Dumez
7609db28f1 Fix scan folder display on Windows and OS/2 2010-08-16 08:58:25 +00:00
Christophe Dumez
fefda39284 Added priority actions to Web UI right-click menu 2010-08-15 08:49:19 +00:00
Christophe Dumez
b2f98bd059 Priority actions should work only if the tab is displayed 2010-08-15 07:47:33 +00:00
Christophe Dumez
26c69fe6d4 Priority actions are only effective if the transfer list tab is displayed 2010-08-15 07:45:20 +00:00
Christophe Dumez
bf4f1a7c37 Fix speed limit sliders initialization in Web UI 2010-08-15 07:39:36 +00:00
Christophe Dumez
9b0dd39d9d Added missing icon 2010-08-15 07:23:37 +00:00
Christophe Dumez
66d4cc2ab8 FEATURE: Added actions to "Move to top/bottom" of priority queue 2010-08-14 15:53:05 +00:00
Christophe Dumez
0bcbaf6521 Remember last selected paths in torrent creation dialog 2010-08-13 14:02:19 +00:00
Christophe Dumez
e074872b24 Fix about dialog layout 2010-08-13 13:35:24 +00:00
Christophe Dumez
63ec1e618e Fix compilation with gcc 4.5 2010-08-13 13:29:17 +00:00
Christophe Dumez
331c15b76c Bump to v2.4.0alpha 2010-07-27 08:07:46 +00:00
Christophe Dumez
d2089c9aad Updated about dialog 2010-07-27 00:00:52 +00:00
Christophe Dumez
3c8326d3b6 Fix default temp path on Windows
Bump to rc11
2010-07-26 09:11:32 +00:00
Christophe Dumez
2d0713ca1d Should finally fix permissions issues on Windows 2010-07-26 08:58:12 +00:00
Christophe Dumez
afaca423cc Minor Windows bug fixes 2010-07-25 15:30:26 +00:00
Christophe Dumez
ff08abe177 Forgot to use the new safeRemove() function at some places 2010-07-25 15:26:27 +00:00
Christophe Dumez
159be479cc Fix drag'n drop on Windows (Thanks GeekyGirl) 2010-07-25 15:20:37 +00:00
Christophe Dumez
f3066b07b5 Use a proper error icon for seeding torrents whose files have been removed from hard drive (manually) 2010-07-25 15:08:54 +00:00
Christophe Dumez
aa58636832 When resuming a torrent with error, checking if the previous data is present before redownloading it. (closes #609748) 2010-07-25 14:55:30 +00:00
Christophe Dumez
5d1a584eac Do not display !.qB extension in save path 2010-07-25 14:00:35 +00:00
Christophe Dumez
7ee9abd646 Fix country names translation 2010-07-25 11:37:49 +00:00
Christophe Dumez
4d977a8d46 Improvement to last commit 2010-07-24 19:34:51 +00:00
Christophe Dumez
5c891724c4 Improvement to last fix 2010-07-24 19:26:26 +00:00
Christophe Dumez
185af18790 Fix improvement for file permissions on Windows 2010-07-24 19:22:55 +00:00
Christophe Dumez
fa6da97cf9 Fix compilation error
Attempt to fix permissions problem on Windows
2010-07-24 19:13:15 +00:00
Christophe Dumez
9503d9b024 Updated Spanish and Catalan translations 2010-07-24 18:57:54 +00:00
Christophe Dumez
de7b6ca553 Code clean up 2010-07-24 18:43:15 +00:00
Christophe Dumez
1788078594 Code clean up 2010-07-24 18:18:13 +00:00
Christophe Dumez
3caf473424 BUGFIX: Removed client spoofing feature to avoid tracker blacklisting 2010-07-24 17:35:29 +00:00
Christophe Dumez
5435bd2354 Improved detection of modal windows 2010-07-24 15:42:51 +00:00
Christophe Dumez
1cdb22a7e3 Bump to rc10 2010-07-24 14:29:26 +00:00
Christophe Dumez
95a9424ae7 Updated Russian translation (Thanks Arago) 2010-07-24 14:23:37 +00:00
Christophe Dumez
902196a176 Fix crash when accessing trackers and using libtorrent v0.15.x 2010-07-24 14:18:36 +00:00
Christophe Dumez
dbfef8665b Fix "Select All/None" buttons in torrent properties 2010-07-24 13:16:57 +00:00
Christophe Dumez
b3d8f2400f Optimization in tracker list code 2010-07-24 11:59:00 +00:00
Christophe Dumez
c12ae58868 Stop altering search engine files permissions 2010-07-24 10:41:44 +00:00
Christophe Dumez
4b77bb57ad Fix crash on torrent completion 2010-07-23 17:15:47 +00:00
Christophe Dumez
a6b1d308c2 More code clean up 2010-07-23 14:09:53 +00:00
Christophe Dumez
b483f09d11 Code cleanup 2010-07-23 14:05:53 +00:00
Christophe Dumez
bbb5ad31c4 Removed debug alert in Web UI 2010-07-22 22:29:56 +00:00
Christophe Dumez
3d4c1fe7da FEATURE: Added support for BitComet links (bc://bt/...) 2010-07-22 22:19:42 +00:00
Christophe Dumez
7a2c0d5d5a Updated French translation 2010-07-22 09:44:16 +00:00
Christophe Dumez
39d86c5f61 Made it possible to disable notification balloons again 2010-07-22 09:39:51 +00:00
Christophe Dumez
e2cdbbb184 Fix project file to support the new qtsinglecoreapplication.prf 2010-07-22 09:05:44 +00:00
Christophe Dumez
e83f9245a9 Mac toolbar toggling improvement (Mirco Chinelli) 2010-07-22 08:36:40 +00:00
Christophe Dumez
52f25c44eb Should fix toolbar toggling on mac 2010-07-21 23:59:09 +00:00
Christophe Dumez
1ed565d8e5 Added some debug 2010-07-21 23:46:30 +00:00
Christophe Dumez
10801f111b Attempt to fix toolbar toggling on Mac 2010-07-21 23:44:29 +00:00
Christophe Dumez
efe1655834 Added document icon for Mac (Mirco Chinelli) 2010-07-21 23:39:57 +00:00
Christophe Dumez
7f71e3981e Still cleaning up registry access code 2010-07-21 21:47:56 +00:00
Christophe Dumez
8113f8df63 Use a new icon for torrents on Windows
Clean up registry access code
2010-07-21 21:45:32 +00:00
Christophe Dumez
62f579fdbe New icon for file association on Windows 2010-07-21 19:57:07 +00:00
Christophe Dumez
1d4454c6eb Improve last commit 2010-07-21 18:09:22 +00:00
Christophe Dumez
310433fb54 Process Mac toolbar toggling event 2010-07-21 18:02:29 +00:00
Christophe Dumez
c0520146e9 Removed force_reannounce button from the main properties tab since the action is available from the trackers list now 2010-07-21 14:03:04 +00:00
Christophe Dumez
35f6675d86 Fix possible crash when saving fast resume data 2010-07-21 13:06:09 +00:00
Christophe Dumez
9494b15bd5 Fix possible crash on Windows 2010-07-21 12:44:29 +00:00
Christophe Dumez
3b82120923 Bump to rc6 2010-07-21 11:03:35 +00:00
Christophe Dumez
b9a0adc311 Fix compilation on Linux/Mac 2010-07-21 10:51:01 +00:00
Christophe Dumez
1e21ac3d79 Fixed possible crash on exit
Cleaned up main() function
2010-07-21 10:40:46 +00:00
Christophe Dumez
864bb8285e Fixed QIniSettings on Windows 2010-07-21 09:36:25 +00:00
Christophe Dumez
208e988c70 Added --with-qtsingleapplication=[shipped|system] flag to the configure file to comply with Linux distributions that are packaging qtsingleapplication solution. 2010-07-20 21:10:58 +00:00
Christophe Dumez
5cbcfb8efb Updated Hungarian translation 2010-07-20 18:46:31 +00:00
Christophe Dumez
107b833703 Imported recent patches from stable branch 2010-07-20 17:13:28 +00:00
Christophe Dumez
e2208a484e Forgot to remove outdated code 2010-07-20 15:55:59 +00:00
Christophe Dumez
5ab7c91d49 Updated Ukrainian translation 2010-07-20 12:11:37 +00:00
Christophe Dumez
a91ad3c9c7 Fix "Open destination folder" that would open a subfolder instead (closes #607510) 2010-07-20 09:02:41 +00:00
Christophe Dumez
385f950c2b Updated Croatian translation 2010-07-20 08:56:41 +00:00
Christophe Dumez
4667a84939 Suppress compiler warning 2010-07-19 19:48:16 +00:00
Christophe Dumez
5af0cacf0c Bump to rc5 2010-07-19 18:50:29 +00:00
Christophe Dumez
bceb00d35f Fix issues related to tab order in main window
Make sure the search input has focus when switching to the search tab
2010-07-19 18:49:53 +00:00
Christophe Dumez
51068294f1 Vavious Magnet link related fixes 2010-07-19 18:17:37 +00:00
Christophe Dumez
bcdf4e42fa Code cleanup in torrent addition dialog
Magnet link related fixes to torrent addition dialog
2010-07-19 17:29:48 +00:00
Christophe Dumez
214bb13843 Several torrent addition dialog fixes (Save path and label combo boxes) 2010-07-19 16:37:00 +00:00
Christophe Dumez
7998395532 Updated Turkish translation 2010-07-18 19:44:12 +00:00
Christophe Dumez
35aee18112 Code clean up 2010-07-18 12:53:16 +00:00
Christophe Dumez
8ddbdd34ed Updated language files 2010-07-17 21:37:07 +00:00
Christophe Dumez
66a5e479c7 Bump to rc4 2010-07-17 21:35:44 +00:00
Christophe Dumez
8f5bd2bc9f Fix other temp path issues 2010-07-17 21:35:00 +00:00
Christophe Dumez
5be2624cb1 Other temp path fixes 2010-07-17 21:12:13 +00:00
Christophe Dumez
f9684d662d When removing torrents from hard disk, also remove root folders 2010-07-17 20:55:40 +00:00
Christophe Dumez
9373796dd5 Updated Traditional Chinese translation 2010-07-17 08:32:58 +00:00
Christophe Dumez
2634517cdb Forgot to fix the magnet function too 2010-07-16 19:58:07 +00:00
Christophe Dumez
121a636b4e Fix several problems when incomplete torrent are kept in a temp folder
Bump to rc3
2010-07-16 19:53:47 +00:00
Christophe Dumez
aad42d4a57 Another Windows compilation fix 2010-07-16 16:02:58 +00:00
Christophe Dumez
c8b8518608 Windows compilation fixes 2010-07-16 15:42:32 +00:00
Christophe Dumez
0c40a8ab05 Keep compatibility with qBittorrent < 2.3.0 (import settings from the registry) 2010-07-16 15:11:20 +00:00
Christophe Dumez
b9241ad5ad Proper fix to use an INI file instead of the registry on Windows 2010-07-16 15:03:18 +00:00
Christophe Dumez
d354d7133e Fix to last commit 2010-07-16 14:40:50 +00:00
Christophe Dumez
a1157c78b2 BUGFIX: Use an INI file instead of the registry on Windows (More reliable) 2010-07-16 14:39:19 +00:00
Christophe Dumez
fb8d52e6e0 Safer registry usage on Win32 2010-07-16 14:06:30 +00:00
Christophe Dumez
80c42cae1a Fix torrent association detection on Win32 2010-07-15 13:27:57 +00:00
Christophe Dumez
f242fce5fd Fix for 0.0 2010-07-14 08:00:21 +00:00
Christophe Dumez
6223514704 Max ratio spin box starts at 0.0 not 0.1 2010-07-14 07:58:35 +00:00
Christophe Dumez
8fb7445e20 Remember "display speed in title bar" on restart (closes #605134) 2010-07-13 20:50:54 +00:00
Christophe Dumez
3172c6859d Updated Swedish translation 2010-07-13 09:09:38 +00:00
Christophe Dumez
58be573d02 Updated Serbian translation 2010-07-10 19:45:50 +00:00
Christophe Dumez
82f7bdb9cc Updated Hungarian translation 2010-07-10 08:56:04 +00:00
Christophe Dumez
b41c39b7ce Updated Greek and Bulgarian translations 2010-07-08 19:11:03 +00:00
Christophe Dumez
9e4958e96a Fix importing of torrents from qBT < v2.3.0 when using a temporary folder for incomplete torrents 2010-07-08 14:50:23 +00:00
Christophe Dumez
65091f7cb9 Updated Spanish and Catalan translations 2010-07-08 08:07:41 +00:00
Christophe Dumez
75b758bb1f Bump to rc1 2010-07-07 20:28:54 +00:00
Christophe Dumez
5028ff3ddd Minor options UI fixes by Mariusz Fik 2010-07-05 18:58:12 +00:00
Christophe Dumez
a246f76ec3 Updated Polish translation 2010-07-05 18:55:12 +00:00
Christophe Dumez
eeec067481 Updated Chinese translation 2010-07-05 07:46:16 +00:00
Christophe Dumez
3ee44ad0c2 Updated Portuguese and Brazilian translations 2010-07-04 16:06:22 +00:00
Christophe Dumez
c38ff5b0b7 OS/2 Fix 2010-06-30 22:32:40 +00:00
Christophe Dumez
e51dc6758c Update French translation 2010-06-30 22:29:19 +00:00
Christophe Dumez
7bb32643fa Peer IPs can be copied to clipboard 2010-06-30 22:28:23 +00:00
Christophe Dumez
3172e1f530 Fix tables appearance in Web UI
Fix empty array parsing in JSON
2010-06-29 08:44:56 +00:00
Christophe Dumez
7778877fa7 Fix Web UI translation 2010-06-29 08:08:43 +00:00
Christophe Dumez
b4f6745251 Updated German translation 2010-06-28 21:23:40 +00:00
Christophe Dumez
4fd7f16911 Updated Czech translation 2010-06-28 13:30:43 +00:00
Christophe Dumez
ca29b5d7fc Updated Finish translation 2010-06-28 08:12:04 +00:00
Christophe Dumez
79d5a635a4 Updated Slovak translation again 2010-06-27 21:50:52 +00:00
Christophe Dumez
7f615c580e Updated french translation 2010-06-27 21:31:05 +00:00
Christophe Dumez
967dbbda89 Updated Slovak translation 2010-06-27 21:24:30 +00:00
Christophe Dumez
452c0411d2 Added "Force reannounce" action to tracker list
Fixed typo in "Saudi Arabia"
2010-06-27 21:18:41 +00:00
Christophe Dumez
32d3ed2144 PeX status is now correctly reported 2010-06-27 21:07:12 +00:00
Christophe Dumez
4efae21f1d Use "Do no download" in action instead of "Not downloaded"
Added "Select All/Select None" buttons to files list
2010-06-27 21:01:47 +00:00
Christophe Dumez
c43efd7fb3 Bump to beta4 2010-06-27 19:40:32 +00:00
Christophe Dumez
93b1dbd931 Updated language files 2010-06-27 19:35:25 +00:00
Christophe Dumez
571896b888 Updated language files 2010-06-27 18:39:27 +00:00
Christophe Dumez
9f5d31b2b1 Use the same save path editing behaviour in properties panel as in torrent addition dialog 2010-06-27 17:58:08 +00:00
Christophe Dumez
c01f7102e6 FEATURE: Several files can now be disabled at once (closes #598365) 2010-06-27 16:55:02 +00:00
Christophe Dumez
df39e46c84 Fix font size in program options 2010-06-27 16:38:21 +00:00
Christophe Dumez
7f12bb5dfb Ask for confirmation before clearing search history (closes #598605) 2010-06-27 16:35:19 +00:00
Christophe Dumez
ca762139f6 FEATURE: Remember previous save paths in torrent addition dialog (closes #579305) 2010-06-27 16:30:37 +00:00
Christophe Dumez
67f41ad991 Do not display bytes values decimal digits 2010-06-27 14:19:24 +00:00
Christophe Dumez
621ec11ae3 Fix possible crash when using alternative speed limits 2010-06-24 21:34:31 +00:00
Christophe Dumez
de3135c43b Safer variable checking 2010-06-24 19:29:10 +00:00
Christophe Dumez
faed0ba45a Another magnet fix 2010-06-24 18:18:40 +00:00
Christophe Dumez
2104e4e2ce Fix crash when adding magnet links 2010-06-24 18:16:59 +00:00
Christophe Dumez
907a17a73b Updated spanish and catalan translations 2010-06-23 21:42:38 +00:00
Christophe Dumez
a1a9f8bc7e Fix processing of arguments including spaces 2010-06-23 19:07:54 +00:00
Christophe Dumez
a9a3bb74e7 Updated spanish and catalan translations 2010-06-23 18:54:47 +00:00
Christophe Dumez
b7de3fcebd Check if torrent_info is initialized in torrent addition dialog destructor (safer) 2010-06-23 17:58:32 +00:00
Christophe Dumez
0b70b857b9 Remove comment 2010-06-23 15:47:45 +00:00
Christophe Dumez
9c8a957dd7 Simplified Main windows geometry saving code 2010-06-23 15:47:03 +00:00
Christophe Dumez
cf65e4d77d Torrent addition dialog size/pos are now remembered correctly 2010-06-23 15:14:38 +00:00
Christophe Dumez
762962270c Fix error in last commit 2010-06-23 12:48:08 +00:00
Christophe Dumez
a2067af4ea Use putenv on Windows too 2010-06-23 12:44:23 +00:00
Christophe Dumez
2f4f06ca8b Do not redownload files if they were moved 2010-06-23 11:59:28 +00:00
Christophe Dumez
56dba2cb10 Updated Spanish and Catalan translations 2010-06-23 06:56:59 +00:00
Christophe Dumez
f824357358 Added Silvan Scherrer to AUTHORS file 2010-06-22 19:21:48 +00:00
Christophe Dumez
778cfff4b3 Several OS/2 fixes from Silvan Scherrer 2010-06-22 19:17:47 +00:00
Christophe Dumez
8ee762695b Fix "add extension to incomplete files" feature 2010-06-22 18:40:30 +00:00
Christophe Dumez
7dd9680e26 Fix torrent addition dialog settings saving 2010-06-22 18:18:53 +00:00
Christophe Dumez
92661e1d53 Fix qBittorrent console tab icon and window title 2010-06-22 18:15:42 +00:00
Christophe Dumez
09d5665ff9 Bump to beta3 2010-06-22 18:03:40 +00:00
Christophe Dumez
c5dfe623c8 Increased options window height to avoid scrollbars 2010-06-22 17:59:26 +00:00
Christophe Dumez
2665e2ef39 Fixed exit confirmation title 2010-06-22 17:51:59 +00:00
Christophe Dumez
dfecdb1956 Fix "Pause/Delete" torrents once they reach a given ratio 2010-06-22 17:46:07 +00:00
Christophe Dumez
5a82aee76b FEATURE: Torrents can be automatically paused once they reach a given ratio 2010-06-22 17:06:11 +00:00
Christophe Dumez
4f07426010 Fix file naming 2010-06-22 14:20:21 +00:00
Christophe Dumez
9e575e45b7 Hide tabs when only one is visible 2010-06-22 14:18:43 +00:00
Christophe Dumez
39b32bf1cd Search engine can now be disabled 2010-06-22 13:58:22 +00:00
Christophe Dumez
54131001b0 Move RSS settings to a separate dialog 2010-06-22 13:39:49 +00:00
Christophe Dumez
f8134b1a62 Fix issues with single file torrents 2010-06-22 12:02:18 +00:00
Christophe Dumez
13927599c8 Define add button as default in torrent addition dialog 2010-06-22 11:59:20 +00:00
Christophe Dumez
0d85d0a777 Free disk space calculation also works if the destination path does not exist 2010-06-22 11:53:49 +00:00
Christophe Dumez
0da83694e0 Hide torrent content in torrent addition dialog when there is only one file in it 2010-06-22 11:47:25 +00:00
Christophe Dumez
9bdac4d1e3 Use busy cursor when downloading search plugins updates 2010-06-22 09:56:49 +00:00
Christophe Dumez
00c92d6d61 Use checkable action for alternative speed limits and display button as "pressed when enabled" 2010-06-21 22:38:28 +00:00
Christophe Dumez
9628a9e156 Updated language files 2010-06-21 22:24:45 +00:00
Christophe Dumez
f1bfcb4822 COSMETIC: Fix naming of actions opening new dialogs (use Name...) 2010-06-21 22:22:00 +00:00
Christophe Dumez
87879b6738 Use checkable actions instead of check/uncheck icons to avoid issues on systems disabling menu icons (e.g. Recent Gnome) 2010-06-21 22:07:36 +00:00
Christophe Dumez
a4ff7047d1 Updated Changelog 2010-06-21 21:48:45 +00:00
Christophe Dumez
da599da36d Still simplifying program options 2010-06-21 21:39:29 +00:00
Christophe Dumez
335e7366fd Improved program options 2010-06-21 21:27:59 +00:00
Christophe Dumez
a993b2b3f1 Still improving program options 2010-06-21 21:06:11 +00:00
Christophe Dumez
b81c8d29ba Still improving program options 2010-06-21 20:29:51 +00:00
Christophe Dumez
08a08e4b24 Still simplifying program options 2010-06-21 19:20:58 +00:00
Christophe Dumez
8b5886cc6e Simplifying program options 2010-06-21 18:32:01 +00:00
Christophe Dumez
22b3d8d594 Fix exit confirmation dialog centering 2010-06-21 16:10:09 +00:00
Christophe Dumez
17efa04257 Further preferences simplifying 2010-06-21 16:02:21 +00:00
Christophe Dumez
e71f144c40 Started preferences simplifying 2010-06-21 15:53:42 +00:00
Christophe Dumez
5e7cafb8c0 More readable display of ETA 2010-06-21 14:10:20 +00:00
Christophe Dumez
d01385a7ac Moc bug workaround 2010-06-20 17:35:26 +00:00
Christophe Dumez
ac80dd78a8 Improved file saving in torrent addition dialog (uTorrent like) 2010-06-19 14:39:23 +00:00
Christophe Dumez
061f1000cf Unicode fix 2010-06-19 12:25:14 +00:00
Christophe Dumez
c36fed3081 Code cleanup 2010-06-19 12:07:39 +00:00
Christophe Dumez
75002906aa Improved torrent creator tool behavior during creation process 2010-06-17 17:52:14 +00:00
Christophe Dumez
a451cf2d5f Fix Web UI in nox 2010-06-17 11:55:47 +00:00
Christophe Dumez
ca10c0ab09 Fix unicode problem in torrent creator tool 2010-06-17 09:55:15 +00:00
Christophe Dumez
80d76ae038 BUGFIX: The user can disable permanently recursive torrent download 2010-06-14 17:46:33 +00:00
Christophe Dumez
f699ee1363 Fix font issue in search engine (closes #594200) 2010-06-14 15:42:15 +00:00
Christophe Dumez
bd97a4bd7c Fix registry access on 64bits windows 2010-06-14 12:51:07 +00:00
Christophe Dumez
ec3b749ef6 Merge fixes from stable branches (libtorrent v0.15 related) 2010-06-14 09:55:35 +00:00
Christophe Dumez
44fc86e7da Forgot to bump the version in project file 2010-06-13 20:36:08 +00:00
Christophe Dumez
2cd940e7c7 Another compilation Fix for Mac 2010-06-13 16:30:48 +00:00
Christophe Dumez
cc6d371667 Fix build on Mac 2010-06-13 16:28:41 +00:00
Christophe Dumez
8fcc33b375 Updated czech translation 2010-06-13 11:43:58 +00:00
Christophe Dumez
e44b570c3d Updated German translation 2010-06-13 11:40:25 +00:00
Christophe Dumez
8576847a99 Fix bundle identifier 2010-06-13 09:39:55 +00:00
Christophe Dumez
c9fc9373e5 Fix version number 2010-06-13 09:30:45 +00:00
Christophe Dumez
ae46d449e5 Added Magnet support 2010-06-13 09:25:06 +00:00
Christophe Dumez
fe57cef756 Added support for url open event on Mac 2010-06-13 09:20:16 +00:00
Christophe Dumez
3affb38ba2 Fix mime type 2010-06-13 09:14:30 +00:00
Christophe Dumez
a0dc6aa173 Several language files updates 2010-06-13 08:40:28 +00:00
Christophe Dumez
a357a690ce Updated Serbian and Croatian translations 2010-06-12 08:20:25 +00:00
Christophe Dumez
bce7959332 Attempt to make Ishan's patch lighter (the new patch may not take into consideration all use cases but it seems to work ok) 2010-06-10 19:54:20 +00:00
Ishan Arora
eef6f600c9 Fixed Bug #589070
qBittorrent wont hide on minimization if a modal window is visible over it.
2010-06-10 18:54:23 +00:00
Christophe Dumez
a3822c5aa8 Added debug output 2010-06-10 12:51:27 +00:00
Christophe Dumez
eeaa1e83a9 Fix typo 2010-06-10 09:05:15 +00:00
Christophe Dumez
387fb93b5b Fix typo 2010-06-10 09:03:54 +00:00
Christophe Dumez
d470059c56 Mac fixes 2010-06-09 22:16:37 +00:00
Christophe Dumez
2e382fa88c Removed useless include 2010-06-09 21:25:34 +00:00
Christophe Dumez
e1e7e782d5 Fix typo in plist file 2010-06-09 15:53:32 +00:00
Christophe Dumez
6f314502f6 Fix memory leak in last commit 2010-06-09 15:45:59 +00:00
Christophe Dumez
3284d7a8e6 Fix for last commit 2010-06-09 15:43:29 +00:00
Christophe Dumez
609ea7b4c2 Disable systray icon on Mac (Mirco Chinelli) 2010-06-09 15:40:55 +00:00
Christophe Dumez
7e8d21145e Fix typo 2010-06-09 15:19:43 +00:00
Christophe Dumez
c31b5f1f97 Various Mac related fixes (Thanks Mirco Chinelli) 2010-06-09 15:13:52 +00:00
Christophe Dumez
11fe685a6b Comment useless pri import 2010-06-09 14:46:55 +00:00
Christophe Dumez
1127947f52 Fix compilation on Windows 2010-06-09 14:39:53 +00:00
Christophe Dumez
789b2cf326 Updated AUTHORS file
Fix compilation in release mode
2010-06-09 10:06:42 +00:00
Christophe Dumez
b9394f2ba2 Fix race condition allowing to run several instances of qBittorrent at the same time 2010-06-09 09:48:14 +00:00
Christophe Dumez
7ab206ebac Use unified title and toolbar on Mac 2010-06-09 07:37:05 +00:00
Christophe Dumez
0beb9fff73 Updated Spanish and Catalan translations 2010-06-09 07:31:50 +00:00
Christophe Dumez
65b8d0c24d Delete qApp on exit 2010-06-09 06:38:14 +00:00
Christophe Dumez
715fe46f45 Updated arabic translation 2010-06-08 20:24:54 +00:00
Christophe Dumez
8209f341fb Updated Hungarian and Finnish translations 2010-06-08 18:29:42 +00:00
Christophe Dumez
0d4b55ca32 Better Mac integration 2010-06-08 15:17:15 +00:00
Christophe Dumez
ae7362706f Updated swedish translation 2010-06-08 15:07:16 +00:00
Christophe Dumez
4ca648a79b Updated Ukrainian translation 2010-06-08 14:47:16 +00:00
Christophe Dumez
4ca0b14300 Updated slovak translation 2010-06-08 11:41:36 +00:00
Christophe Dumez
4386b6c2c4 Merge javascript changes from stable branch 2010-06-07 13:41:32 +00:00
Christophe Dumez
61246f81c7 Fix msvc warnings 2010-06-07 10:39:03 +00:00
Christophe Dumez
70f2bfdd9a Updated configure file to remove our libtorrent DEFINE 2010-06-07 08:36:06 +00:00
Christophe Dumez
5f23cbc470 Use libtorrent version.hpp instead of our own DEFINE 2010-06-07 08:32:41 +00:00
Christophe Dumez
2e0c8f848f Fix Web UI authentication with Opera 2010-06-06 20:49:28 +00:00
Christophe Dumez
f8add0ee04 Back to debug mode in trunk 2010-06-06 20:02:11 +00:00
Christophe Dumez
f23051c1fd Fix signal / slot 2010-06-06 20:01:09 +00:00
Christophe Dumez
60636af544 Fix encoding problem in search engine 2010-06-06 15:41:08 +00:00
Christophe Dumez
2e685ea851 Updated language files 2010-06-06 15:36:22 +00:00
Christophe Dumez
b61a06350f Fix file encoding problem 2010-06-06 15:31:15 +00:00
Christophe Dumez
c9ece4695e Merge latest changes for stable branch (mostly unicode fixes) 2010-06-06 13:58:43 +00:00
Christophe Dumez
4805690dbe Merge latest msvc fixes from stable branch 2010-06-06 10:10:45 +00:00
Christophe Dumez
8ec1621334 Merge msvc fixes from stable branch 2010-06-05 18:59:05 +00:00
Christophe Dumez
682377ff66 Merge msvc compilation fixes from stable branch 2010-06-05 13:43:36 +00:00
Christophe Dumez
656beed82b Fix other unicode issues 2010-06-04 16:54:30 +00:00
Christophe Dumez
ba4a0fac77 Added Mirco Chinelli to contributors 2010-06-04 10:44:25 +00:00
Christophe Dumez
b719bfaecb Merge Win32 fixes from stable branch 2010-06-03 21:08:28 +00:00
Christophe Dumez
4e1366bf0d Merge latest fixes from stable branch 2010-06-03 20:08:19 +00:00
Christophe Dumez
b67938aa3f Fixed default save path on Windows 2010-06-02 22:31:49 +00:00
Christophe Dumez
f4c29c07bf Workaround for torrentdownloads.net search engine (The web site seems partly broken though) 2010-06-02 22:26:52 +00:00
Christophe Dumez
63a0f4bf11 Improved column visibility patch 2010-06-02 13:50:11 +00:00
Christophe Dumez
a8a2ba188d Search requests can now be cancelled on Win32 2010-06-02 13:45:20 +00:00
Christophe Dumez
a0d685bfe2 Merge Win32 changes from stable branch 2010-06-02 13:08:26 +00:00
Christophe Dumez
a3041b7f9f Improved Python detection (Win32)
Propose to download and install python if missing (Win32)
2010-06-01 22:47:14 +00:00
Christophe Dumez
83a2ae7ad3 Disable torrent addition dialog as a default 2010-06-01 16:29:40 +00:00
Christophe Dumez
830a6250c6 Changed window title on Win32 and Mac 2010-06-01 16:10:59 +00:00
Christophe Dumez
f0e23ab1fc Fix encoding in Web UI on non-unicode systems 2010-06-01 14:34:58 +00:00
Christophe Dumez
5b07c488b0 Link dynamically against OpenSSL on Windows 2010-06-01 13:56:59 +00:00
Christophe Dumez
f61bccf700 Fix torrent availability computation 2010-05-31 14:25:12 +00:00
Christophe Dumez
4fd10bc5f5 Merge Win32 changes 2010-05-31 12:48:00 +00:00
Christophe Dumez
c1a72f075d Updated French translation 2010-05-30 22:08:41 +00:00
Christophe Dumez
5c4450f3cd Some Win32 improvements 2010-05-30 21:45:55 +00:00
Christophe Dumez
bb606e0b2f Updated language files 2010-05-30 18:37:11 +00:00
Christophe Dumez
eed86aa9e1 Updated Authors 2010-05-30 17:54:58 +00:00
Christophe Dumez
338d4fd31e Windows execution fixes 2010-05-30 17:51:40 +00:00
Christophe Dumez
58a36f7cfd Windows compilation Fix 2010-05-28 22:03:30 +00:00
Christophe Dumez
8b436f70d6 Mac compilation Fix 2010-05-25 11:09:20 +00:00
Christophe Dumez
223fd4f0ba BUGFIX: Hide seeding torrents files priorities in Web UI 2010-05-24 19:37:56 +00:00
Christophe Dumez
2e51e69cc9 Added "Paused" filter to the Web UI too 2010-05-24 19:05:07 +00:00
Christophe Dumez
bbac79c030 FEATURE: Add Check/Uncheck all feature in Web UI 2010-05-24 18:57:44 +00:00
Christophe Dumez
607bba4625 FEATURE: Added filter for paused/error torrents 2010-05-24 15:16:14 +00:00
Christophe Dumez
1a0cc3215c Removed useless icons 2010-05-24 14:51:03 +00:00
Christophe Dumez
f0981c81c8 Removed another useless icon 2010-05-24 14:45:47 +00:00
Christophe Dumez
472604d1b0 Removed useless icons to reduce tarball size 2010-05-24 14:43:31 +00:00
Christophe Dumez
781d33b869 FEATURE: Added error state for torrents (error is displayed in a tooltip) 2010-05-24 14:19:25 +00:00
Christophe Dumez
8db8841c9c Added error state icon
Update language files
2010-05-24 13:51:23 +00:00
Christophe Dumez
6e3b570be4 Add a setting to also delete torrents files on hard disk as a default 2010-05-21 15:42:17 +00:00
Christophe Dumez
defd77b94c COSMETIC: Display number of torrents in transfers tab label 2010-05-21 14:56:56 +00:00
Christophe Dumez
c09294df2f FEATURE: Several torrents can be moved at once 2010-05-21 14:26:18 +00:00
Christophe Dumez
cc97ee86df FEATURE: Added "No action" setting for double-click action 2010-05-21 12:30:57 +00:00
Christophe Dumez
10d6dd5a23 Torrent queue position now starts at 1 (closes #581130) 2010-05-21 11:58:14 +00:00
Christophe Dumez
29e79dc54d Fix sorting of ETA column when having infinite values (closes #583347) 2010-05-21 11:46:12 +00:00
Christophe Dumez
982390f074 Make sure seeding torrents ETA stays 0 under all circumstances 2010-05-21 11:34:31 +00:00
Christophe Dumez
963d73af4e ETA for finished torrent is now 0 instead of Infinite (closes #583704)
Fix unicode issue in start seeding after torrent creation code
2010-05-21 11:25:30 +00:00
Christophe Dumez
bdd8cbb1d8 Another nox compilation fix 2010-05-20 14:14:16 +00:00
Christophe Dumez
80bd232054 nox compilation fix 2010-05-20 11:16:39 +00:00
Christophe Dumez
c2da227254 User can force tracker reannounce 2010-05-18 09:35:55 +00:00
Christophe Dumez
e846c67bfa Fix torrent properties layout 2010-05-18 07:22:51 +00:00
Christophe Dumez
475c7094ab Fixed Croatian translator name 2010-05-17 21:45:29 +00:00
Christophe Dumez
4434566d85 Forot to commit this file 2010-05-17 19:57:57 +00:00
Christophe Dumez
6bd557d22c Forgot to commit this file 2010-05-17 19:34:17 +00:00
Christophe Dumez
4832a24ac5 Fix RSS cookie support 2010-05-17 19:23:16 +00:00
Christophe Dumez
b9a3890dd5 Updated Changelog 2010-05-17 15:45:42 +00:00
Christophe Dumez
4cf9de6515 Updated language files 2010-05-17 15:35:17 +00:00
Christophe Dumez
994c798264 Added cookie support for RSS feeds (Needs testing) 2010-05-17 14:57:45 +00:00
Christophe Dumez
119bda1595 Fix url encoded ampersand issue in RSS 2010-05-12 19:41:12 +00:00
Christophe Dumez
bf73c47bc5 Sort labels in right click menu 2010-05-12 19:03:31 +00:00
Christophe Dumez
ea99f44893 Fix wrong warning in torrent addition dialog (closes #579301) 2010-05-12 18:34:16 +00:00
Christophe Dumez
4ec1fd3968 The user can force listening on a particular network interface 2010-05-11 15:53:14 +00:00
Christophe Dumez
0b9e25ee65 Update Croatian language name 2010-05-05 20:40:14 +00:00
Christophe Dumez
73a9985599 Fix crash when pressing mouse button and selecting different rss items 2010-05-05 14:28:40 +00:00
Christophe Dumez
a65f7bfa65 Updated Spanish and Catalan translations 2010-05-03 18:00:43 +00:00
Christophe Dumez
72cc1eb4d4 Even safer datetime parsing 2010-05-01 18:07:56 +00:00
Christophe Dumez
ed7ae32a69 Made datetime parsing more reliable 2010-05-01 17:37:12 +00:00
Christophe Dumez
54b53f3aba RSS: News title is no longer used as identifier (use guid or url instead) 2010-05-01 09:41:37 +00:00
Christophe Dumez
2f7728f987 Added Croatian translation to Desktop file 2010-05-01 09:12:43 +00:00
Christophe Dumez
f3a93af242 Update resource file 2010-05-01 08:50:17 +00:00
Christophe Dumez
5a4ad2f822 Added Croatian binary file 2010-05-01 08:48:28 +00:00
Christophe Dumez
c669240037 Commit more Croatian specific changes 2010-05-01 08:45:38 +00:00
Christophe Dumez
ce4fd8429e Commit Croatian translation 2010-05-01 08:41:14 +00:00
Christophe Dumez
cc532d95da Improved folder removing code 2010-05-01 08:29:04 +00:00
Christophe Dumez
c800a0a6b5 Fix moving torrent from temp dir when they are complete 2010-05-01 08:12:42 +00:00
Christophe Dumez
5675c045ae Windows compilation fixes (Thanks LiHuiShuo) 2010-04-28 11:45:13 +00:00
Christophe Dumez
e16ca862f4 Fix in last commit 2010-04-23 16:48:17 +00:00
Christophe Dumez
29e757bb3a Another initialization fix for Web UI 2010-04-23 08:12:06 +00:00
Christophe Dumez
822f1a9557 Fix possible initialization problem in Web UI 2010-04-23 08:04:21 +00:00
Christophe Dumez
7acfb27a1f Fix torrent relabeling with unicode names 2010-04-22 16:19:49 +00:00
Christophe Dumez
83d6731fa9 Translated menu entry in Arabic 2010-04-19 12:54:46 +00:00
Christophe Dumez
de4f0272c1 Make sure status filters height is correct when the visual style changes 2010-04-17 14:21:19 +00:00
Christophe Dumez
df50a875df Updated arabic translation 2010-04-16 18:12:14 +00:00
Christophe Dumez
5f814f23b4 Arabic translation fixes 2010-04-15 19:25:06 +00:00
Christophe Dumez
98ec373f8c Support Right to left languages 2010-04-13 18:40:07 +00:00
Christophe Dumez
0bbeab9ad2 Added an OS/2 specific REAME file 2010-04-13 10:41:32 +00:00
Christophe Dumez
ed4c711ef5 Some Arabic related improvements 2010-04-12 19:13:51 +00:00
Christophe Dumez
fc33702b81 Added Arabic translation 2010-04-12 18:51:23 +00:00
Christophe Dumez
70c79f31c3 Stop rechecking torrents everytime they are moved 2010-04-10 15:54:55 +00:00
Christophe Dumez
82dc2103b5 COSMETIC: Display peers country name in tooltip (Thanks mrovi) 2010-04-10 15:46:52 +00:00
Christophe Dumez
529ab304b4 Remove old folder when moving a torrent 2010-04-10 15:00:35 +00:00
Christophe Dumez
53919446d4 FS should be updated properly on labeling now 2010-04-10 14:50:11 +00:00
Christophe Dumez
1052cd019b Better fix for FS changes on torrent labeling 2010-04-10 14:17:26 +00:00
Christophe Dumez
4f87819abf Fix for torrent labeling: label was not appended to save path correctly 2010-04-10 13:58:36 +00:00
Christophe Dumez
b94ecb2383 Added support for single-thread boost 2010-04-09 18:45:33 +00:00
Christophe Dumez
c00d83dee9 Announce to all trackers 2010-04-09 18:24:57 +00:00
Christophe Dumez
34052ce8f9 Less dependencies for nox 2010-04-09 15:26:41 +00:00
Christophe Dumez
0a0c8948ee Improved previous patch 2010-04-08 16:33:47 +00:00
Christophe Dumez
0cc9283275 eCS (OS/2) compilation fix (Thanks Silvan Scherrer) 2010-04-08 16:28:47 +00:00
Christophe Dumez
6b2e9f057b Qt 4.4 compilation fix 2010-04-07 10:00:32 +00:00
Christophe Dumez
3a1fc9ec77 Updated INSTALL file 2010-04-07 09:58:22 +00:00
Christophe Dumez
e4399412b6 Attempt to fix compatibility with libboost v1.34 2010-04-07 09:52:43 +00:00
Christophe Dumez
37650d8156 Improved libboost detection again 2010-04-07 09:48:04 +00:00
Christophe Dumez
b4fa164dc3 Updated boost dependencies in INSTALL file 2010-04-07 09:42:47 +00:00
Christophe Dumez
6148e6b192 Improved libbost detection 2010-04-07 09:35:43 +00:00
Christophe Dumez
057743a779 Do not display a warning when libtorrent < 0.14.x is detected since it is the advised version 2010-04-07 09:06:11 +00:00
Christophe Dumez
530ba2a0bd Improved slow_off icon 2010-04-07 09:03:18 +00:00
Christophe Dumez
977b2bda7c Added icons to menu actions in Web UI 2010-04-07 08:30:47 +00:00
Christophe Dumez
76eb93ba1a Flat buttons in status bar should never get focus 2010-04-07 08:19:17 +00:00
Christophe Dumez
ae3c50c074 Improved speed limits icons location in preferences 2010-04-07 08:02:42 +00:00
Christophe Dumez
31017602fc Fix transparency of speed limits icons
Dropped dependency on Qt gif library
2010-04-07 07:59:26 +00:00
Christophe Dumez
ef7e2abdaf Fix download from URL title in Web UI 2010-04-06 17:00:53 +00:00
Christophe Dumez
a6abedd67d Fix deprecation warnings with libtorrent v0.15 2010-04-06 16:52:17 +00:00
Christophe Dumez
9824d86a3c Fix HTTPS protocol support in torrent/rss downloader 2010-04-06 16:25:24 +00:00
Christophe Dumez
1eac3d1700 Fix torrent addition dialog buttons height (Thanks Mariusz Fik) 2010-04-06 16:13:32 +00:00
Christophe Dumez
48585bb049 Fix crash when adding a new label 2010-04-06 16:06:25 +00:00
Christophe Dumez
843e49a5a8 Updated polish translation 2010-04-06 16:03:26 +00:00
Christophe Dumez
db01276f1d Fix default width of file name column in torrent content 2010-04-06 09:28:42 +00:00
Christophe Dumez
772028106e FEATURE: Simplified torrent root folder renaming/truncating (< v2.3.0 is no longer forward compatible) 2010-04-06 09:17:33 +00:00
Christophe Dumez
0cd5253857 Forgot to commit those icons 2010-04-06 07:47:11 +00:00
Christophe Dumez
eaf321facb Fix in last commit 2010-04-05 21:03:50 +00:00
Christophe Dumez
81ecb5c7c8 Improved alternative speed limits icons 2010-04-05 20:52:48 +00:00
Christophe Dumez
3b3a452df6 Display the correct ratio for paused torrents 2010-04-05 20:07:56 +00:00
Christophe Dumez
65b1e29414 Correctly clear trackers error messages once they work 2010-04-05 19:56:58 +00:00
Christophe Dumez
a6e3b9afac Fix about dialog in Web UI 2010-04-05 19:50:34 +00:00
Christophe Dumez
a7792701a2 When resizing torrent addition dialog, torrent content should be expanding 2010-04-05 19:39:13 +00:00
Christophe Dumez
846372e48b Similar fixes 2010-04-05 19:32:44 +00:00
Christophe Dumez
1597007ea1 Fix possible crash when adding a torrent 2010-04-05 19:03:00 +00:00
Christophe Dumez
dbceed21f5 Clean fix for progress display with cleanlooks style 2010-03-31 14:33:49 +00:00
Christophe Dumez
3254dae59f A msvc compilation fix 2010-03-30 19:38:19 +00:00
Christophe Dumez
12881dd4c4 On Windows, add qBittorrent executable folder to PATH environment variable 2010-03-30 18:59:15 +00:00
Christophe Dumez
35ec93ccb1 Bump to v2.3.0alpha 2010-03-30 12:09:31 +00:00
Christophe Dumez
cb159ed00d Enable Apply button when alternative rate limits are changed 2010-03-30 12:08:00 +00:00
Christophe Dumez
e5b8b41373 Several compilation and execution fixes for Windows and OS/2
Cleaner binutils gold linker support
2010-03-30 11:35:20 +00:00
Christophe Dumez
492814a56e Fix possible crash in boost exception handling 2010-03-29 10:43:56 +00:00
Christophe Dumez
d639712303 Fix typo 2010-03-27 16:00:21 +00:00
Christophe Dumez
f5d1c8a679 Another compilation fix 2010-03-27 15:56:49 +00:00
Christophe Dumez
aea3d4be7a Another Windows compilation fix 2010-03-27 15:50:27 +00:00
Christophe Dumez
8d1fd7ee8e Windows compilation fix improvement 2010-03-27 09:15:33 +00:00
Christophe Dumez
a98a002d57 Compilation fix on Windows (getuid missing) 2010-03-27 09:03:37 +00:00
Christophe Dumez
fb874695c9 Added support for strict super seeding 2010-03-25 19:31:48 +00:00
Christophe Dumez
63457c034f Maximum number of half-open connections can now be changed from program preferences (default is now 50 instead of unlimited) 2010-03-25 19:16:43 +00:00
Christophe Dumez
daff6dce4c Fix possible crash when deleting a torrent just after pausing it 2010-03-23 21:35:47 +00:00
Christophe Dumez
94c7c5cebe DHT port can be changed from Web UI 2010-03-22 20:34:12 +00:00
Christophe Dumez
f2c4901dd0 Updated language files 2010-03-22 19:58:29 +00:00
Christophe Dumez
95d8eb9714 Improvement to last fix 2010-03-22 19:15:38 +00:00
Christophe Dumez
62165445fe Updated languages files 2010-03-22 19:04:28 +00:00
Christophe Dumez
6b12371f50 Improvement to last fix 2010-03-22 18:58:30 +00:00
Christophe Dumez
38cb4ccbd3 Fix possible crash with folder watching 2010-03-22 18:50:04 +00:00
Christophe Dumez
8ccaaae085 I18N: Updated Polish translation (thanks Szymon Świerkosz) 2010-03-22 18:23:02 +00:00
Christophe Dumez
6f7ae4770a Properly raise SIGSEGV/SIGABRT after catching it 2010-03-20 21:43:01 +00:00
Christophe Dumez
5aa348a574 Save fast resume data every 3 minutes 2010-03-20 21:21:42 +00:00
Christophe Dumez
7b8fa49482 Made M3U files previewable 2010-03-20 19:37:28 +00:00
Christophe Dumez
789cf654d0 Another attempt to fixing Mac compilation 2010-03-20 19:09:27 +00:00
Christophe Dumez
a300a6094e Mac compilation fix 2010-03-20 17:39:43 +00:00
Christophe Dumez
37b09e70b0 Fix "Ctrl+A" in Web UI 2010-03-20 15:45:14 +00:00
Christophe Dumez
530fbfc9b4 Ask for user confirmation because proceeding with recursive torrent download (security risk)
Fix "add file" dialog in torrent creation tool
2010-03-20 11:30:11 +00:00
Christophe Dumez
73c312ec1a Slight code optimization 2010-03-19 19:41:59 +00:00
Christophe Dumez
318a959470 Fix file filtering in complex torrent files 2010-03-19 11:12:17 +00:00
Christophe Dumez
f9cc98791a Subclass Cleanlook style to make sure the progress value is displayed when selected 2010-03-19 08:04:35 +00:00
Christophe Dumez
263eb3c632 Code optimization 2010-03-18 23:25:10 +00:00
Christophe Dumez
52b3926f92 Code optimization 2010-03-18 23:12:25 +00:00
Christophe Dumez
af3755bf91 "Downloaded pieces" bar now displays in yellow the pieces being downloaded 2010-03-18 22:58:32 +00:00
Christophe Dumez
419d719ab8 Added back file prioritizing in Web UI 2010-03-18 20:04:03 +00:00
Christophe Dumez
3877cf9ab8 Update to v2.3.0 alpha 2010-03-18 19:26:07 +00:00
Christophe Dumez
912056a364 Added back folder watching in Web UI 2010-03-18 19:25:16 +00:00
Christophe Dumez
165b33a94e Fixed Web UI compatibility with Safari 2010-03-16 00:20:32 +00:00
Christophe Dumez
12fff1b966 Compilation fix with Qt 4.4 2010-03-15 18:10:18 +00:00
Christophe Dumez
128eba7ec3 Bump to v2.2.0 final 2010-03-14 20:00:56 +00:00
Christophe Dumez
5bb370df0e Updated Hungarian translation 2010-03-14 16:05:30 +00:00
Christophe Dumez
6431343ad7 Made preferences columns resizable 2010-03-13 14:10:26 +00:00
Christophe Dumez
bd292076e3 Another Qt 4.6 fix 2010-03-13 13:45:10 +00:00
Christophe Dumez
ce0ddbe517 Qt 4.6 fix 2010-03-13 13:40:26 +00:00
Christophe Dumez
5451bb185e Updated Russian translation 2010-03-13 13:25:20 +00:00
Christophe Dumez
057cf3648e BUGFIX: Set Web UI ban period to 1 hour 2010-03-13 12:21:15 +00:00
Christophe Dumez
80d5c5d85c Made Web UI authentication even more robust 2010-03-12 20:55:09 +00:00
Christophe Dumez
671a997092 BUGFIX: Fix Web UI authentication with some browsers (e.g. epiphany) 2010-03-12 20:28:47 +00:00
Christophe Dumez
f2fbfdf017 Fix "download from URL" dialog height to avoid having a scrollbar 2010-03-12 20:24:12 +00:00
Christophe Dumez
1ea7340111 BUGFIX: Consider HTTP downloads >1MB as invalid .torrent files and abort them 2010-03-12 20:00:51 +00:00
Christophe Dumez
7b38ea4151 Updated Traditional Chinese translation 2010-03-12 15:12:59 +00:00
Christophe Dumez
c4ed12bbd1 Code cleanup 2010-03-11 21:59:25 +00:00
Christophe Dumez
c32b352ec1 Mark QTorrentHandle constructor as explicit 2010-03-11 21:43:09 +00:00
Christophe Dumez
9b2565dff9 Updated swedish translation 2010-03-11 18:09:50 +00:00
Christophe Dumez
f833f26212 Duplicate torrent trackers and url seeds are added to existing torrent even if it was added through folder scanning 2010-03-11 16:37:49 +00:00
Christophe Dumez
66a7082b5c Updated Greek translation 2010-03-11 08:42:40 +00:00
Christophe Dumez
cc3a6350a5 Enabled modality for appropriate dialogs
Make sure it is impossible to open more than one torrent addition from URL dialog
2010-03-10 20:21:56 +00:00
Christophe Dumez
9202ce8757 Deleting windows that are possibly still open on exit 2010-03-10 20:08:43 +00:00
Christophe Dumez
c0e4f126de Updated Korean, Portuguese and Brazilian translations 2010-03-09 07:59:17 +00:00
Christophe Dumez
44ca0a4904 Bump to rc2 2010-03-08 22:14:40 +00:00
Christophe Dumez
64ddf393aa Rss Feed downloader fix 2010-03-08 22:13:22 +00:00
Christophe Dumez
a60615a2d8 Improved RSS filters sorting code 2010-03-08 22:09:17 +00:00
Christophe Dumez
d9fa9c3566 Fix folder scanning: it would not detect torrents already present in the folder on startup. This bug was introduced recently (in rc1) 2010-03-08 19:19:17 +00:00
Christophe Dumez
5115b8739e Updated Spanish, Catalan and Czech translations 2010-03-08 19:07:13 +00:00
Christophe Dumez
854fb4acc0 Updated Italian translation 2010-03-08 11:30:13 +00:00
Christophe Dumez
07ef81fd95 Fix compilation error 2010-03-08 07:32:46 +00:00
Christophe Dumez
17e39f56dd Make sure path cannot be null 2010-03-07 21:06:07 +00:00
Christophe Dumez
040e94cab7 Added another check 2010-03-07 21:03:51 +00:00
Christophe Dumez
93563365ac Slight Optimization 2010-03-07 20:33:06 +00:00
Christophe Dumez
c287879e55 Fix possible crash with Qt 4.4 2010-03-07 20:27:39 +00:00
Christophe Dumez
537c73d548 Updated Serbian translation 2010-03-07 08:59:52 +00:00
Christophe Dumez
ad3f5f6e20 Drop our QCleanLooks style subclass since there no longer seem to be an issue with the standard one 2010-03-06 21:36:08 +00:00
Christophe Dumez
a468404ab5 Make use of Fast concatenation feature in Qt 4.6 2010-03-06 21:11:47 +00:00
Christophe Dumez
6d7fba1a6c Slight cleanup 2010-03-06 20:22:36 +00:00
Christophe Dumez
5c734a80f8 Updated Chinese translation 2010-03-06 19:58:10 +00:00
Christophe Dumez
edfee5193c Updated Bulgarian translation and translator name 2010-03-06 11:13:13 +00:00
Christophe Dumez
9900651c55 Updated slovak translation 2010-03-05 08:00:26 +00:00
Christophe Dumez
948adbe350 Uploaded Ukrainian translation 2010-03-04 21:15:35 +00:00
Christophe Dumez
ade0ba794c Little fix 2010-03-04 21:10:46 +00:00
Christophe Dumez
5494c33a89 Fix compilation with Qt 4.4 2010-03-04 20:33:48 +00:00
Christophe Dumez
c8f5cab636 Set as RELEASE_CANDIDATE 2010-03-04 20:30:34 +00:00
Christophe Dumez
4a8a40a6f2 Updated French translation 2010-03-04 20:26:57 +00:00
Christophe Dumez
70d41cdc79 Updated German and Finnish translations 2010-03-04 20:22:12 +00:00
Christophe Dumez
aec99ed14f More code cleanup 2010-03-04 20:19:25 +00:00
Christophe Dumez
9a645b4b19 Bump to rc1 2010-03-04 19:30:22 +00:00
Christophe Dumez
bea3c33a46 Fix several signals/slots bindings
Drop backward compatiblity functions for qBT <= 1.4.0
Clean up torrent loading code (Use priority queue instead of insertion sort)
2010-03-04 19:29:48 +00:00
Christophe Dumez
e082c02630 Make use of QT_VERSION define instead of using our own define 2010-03-04 18:40:11 +00:00
Christophe Dumez
291b94bef0 Code cleanup 2010-03-04 18:03:12 +00:00
Christophe Dumez
f119be3ed5 Updated language files 2010-03-04 17:41:33 +00:00
Christophe Dumez
9034094cf9 Fix headless compilation 2010-03-04 08:36:23 +00:00
Christophe Dumez
c48766aeb7 - Slight RSS cleanup 2010-03-03 23:11:40 +00:00
Christophe Dumez
28a6afeb02 Clean up and optimize transferlist class 2010-03-03 21:59:12 +00:00
Christophe Dumez
c8d0f5a104 Folder scanning settings are now properly saved 2010-03-03 21:17:45 +00:00
Christophe Dumez
3c396257de Use QXmlStreamReader instead of QDomDocument to save memory when parsing the RSS documents 2010-03-03 21:11:40 +00:00
Christophe Dumez
a9be841d2d Keep on cleaning up 2010-03-03 19:04:34 +00:00
Christophe Dumez
7d0581a7a5 Started code clean up and optimization 2010-03-03 17:27:25 +00:00
Christophe Dumez
4efeb66b73 Remove useless cast
Added missing include that caused misleading error message
2010-03-03 15:23:34 +00:00
Christophe Dumez
3b05f8b4b4 Reorganized header file 2010-03-03 14:48:49 +00:00
Christophe Dumez
6b4f09d740 - Cleanup GUI class 2010-03-03 14:42:57 +00:00
Christophe Dumez
f1b02c1280 Make sure options and console windows are deleted on exit 2010-03-03 13:15:13 +00:00
Christophe Dumez
3d546a4c5d BUGFIX: Only one log window can be opened at a time 2010-03-03 13:07:27 +00:00
Christophe Dumez
19368bcefa Added virtual destructor to avoid memory leaks 2010-03-03 13:03:13 +00:00
Christophe Dumez
dbbf26449c - Clean up main code
- Use fromLocal8Bit() instead fromUtf8() on program parameters
2010-03-03 12:55:42 +00:00
Christophe Dumez
8f28804f8c Added Json encode support for QVariantList and QStringList 2010-02-28 17:24:35 +00:00
Christophe Dumez
b7edfea4ce Disable scan folder preferences in Web UI (for now) since it was broken by "multipleScanFolders" patch 2010-02-28 17:17:14 +00:00
Christophe Dumez
23b2f94c40 Call qDeleteAll on m_pathList 2010-02-28 16:23:59 +00:00
Christophe Dumez
8f40f41fef Qt4.4 Compatibility fix (QDate::StandaloneFormat) 2010-02-28 16:07:09 +00:00
Christophe Dumez
33f868144b Use a regular pointer instead of a QSharedPointer to fix Qt 4.4 compatibility 2010-02-28 16:00:52 +00:00
Christophe Dumez
b2545bb709 Added Christian Kandeler to contributors 2010-02-28 15:50:25 +00:00
Christophe Dumez
3b6e1e82d9 Updated language files 2010-02-28 15:22:31 +00:00
Christophe Dumez
7710c88797 FEATURE: Support for multiple scan folders
* Patch by Christian Kandeler (Thanks!)
2010-02-28 15:15:00 +00:00
Christophe Dumez
4d5001d18d Display more useful information in log window when an I/O error occurs
I/O errors are now reported in nox version too
2010-02-22 19:30:36 +00:00
Christophe Dumez
0f4f108eb5 BUGFIX: Fix ratio calculation for directly seeded torrents (Thanks phorane) 2010-02-17 08:10:57 +00:00
Christophe Dumez
f0d0bb7170 FEATURE: Allow to change the priority of several files at once 2010-02-16 20:50:44 +00:00
Christophe Dumez
66157da5c2 Fix browse button for torrent export directory in preferences 2010-02-16 19:40:41 +00:00
Christophe Dumez
13493e1afe - Global Upload/Download rates can be set by clicking on the status bar values 2010-02-15 20:57:55 +00:00
Christophe Dumez
f6bfacda2c FEATURE: Global transfer information are displayed in the new Web UI status bar 2010-02-15 20:07:15 +00:00
Christophe Dumez
f7a86b5484 Add URL seeds from duplicate torrents to existing ones 2010-02-15 18:45:39 +00:00
Christophe Dumez
66cd3f8184 Fix save path display in Web UI too 2010-02-14 15:30:10 +00:00
Christophe Dumez
3a237c93be Make sure torrent save path is displayed 2010-02-14 15:22:34 +00:00
Christophe Dumez
4c34066727 FEATURE: Trackers can be added from Web UI 2010-02-14 15:15:35 +00:00
Christophe Dumez
1960008c83 Fix Web UI authentication with Konqueror 2010-02-12 00:00:55 +00:00
Christophe Dumez
deffbd6321 Updated Russian translation 2010-02-11 11:45:30 +00:00
Christophe Dumez
53927c9aa0 Revert useless 64bits patch 2010-02-10 23:22:47 +00:00
Christophe Dumez
d84346616a Added -L/usr/lib64 for 64bits 2010-02-10 22:28:01 +00:00
Christophe Dumez
e1183dbc0b Bump to beta4 2010-02-10 21:34:31 +00:00
Christophe Dumez
602f1574ca - Fix possible race condition in search engine 2010-02-10 21:20:44 +00:00
Christophe Dumez
358f7d16da Add back CONFIG += link_pkgconfig or it causes crashes 2010-02-10 21:14:44 +00:00
Christophe Dumez
e4006d6175 - Update helper version 2010-02-10 20:15:21 +00:00
Christophe Dumez
949b4ce4e9 - Improve gzip file detection in HTTP downloader (do not trust HTTP header, check magic number) 2010-02-10 20:02:55 +00:00
Christophe Dumez
cbafac8ea9 - Make it impossible to open more than one options dialog 2010-02-09 23:32:54 +00:00
Christophe Dumez
e4bf116ce8 - Fix a crash when adding an already existing torrent 2010-02-09 21:35:20 +00:00
Christophe Dumez
bccdad4b1b - Fix memory leak in rss 2010-02-09 21:20:43 +00:00
Christophe Dumez
9b372b3cce Important fix regarding actions on selected torrents. With filters enabled, it could happen that non-selected torrents are affected. 2010-02-09 20:44:33 +00:00
Christophe Dumez
98d0c00f85 Link against boost and ssl to fix issues with gold linker 2010-02-09 12:01:13 +00:00
Christophe Dumez
9d2f2230ee - Fix bugs with new feature: "Add trackers from duplicate torrent" 2010-02-09 08:06:49 +00:00
Christophe Dumez
81c6958428 - Bump to beta3 2010-02-08 19:06:21 +00:00
Christophe Dumez
f976eda6a9 - Updated French translation 2010-02-08 19:05:41 +00:00
Christophe Dumez
fe8d5a3528 - Fix file prioritizing in a torrent 2010-02-08 18:49:04 +00:00
Christophe Dumez
240c3508fe Fix possible crash when changing torrents label 2010-02-07 18:37:26 +00:00
Christophe Dumez
1065f5fb86 FEATURE: If 2 torrents have the same hash, add new trackers to the existin
g torrent
2010-02-07 14:31:45 +00:00
Christophe Dumez
2b37986007 Updated Spanish/Catalan translations 2010-02-06 21:45:47 +00:00
Christophe Dumez
22d0c4a241 - Fix possible crash when removing a torrent 2010-02-06 21:31:51 +00:00
Christophe Dumez
dd47ce6767 Fix font size of two torrent addition dialog buttons (Patch by Mariusz Fik) 2010-02-05 19:06:11 +00:00
Christophe Dumez
5c80ce42e0 Cosmetic fix to usage display (--help)
Usage display is now localized
2010-02-05 19:02:27 +00:00
Christophe Dumez
adb727d282 Make sure seeding torrents display a progress of 100% 2010-02-04 20:18:58 +00:00
Christophe Dumez
e17ca355ae Startup optimization 2010-02-04 19:16:04 +00:00
Christophe Dumez
b80940ac4f - Optimize startup speed (do not resave fastresume data for torrents that were seeded in the previous session) 2010-02-04 17:19:00 +00:00
Christophe Dumez
1eca139db9 Fix new "Automatically recheck torrents on completion" feature (would keep on rechecking) 2010-02-03 19:44:19 +00:00
Christophe Dumez
25278beb2f Minor code optimization 2010-02-03 19:31:13 +00:00
Christophe Dumez
5922ffff62 Fix to Spanish and catalan translations 2010-02-03 18:55:49 +00:00
Christophe Dumez
ff084e9681 - Fixes to German translation 2010-02-03 07:59:36 +00:00
Christophe Dumez
86e5d219d2 Updated Ukranian translation
Added Oleh Prypin as Ukrainian translator
2010-02-02 20:24:52 +00:00
Christophe Dumez
b78e0a54ed Updated spanish and catalan translations 2010-02-02 20:05:47 +00:00
Christophe Dumez
4bfacb8b91 - Clear torrent errors when starting a torrent 2010-01-31 19:03:34 +00:00
Christophe Dumez
e9ad58a373 Improved application style handling 2010-01-31 17:46:21 +00:00
Christophe Dumez
09c48539ad - COSMETIC: Improved style management 2010-01-31 17:30:17 +00:00
Christophe Dumez
3693ecdd30 Moved peer resolution settings to advanced settings 2010-01-31 16:43:19 +00:00
Christophe Dumez
ddc66e6005 - Cosmetic changes to advanced preferences 2010-01-31 16:34:38 +00:00
Christophe Dumez
fd0b1f8931 - Did not mean to commit that 2010-01-31 16:27:05 +00:00
Christophe Dumez
1a4f638ff6 - Moved "Transfer list refresh interval" to advanced settings 2010-01-31 16:25:04 +00:00
Christophe Dumez
77239db3c5 FEATURE: Torrents can be automatically rechecked on completion 2010-01-31 16:14:56 +00:00
Christophe Dumez
0ea59c8d58 Bump to beta2 2010-01-31 16:00:50 +00:00
Christophe Dumez
54e2a8c7fe - Update language files 2010-01-31 16:00:14 +00:00
Christophe Dumez
245a8e0a3a FEATURE: User can choose to include the protocol overhead in transfer limits 2010-01-31 15:57:07 +00:00
Christophe Dumez
51e474c893 FEATURE: User can choose to apply transfer limits on LAN too 2010-01-31 15:42:24 +00:00
Christophe Dumez
81d3e64518 - Advanced preferences: Property column should not be editable 2010-01-31 15:31:41 +00:00
Christophe Dumez
95da161be3 FEATURE: Outgoing ports range can be customized (for QoS) 2010-01-31 15:27:54 +00:00
Christophe Dumez
8618f13b7a - Created "Advanced settings" tab in program preferences and moved "Disk cache" there 2010-01-31 15:11:15 +00:00
Christophe Dumez
e24e7578f2 Added "Export .torrent files to..." feature to the Web UI
Fix Scan dir preferences in Web UI
2010-01-31 13:47:57 +00:00
Christophe Dumez
a03ad3de23 FEATURE: Torrent files can be exported to a given directory
BUGFIX: Fix crash when double-clicking on a torrent that has no metadata to open its save path
2010-01-31 13:09:46 +00:00
Christophe Dumez
9bd40a9b79 - Updated language files 2010-01-30 18:17:27 +00:00
Christophe Dumez
b4b61b9b7d - Launch directly the new search instead of stopping the current one if the user changed the search pattern 2010-01-30 18:15:25 +00:00
Christophe Dumez
5656fe9a9b FEATURE: Added "Upload/Download limit" columns to transfer list 2010-01-30 17:47:01 +00:00
Christophe Dumez
fb79146ae6 FEATURE: Added "Added/Completed On" columns to transfer list 2010-01-30 16:28:07 +00:00
Christophe Dumez
ba27191b2a - Fix compilation error when geoip database is embedded 2010-01-29 19:01:32 +00:00
Christophe Dumez
dc87aa3d5c - Download thread now supports HTTP redirection 2010-01-29 18:37:47 +00:00
Christophe Dumez
83cf3aebab Clean up URL seed code
Center bandwidth limiting dialogs
2010-01-27 20:34:53 +00:00
Christophe Dumez
dedd9bd03c - Add more RSS and tracker debug 2010-01-27 12:21:14 +00:00
Christophe Dumez
ab36a358b7 - Fix "Append .!qB extension to incomplete files". The extension would stay under certain conditions 2010-01-26 08:02:15 +00:00
Christophe Dumez
6ea97f09cf - Updated spanish and catalan translations 2010-01-25 20:06:22 +00:00
Christophe Dumez
5f7822d202 Fix alternative upload speed limit overwriting standard upload speed limit. 2010-01-25 19:54:46 +00:00
Christophe Dumez
6a87225dd0 - Fix typo in src.pro 2010-01-24 19:19:58 +00:00
Christophe Dumez
b6f56c0812 - Bump to v2.2.0beta1 2010-01-24 18:16:42 +00:00
Christophe Dumez
c4ce2a2549 Improved user friendlyness of size units (Use 1KiB/s instead of 1024B/s)
Optimized transfer list repainting
2010-01-24 18:06:51 +00:00
Christophe Dumez
41650da297 - I should not have to call repaint() manually 2010-01-24 17:16:20 +00:00
Christophe Dumez
74c61e6805 - Fix for translations 2010-01-24 17:03:57 +00:00
Christophe Dumez
e8dd7bbcc9 - Fix possible race condition in RSS that could cause crash on startup (bug #511441) 2010-01-24 16:46:10 +00:00
Christophe Dumez
335d012d55 - Updated a field that should not be translatable 2010-01-24 15:55:55 +00:00
Christophe Dumez
17fc58840a - Updated language files 2010-01-24 15:37:58 +00:00
Christophe Dumez
0e8c55b9f5 FEATURE: Added back file prioritizing in a torrent (it seems users were using it after all) 2010-01-24 15:26:29 +00:00
Christophe Dumez
d581f653c6 Nox compilation fix 2010-01-24 12:07:07 +00:00
Christophe Dumez
48dbaf05ae FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period) 2010-01-24 11:57:15 +00:00
Christophe Dumez
540da69d61 - Remember alternative speeds state on restart 2010-01-23 20:45:14 +00:00
Christophe Dumez
06efd64a80 FEATURE: User can set alternative speed limits for fast toggling
Bandwidth scheduler is not functional yet (but appears in program preferences)
2010-01-23 20:44:09 +00:00
Christophe Dumez
62d872984b Make sure invalid torrent are removed from the transfer list 2010-01-23 19:15:00 +00:00
Christophe Dumez
1dd11dd8f8 Fix possible issue where torrents would not be displayed in the transfer list 2010-01-23 19:01:10 +00:00
Christophe Dumez
2ce375d8eb - Improved date handling in RSS 2010-01-23 16:16:42 +00:00
Christophe Dumez
8ed0e58d63 - "Open destination folder" now opens torrent root folder (if it contains one) instead of the parent folder 2010-01-23 09:54:50 +00:00
Christophe Dumez
660a6929fd Apply patch from Elrond to improve transfer speed display in peers list 2010-01-21 23:59:55 +00:00
Christophe Dumez
44f6c972d4 Moved screenCenter function to misc.h to avoid code duplication
Make sure torrent deletion dialog is now centered on screen
2010-01-21 22:23:13 +00:00
Christophe Dumez
6a6077bf1d Improved previous patch: Force recheck only if we detected that renaming overwrote an existing file 2010-01-21 21:14:54 +00:00
Christophe Dumez
30234a4e78 - Force recheck after renaming files 2010-01-21 20:27:59 +00:00
Christophe Dumez
dc9edf7538 - Fix overwrite check when renaming a folder in a torrent 2010-01-21 18:33:53 +00:00
Christophe Dumez
92574458d0 "Add in pause" setting is no longer ignored if torrent is loaded from a watched directory 2010-01-20 18:53:11 +00:00
Christophe Dumez
c35ef9ad15 - Fix opening on torrent folder in explorer when path contains special characters or spaces 2010-01-20 18:41:12 +00:00
Christophe Dumez
4059bcc0fa Updated Russian translation 2010-01-20 18:38:38 +00:00
Christophe Dumez
1840d1c49f - Paused torrents can now be rechecked 2010-01-20 18:02:26 +00:00
Christophe Dumez
cbd948f6f3 Updated hungarian translation 2010-01-20 16:02:56 +00:00
Christophe Dumez
454c093033 - qBittorrent can now listen on ports < 1024 (must be root) 2010-01-20 09:54:51 +00:00
Christophe Dumez
45eaf7ce58 - Updated Simplified chinese translation (legal notice was missing) 2010-01-20 09:44:45 +00:00
Christophe Dumez
04b7af4df5 - Fix renaming of files with unicode characters 2010-01-20 08:45:31 +00:00
Christophe Dumez
8c6978be82 - Exceptions to "Add Torrent is paused" setting can now be set in torrent addition dialog 2010-01-20 08:35:36 +00:00
Christophe Dumez
6c9e7156f7 - Fix magnet link support 2010-01-19 23:43:29 +00:00
Christophe Dumez
bc89845523 - Improve configure file output 2010-01-19 23:12:13 +00:00
Christophe Dumez
9ffe9c2006 - Configure file now checks for pkg-config executable since it is required to detect libtorrent-rasterbar 2010-01-19 22:55:49 +00:00
Christophe Dumez
1d598d7772 - Nox version should not require libqtxml 2010-01-19 22:40:23 +00:00
Christophe Dumez
7f576ccc82 - Fix folder renaming (would misbehave under certain conditions) 2010-01-19 22:35:54 +00:00
Christophe Dumez
d5da8a6277 - Save torrent file as soon as we get the torrent metadata so that it does not have to be redownloaded on restart 2010-01-19 21:47:53 +00:00
Christophe Dumez
a297204b27 Updated spanish and catalan translations 2010-01-19 09:42:55 +00:00
Christophe Dumez
e0182bb03e - Enabling debug in trunk 2010-01-19 00:32:53 +00:00
Christophe Dumez
ca5bf5e9d7 Removed useless include in project file 2010-01-18 23:52:05 +00:00
Christophe Dumez
5475d730ff - Actual Qt4.4 compilation fix 2010-01-18 22:09:28 +00:00
Christophe Dumez
7796520580 - Attempt to fix compilation with Qt 4.4 2010-01-18 21:46:04 +00:00
Christophe Dumez
340500c351 - Fix compilation warning in nox mode (introduced in v2.2.0alpha) 2010-01-18 21:28:54 +00:00
Christophe Dumez
043d33ff91 - Updated language files 2010-01-18 19:29:02 +00:00
Christophe Dumez
baf991b342 - The user must now press 'y' to accept the legal notice in nox mode (other keys will refuse and stop the program). Thanks Mariusz Fik 2010-01-18 19:20:59 +00:00
Christophe Dumez
dc47e90126 Applied legal notice patch for Mariusz Fik 2010-01-18 19:16:18 +00:00
Christophe Dumez
67e3f9e686 - Trunk is now v2.2.0alpha 2010-01-18 19:14:33 +00:00
259 changed files with 72276 additions and 117313 deletions

14
AUTHORS
View File

@@ -3,11 +3,19 @@ Author:
Contributors:
* Stefanos Antaris <santaris@csd.auth.gr>
* Mohammad Dib <mdib@qbittorrent.org>
* Mirco Chinelli <infinity89@fastwebmail.it>
* Ishan Arora <ishan@qbittorrent.org>
* Arnaud Demaizière <arnaud@qbittorrent.org>
* Grigis Gaëtan <cipher16@gmail.com>
* Christian Kandeler <zambesi@users.sourceforge.net>
* Silvan Scherrer <silvan.scherrer@aroa.ch>
Code from other projects:
* files src/qtsingleapp/* src/lineedit/*
copyright: Nokia Corporation
license: LGPL
* files src/ico.cpp src/ico.h
copyright: Malte Starostik <malte@kde.org>
license: LGPL
@@ -59,11 +67,13 @@ Images Authors:
Translations authors:
* files: src/lang/*.ts
copyright:
- Arabic: SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)
- Brazilian: Nick Marinho (nickmarinho@gmail.com)
- Bulgarian: Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)
- Bulgarian: Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)
- Catalan: Francisco Luque Contreras (frannoe@ya.com)
- Chinese (Simplified): Guo Yue (yue.guo0418@gmail.com)
- Chinese (Traditional): Yi-Shun Wang (dnextstep@gmail.com)
- Croatian: Oliver Mucafir (oliver.untwist@gmail.com)
- Czech: Jirka Vilim (web@tets.cz)
- Danish: Mathias Nielsen (comoneo@gmail.com)
- Dutch: Joost Schipper (heavyjoost@users.sourceforge.net)
@@ -86,5 +96,5 @@ Translations authors:
- Spanish: Francisco Luque Contreras (frannoe@ya.com)
- Swedish: Daniel Nylander (po@danielnylander.se)
- Turkish: Hasan Yilmaz (iletisim@hedefturkce.com)
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net)
- Ukrainian: Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)
license: GPLv2

137
Changelog
View File

@@ -1,17 +1,126 @@
* Wed Jan 20 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.1
- BUGFIX: Fix compilation with Qt4.4
- BUGFIX: Save torrent metadata so that it does not have to be re-downloaded on restart (Magnet links)
- BUGFIX: Fix folder renaming in a torrent (would rename children under certain conditions)
- BUGFIX: Nox version no longer requires libQtXml
- BUGFIX: Configure file now checks for pkg-config executable which is required
- BUGFIX: Torrents added from magnet links were not remembered on restart
- BUGFIX: "Add in pause" setting can be ignored from torrent addition dialog
- BUGFIX: Fix renaming of files with unicode characters in their name
- BUGFIX: Fix typo in legal notice (startup)
- BUGFIX: Can listen on ports < 1024 (must be root)
- BUGFIX: Paused torrents can now be rechecked
- BUGFIX: Fix "open torrent destination" feature when path contains spaces
- I18N: Updated translations (Hungarian, Chinese, Russian)
* Sun Oct 24 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.8
- BUGFIX: Fix possible crash on manual peer ban
- BUGFIX: Improved hostname resolution code
- BUGFIX: Several search plugins fixed
- BUGFIX: Auto-disable the shutdown feature
- BUGFIX: Remember the current property tab on startup
- BUGFIX: Fix status list widget height issue on style change
- BUGFIX: Fix rounding issue in torrent progress display
- BUGFIX: Fix issue when altering files priorities of a seeding torrent
- BUGFIX: Better fix for save path editing issues in torrent addition dialog
- BUGFIX: Peers can now be sorted by country
* Tue Oct 19 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.7
- BUGFIX: Display the priority column when the queueing system gets enabled
- BUGFIX: Fix encoding problem in file renaming
- BUGFIX: Delete uneeded files on torrent "soft" deletion
- BUGFIX: Fix issues when marking a file as 'not downloaded' causes the torrent to complete
- BUGFIX: Improved "Set Location" and "Change save path" dialogs
- BUGFIX: Fix display of queued seeding torrents
* Sun Oct 17 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.6
- BUGFIX: Fix "torrent seeding after creation" feature
- BUGFIX: The properties panel data would sometimes not match the selected torrent
- BUGFIX: Fix detection of files at final destination when temp dir is used
- BUGFIX: Fix moving of a torrent to an unexisting directory
* Tue Oct 12 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.5
- BUGFIX: Remember torrent completion date correctly
- BUGFIX: Fix feature to keep incomplete torrents in a separate folder
- BUGFIX: Fix display of URL seeds in the UI
- BUGFIX: Improved peer hostname resolution with caching
- BUGFIX: Piece availability/downloaded widgets performance improvement
* Fri Oct 1 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.4
- BUGFIX: Clean program exit on system shutdown/logout
- BUGFIX: Fix possible search engine plugin update
* Tue Sep 28 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.3
- BUGFIX: Fix encoding issue in command line parameters processing
- BUGFIX: Fix possible crash when changing the save path in addition dialog
- BUGFIX: Fix wrong mapping to source model
* Sun Sep 26 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.2
- BUGFIX: Fix display of torrent content in addition dialog
- BUGFIX: Really fix manual editing of save path in torrent addition dialog
* Sun Sep 26 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.1
- I18N: Updated Arabic translation
- I18N: Fixes to German translation
- BUGFIX: Save path can now be edited in torrent addition dialog
- BUGFIX: Fix save path encoding on non-utf8 systems
- BUGFIX: Fix saving to drive root on Windows
- BUGFIX: OGV can now be previewed
- BUGFIX: Maximum download limit is now 10MB/s
- BUGFIX: Fix 'download in scan dir' persistence
- BUGFIX: Add .torrent extension only when missing (torrent creator)
- BUGFIX: Fix possible issue with temporary download path persistence
- BUGFIX: Added support for | (OR) operator in RSS feed downloader
- BUGFIX: Fix Web UI for spanish users
- BUGFIX: Fix locale switching from Web UI
- BUGFIX: Use AND operator for torrentdownloads.net searches
- BUGFIX: Limit torrent addition dialog width to fit the screen
- COSMETIC: Fix progress bars style on Windows
* Tue Aug 24 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.4.0
- FEATURE: Added actions to "Move to top/bottom" of priority queue
- FEATURE: Auto-Shutdown on downloads completion
- FEATURE: Email notification on download completion
- FEATURE: Added button to password-lock the UI
- FEATURE: Added label-level Pause/Resume/Delete actions
- FEATURE: Torrents can now be filtered by name
- FEATURE: Run external program on torrent completion
- FEATURE: Detect executable updates in order to advise the user to restart
* Tue Jul 27 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.3.0
- FEATURE: Simplified torrent root folder renaming/truncating (< v2.3.0 is no longer forward compatible)
- FEATURE: Remember previous save paths in torrent addition dialog
- FEATURE: Max number of half-open connections can now be edited
- FEATURE: Added support for strict super seeding
- FEATURE: The user can force listening on a particular network interface
- FEATURE: Added cookie support for RSS feeds
- FEATURE: User can force tracker reannounce
- FEATURE: Added "No action" setting for double-click action
- FEATURE: Several torrents can be moved at once
- FEATURE: Added error state for torrents (error is displayed in a tooltip)
- FEATURE: Added filter for paused/error torrents
- FEATURE: Add Check/Uncheck all feature in Web UI
- FEATURE: Search engine can now be disabled
- FEATURE: Torrents can be automatically paused once they reach a given ratio
- FEATURE: Several files can now be disabled at once
- FEATURE: Added "Select All/None" buttons to files list
- FEATURE: Added support for BitComet links (bc://bt/...)
- BUGFIX: Hide seeding torrents files priorities in Web UI
- BUGFIX: The user can disable permanently recursive torrent download
- BUGFIX: Peer Exchange status is now correctly reported
- BUGFIX: Use an INI file instead of the registry on Windows (More reliable)
- BUGFIX: Removed client spoofing feature to avoid tracker blacklisting
- COSMETIC: Display peers country name in tooltip
- COSMETIC: Display number of torrents in transfers tab label
- COSMETIC: Simplified program preferences
- COSMETIC: Fix naming of actions opening new dialogs (use Name...)
* Sun Mar 14 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.2.0
- FEATURE: User can set alternative speed limits for fast toggling
- FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period)
- FEATURE: Added "Added/Completed On" columns to transfer list
- FEATURE: Added "Upload/Download limit" columns to transfer list
- FEATURE: Torrent files can be exported to a given directory
- FEATURE: Outgoing ports range can be customized (for QoS)
- FEATURE: User can choose to apply transfer limits on LAN too
- FEATURE: User can choose to include the protocol overhead in transfer limits
- FEATURE: Torrents can be automatically rechecked on completion
- FEATURE: If 2 torrents have the same hash, add new trackers/URL seeds to the existing torrent
- FEATURE: Trackers can be added from Web UI
- FEATURE: Global transfer information are displayed in the new Web UI status bar
- FEATURE: Allow to change the priority of several files at once
- FEATURE: Support for multiple scan folders (Patch by Christian Kandeler)
- BUGFIX: Only one log window can be opened at a time
- BUGFIX: Optimized RSS module memory usage
- BUGFIX: Consider HTTP downloads >1MB as invalid .torrent files and abort
- BUGFIX: Fix Web UI authentication with some browsers
- BUGFIX: Set Web UI ban period to 1 hour
- COSMETIC: Improved style management
* Mon Jan 18 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.0
- FEATURE: Graphical User Interface can be disabled at compilation time (headless running)

View File

@@ -14,11 +14,13 @@ qBittorrent - A BitTorrent client in C++ / Qt4
- pkg-config executable
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, >= v0.15.0 ADVISED)
- libtorrent-rasterbar by Arvid Norberg (>= 0.14.4 REQUIRED, compatible with v0.15.x)
-> http://www.libtorrent.net
Be careful: another library (the one used by rTorrent) uses a similar name.
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
- libboost 1.34.x (libboost-filesystem, libboost-thread, libboost-date-time) + libasio
or
- libboost >= 1.35.x (libboost-system, libboost-filesystem, libboost-thread, libboost-date-time)
- python >= 2.3 (needed by search engine)
* Run time only dependency

62
README.os2 Normal file
View File

@@ -0,0 +1,62 @@
qBittorrent - A BitTorrent client in Qt4
------------------------------------------
This is the eComStation (OS/2) qBittorrent part of the readme. See also README for more general information.
Building qBittorrent
********************
Requirements
============
- gcc based build env (recommended gcc v4.4.2 or greater)
- Qt4 for eCS (OS/2) dev package (see http://svn.netlabs.org/qt4 for more information)
- libtorrent-rasterbar for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information)
- boost for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information)
How to build
============
First you need to create the conf.pri file in the same dir as this readme.os2 is.
the conf.pri file has the following content:
##### conf.pri content beginn #####
PREFIX = .
BINDIR = ./bin
INCDIR = ./include
LIBDIR = ./lib
DATADIR = ./share
CONFIG += staticlib
INCLUDEPATH += x:/trees/libtorrent/trunk/include
LIBS += -Lx:/trees/libtorrent/trunk/src/.libs \
-Lx:/trees/boost/trunk/stage/lib \
-Lx:/trees/openssl \
-Lx:/extras/lib
##### conf.pri content end #####
Of course all the above path references have to be adjusted to your build env.
It should now be easy to build qBittorrent:
Simply type:
$ qmake
Followed by:
$ make
If all works fine you should get a working qbittorrent executable.
If you have any question regarding the eCS (OS/2) port of qBittorrent you can meet me (_diver) on IRC:
#netlabs on irc.freenode.net
------------------------------------------
Silvan Scherrer <silvan.scherrer@aroa.ch>

166
configure vendored
View File

@@ -18,14 +18,24 @@ Main options:
--help This help text.
Dependency options:
--disable-gui Disable qBittorrent Graphical user
interface for headless running
--with-libboost-inc=[path] Path to libboost include files
--disable-libnotify Disable use of libnotify
--disable-geoip-database Disable use of geoip-database
--with-geoip-database-embedded Geoip Database will be embedded in
qBittorrent executable (please follow
instructions in src/geoip/README)
--disable-gui Disable qBittorrent
Graphical user interface for
headless running
--with-libboost-inc=[path] Path to libboost include
files
--with-libboost-lib=[path] Path to libboost library
files
--disable-libnotify Disable use of libnotify
--disable-geoip-database Disable use of geoip-database
--with-geoip-database-embedded Geoip Database will be
embedded in qBittorrent
executable (please follow
instructions in
src/geoip/README)
--disable-qtsingleapplication Disable use of libboost
--with-qtsingleapplication=[system|shipped] Use the shipped
qtsingleapplication library
or the system one
EOT
}
@@ -152,6 +162,11 @@ while [ $# -gt 0 ]; do
shift
;;
--with-libboost-lib=*)
QC_WITH_LIBBOOST_LIB=$optarg
shift
;;
--disable-libnotify)
QC_DISABLE_libnotify="Y"
shift
@@ -167,6 +182,16 @@ while [ $# -gt 0 ]; do
shift
;;
--disable-qtsingleapplication)
QC_DISABLE_qtsingleapplication="Y"
shift
;;
--with-qtsingleapplication=*)
QC_WITH_QTSINGLEAPPLICATION=$optarg
shift
;;
--verbose)
QC_VERBOSE="Y"
shift
@@ -190,9 +215,12 @@ echo DATADIR=$DATADIR
echo EX_QTDIR=$EX_QTDIR
echo QC_DISABLE_GUI=$QC_DISABLE_GUI
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
echo QC_WITH_LIBBOOST_LIB=$QC_WITH_LIBBOOST_LIB
echo QC_DISABLE_libnotify=$QC_DISABLE_libnotify
echo QC_DISABLE_geoip_database=$QC_DISABLE_geoip_database
echo QC_WITH_GEOIP_DATABASE_EMBEDDED=$QC_WITH_GEOIP_DATABASE_EMBEDDED
echo QC_DISABLE_qtsingleapplication=$QC_DISABLE_qtsingleapplication
echo QC_WITH_QTSINGLEAPPLICATION=$QC_WITH_QTSINGLEAPPLICATION
echo
fi
@@ -312,11 +340,7 @@ public:
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
conf->addDefine("DISABLE_GUI");
}
if(QT_VERSION >= 0x040500) {
conf->addDefine("QT_4_5");
}
return(QT_VERSION >= 0x040400);
}
};
#line 1 "pkg-config.qcm"
@@ -352,19 +376,15 @@ public:
bool exec(){
QStringList incs;
QString req_ver = "0.14.4";
QString adv_ver = "0.15.0";
QString version, libs, other;
VersionMode mode = VersionMin;
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
return false;
for(int n = 0; n < incs.count(); ++n)
conf->addIncludePath(incs[n]);
if(!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. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
else
conf->addDefine("LIBTORRENT_0_15");
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
conf->addLib("-lcrypto");
}
return true;
}
};
@@ -373,14 +393,39 @@ public:
-----BEGIN QCMOD-----
name: libboost
arg: with-libboost-inc=[path], Path to libboost include files
arg: with-libboost-lib=[path], Path to libboost library files
-----END QCMOD-----
*/
#include <boost/version.hpp>
class qc_libboost : public ConfObj
{
public:
qc_libboost(Conf *c) : ConfObj(c) {}
QString name() const { return "libboost"; }
QString shortname() const { return "libboost"; }
QString findBoostLib(QString path, QString lib) const {
QString name;
QDir libDir(path);
QStringList filters;
filters << "libboost_"+lib+"*-mt*.so";
QStringList result = libDir.entryList(filters, QDir::Files);
if(!result.empty()) {
name = result.first().mid(3);
// Remove .so
name.chop(3);
} else {
// Fall back to non -mt boost lib
filters.clear();
filters << "libboost_"+lib+"*.so";
result = libDir.entryList(filters, QDir::Files);
if(!result.empty()) {
name = result.first().mid(3);
// Remove .so
name.chop(3);
}
}
return name;
}
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBBOOST_INC");
@@ -422,6 +467,43 @@ public:
}
}
conf->addIncludePath(s);
// Find library
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
QStringList required_libs;
#if BOOST_VERSION >= 103500
required_libs << "system";
#endif
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
// Not required by nox
required_libs << "filesystem" << "thread";
}
QStringList libDirs;
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
foreach(const QString& lib, required_libs) {
if(!s.isEmpty()) {
QString detected_name = findBoostLib(s, lib);
if(detected_name.isEmpty()) {
printf("Could not find boost %s library!\n", qPrintable(lib));
return false;
} else {
conf->addLib("-l"+detected_name);
}
} else {
bool found = false;
foreach(const QString& libDir, libDirs) {
QString detected_name = findBoostLib(libDir, lib);
if(!detected_name.isEmpty()) {
conf->addLib("-l"+detected_name);
found = true;
break;
}
}
if(!found) {
printf("Could not find boost %s library!\n", qPrintable(lib));
return false;
}
}
}
return true;
}
};
@@ -468,10 +550,21 @@ public:
} else {
return false;
}
QStringList incs3;
QString req_ver3 = "2.0";
QString version3, libs3, other3;
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
for(int n = 0; n < incs3.count(); ++n)
conf->addIncludePath(incs3[n]);
if(!libs3.isEmpty())
conf->addLib(libs3);
} else {
return false;
}
} else {
return false;
}
return true;
}
};
@@ -513,6 +606,33 @@ public:
#endif
}
};
#line 1 "qtsingleapplication.qcm"
/*
-----BEGIN QCMOD-----
name: libboost
arg: with-qtsingleapplication=[system|shipped], Use the shipped qtsingleapplication library or the system one
-----END QCMOD-----
*/
class qc_qtsingleapplication : public ConfObj
{
public:
qc_qtsingleapplication(Conf *c) : ConfObj(c) {}
QString name() const { return "qtsingleapplication library"; }
QString shortname() const { return "qtsingleapplication"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_QTSINGLEAPPLICATION");
if(s.compare("system", Qt::CaseInsensitive) == 0) {
// System
conf->addDefine("USE_SYSTEM_QTSINGLEAPPLICATION");
printf(" [system] ");
} else {
printf(" [shipped] ");
}
return true;
}
};
EOT
cat >$1/modules_new.cpp <<EOT
@@ -534,6 +654,9 @@ cat >$1/modules_new.cpp <<EOT
o = new qc_geoip_database(conf);
o->required = false;
o->disabled = false;
o = new qc_qtsingleapplication(conf);
o->required = false;
o->disabled = false;
EOT
cat >$1/conf4.h <<EOT
@@ -1481,9 +1604,12 @@ export DATADIR
export EX_QTDIR
export QC_DISABLE_GUI
export QC_WITH_LIBBOOST_INC
export QC_WITH_LIBBOOST_LIB
export QC_DISABLE_libnotify
export QC_DISABLE_geoip_database
export QC_WITH_GEOIP_DATABASE_EMBEDDED
export QC_DISABLE_qtsingleapplication
export QC_WITH_QTSINGLEAPPLICATION
export QC_VERBOSE
rm -rf .qconftemp
(

View File

@@ -19,4 +19,6 @@
</dep>
<dep type='geoip-database'>
</dep>
<dep type='qtsingleapplication'>
</dep>
</qconf>

View File

@@ -2,14 +2,39 @@
-----BEGIN QCMOD-----
name: libboost
arg: with-libboost-inc=[path], Path to libboost include files
arg: with-libboost-lib=[path], Path to libboost library files
-----END QCMOD-----
*/
#include <boost/version.hpp>
class qc_libboost : public ConfObj
{
public:
qc_libboost(Conf *c) : ConfObj(c) {}
QString name() const { return "libboost"; }
QString shortname() const { return "libboost"; }
QString findBoostLib(QString path, QString lib) const {
QString name;
QDir libDir(path);
QStringList filters;
filters << "libboost_"+lib+"*-mt*.so";
QStringList result = libDir.entryList(filters, QDir::Files);
if(!result.empty()) {
name = result.first().mid(3);
// Remove .so
name.chop(3);
} else {
// Fall back to non -mt boost lib
filters.clear();
filters << "libboost_"+lib+"*.so";
result = libDir.entryList(filters, QDir::Files);
if(!result.empty()) {
name = result.first().mid(3);
// Remove .so
name.chop(3);
}
}
return name;
}
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBBOOST_INC");
@@ -51,6 +76,43 @@ public:
}
}
conf->addIncludePath(s);
// Find library
s = conf->getenv("QC_WITH_LIBBOOST_LIB");
QStringList required_libs;
#if BOOST_VERSION >= 103500
required_libs << "system";
#endif
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
// Not required by nox
required_libs << "filesystem" << "thread";
}
QStringList libDirs;
libDirs << "/usr/lib/" << "/usr/lib64/" << "/usr/local/lib/" << "/usr/local/lib64/";
foreach(const QString& lib, required_libs) {
if(!s.isEmpty()) {
QString detected_name = findBoostLib(s, lib);
if(detected_name.isEmpty()) {
printf("Could not find boost %s library!\n", qPrintable(lib));
return false;
} else {
conf->addLib("-l"+detected_name);
}
} else {
bool found = false;
foreach(const QString& libDir, libDirs) {
QString detected_name = findBoostLib(libDir, lib);
if(!detected_name.isEmpty()) {
conf->addLib("-l"+detected_name);
found = true;
break;
}
}
if(!found) {
printf("Could not find boost %s library!\n", qPrintable(lib));
return false;
}
}
}
return true;
}
};

View File

@@ -40,10 +40,21 @@ public:
} else {
return false;
}
QStringList incs3;
QString req_ver3 = "2.0";
QString version3, libs3, other3;
if(conf->findPkgConfig("gtk+-2.0", mode, req_ver3, &version3, &incs3, &libs3, &other3)) {
for(int n = 0; n < incs3.count(); ++n)
conf->addIncludePath(incs3[n]);
if(!libs3.isEmpty())
conf->addLib(libs3);
} else {
return false;
}
} else {
return false;
}
return true;
}
};

View File

@@ -13,19 +13,15 @@ public:
bool exec(){
QStringList incs;
QString req_ver = "0.14.4";
QString adv_ver = "0.15.0";
QString version, libs, other;
VersionMode mode = VersionMin;
if(!conf->findPkgConfig("libtorrent-rasterbar", mode, req_ver, &version, &incs, &libs, &other))
return false;
for(int n = 0; n < incs.count(); ++n)
conf->addIncludePath(incs[n]);
if(!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. Some feature will be disabled because they require v%s.\n", version.toLocal8Bit().data(), adv_ver.toUtf8().data());
else
conf->addDefine("LIBTORRENT_0_15");
if(conf->getenv("QC_DISABLE_GUI").isEmpty()) {
conf->addLib("-lcrypto");
}
return true;
}
};

View File

@@ -15,10 +15,6 @@ public:
if(!conf->getenv("QC_DISABLE_GUI").isEmpty()) {
conf->addDefine("DISABLE_GUI");
}
if(QT_VERSION >= 0x040500) {
conf->addDefine("QT_4_5");
}
return(QT_VERSION >= 0x040400);
}
};

View File

@@ -0,0 +1,26 @@
/*
-----BEGIN QCMOD-----
name: libboost
arg: with-qtsingleapplication=[system|shipped], Use the shipped qtsingleapplication library or the system one
-----END QCMOD-----
*/
class qc_qtsingleapplication : public ConfObj
{
public:
qc_qtsingleapplication(Conf *c) : ConfObj(c) {}
QString name() const { return "qtsingleapplication library"; }
QString shortname() const { return "qtsingleapplication"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_QTSINGLEAPPLICATION");
if(s.compare("system", Qt::CaseInsensitive) == 0) {
// System
conf->addDefine("USE_SYSTEM_QTSINGLEAPPLICATION");
printf(" [system] ");
} else {
printf(" [shipped] ");
}
return true;
}
};

File diff suppressed because it is too large Load Diff

133
src/GUI.h
View File

@@ -37,13 +37,10 @@
#include "ui_mainwindow.h"
#include "qtorrenthandle.h"
enum TabIndex{TAB_TRANSFER, TAB_SEARCH, TAB_RSS};
class Bittorrent;
class QTimer;
class downloadFromURL;
class SearchEngine;
class QLocalServer;
class QCloseEvent;
class RSSImp;
class QShortcut;
@@ -55,43 +52,35 @@ class TransferListFiltersWidget;
class QSplitter;
class PropertiesWidget;
class StatusBar;
class consoleDlg;
class about;
class createtorrent;
class downloadFromURL;
class HidableTabWidget;
class LineEdit;
class QFileSystemWatcher;
class GUI : public QMainWindow, private Ui::MainWindow{
Q_OBJECT
private:
// Bittorrent
Bittorrent *BTSession;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
// GUI related
QTimer *guiUpdater;
QTabWidget *tabs;
StatusBar *status_bar;
QPointer<options_imp> options;
QPointer<QSystemTrayIcon> systrayIcon;
QPointer<QTimer> systrayCreator;
QMenu *myTrayIconMenu;
TransferListWidget *transferList;
TransferListFiltersWidget *transferListFilters;
PropertiesWidget *properties;
bool displaySpeedInTitle;
bool force_exit;
// Keyboard shortcuts
QShortcut *switchSearchShortcut;
QShortcut *switchSearchShortcut2;
QShortcut *switchTransferShortcut;
QShortcut *switchRSSShortcut;
// Widgets
QAction *prioSeparator;
QAction *prioSeparator2;
QSplitter *hSplitter;
QSplitter *vSplitter;
// Search
SearchEngine *searchEngine;
// RSS
QPointer<RSSImp> rssWidget;
// Misc
QLocalServer *localServer;
public:
// Construct / Destruct
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
~GUI();
// Methods
QWidget* getCurrentTabWidget() const;
TransferListWidget* getTransferList() const { return transferList; }
QMenu* getTrayIconMenu();
PropertiesWidget *getProperties() const { return properties; }
public slots:
void trackerAuthenticationRequired(QTorrentHandle& h);
void setTabText(int index, QString text) const;
void showNotificationBaloon(QString title, QString msg) const;
void downloadFromURLList(const QStringList& urls);
void updateAltSpeedsBtn(bool alternative);
void updateNbTorrents(unsigned int nb_downloading, unsigned int nb_seeding, unsigned int nb_active, unsigned int nb_inactive, unsigned int nb_paused);
void deleteBTSession();
protected slots:
// GUI related slots
@@ -103,8 +92,6 @@ protected slots:
void on_actionWebsite_triggered() const;
void on_actionBugReport_triggered() const;
void on_actionShow_console_triggered();
void readParamsOnSocket();
void acceptConnection();
void balloonClicked();
void writeSettings();
void readSettings();
@@ -114,6 +101,10 @@ protected slots:
void handleDownloadFromUrlFailure(QString, QString) const;
void createSystrayDelayed();
void tab_changed(int);
void on_actionLock_qBittorrent_triggered();
void defineUILockPassword();
bool unlockUI();
void notifyOfUpdate(QString);
// Keyboard shortcuts
void createKeyboardShortcuts();
void displayTransferTab() const;
@@ -126,38 +117,72 @@ protected slots:
void on_actionOpen_triggered();
void updateGUI();
void loadPreferences(bool configure_session=true);
void processParams(const QString& params);
void processParams(const QStringList& params);
void addTorrent(QString path);
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
void addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker);
void processDownloadedFiles(QString path, QString url);
void finishedTorrent(QTorrentHandle& h) const;
void askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h);
// Options slots
void on_actionOptions_triggered();
void optionsSaved();
// HTTP slots
void on_actionDownload_from_URL_triggered();
public slots:
void trackerAuthenticationRequired(QTorrentHandle& h);
void setTabText(int index, QString text) const;
void showNotificationBaloon(QString title, QString msg) const;
void downloadFromURLList(const QStringList& urls);
protected:
void closeEvent(QCloseEvent *);
void showEvent(QShowEvent *);
bool event(QEvent * event);
void displayRSSTab(bool enable);
void displaySearchTab(bool enable);
public:
// Construct / Destruct
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
~GUI();
// Methods
int getCurrentTabIndex() const;
QPoint screenCenter() const;
TransferListWidget* getTransferList() const { return transferList; }
private:
QFileSystemWatcher *executable_watcher;
// Bittorrent
Bittorrent *BTSession;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers; // Still needed?
// GUI related
QTimer *guiUpdater;
HidableTabWidget *tabs;
StatusBar *status_bar;
QPointer<options_imp> options;
QPointer<consoleDlg> console;
QPointer<about> aboutDlg;
QPointer<createtorrent> createTorrentDlg;
QPointer<downloadFromURL> downloadFromURLDialog;
QPointer<QSystemTrayIcon> systrayIcon;
QPointer<QTimer> systrayCreator;
QPointer<QMenu> myTrayIconMenu;
TransferListWidget *transferList;
TransferListFiltersWidget *transferListFilters;
PropertiesWidget *properties;
bool displaySpeedInTitle;
bool force_exit;
bool ui_locked;
LineEdit *search_filter;
// Keyboard shortcuts
QShortcut *switchSearchShortcut;
QShortcut *switchSearchShortcut2;
QShortcut *switchTransferShortcut;
QShortcut *switchRSSShortcut;
// Widgets
QAction *prioSeparator;
QAction *prioSeparator2;
QSplitter *hSplitter;
QSplitter *vSplitter;
QMenu *lockMenu;
// Search
QPointer<SearchEngine> searchEngine;
// RSS
QPointer<RSSImp> rssWidget;
private slots:
void on_actionSearch_engine_triggered();
void on_actionRSS_Reader_triggered();
void on_actionSpeed_in_title_bar_triggered();
void on_actionTop_tool_bar_triggered();
void on_actionShutdown_when_downloads_complete_triggered();
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

BIN
src/Icons/L.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/Icons/oxygen/gear32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

BIN
src/Icons/oxygen/go-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

BIN
src/Icons/oxygen/go-up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

View File

@@ -1,8 +1,9 @@
[Desktop Entry]
Categories=Qt;Network;P2P;
Comment=V2.1.1
Comment=V2.4.8
Exec=qbittorrent %f
GenericName=Bittorrent client
GenericName[ar]=العميل Bittorrent
GenericName[bg]=Торент клиент
GenericName[cs]=Bittorrent klient
GenericName[de]=Bittorren Client
@@ -10,6 +11,7 @@ GenericName[el]=Bittorrent πελάτης
GenericName[es]=Cliente Bittorrent
GenericName[fi]=Bittorrent-ohjelma
GenericName[fr]=Client Bittorrent
GenericName[hr]=Bittorrent klijent
GenericName[hu]=Bittorrent kliens
GenericName[it]=Client Bittorrent
GenericName[ja]=Bittorrent クライアント

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

BIN
src/Icons/slow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/Icons/slow_off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

60
src/Info.plist Normal file
View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>torrent</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>qBitTorrentDocument</string>
<key>CFBundleTypeName</key>
<string>BitTorrent Document</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/x-bittorrent</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>org.bittorrent.torrent</string>
</array>
<key>LSIsAppleDefaultForType</key>
<true/>
</dict>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>magnet</string>
</array>
<key>CFBundleURLName</key>
<string>BitTorrent Magnet URL</string>
</dict>
</array>
<key>CFBundleIconFile</key>
<string>qbittorrent_mac.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleGetInfoString</key>
<string>2.4.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleExecutable</key>
<string>qbittorrent</string>
<key>CFBundleIdentifier</key>
<string>org.qbittorrent</string>
<key>NOTE</key>
<string>This file was generated by Qt/QMake.</string>
</dict>
</plist>

6
src/about.qrc Normal file
View File

@@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>gpl.html</file>
</qresource>
</RCC>

View File

@@ -32,7 +32,7 @@
#define ABOUT_H
#include "ui_about.h"
#include <QScrollBar>
#include <QFile>
class about : public QDialog, private Ui::AboutDlg{
Q_OBJECT
@@ -47,399 +47,56 @@ class about : public QDialog, private Ui::AboutDlg{
setAttribute(Qt::WA_DeleteOnClose);
// Set icons
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")));
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/mascot.png")));
//Title
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
// Thanks
te_thanks->append(QString::fromUtf8("<a name='top'></a>"));
te_thanks->append(QString::fromUtf8("<ul><li>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</li>"));
te_thanks->append(QString::fromUtf8("<li>I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</li>"));
te_thanks->append(QString::fromUtf8("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, for his help and support since the beginning of this project.</li>"));
te_thanks->append(QString::fromUtf8("<li>I am grateful to Peter Koeleman (peter@qbittorrent.org) for working on qBittorrent port to Windows.</li>"));
te_thanks->append(QString::fromUtf8("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul><br><br>"));
te_thanks->scrollToAnchor(QString::fromUtf8("top"));
QString thanks_txt;
thanks_txt += QString::fromUtf8("<p>I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</p>");
thanks_txt += QString::fromUtf8("<p>I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</p>");
thanks_txt += QString::fromUtf8("<p>I also want to thank Στέφανος Αντάρης (santaris@csd.auth.gr) and Mirco Chinelli (infinity89@fastwebmail.it) for working on Mac OS X packaging.</p>");
thanks_txt += QString::fromUtf8("<p>I am grateful to Peter Koeleman (peter@qbittorrent.org) and Mohammad Dib (mdib@qbittorrent.org) for working on qBittorrent port to Windows.</p>");
thanks_txt += QString::fromUtf8("<p>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</p>");
te_thanks->setHtml(thanks_txt);
// Translation
te_translation->append(QString::fromUtf8("<a name='top'></a>"));
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+QString::fromUtf8("<br>"));
te_translation->append(QString::fromUtf8(
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
- <u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)<br>\
- <u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)<br>\
- <u>Czech:</u> Jirka Vilim (web@tets.cz)<br>\
- <u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)<br>\
- <u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net) and Peter Koeleman (peter@peerweb.nl)<br>\
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)<br>\
- <u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)<br>\
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)<br>\
- <u>Italian:</u> Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
- <u>Japanese:</u> Nardog (alphisation@gmail.com)<br>\
- <u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)<br>\
- <u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)<br>\
- <u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)<br>\
- <u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
- <u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)<br>\
- <u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)<br>\
- <u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)<br>\
- <u>Slovak:</u> helix84<br>\
- <u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)<br>\
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
- <u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)<br>\
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net)<br><br>"));
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
te_translation->scrollToAnchor(QString::fromUtf8("top"));
QString trans_txt = "<p>"+tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"</p>";
trans_txt += QString::fromUtf8("<ul><li><u>Arabic:</u> SDERAWI (abz8868@msn.com) and sn51234 (nesseyan@gmail.com)</li>\
<li><u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
<li><u>Bulgarian:</u> Tsvetan & Boyko Bankoff (emerge_life@users.sourceforge.net)</li>\
<li><u>Catalan:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
<li><u>Chinese (Simplified):</u> Guo Yue (yue.guo0418@gmail.com)</li>\
<li><u>Chinese (Traditional):</u> Yi-Shun Wang (dnextstep@gmail.com)</li>\
<li><u>Croatian:</u> Oliver Mucafir (oliver.untwist@gmail.com)</li>\
<li><u>Czech:</u> Jirka Vilim (web@tets.cz)</li>\
<li><u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)</li>\
<li><u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net) and Peter Koeleman (peter@peerweb.nl)</li>\
<li><u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net) and Pekka Niemi (pekka.niemi@iki.fi)</li>\
<li><u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)</li>\
<li><u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)</li>\
<li><u>Hungarian:</u> Majoros Péter (majoros.peterj@gmail.com)</li>\
<li><u>Italian:</u> Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)</li>\
<li><u>Japanese:</u> Nardog (alphisation@gmail.com)</li>\
<li><u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)</li>\
<li><u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)</li>\
<li><u>Polish:</u> Mariusz Fik (fisiu@opensuse.org)</li>\
<li><u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)</li>\
<li><u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)</li>\
<li><u>Russian:</u> Nick Khazov (m2k3d0n@users.sourceforge.net) and Alexey Morsov (samurai@ricom.ru)</li>\
<li><u>Serbian:</u> Anaximandar Milet (anaximandar@operamail.com)</li>\
<li><u>Slovak:</u> helix84</li>\
<li><u>Spanish:</u> Francisco Luque Contreras (frannoe@ya.com)</li>\
<li><u>Swedish:</u> Daniel Nylander (po@danielnylander.se)</li>\
<li><u>Turkish:</u> Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)</li>\
<li><u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net) and Oleh Prypin (blaxpirit@gmail.com)</li></ul>");
trans_txt += "<p>"+tr("Please contact me if you would like to translate qBittorrent into your own language.")+"</p>";
te_translation->setHtml(trans_txt);
// License
te_license->append(QString::fromUtf8("<a name='top'></a>"));
te_license->append(QString::fromUtf8("qBittorrent is licensed under the GNU General Public License version 2 with the\
addition of the following special exception:\
<br><br>\
<i>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.</i>\
<br><br>\
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
<center>Version 2, June 1991</center><br>\
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
Everyone is permitted to copy and distribute verbatim copies<br>\
of this license document, but changing it is not allowed.<br>\
<br>\
<center><b>Preamble</b></center><br>\
The licenses for most software are designed to take away your<br>\
freedom to share and change it. By contrast, the GNU General Public<br>\
License is intended to guarantee your freedom to share and change free<br>\
software--to make sure the software is free for all its users. This<br>\
General Public License applies to most of the Free Software<br>\
Foundation's software and to any other program whose authors commit to<br>\
using it. (Some other Free Software Foundation software is covered by<br>\
the GNU Library General Public License instead.) You can apply it to<br>\
your programs, too.<br>\
<br>\
When we speak of free software, we are referring to freedom, not<br>\
price. Our General Public Licenses are designed to make sure that you<br>\
have the freedom to distribute copies of free software (and charge for<br>\
this service if you wish), that you receive source code or can get it<br>\
if you want it, that you can change the software or use pieces of it<br>\
in new free programs; and that you know you can do these things.<br>\
<br>\
To protect your rights, we need to make restrictions that forbid<br>\
anyone to deny you these rights or to ask you to surrender the rights.<br>\
These restrictions translate to certain responsibilities for you if you<br>\
distribute copies of the software, or if you modify it.<br>\
<br>\
For example, if you distribute copies of such a program, whether<br>\
gratis or for a fee, you must give the recipients all the rights that<br>\
you have. You must make sure that they, too, receive or can get the<br>\
source code. And you must show them these terms so they know their<br>\
rights.<br>\
<br>\
We protect your rights with two steps: (1) copyright the software, and<br>\
(2) offer you this license which gives you legal permission to copy,<br>\
distribute and/or modify the software.<br>\
<br>\
Also, for each author's protection and ours, we want to make certain<br>\
that everyone understands that there is no warranty for this free<br>\
software. If the software is modified by someone else and passed on, we<br>\
want its recipients to know that what they have is not the original, so<br>\
that any problems introduced by others will not reflect on the original<br>\
authors' reputations.<br>\
<br>\
Finally, any free program is threatened constantly by software<br>\
patents. We wish to avoid the danger that redistributors of a free<br>\
program will individually obtain patent licenses, in effect making the<br>\
program proprietary. To prevent this, we have made it clear that any<br>\
patent must be licensed for everyone's free use or not licensed at all.<br>\
<br>\
The precise terms and conditions for copying, distribution and<br>\
modification follow.<br>\
<br>\
<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
<center><b>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</b></center><br>\
0. This License applies to any program or other work which contains<br>\
a notice placed by the copyright holder saying it may be distributed<br>\
under the terms of this General Public License. The 'Program', below,<br>\
refers to any such program or work, and a 'work based on the Program'<br>\
means either the Program or any derivative work under copyright law:<br>\
that is to say, a work containing the Program or a portion of it,<br>\
either verbatim or with modifications and/or translated into another<br>\
language. (Hereinafter, translation is included without limitation in<br>\
the term 'modification'.) Each licensee is addressed as 'you'.<br>\
<br>\
Activities other than copying, distribution and modification are not<br>\
covered by this License; they are outside its scope. The act of<br>\
running the Program is not restricted, and the output from the Program<br>\
is covered only if its contents constitute a work based on the<br>\
Program (independent of having been made by running the Program).<br>\
Whether that is true depends on what the Program does.<br>\
<br>\
1. You may copy and distribute verbatim copies of the Program's<br>\
source code as you receive it, in any medium, provided that you<br>\
conspicuously and appropriately publish on each copy an appropriate<br>\
copyright notice and disclaimer of warranty; keep intact all the<br>\
notices that refer to this License and to the absence of any warranty;<br>\
and give any other recipients of the Program a copy of this License<br>\
along with the Program.<br>\
<br>\
You may charge a fee for the physical act of transferring a copy, and<br>\
you may at your option offer warranty protection in exchange for a fee.<br>\
<br>\
2. You may modify your copy or copies of the Program or any portion<br>\
of it, thus forming a work based on the Program, and copy and<br>\
distribute such modifications or work under the terms of Section 1<br>\
above, provided that you also meet all of these conditions:<br>\
<br>\
a) You must cause the modified files to carry prominent notices<br>\
stating that you changed the files and the date of any change.<br>\
<br>\
b) You must cause any work that you distribute or publish, that in<br>\
whole or in part contains or is derived from the Program or any<br>\
part thereof, to be licensed as a whole at no charge to all third<br>\
parties under the terms of this License.<br>\
<br>\
c) If the modified program normally reads commands interactively<br>\
when run, you must cause it, when started running for such<br>\
interactive use in the most ordinary way, to print or display an<br>\
announcement including an appropriate copyright notice and a<br>\
notice that there is no warranty (or else, saying that you provide<br>\
a warranty) and that users may redistribute the program under<br>\
these conditions, and telling the user how to view a copy of this<br>\
License. (Exception: if the Program itself is interactive but<br>\
does not normally print such an announcement, your work based on<br>\
the Program is not required to print an announcement.)<br>\
<br>\
These requirements apply to the modified work as a whole. If<br>\
identifiable sections of that work are not derived from the Program,<br>\
and can be reasonably considered independent and separate works in<br>\
themselves, then this License, and its terms, do not apply to those<br>\
sections when you distribute them as separate works. But when you<br>\
distribute the same sections as part of a whole which is a work based<br>\
on the Program, the distribution of the whole must be on the terms of<br>\
this License, whose permissions for other licensees extend to the<br>\
entire whole, and thus to each and every part regardless of who wrote it.<br>\
<br>\
Thus, it is not the intent of this section to claim rights or contest<br>\
your rights to work written entirely by you; rather, the intent is to<br>\
exercise the right to control the distribution of derivative or<br>\
collective works based on the Program.<br>\
<br>\
In addition, mere aggregation of another work not based on the Program<br>\
with the Program (or with a work based on the Program) on a volume of<br>\
a storage or distribution medium does not bring the other work under<br>\
the scope of this License.<br>\
<br>\
3. You may copy and distribute the Program (or a work based on it,<br>\
under Section 2) in object code or executable form under the terms of<br>\
Sections 1 and 2 above provided that you also do one of the following:<br>\
<br>\
a) Accompany it with the complete corresponding machine-readable<br>\
source code, which must be distributed under the terms of Sections<br>\
1 and 2 above on a medium customarily used for software interchange; or,<br>\
<br>\
b) Accompany it with a written offer, valid for at least three<br>\
years, to give any third party, for a charge no more than your<br>\
cost of physically performing source distribution, a complete<br>\
machine-readable copy of the corresponding source code, to be<br>\
distributed under the terms of Sections 1 and 2 above on a medium<br>\
customarily used for software interchange; or,<br>\
<br>\
c) Accompany it with the information you received as to the offer<br>\
to distribute corresponding source code. (This alternative is<br>\
allowed only for noncommercial distribution and only if you<br>\
received the program in object code or executable form with such<br>\
an offer, in accord with Subsection b above.)<br>\
<br>\
The source code for a work means the preferred form of the work for<br>\
making modifications to it. For an executable work, complete source<br>\
code means all the source code for all modules it contains, plus any<br>\
associated interface definition files, plus the scripts used to<br>\
control compilation and installation of the executable. However, as a<br>\
special exception, the source code distributed need not include<br>\
anything that is normally distributed (in either source or binary<br>\
form) with the major components (compiler, kernel, and so on) of the<br>\
operating system on which the executable runs, unless that component<br>\
itself accompanies the executable.<br>\
<br>\
If distribution of executable or object code is made by offering<br>\
access to copy from a designated place, then offering equivalent<br>\
access to copy the source code from the same place counts as<br>\
distribution of the source code, even though third parties are not<br>\
compelled to copy the source along with the object code.<br>\
<br>\
4. You may not copy, modify, sublicense, or distribute the Program<br>\
except as expressly provided under this License. Any attempt<br>\
otherwise to copy, modify, sublicense or distribute the Program is<br>\
void, and will automatically terminate your rights under this License.<br>\
However, parties who have received copies, or rights, from you under<br>\
this License will not have their licenses terminated so long as such<br>\
parties remain in full compliance.<br>\
<br>\
5. You are not required to accept this License, since you have not<br>\
signed it. However, nothing else grants you permission to modify or<br>\
distribute the Program or its derivative works. These actions are<br>\
prohibited by law if you do not accept this License. Therefore, by<br>\
modifying or distributing the Program (or any work based on the<br>\
Program), you indicate your acceptance of this License to do so, and<br>\
all its terms and conditions for copying, distributing or modifying<br>\
the Program or works based on it.<br>\
<br>\
6. Each time you redistribute the Program (or any work based on the<br>\
Program), the recipient automatically receives a license from the<br>\
original licensor to copy, distribute or modify the Program subject to<br>\
these terms and conditions. You may not impose any further<br>\
restrictions on the recipients' exercise of the rights granted herein.<br>\
You are not responsible for enforcing compliance by third parties to<br>\
this License.<br>\
<br>\
7. If, as a consequence of a court judgment or allegation of patent<br>\
infringement or for any other reason (not limited to patent issues),<br>\
conditions are imposed on you (whether by court order, agreement or<br>\
otherwise) that contradict the conditions of this License, they do not<br>\
excuse you from the conditions of this License. If you cannot<br>\
distribute so as to satisfy simultaneously your obligations under this<br>\
License and any other pertinent obligations, then as a consequence you<br>\
may not distribute the Program at all. For example, if a patent<br>\
license would not permit royalty-free redistribution of the Program by<br>\
all those who receive copies directly or indirectly through you, then<br>\
the only way you could satisfy both it and this License would be to<br>\
refrain entirely from distribution of the Program.<br>\
<br>\
If any portion of this section is held invalid or unenforceable under<br>\
any particular circumstance, the balance of the section is intended to<br>\
apply and the section as a whole is intended to apply in other<br>\
circumstances.<br>\
<br>\
It is not the purpose of this section to induce you to infringe any<br>\
patents or other property right claims or to contest validity of any<br>\
such claims; this section has the sole purpose of protecting the<br>\
integrity of the free software distribution system, which is<br>\
implemented by public license practices. Many people have made<br>\
generous contributions to the wide range of software distributed<br>\
through that system in reliance on consistent application of that<br>\
system; it is up to the author/donor to decide if he or she is willing<br>\
to distribute software through any other system and a licensee cannot<br>\
impose that choice.<br>\
<br>\
This section is intended to make thoroughly clear what is believed to<br>\
be a consequence of the rest of this License.<br>\
<br>\
8. If the distribution and/or use of the Program is restricted in<br>\
certain countries either by patents or by copyrighted interfaces, the<br>\
original copyright holder who places the Program under this License<br>\
may add an explicit geographical distribution limitation excluding<br>\
those countries, so that distribution is permitted only in or among<br>\
countries not thus excluded. In such case, this License incorporates<br>\
the limitation as if written in the body of this License.<br>\
<br>\
9. The Free Software Foundation may publish revised and/or new versions<br>\
of the General Public License from time to time. Such new versions will<br>\
be similar in spirit to the present version, but may differ in detail to<br>\
address new problems or concerns.<br>\
<br>\
Each version is given a distinguishing version number. If the Program<br>\
specifies a version number of this License which applies to it and 'any<br>\
later version', you have the option of following the terms and conditions<br>\
either of that version or of any later version published by the Free<br>\
Software Foundation. If the Program does not specify a version number of<br>\
this License, you may choose any version ever published by the Free Software<br>\
Foundation.<br>\
<br>\
10. If you wish to incorporate parts of the Program into other free<br>\
programs whose distribution conditions are different, write to the author<br>\
to ask for permission. For software which is copyrighted by the Free<br>\
Software Foundation, write to the Free Software Foundation; we sometimes<br>\
make exceptions for this. Our decision will be guided by the two goals<br>\
of preserving the free status of all derivatives of our free software and<br>\
of promoting the sharing and reuse of software generally.<br>\
<br>\
<center><b>NO WARRANTY</b></center><br>\
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY<br>\
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN<br>\
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES<br>\
PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED<br>\
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF<br>\
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS<br>\
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE<br>\
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,<br>\
REPAIR OR CORRECTION.<br>\
<br>\
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING<br>\
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR<br>\
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,<br>\
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING<br>\
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED<br>\
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY<br>\
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER<br>\
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE<br>\
POSSIBILITY OF SUCH DAMAGES.<br>\
<br>\
<center><b>END OF TERMS AND CONDITIONS</b></center><br>\
<center>How to Apply These Terms to Your New Programs</center><br>\
If you develop a new program, and you want it to be of the greatest<br>\
possible use to the public, the best way to achieve this is to make it<br>\
free software which everyone can redistribute and change under these terms.<br>\
<br>\
To do so, attach the following notices to the program. It is safest<br>\
to attach them to the start of each source file to most effectively<br>\
convey the exclusion of warranty; and each file should have at least<br>\
the 'copyright' line and a pointer to where the full notice is found.<br>\
<br>\
<one line to give the program's name and a brief idea of what it does.><br>\
Copyright (C) <year> <name of author><br>\
<br>\
This program is free software; you can redistribute it and/or modify<br>\
it under the terms of the GNU General Public License as published by<br>\
the Free Software Foundation; either version 2 of the License, or<br>\
(at your option) any later version.<br>\
<br>\
This program is distributed in the hope that it will be useful,<br>\
but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\
GNU General Public License for more details.<br>\
<br>\
You should have received a copy of the GNU General Public License<br>\
along with this program; if not, write to the Free Software<br>\
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
<br>\
<br>\
Also add information on how to contact you by electronic and paper mail.<br>\
<br>\
If the program is interactive, make it output a short notice like this<br>\
when it starts in an interactive mode:<br>\
<br>\
Gnomovision version 69, Copyright (C) year name of author<br>\
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.<br>\
This is free software, and you are welcome to redistribute it<br>\
under certain conditions; type `show c' for details.<br>\
<br>\
The hypothetical commands `show w' and `show c' should show the appropriate<br>\
parts of the General Public License. Of course, the commands you use may<br>\
be called something other than `show w' and `show c'; they could even be<br>\
mouse-clicks or menu items--whatever suits your program.<br>\
<br>\
You should also get your employer (if you work as a programmer) or your<br>\
school, if any, to sign a 'copyright disclaimer' for the program, if<br>\
necessary. Here is a sample; alter the names:<br>\
<br>\
Yoyodyne, Inc., hereby disclaims all copyright interest in the program<br>\
`Gnomovision' (which makes passes at compilers) written by James Hacker.<br>\
<br>\
'signature of Ty Coon', 1 April 1989<br>\
Ty Coon, President of Vice<br>\
<br>\
This General Public License does not permit incorporating your program into<br>\
proprietary programs. If your program is a subroutine library, you may<br>\
consider it more useful to permit linking proprietary applications with the<br>\
library. If this is what you want to do, use the GNU Library General<br>\
Public License instead of this License.<br>"));
te_license->scrollToAnchor(QString::fromUtf8("top"));
show();
QFile licensefile(":/gpl.html");
if(licensefile.open(QIODevice::ReadOnly|QIODevice::Text)) {
te_license->setHtml(licensefile.readAll());
licensefile.close();
}
show();
}
};

208
src/advancedsettings.h Normal file
View File

@@ -0,0 +1,208 @@
#ifndef ADVANCEDSETTINGS_H
#define ADVANCEDSETTINGS_H
#include <QTableWidget>
#include <QHeaderView>
#include <QSpinBox>
#include <QCheckBox>
#include <QComboBox>
#include <QNetworkInterface>
#include <libtorrent/version.hpp>
#include "preferences.h"
enum AdvSettingsCols {PROPERTY, VALUE};
enum AdvSettingsRows {DISK_CACHE, OUTGOING_PORT_MIN, OUTGOING_PORT_MAX, IGNORE_LIMIT_LAN, COUNT_OVERHEAD, RECHECK_COMPLETED, LIST_REFRESH, RESOLVE_COUNTRIES, RESOLVE_HOSTS, MAX_HALF_OPEN, SUPER_SEEDING, NETWORK_IFACE, PROGRAM_NOTIFICATIONS };
#define ROW_COUNT 13
class AdvancedSettings: public QTableWidget {
Q_OBJECT
private:
QSpinBox *spin_cache, *outgoing_ports_min, *outgoing_ports_max, *spin_list_refresh, *spin_maxhalfopen;
QCheckBox *cb_ignore_limits_lan, *cb_count_overhead, *cb_recheck_completed, *cb_resolve_countries, *cb_resolve_hosts, *cb_super_seeding, *cb_program_notifications;
QComboBox *combo_iface;
public:
AdvancedSettings(QWidget *parent=0): QTableWidget(parent) {
// Set visual appearance
setEditTriggers(QAbstractItemView::NoEditTriggers);
setAlternatingRowColors(true);
setColumnCount(2);
QStringList header;
header << tr("Property") << tr("Value");
setHorizontalHeaderLabels(header);
setColumnWidth(0, width()/2);
horizontalHeader()->setStretchLastSection(true);
verticalHeader()->setVisible(false);
setRowCount(ROW_COUNT);
// Load settings
loadAdvancedSettings();
}
~AdvancedSettings() {
delete spin_cache;
delete outgoing_ports_min;
delete outgoing_ports_max;
delete cb_ignore_limits_lan;
delete cb_count_overhead;
delete cb_recheck_completed;
delete spin_list_refresh;
delete cb_resolve_countries;
delete cb_resolve_hosts;
delete spin_maxhalfopen;
delete cb_super_seeding;
delete combo_iface;
delete cb_program_notifications;
}
public slots:
void saveAdvancedSettings() {
// Disk write cache
Preferences::setDiskCacheSize(spin_cache->value());
// Outgoing ports
Preferences::setOutgoingPortsMin(outgoing_ports_min->value());
Preferences::setOutgoingPortsMax(outgoing_ports_max->value());
// Ignore limits on LAN
Preferences::ignoreLimitsOnLAN(cb_ignore_limits_lan->isChecked());
// Include protocol overhead in transfer limits
Preferences::includeOverheadInLimits(cb_count_overhead->isChecked());
// Recheck torrents on completion
Preferences::recheckTorrentsOnCompletion(cb_recheck_completed->isChecked());
// Transfer list refresh interval
Preferences::setRefreshInterval(spin_list_refresh->value());
// Peer resolution
Preferences::resolvePeerCountries(cb_resolve_countries->isChecked());
Preferences::resolvePeerHostNames(cb_resolve_hosts->isChecked());
// Max Half-Open connections
Preferences::setMaxHalfOpenConnections(spin_maxhalfopen->value());
#if LIBTORRENT_VERSION_MINOR > 14
// Super seeding
Preferences::enableSuperSeeding(cb_super_seeding->isChecked());
#endif
// Network interface
if(combo_iface->currentIndex() == 0) {
// All interfaces (default)
Preferences::setNetworkInterface(QString::null);
} else {
Preferences::setNetworkInterface(combo_iface->currentText());
}
// Program notification
Preferences::useProgramNotification(cb_program_notifications->isChecked());
}
protected slots:
void loadAdvancedSettings() {
// Disk write cache
setItem(DISK_CACHE, PROPERTY, new QTableWidgetItem(tr("Disk write cache size")));
spin_cache = new QSpinBox();
connect(spin_cache, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
spin_cache->setMinimum(1);
spin_cache->setMaximum(200);
spin_cache->setValue(Preferences::diskCacheSize());
spin_cache->setSuffix(tr(" MiB"));
setCellWidget(DISK_CACHE, VALUE, spin_cache);
// Outgoing port Min
setItem(OUTGOING_PORT_MIN, PROPERTY, new QTableWidgetItem(tr("Outgoing ports (Min) [0: Disabled]")));
outgoing_ports_min = new QSpinBox();
connect(outgoing_ports_min, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
outgoing_ports_min->setMinimum(0);
outgoing_ports_min->setMaximum(65535);
outgoing_ports_min->setValue(Preferences::outgoingPortsMin());
setCellWidget(OUTGOING_PORT_MIN, VALUE, outgoing_ports_min);
// Outgoing port Min
setItem(OUTGOING_PORT_MAX, PROPERTY, new QTableWidgetItem(tr("Outgoing ports (Max) [0: Disabled]")));
outgoing_ports_max = new QSpinBox();
connect(outgoing_ports_max, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
outgoing_ports_max->setMinimum(0);
outgoing_ports_max->setMaximum(65535);
outgoing_ports_max->setValue(Preferences::outgoingPortsMax());
setCellWidget(OUTGOING_PORT_MAX, VALUE, outgoing_ports_max);
// Ignore transfer limits on local network
setItem(IGNORE_LIMIT_LAN, PROPERTY, new QTableWidgetItem(tr("Ignore transfer limits on local network")));
cb_ignore_limits_lan = new QCheckBox();
connect(cb_ignore_limits_lan, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_ignore_limits_lan->setChecked(Preferences::ignoreLimitsOnLAN());
setCellWidget(IGNORE_LIMIT_LAN, VALUE, cb_ignore_limits_lan);
// Consider protocol overhead in transfer limits
setItem(COUNT_OVERHEAD, PROPERTY, new QTableWidgetItem(tr("Include TCP/IP overhead in transfer limits")));
cb_count_overhead = new QCheckBox();
connect(cb_count_overhead, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_count_overhead->setChecked(Preferences::includeOverheadInLimits());
setCellWidget(COUNT_OVERHEAD, VALUE, cb_count_overhead);
// Recheck completed torrents
setItem(RECHECK_COMPLETED, PROPERTY, new QTableWidgetItem(tr("Recheck torrents on completion")));
cb_recheck_completed = new QCheckBox();
connect(cb_recheck_completed, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_recheck_completed->setChecked(Preferences::recheckTorrentsOnCompletion());
setCellWidget(RECHECK_COMPLETED, VALUE, cb_recheck_completed);
// Transfer list refresh interval
setItem(LIST_REFRESH, PROPERTY, new QTableWidgetItem(tr("Transfer list refresh interval")));
spin_list_refresh = new QSpinBox();
connect(spin_list_refresh, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
spin_list_refresh->setMinimum(30);
spin_list_refresh->setMaximum(99999);
spin_list_refresh->setValue(Preferences::getRefreshInterval());
spin_list_refresh->setSuffix(tr(" ms", " milliseconds"));
setCellWidget(LIST_REFRESH, VALUE, spin_list_refresh);
// Resolve Peer countries
setItem(RESOLVE_COUNTRIES, PROPERTY, new QTableWidgetItem(tr("Resolve peer countries (GeoIP)")));
cb_resolve_countries = new QCheckBox();
connect(cb_resolve_countries, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_resolve_countries->setChecked(Preferences::resolvePeerCountries());
setCellWidget(RESOLVE_COUNTRIES, VALUE, cb_resolve_countries);
// Resolve peer hosts
setItem(RESOLVE_HOSTS, PROPERTY, new QTableWidgetItem(tr("Resolve peer host names")));
cb_resolve_hosts = new QCheckBox();
connect(cb_resolve_hosts, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_resolve_hosts->setChecked(Preferences::resolvePeerHostNames());
setCellWidget(RESOLVE_HOSTS, VALUE, cb_resolve_hosts);
// Max Half Open connections
setItem(MAX_HALF_OPEN, PROPERTY, new QTableWidgetItem(tr("Maximum number of half-open connections [0: Disabled]")));
spin_maxhalfopen = new QSpinBox();
connect(spin_maxhalfopen, SIGNAL(valueChanged(int)), this, SLOT(emitSettingsChanged()));
spin_maxhalfopen->setMinimum(0);
spin_maxhalfopen->setMaximum(99999);
spin_maxhalfopen->setValue(Preferences::getMaxHalfOpenConnections());
setCellWidget(MAX_HALF_OPEN, VALUE, spin_maxhalfopen);
// Super seeding
setItem(SUPER_SEEDING, PROPERTY, new QTableWidgetItem(tr("Strict super seeding")));
cb_super_seeding = new QCheckBox();
connect(cb_super_seeding, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
#if LIBTORRENT_VERSION_MINOR > 14
cb_super_seeding->setChecked(Preferences::isSuperSeedingEnabled());
#else
cb_super_seeding->setEnabled(false);
#endif
setCellWidget(SUPER_SEEDING, VALUE, cb_super_seeding);
// Network interface
setItem(NETWORK_IFACE, PROPERTY, new QTableWidgetItem(tr("Network Interface (requires restart)")));
combo_iface = new QComboBox;
combo_iface->addItem(tr("Any interface", "i.e. Any network interface"));
const QString current_iface = Preferences::getNetworkInterface();
int i = 1;
foreach(const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
if(iface.name() == "lo") continue;
combo_iface->addItem(iface.name());
if(!current_iface.isEmpty() && iface.name() == current_iface)
combo_iface->setCurrentIndex(i);
++i;
}
connect(combo_iface, SIGNAL(currentIndexChanged(int)), this, SLOT(emitSettingsChanged()));
setCellWidget(NETWORK_IFACE, VALUE, combo_iface);
// Program notifications
setItem(PROGRAM_NOTIFICATIONS, PROPERTY, new QTableWidgetItem(tr("Display program notification baloons")));
cb_program_notifications = new QCheckBox();
connect(cb_program_notifications, SIGNAL(toggled(bool)), this, SLOT(emitSettingsChanged()));
cb_program_notifications->setChecked(Preferences::useProgramNotification());
setCellWidget(PROGRAM_NOTIFICATIONS, VALUE, cb_program_notifications);
}
void emitSettingsChanged() {
emit settingsChanged();
}
signals:
void settingsChanged();
};
#endif // ADVANCEDSETTINGS_H

111
src/bandwidthscheduler.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef BANDWIDTHSCHEDULER_H
#define BANDWIDTHSCHEDULER_H
#include <QTimer>
#include <QTime>
#include <QDateTime>
#include "preferences.h"
#include <iostream>
class BandwidthScheduler: public QTimer {
Q_OBJECT
private:
bool in_alternative_mode;
public:
BandwidthScheduler(QObject *parent): QTimer(parent), in_alternative_mode(false) {
Q_ASSERT(Preferences::isSchedulerEnabled());
// Signal shot, we call start() again manually
setSingleShot(true);
// Connect Signals/Slots
connect(this, SIGNAL(timeout()), this, SLOT(switchMode()));
}
public slots:
void start() {
Q_ASSERT(Preferences::isSchedulerEnabled());
QTime startAltSpeeds = Preferences::getSchedulerStartTime();
QTime endAltSpeeds = Preferences::getSchedulerEndTime();
if(startAltSpeeds == endAltSpeeds) {
std::cerr << "Error: bandwidth scheduler have the same start time and end time." << std::endl;
std::cerr << "The bandwidth scheduler will be disabled" << std::endl;
stop();
emit switchToAlternativeMode(false);
return;
}
// Determine what the closest QTime is
QTime now = QTime::currentTime();
uint time_to_start = secsTo(now, startAltSpeeds);
uint time_to_end = secsTo(now, endAltSpeeds);
if(time_to_end < time_to_start) {
// We should be in alternative mode
in_alternative_mode = true;
// Start counting
QTimer::start(time_to_end*1000);
} else {
// We should be in normal mode
in_alternative_mode = false;
// Start counting
QTimer::start(time_to_start*1000);
}
// Send signal to notify BTSession
emit switchToAlternativeMode(in_alternative_mode);
}
void switchMode() {
// Get the day this mode was started (either today or yesterday)
QDate current_date = QDateTime::currentDateTime().toLocalTime().date();
int day = current_date.dayOfWeek();
if(in_alternative_mode) {
// It is possible that starttime was yesterday
if(QTime::currentTime().secsTo(Preferences::getSchedulerStartTime()) > 0) {
current_date.addDays(-1); // Go to yesterday
day = current_date.day();
}
}
// Check if the day is in scheduler days
// Notify BTSession only if necessary
switch(Preferences::getSchedulerDays()) {
case EVERY_DAY:
emit switchToAlternativeMode(!in_alternative_mode);
break;
case WEEK_ENDS:
if(day == Qt::Saturday || day == Qt::Sunday)
emit switchToAlternativeMode(!in_alternative_mode);
break;
case WEEK_DAYS:
if(day != Qt::Saturday && day != Qt::Sunday)
emit switchToAlternativeMode(!in_alternative_mode);
break;
default:
// Convert our enum index to Qt enum index
int scheduler_day = ((int)Preferences::getSchedulerDays()) - 2;
if(day == scheduler_day)
emit switchToAlternativeMode(!in_alternative_mode);
break;
}
// Call start again
start();
}
signals:
void switchToAlternativeMode(bool alternative);
private:
// Qt function can return negative values and we
// don't want that
uint secsTo(QTime now, QTime t) {
int diff = now.secsTo(t);
if(diff < 0) {
// 86400 seconds in a day
diff += 86400;
}
Q_ASSERT(diff >= 0);
return diff;
}
};
#endif // BANDWIDTHSCHEDULER_H

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,9 @@
#include <QPalette>
#endif
#include <QPointer>
#include <QTimer>
#include <libtorrent/version.hpp>
#include <libtorrent/session.hpp>
#include <libtorrent/ip_filter.hpp>
#include "qtorrenthandle.h"
@@ -52,16 +54,17 @@ using namespace libtorrent;
class downloadThread;
class QTimer;
class FileSystemWatcher;
class FilterParserThread;
class HttpServer;
class BandwidthScheduler;
class ScanFoldersModel;
class TrackerInfos {
public:
QString name_or_url;
QString last_message;
unsigned long num_peers;
#ifndef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR < 15
bool verified;
uint fail_count;
#endif
@@ -72,13 +75,13 @@ public:
Q_ASSERT(!name_or_url.isEmpty());
last_message = b.last_message;
num_peers = b.num_peers;
#ifndef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR < 15
verified = b.verified;
fail_count = b.fail_count;
#endif
}
TrackerInfos(QString name_or_url): name_or_url(name_or_url), last_message(""), num_peers(0) {
#ifndef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR < 15
fail_count = 0;
verified = false;
#endif
@@ -88,60 +91,6 @@ public:
class Bittorrent : public QObject {
Q_OBJECT
private:
// Bittorrent
session *s;
QPointer<QTimer> timerAlerts;
QMap<QUrl, QString> savepath_fromurl;
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
QStringList torrentsToPausedAfterChecking;
// Ratio
QPointer<QTimer> BigRatioTimer;
// HTTP
QPointer<downloadThread> downloader;
// File System
QPointer<FileSystemWatcher> FSWatcher;
// Console / Log
QStringList consoleMessages;
QStringList peerBanMessages;
// Settings
bool preAllocateAll;
bool addInPause;
float ratio_limit;
bool UPnPEnabled;
bool NATPMPEnabled;
bool LSDEnabled;
bool DHTEnabled;
int current_dht_port;
bool PeXEnabled;
bool queueingEnabled;
bool appendLabelToSavePath;
#ifdef LIBTORRENT_0_15
bool appendqBExtension;
#endif
QString defaultSavePath;
QString defaultTempPath;
// GeoIP
#ifndef DISABLE_GUI
bool resolve_countries;
bool geoipDBLoaded;
#endif
// ETA Computation
QPointer<QTimer> timerETA;
QHash<QString, QList<int> > ETA_samples;
// IP filtering
QPointer<FilterParserThread> filterParser;
QString filterPath;
// Web UI
QPointer<HttpServer> httpServer;
QList<QUrl> url_skippingDlg;
// Fast exit (async)
bool exiting;
protected:
QString getSavePath(QString hash);
bool initWebUi(QString username, QString password, int port);
public:
// Constructor / Destructor
Bittorrent();
@@ -159,6 +108,7 @@ public:
session* getSession() const;
QHash<QString, TrackerInfos> getTrackersInfo(QString hash) const;
bool hasActiveTorrents() const;
bool hasDownloadingTorrents() const;
bool isQueueingEnabled() const;
int getMaximumActiveDownloads() const;
int getMaximumActiveTorrents() const;
@@ -168,13 +118,15 @@ public:
qlonglong getETA(QString hash);
bool useTemporaryFolder() const;
QString getDefaultSavePath() const;
ScanFoldersModel* getScanFoldersModel() const;
bool isPexEnabled() const;
#if LIBTORRENT_VERSION_MINOR < 15
void saveDHTEntry();
#endif
public slots:
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false);
void importOldTorrents();
void applyFormerAttributeFiles(QTorrentHandle h);
void importOldTempData(QString torrent_path);
void loadSessionState();
void saveSessionState();
void downloadFromUrl(QString url);
@@ -182,17 +134,15 @@ public slots:
void startUpTorrents();
session_proxy asyncDeletion();
void recheckTorrent(QString hash);
void useAlternativeSpeedsLimit(bool alternative);
/* Needed by Web UI */
void pauseAllTorrents();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void resumeAllTorrents();
/* End Web UI */
void saveDHTEntry();
void preAllocateAllFiles(bool b);
void saveFastResumeData();
void enableDirectoryScanning(QString scan_dir);
void disableDirectoryScanning();
void enableIPFilter(QString filter);
void disableIPFilter();
void setQueueingEnabled(bool enable);
@@ -205,19 +155,18 @@ public slots:
void setMaxUploadsPerTorrent(int max);
void setDownloadRateLimit(long rate);
void setUploadRateLimit(long rate);
void setGlobalRatio(float ratio);
void setDeleteRatio(float ratio);
void setMaxRatio(float ratio);
void setDHTPort(int dht_port);
void setPeerProxySettings(proxy_settings proxySettings);
void setHTTPProxySettings(proxy_settings proxySettings);
void setSessionSettings(session_settings sessionSettings);
void setPeerProxySettings(const proxy_settings &proxySettings);
void setHTTPProxySettings(const proxy_settings &proxySettings);
void setSessionSettings(const session_settings &sessionSettings);
void startTorrentsInPause(bool b);
void setDefaultTempPath(QString temppath);
void setAppendLabelToSavePath(bool append);
void appendLabelToTorrentSavePath(QTorrentHandle h);
void changeLabelInTorrentSavePath(QTorrentHandle h, QString old_label, QString new_label);
#ifdef LIBTORRENT_0_15
void appendqBextensionToTorrent(QTorrentHandle h, bool append);
void appendLabelToTorrentSavePath(QTorrentHandle &h);
void changeLabelInTorrentSavePath(QTorrentHandle &h, QString old_label, QString new_label);
#if LIBTORRENT_VERSION_MINOR > 14
void appendqBextensionToTorrent(QTorrentHandle &h, bool append);
void setAppendqBExtension(bool append);
#endif
void applyEncryptionSettings(pe_settings se);
@@ -238,12 +187,22 @@ public slots:
void downloadFromURLList(const QStringList& urls);
void configureSession();
void banIP(QString ip);
void recursiveTorrentDownload(const QTorrentHandle &h);
protected:
QString getSavePath(QString hash, bool fromScanDir = false, QString filePath = QString::null, QString root_folder=QString::null);
bool initWebUi(QString username, QString password, int port);
protected slots:
void addTorrentsFromScanFolder(QStringList&);
void readAlerts();
void deleteBigRatios();
void processBigRatios();
void takeETASamples();
void exportTorrentFiles(QString path);
void saveTempFastResumeData();
void sendNotificationEmail(QTorrentHandle h);
void autoRunExternalProgram(QTorrentHandle h, bool async=true);
void cleanUpAutoRunProcess(int);
signals:
void addedTorrent(QTorrentHandle& h);
@@ -261,6 +220,64 @@ signals:
void metadataReceived(QTorrentHandle &h);
void savePathChanged(QTorrentHandle &h);
void newConsoleMessage(QString msg);
void alternativeSpeedsModeChanged(bool alternative);
void recursiveTorrentDownloadPossible(QTorrentHandle &h);
private:
// Bittorrent
session *s;
QPointer<QTimer> timerAlerts;
QPointer<BandwidthScheduler> bd_scheduler;
QMap<QUrl, QString> savepath_fromurl;
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
QHash<QString, QString> savePathsToRemove;
QStringList torrentsToPausedAfterChecking;
QTimer resumeDataTimer;
// Ratio
QPointer<QTimer> BigRatioTimer;
// HTTP
QPointer<downloadThread> downloader;
// File System
ScanFoldersModel *m_scanFolders;
// Console / Log
QStringList consoleMessages;
QStringList peerBanMessages;
// Settings
bool preAllocateAll;
bool addInPause;
float ratio_limit;
int high_ratio_action;
bool UPnPEnabled;
bool NATPMPEnabled;
bool LSDEnabled;
bool DHTEnabled;
int current_dht_port;
bool PeXEnabled;
bool queueingEnabled;
bool appendLabelToSavePath;
bool torrentExport;
#if LIBTORRENT_VERSION_MINOR > 14
bool appendqBExtension;
#endif
QString defaultSavePath;
QString defaultTempPath;
// ETA Computation
QPointer<QTimer> timerETA;
QHash<QString, QList<int> > ETA_samples;
// IP filtering
QPointer<FilterParserThread> filterParser;
QString filterPath;
// Web UI
QPointer<HttpServer> httpServer;
QList<QUrl> url_skippingDlg;
// Fast exit (async)
bool exiting;
// GeoIP
#ifndef DISABLE_GUI
bool geoipDBLoaded;
bool resolve_countries;
#endif
};
#endif

View File

@@ -46,6 +46,7 @@ class consoleDlg : public QDialog, private Ui_ConsoleDlg{
consoleDlg(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setModal(true);
BTSession = _BTSession;
textConsole->setHtml(BTSession->getConsoleMessages().join("<br>"));
textBannedPeers->setHtml(BTSession->getPeerBanMessages().join("<br>"));

95
src/cookiesdlg.cpp Normal file
View File

@@ -0,0 +1,95 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 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 arnaud@qbittorrent.org
*/
#include "cookiesdlg.h"
#include "ui_cookiesdlg.h"
#include <QNetworkCookie>
enum CookiesCols { COOKIE_KEY, COOKIE_VALUE};
CookiesDlg::CookiesDlg(QWidget *parent, const QList<QByteArray> &raw_cookies) :
QDialog(parent),
ui(new Ui::CookiesDlg)
{
ui->setupUi(this);
ui->infos_lbl->setText(tr("Common keys for cookies are : '%1', '%2'.\nYou should get this information from your Web browser preferences.").arg("uid").arg("pass"));
foreach(const QByteArray &raw_cookie, raw_cookies) {
QList<QByteArray> cookie_parts = raw_cookie.split('=');
if(cookie_parts.size() != 2) continue;
const int i = ui->cookiesTable->rowCount();
ui->cookiesTable->setRowCount(i+1);
ui->cookiesTable->setItem(i, COOKIE_KEY, new QTableWidgetItem(cookie_parts.first().data()));
ui->cookiesTable->setItem(i, COOKIE_VALUE, new QTableWidgetItem(cookie_parts.last().data()));
}
}
CookiesDlg::~CookiesDlg()
{
delete ui;
}
void CookiesDlg::on_add_btn_clicked() {
ui->cookiesTable->setRowCount(ui->cookiesTable->rowCount()+1);
// Edit first column
ui->cookiesTable->editItem(ui->cookiesTable->item(ui->cookiesTable->rowCount()-1, COOKIE_KEY));
}
void CookiesDlg::on_del_btn_clicked() {
// Get selected cookie
QList<QTableWidgetItem*> selection = ui->cookiesTable->selectedItems();
if(!selection.isEmpty()) {
ui->cookiesTable->removeRow(selection.first()->row());
}
}
QList<QByteArray> CookiesDlg::getCookies() const {
QList<QByteArray> ret;
for(int i=0; i<ui->cookiesTable->rowCount(); ++i) {
QString key = ui->cookiesTable->item(i, COOKIE_KEY)->text().trimmed();
QString value = ui->cookiesTable->item(i, COOKIE_VALUE)->text().trimmed();
if(!key.isEmpty() && !value.isEmpty()) {
const QString raw_cookie = key+"="+value;
qDebug("Cookie: %s", qPrintable(raw_cookie));
ret << raw_cookie.toLocal8Bit();
}
}
return ret;
}
QList<QByteArray> CookiesDlg::askForCookies(QWidget *parent, const QList<QByteArray> &raw_cookies, bool *ok) {
CookiesDlg dlg(parent, raw_cookies);
if(dlg.exec()) {
*ok = true;
return dlg.getCookies();
}
*ok = false;
return QList<QByteArray>();
}

58
src/cookiesdlg.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 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 arnaud@qbittorrent.org
*/
#ifndef COOKIESDLG_H
#define COOKIESDLG_H
#include <QDialog>
namespace Ui {
class CookiesDlg;
}
class CookiesDlg : public QDialog
{
Q_OBJECT
public:
explicit CookiesDlg(QWidget *parent = 0, const QList<QByteArray> &raw_cookies = QList<QByteArray>());
~CookiesDlg();
QList<QByteArray> getCookies() const;
static QList<QByteArray> askForCookies(QWidget *parent, const QList<QByteArray> &raw_cookies, bool *ok);
protected slots:
void on_add_btn_clicked();
void on_del_btn_clicked();
private:
Ui::CookiesDlg *ui;
};
#endif // COOKIESDLG_H

View File

@@ -37,6 +37,7 @@
#include <boost/filesystem/fstream.hpp>
#include <boost/bind.hpp>
#include <libtorrent/version.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/torrent_info.hpp>
@@ -49,6 +50,7 @@
#include "torrentpersistentdata.h"
#include "createtorrent_imp.h"
#include "misc.h"
#include "qinisettings.h"
using namespace libtorrent;
using namespace boost::filesystem;
@@ -65,8 +67,9 @@ bool file_filter(boost::filesystem::path const& filename)
createtorrent::createtorrent(QWidget *parent): QDialog(parent){
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setModal(true);
creatorThread = new torrentCreatorThread(this);
connect(creatorThread, SIGNAL(creationSuccess(QString, const char*)), this, SLOT(handleCreationSuccess(QString, const char*)));
connect(creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString)));
connect(creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString)));
connect(creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int)));
path::default_name_check(no_check);
@@ -78,15 +81,29 @@ createtorrent::~createtorrent() {
}
void createtorrent::on_addFolder_button_clicked(){
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
if(!dir.isEmpty())
QIniSettings settings("qBittorrent", "qBittorrent");
QString last_path = settings.value("CreateTorrent/last_add_path", QDir::homePath()).toString();
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), last_path, QFileDialog::ShowDirsOnly);
if(!dir.isEmpty()) {
settings.setValue("CreateTorrent/last_add_path", dir);
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
dir = dir.replace("/", "\\");
#endif
textInputPath->setText(dir);
}
}
void createtorrent::on_addFile_button_clicked(){
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath(), QString(), 0, QFileDialog::ShowDirsOnly);
if(!file.isEmpty())
QIniSettings settings("qBittorrent", "qBittorrent");
QString last_path = settings.value("CreateTorrent/last_add_path", QDir::homePath()).toString();
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), last_path);
if(!file.isEmpty()) {
settings.setValue("CreateTorrent/last_add_path", misc::removeLastPathPart(file));
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
file = file.replace("/", "\\");
#endif
textInputPath->setText(file);
}
}
void createtorrent::on_removeTracker_button_clicked() {
@@ -167,39 +184,59 @@ void createtorrent::on_createButton_clicked(){
return;
}
QStringList trackers = allItems(trackers_list);
/*if(!trackers.size()){
QMessageBox::critical(0, tr("No tracker path set"), tr("Please set at least one tracker"));
return;
}*/
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
QIniSettings settings("qBittorrent", "qBittorrent");
QString last_path = settings.value("CreateTorrent/last_save_path", QDir::homePath()).toString();
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), last_path, tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
if(!destination.isEmpty()) {
if(!destination.endsWith(QString::fromUtf8(".torrent")))
settings.setValue("CreateTorrent/last_save_path", misc::removeLastPathPart(destination));
if(!destination.toUpper().endsWith(".TORRENT"))
destination += QString::fromUtf8(".torrent");
} else {
return;
}
// Disable dialog
setEnabled(false);
// Set busy cursor
setCursor(QCursor(Qt::WaitCursor));
// Actually create the torrent
QStringList url_seeds = allItems(URLSeeds_list);
QString comment = txt_comment->toPlainText();
creatorThread->create(input, destination, trackers, url_seeds, comment, check_private->isChecked(), getPieceSize());
}
void createtorrent::handleCreationFailure(QString msg) {
// Enable dialog
setEnabled(true);
// Remove busy cursor
setCursor(QCursor(Qt::ArrowCursor));
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(msg));
}
void createtorrent::handleCreationSuccess(QString path, const char* branch_path) {
void createtorrent::handleCreationSuccess(QString path, QString branch_path) {
// Enable Dialog
setEnabled(true);
// Remove busy cursor
setCursor(QCursor(Qt::ArrowCursor));
if(checkStartSeeding->isChecked()) {
QString root_folder;
// Create save path temp data
boost::intrusive_ptr<torrent_info> t;
try {
t = new torrent_info(path.toLocal8Bit().data());
t = new torrent_info(path.toUtf8().data());
root_folder = misc::truncateRootFolder(t);
} catch(std::exception&) {
QMessageBox::critical(0, tr("Torrent creation"), tr("Created torrent file is invalid. It won't be added to download list."));
return;
}
QString hash = misc::toQString(t->info_hash());
TorrentTempData::setSavePath(hash, QString(branch_path));
#ifdef LIBTORRENT_0_15
QString save_path = branch_path;
if(!root_folder.isEmpty()) {
save_path = QDir(save_path).absoluteFilePath(root_folder);
}
TorrentTempData::setSavePath(hash, save_path);
#if LIBTORRENT_VERSION_MINOR > 14
// Enable seeding mode (do not recheck the files)
TorrentTempData::setSeedingMode(hash, true);
#endif
@@ -209,6 +246,18 @@ void createtorrent::handleCreationSuccess(QString path, const char* branch_path)
close();
}
void createtorrent::on_cancelButton_clicked() {
// End torrent creation thread
if(creatorThread->isRunning()) {
creatorThread->abortCreation();
creatorThread->terminate();
// Wait for termination
creatorThread->wait();
}
// Close the dialog
reject();
}
void createtorrent::updateProgressBar(int progress) {
progressBar->setValue(progress);
}
@@ -242,8 +291,7 @@ void torrentCreatorThread::run() {
char const* creator_str = "qBittorrent "VERSION;
try {
file_storage fs;
file_pool fp;
path full_path = complete(path(input_path.toLocal8Bit().data()));
path full_path = complete(path(input_path.toUtf8().constData()));
// Adding files to the torrent
add_files(fs, full_path, file_filter);
if(abort) return;
@@ -263,15 +311,15 @@ void torrentCreatorThread::run() {
// Set qBittorrent as creator and add user comment to
// torrent_info structure
t.set_creator(creator_str);
t.set_comment((const char*)comment.toLocal8Bit());
t.set_comment((const char*)comment.toUtf8());
// Is private ?
t.set_priv(is_private);
if(abort) return;
// create the torrent and print it to out
ofstream out(complete(path((const char*)save_path.toLocal8Bit())), std::ios_base::binary);
ofstream out(complete(path((const char*)save_path.toUtf8())), std::ios_base::binary);
bencode(std::ostream_iterator<char>(out), t.generate());
emit updateProgress(100);
emit creationSuccess(save_path, full_path.branch_path().string().c_str());
emit creationSuccess(save_path, QString::fromUtf8(full_path.branch_path().string().c_str()));
}
catch (std::exception& e){
emit creationFailure(QString::fromUtf8(e.what()));

View File

@@ -58,13 +58,14 @@ class torrentCreatorThread : public QThread {
}
void create(QString _input_path, QString _save_path, QStringList _trackers, QStringList _url_seeds, QString _comment, bool _is_private, int _piece_size);
void sendProgressSignal(int progress);
void abortCreation() { abort = true; }
protected:
void run();
signals:
void creationFailure(QString msg);
void creationSuccess(QString path, const char* branch_path);
void creationSuccess(QString path, QString branch_path);
signals:
void updateProgress(int progress);
@@ -87,6 +88,7 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
public slots:
void updateProgressBar(int progress);
void on_cancelButton_clicked();
protected slots:
void on_createButton_clicked();
@@ -97,7 +99,7 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
void on_addURLSeed_button_clicked();
void on_removeURLSeed_button_clicked();
void handleCreationFailure(QString msg);
void handleCreationSuccess(QString path, const char* branch_path);
void handleCreationSuccess(QString path, QString branch_path);
};
#endif

View File

@@ -33,6 +33,8 @@
#include <QDialog>
#include "ui_confirmdeletiondlg.h"
#include "preferences.h"
#include "misc.h"
class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
Q_OBJECT
@@ -40,6 +42,10 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
public:
DeletionConfirmationDlg(QWidget *parent=0): QDialog(parent) {
setupUi(this);
move(misc::screenCenter(this));
checkPermDelete->setChecked(Preferences::deleteTorrentFilesAsDefault());
connect(checkPermDelete, SIGNAL(clicked()), this, SLOT(updateRememberButtonState()));
buttonBox->setFocus();
}
bool shouldDeleteLocalFiles() const {
@@ -55,6 +61,15 @@ class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg {
return false;
}
private slots:
void updateRememberButtonState() {
rememberBtn->setEnabled(checkPermDelete->isChecked() != Preferences::deleteTorrentFilesAsDefault());
}
void on_rememberBtn_clicked() {
Preferences::setDeleteTorrentFilesAsDefault(checkPermDelete->isChecked());
rememberBtn->setEnabled(false);
}
};
#endif // DELETIONCONFIRMATIONDLG_H

View File

@@ -53,46 +53,69 @@ public:
setFixedHeight(BAR_HEIGHT);
}
void setProgress(bitfield pieces) {
void setProgress(const bitfield &pieces, const bitfield &downloading_pieces) {
if(pieces.empty()) {
// Empty bar
QPixmap pix = QPixmap(1, 1);
pix.fill();
pixmap = pix;
} else {
int nb_pieces = pieces.size();
const qulonglong nb_pieces = pieces.size();
// Reduce the number of pieces before creating the pixmap
// otherwise it can crash when there are too many pieces
if(nb_pieces > width()) {
int ratio = floor(nb_pieces/(double)width());
QVector<bool> scaled_pieces;
for(int i=0; i<nb_pieces; i+= ratio) {
const uint w = width();
if(nb_pieces > w) {
const uint ratio = floor(nb_pieces/(double)w);
bitfield scaled_pieces(ceil(nb_pieces/(double)ratio), false);
bitfield scaled_downloading(ceil(nb_pieces/(double)ratio), false);
uint scaled_index = 0;
for(qulonglong i=0; i<nb_pieces; i+= ratio) {
bool have = true;
for(int j=i; j<qMin(i+ratio, nb_pieces); ++j) {
for(qulonglong j=i; j<qMin(i+ratio, nb_pieces); ++j) {
if(!pieces[i]) { have = false; break; }
}
scaled_pieces << have;
if(have) {
scaled_pieces.set_bit(scaled_index);
} else {
bool downloading = false;
for(qulonglong j=i; j<qMin(i+ratio, nb_pieces); ++j) {
if(downloading_pieces[i]) { downloading = true; break; }
}
if(downloading)
scaled_downloading.set_bit(scaled_index);
}
++scaled_index;
}
QPixmap pix = QPixmap(scaled_pieces.size(), 1);
pix.fill();
//pix.fill();
QPainter painter(&pix);
for(int i=0; i<scaled_pieces.size(); ++i) {
if(scaled_pieces[i])
for(uint i=0; i<scaled_pieces.size(); ++i) {
if(scaled_pieces[i]) {
painter.setPen(Qt::blue);
else
painter.setPen(Qt::white);
} else {
if(scaled_downloading[i]) {
painter.setPen(Qt::yellow);
} else {
painter.setPen(Qt::white);
}
}
painter.drawPoint(i,0);
}
pixmap = pix;
} else {
QPixmap pix = QPixmap(pieces.size(), 1);
pix.fill();
//pix.fill();
QPainter painter(&pix);
for(uint i=0; i<pieces.size(); ++i) {
if(pieces[i])
if(pieces[i]) {
painter.setPen(Qt::blue);
else
painter.setPen(Qt::white);
} else {
if(downloading_pieces[i]) {
painter.setPen(Qt::yellow);
} else {
painter.setPen(Qt::white);
}
}
painter.drawPoint(i,0);
}
pixmap = pix;

View File

@@ -47,10 +47,11 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
setModal(true);
show();
// Paste clipboard if there is an URL in it
QString clip_txt = qApp->clipboard()->text();
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive)) {
if(clip_txt.startsWith("http://", Qt::CaseInsensitive) || clip_txt.startsWith("https://", Qt::CaseInsensitive) || clip_txt.startsWith("ftp://", Qt::CaseInsensitive) || clip_txt.startsWith("magnet:", Qt::CaseInsensitive) || clip_txt.startsWith("bc://bt/", Qt::CaseInsensitive)) {
textUrls->setText(clip_txt);
}
}

View File

@@ -28,53 +28,71 @@
* Contact : chris@qbittorrent.org
*/
#include "downloadthread.h"
#include <QTemporaryFile>
#include <QSettings>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include "downloadthread.h"
#include "preferences.h"
#include "qinisettings.h"
enum ProxyType {HTTP=1, SOCKS5=2, HTTP_PW=3, SOCKS5_PW=4, SOCKS4=5};
/** Download Thread **/
downloadThread::downloadThread(QObject* parent) : QObject(parent) {
networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
}
downloadThread::~downloadThread(){
qDebug("Deleting network manager");
delete networkManager;
qDebug("Deleted network manager");
connect(&networkManager, SIGNAL(finished (QNetworkReply*)), this, SLOT(processDlFinished(QNetworkReply*)));
#ifndef QT_NO_OPENSSL
connect(&networkManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
#endif
}
void downloadThread::processDlFinished(QNetworkReply* reply) {
QString url = reply->url().toString();
QString url = reply->url().toEncoded().data();
qDebug("Download finished: %s", qPrintable(url));
if(reply->error() != QNetworkReply::NoError) {
// Failure
qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(reply->error())));
emit downloadFailure(url, errorCodeToString(reply->error()));
} else {
QVariant redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(redirection.isValid()) {
// We should redirect
qDebug("Redirecting from %s to %s", qPrintable(url), qPrintable(redirection.toUrl().toString()));
redirect_mapping.insert(redirection.toUrl().toString(), url);
downloadUrl(redirection.toUrl().toString());
return;
}
// Checking if it was redirecting, restoring initial URL
if(redirect_mapping.contains(url)) {
url = redirect_mapping.take(url);
}
// Success
QString filePath;
QTemporaryFile tmpfile;
tmpfile.setAutoRemove(false);
if (tmpfile.open()) {
filePath = tmpfile.fileName();
qDebug("Temporary filename is: %s", filePath.toLocal8Bit().data());
QTemporaryFile *tmpfile = new QTemporaryFile;
tmpfile->setAutoRemove(false);
if (tmpfile->open()) {
filePath = tmpfile->fileName();
qDebug("Temporary filename is: %s", qPrintable(filePath));
if(reply->open(QIODevice::ReadOnly)) {
tmpfile.write(reply->readAll());
// TODO: Support GZIP compression
tmpfile->write(reply->readAll());
reply->close();
tmpfile.close();
tmpfile->close();
delete tmpfile;
// Send finished signal
emit downloadFinished(url, filePath);
} else {
// Error when reading the request
tmpfile.close();
tmpfile->close();
delete tmpfile;
emit downloadFailure(url, tr("I/O Error"));
}
} else {
delete tmpfile;
emit downloadFailure(url, tr("I/O Error"));
}
}
@@ -82,29 +100,84 @@ void downloadThread::processDlFinished(QNetworkReply* reply) {
reply->deleteLater();
}
void downloadThread::downloadUrl(QString url){
void downloadThread::loadCookies(const QString &host_name, QString url) {
const QList<QByteArray> raw_cookies = Preferences::getHostNameCookies(host_name);
QNetworkCookieJar *cookie_jar = networkManager.cookieJar();
QList<QNetworkCookie> cookies;
qDebug("Loading cookies for host name: %s", qPrintable(host_name));
foreach(const QByteArray& raw_cookie, raw_cookies) {
QList<QByteArray> cookie_parts = raw_cookie.split('=');
if(cookie_parts.size() == 2) {
qDebug("Loading cookie: %s", raw_cookie.constData());
cookies << QNetworkCookie(cookie_parts.first(), cookie_parts.last());
}
}
cookie_jar->setCookiesFromUrl(cookies, url);
networkManager.setCookieJar(cookie_jar);
}
void downloadThread::downloadTorrentUrl(QString url){
// Load cookies
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
if(!host_name.isEmpty())
loadCookies(host_name, url);
// Process request
QNetworkReply *reply = downloadUrl(url);
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
}
QNetworkReply* downloadThread::downloadUrl(QString url){
// Update proxy settings
applyProxySettings();
// Load cookies
QString host_name = QUrl::fromEncoded(url.toLocal8Bit()).host();
if(!host_name.isEmpty())
loadCookies(host_name, url);
// Process download request
QNetworkRequest request;
request.setUrl(QUrl::fromEncoded(url.toLocal8Bit()));
qDebug("url is %s", qPrintable(url));
const QUrl qurl = QUrl::fromEncoded(url.toLocal8Bit());
QNetworkRequest request(qurl);
// Spoof Firefox 3.5 user agent to avoid
// Web server banning
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");
qDebug("Downloading %s...", request.url().toString().toLocal8Bit().data());
networkManager->get(request);
qDebug("Downloading %s...", request.url().toEncoded().data());
qDebug("%d cookies for this URL", networkManager.cookieJar()->cookiesForUrl(url).size());
for(int i=0; i<networkManager.cookieJar()->cookiesForUrl(url).size(); ++i) {
qDebug("%s=%s", networkManager.cookieJar()->cookiesForUrl(url).at(i).name().data(), networkManager.cookieJar()->cookiesForUrl(url).at(i).value().data());
qDebug("Domain: %s, Path: %s", qPrintable(networkManager.cookieJar()->cookiesForUrl(url).at(i).domain()), qPrintable(networkManager.cookieJar()->cookiesForUrl(url).at(i).path()));
}
return networkManager.get(request);
}
void downloadThread::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) {
if(bytesTotal > 0) {
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
// Total number of bytes is available
if(bytesTotal > 1048576) {
// More than 1MB, this is probably not a torrent file, aborting...
reply->abort();
} else {
disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(checkDownloadSize(qint64,qint64)));
}
} else {
if(bytesReceived > 1048576) {
// More than 1MB, this is probably not a torrent file, aborting...
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
reply->abort();
}
}
}
void downloadThread::applyProxySettings() {
QNetworkProxy proxy;
QSettings settings("qBittorrent", "qBittorrent");
QIniSettings settings("qBittorrent", "qBittorrent");
int intValue = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxyType"), 0).toInt();
if(intValue > 0) {
// Proxy enabled
QString IP = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/IP"), "0.0.0.0").toString();
proxy.setHostName(IP);
QString port = settings.value(QString::fromUtf8("Preferences/Connection/HTTPProxy/Port"), 8080).toString();
qDebug("Using proxy: %s", (IP+QString(":")+port).toLocal8Bit().data());
qDebug("Using proxy: %s", qPrintable(IP));
proxy.setPort(port.toUShort());
// Default proxy type is HTTP, we must change if it is SOCKS5
if(intValue == SOCKS5 || intValue == SOCKS5_PW) {
@@ -125,7 +198,7 @@ void downloadThread::applyProxySettings() {
} else {
proxy.setType(QNetworkProxy::NoProxy);
}
networkManager->setProxy(proxy);
networkManager.setProxy(proxy);
}
QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
@@ -176,3 +249,11 @@ QString downloadThread::errorCodeToString(QNetworkReply::NetworkError status) {
return tr("Unknown error");
}
}
#ifndef QT_NO_OPENSSL
void downloadThread::ignoreSslErrors(QNetworkReply* reply,QList<QSslError> errors) {
Q_UNUSED(errors)
// Ignore all SSL errors
reply->ignoreSslErrors();
}
#endif

View File

@@ -33,6 +33,8 @@
#include <QNetworkReply>
#include <QObject>
#include <QHash>
#include <QSslError>
class QNetworkAccessManager;
@@ -40,7 +42,8 @@ class downloadThread : public QObject {
Q_OBJECT
private:
QNetworkAccessManager *networkManager;
QNetworkAccessManager networkManager;
QHash<QString, QString> redirect_mapping;
signals:
void downloadFinished(QString url, QString file_path);
@@ -48,16 +51,21 @@ signals:
public:
downloadThread(QObject* parent);
~downloadThread();
void downloadUrl(QString url);
QNetworkReply* downloadUrl(QString url);
void downloadTorrentUrl(QString url);
//void setProxy(QString IP, int port, QString username, QString password);
protected:
QString errorCodeToString(QNetworkReply::NetworkError status);
void applyProxySettings();
void loadCookies(const QString &host_name, QString url);
protected slots:
void processDlFinished(QNetworkReply* reply);
void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal);
#ifndef QT_NO_OPENSSL
void ignoreSslErrors(QNetworkReply*,QList<QSslError>);
#endif
};

View File

@@ -36,7 +36,6 @@
#include "pluginsource.h"
#include <QProcess>
#include <QHeaderView>
#include <QSettings>
#include <QMenu>
#include <QMessageBox>
#include <QFileDialog>
@@ -45,7 +44,7 @@
#include <QTemporaryFile>
enum EngineColumns {ENGINE_NAME, ENGINE_URL, ENGINE_STATE, ENGINE_ID};
#define UPDATE_URL "http://qbittorrent.svn.sourceforge.net/viewvc/qbittorrent/trunk/src/search_engine/engines/"
#define UPDATE_URL "http://qbittorrent.svn.sourceforge.net/viewvc/qbittorrent/branches/v2_4_x/src/search_engine/engines/"
engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_engines) : QDialog(parent), supported_engines(supported_engines) {
setupUi(this);
@@ -81,9 +80,14 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
QString file;
foreach(file, files) {
qDebug("dropped %s", file.toLocal8Bit().data());
qDebug("dropped %s", qPrintable(file));
#ifdef Q_WS_WIN
file = file.replace("file:///", "");
#else
file = file.replace("file://", "");
#endif
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(file);
continue;
}
@@ -99,7 +103,7 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
QString mime;
foreach(mime, event->mimeData()->formats()){
qDebug("mimeData: %s", mime.toLocal8Bit().data());
qDebug("mimeData: %s", qPrintable(mime));
}
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
event->acceptProposedAction();
@@ -108,6 +112,7 @@ void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
void engineSelectDlg::on_updateButton_clicked() {
// Download version file from update server on sourceforge
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(QString(UPDATE_URL)+"versions.txt");
}
@@ -125,18 +130,17 @@ void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
void engineSelectDlg::displayContextMenu(const QPoint&) {
QMenu myContextMenu(this);
QModelIndex index;
// Enable/disable pause/start action given the DL state
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
bool has_enable = false, has_disable = false;
QTreeWidgetItem *item;
foreach(item, items) {
QString id = item->text(ENGINE_ID);
if(supported_engines->value(id)->isEnabled() and !has_disable) {
if(supported_engines->value(id)->isEnabled() && !has_disable) {
myContextMenu.addAction(actionDisable);
has_disable = true;
}
if(!supported_engines->value(id)->isEnabled() and !has_enable) {
if(!supported_engines->value(id)->isEnabled() && !has_enable) {
myContextMenu.addAction(actionEnable);
has_enable = true;
}
@@ -251,12 +255,12 @@ bool engineSelectDlg::isUpdateNeeded(QString plugin_name, float new_version) con
}
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
qDebug("Asked to install plugin at %s", path.toLocal8Bit().data());
qDebug("Asked to install plugin at %s", qPrintable(path));
float new_version = SearchEngine::getPluginVersion(path);
qDebug("Version to be installed: %.2f", new_version);
if(!isUpdateNeeded(plugin_name, new_version)) {
qDebug("Apparently update is not needed, we have a more recent version");
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name));
return;
}
// Process with install
@@ -265,7 +269,8 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
if(QFile::exists(dest_path)) {
// Backup in case install fails
QFile::copy(dest_path, dest_path+".bak");
QFile::remove(dest_path);
misc::safeRemove(dest_path);
misc::safeRemove(dest_path+"c");
update = true;
}
// Copy the plugin
@@ -276,28 +281,28 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
if(!supported_engines->contains(plugin_name)) {
if(update) {
// Remove broken file
QFile::remove(dest_path);
misc::safeRemove(dest_path);
// restore backup
QFile::copy(dest_path+".bak", dest_path);
QFile::remove(dest_path+".bak");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
misc::safeRemove(dest_path+".bak");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name));
return;
} else {
// Remove broken file
QFile::remove(dest_path);
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
misc::safeRemove(dest_path);
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name));
return;
}
}
// Install was successful, remove backup
if(update) {
QFile::remove(dest_path+".bak");
misc::safeRemove(dest_path+".bak");
}
if(update) {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name));
return;
} else {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name));
return;
}
}
@@ -350,8 +355,10 @@ void engineSelectDlg::askForPluginUrl() {
QString url = QInputDialog::getText(this, tr("New search engine plugin URL"),
tr("URL:"), QLineEdit::Normal,
"http://", &ok);
if (ok && !url.isEmpty())
if (ok && !url.isEmpty()) {
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(url);
}
}
void engineSelectDlg::askForLocalPlugin() {
@@ -390,23 +397,24 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
plugin_name.chop(1); // remove trailing ':'
bool ok;
float version = list.last().toFloat(&ok);
qDebug("read line %s: %.2f", plugin_name.toLocal8Bit().data(), version);
qDebug("read line %s: %.2f", qPrintable(plugin_name), version);
if(!ok) continue;
file_correct = true;
if(isUpdateNeeded(plugin_name, version)) {
qDebug("Plugin: %s is outdated", plugin_name.toLocal8Bit().data());
qDebug("Plugin: %s is outdated", qPrintable(plugin_name));
// Downloading update
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(UPDATE_URL+plugin_name+".py");
//downloader->downloadUrl(UPDATE_URL+plugin_name+".png");
updated = true;
}else {
qDebug("Plugin: %s is up to date", plugin_name.toLocal8Bit().data());
qDebug("Plugin: %s is up to date", qPrintable(plugin_name));
}
}
// Close file
versions.close();
// Clean up tmp file
QFile::remove(versions_file);
misc::safeRemove(versions_file);
if(file_correct && !updated) {
QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date."));
}
@@ -414,7 +422,8 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
}
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
qDebug("engineSelectDlg received %s", url.toLocal8Bit().data());
setCursor(QCursor(Qt::ArrowCursor));
qDebug("engineSelectDlg received %s", qPrintable(url));
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
// Icon downloaded
QImage fileIcon;
@@ -435,28 +444,29 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
}
}
// Delete tmp file
QFile::remove(filePath);
misc::safeRemove(filePath);
return;
}
if(url.endsWith("versions.txt")) {
if(!parseVersionsFile(filePath)) {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
}
QFile::remove(filePath);
misc::safeRemove(filePath);
return;
}
if(url.endsWith(".py", Qt::CaseInsensitive)) {
QString plugin_name = url.split('/').last();
plugin_name.replace(".py", "");
installPlugin(filePath, plugin_name);
QFile::remove(filePath);
misc::safeRemove(filePath);
return;
}
}
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
setCursor(QCursor(Qt::ArrowCursor));
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
qDebug("Could not download favicon: %s, reason: %s", url.toLocal8Bit().data(), reason.toLocal8Bit().data());
qDebug("Could not download favicon: %s, reason: %s", qPrintable(url), qPrintable(reason));
return;
}
if(url.endsWith("versions.txt")) {
@@ -467,6 +477,6 @@ void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
// a plugin update download has been failed
QString plugin_name = url.split('/').last();
plugin_name.replace(".py", "", Qt::CaseInsensitive);
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toLocal8Bit().data()));
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name));
}
}

View File

@@ -29,13 +29,16 @@
*/
#include <libtorrent/version.hpp>
#include "eventmanager.h"
#include "bittorrent.h"
#include "scannedfoldersmodel.h"
#include "misc.h"
#include "preferences.h"
//#include "proplistdelegate.h"
#include "torrentpersistentdata.h"
#include <QDebug>
#include <QTranslator>
EventManager::EventManager(QObject *parent, Bittorrent *BTSession)
: QObject(parent), BTSession(BTSession)
@@ -59,7 +62,7 @@ QList<QVariantMap> EventManager::getPropTrackersInfo(QString hash) const {
tracker["url"] = tracker_url;
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
QString error_message = data.last_message.trimmed();
#ifdef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR > 14
if(it->verified) {
tracker["status"] = tr("Working");
} else {
@@ -103,7 +106,7 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
int i=0;
for(fi=t.begin_files(); fi != t.end_files(); fi++) {
QVariantMap file;
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
QString path = QDir::cleanPath(misc::toQStringU(fi->path.string()));
QString name = path.split('/').last();
file["name"] = name;
file["size"] = misc::friendlyUnit((double)fi->size);
@@ -112,6 +115,8 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
else
file["progress"] = 1.; // Empty file...
file["priority"] = priorities[i];
if(i == 0)
file["is_seed"] = h.is_seed();
files << file;
++i;
}
@@ -120,8 +125,20 @@ QList<QVariantMap> EventManager::getPropFilesInfo(QString hash) const {
void EventManager::setGlobalPreferences(QVariantMap m) const {
// UI
if(m.contains("locale"))
Preferences::setLocale(m["locale"].toString());
if(m.contains("locale")) {
QString locale = m["locale"].toString();
if(Preferences::getLocale() != locale) {
QTranslator *translator = new QTranslator;
if(translator->load(QString::fromUtf8(":/lang/qbittorrent_") + locale)){
qDebug("%s locale recognized, using translation.", qPrintable(locale));
}else{
qDebug("%s locale unrecognized, using default (en_GB).", qPrintable(locale));
}
qApp->installTranslator(translator);
}
Preferences::setLocale(locale);
}
// Downloads
if(m.contains("save_path"))
Preferences::setSavePath(m["save_path"].toString());
@@ -129,8 +146,46 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
Preferences::setTempPathEnabled(m["temp_path_enabled"].toBool());
if(m.contains("temp_path"))
Preferences::setTempPath(m["temp_path"].toString());
if(m.contains("scan_dir"))
Preferences::setScanDir(m["scan_dir"].toString());
if(m.contains("scan_dirs") && m.contains("download_in_scan_dirs")) {
QVariantList download_at_path_tmp = m["download_in_scan_dirs"].toList();
QList<bool> download_at_path;
foreach(QVariant var, download_at_path_tmp) {
download_at_path << var.toBool();
}
QStringList old_folders = Preferences::getScanDirs();
QStringList new_folders = m["scan_dirs"].toStringList();
if(download_at_path.size() == new_folders.size()) {
Preferences::setScanDirs(new_folders);
Preferences::setDownloadInScanDirs(download_at_path);
foreach(const QString &old_folder, old_folders) {
// Update deleted folders
if(!new_folders.contains(old_folder)) {
BTSession->getScanFoldersModel()->removePath(old_folder);
}
}
int i = 0;
foreach(const QString &new_folder, new_folders) {
qDebug("New watched folder: %s", qPrintable(new_folder));
// Update new folders
if(!old_folders.contains(new_folder)) {
BTSession->getScanFoldersModel()->addPath(new_folder, download_at_path.at(i));
}
++i;
}
}
}
if(m.contains("export_dir"))
Preferences::setExportDir(m["export_dir"].toString());
if(m.contains("mail_notification_enabled"))
Preferences::setMailNotificationEnabled(m["mail_notification_enabled"].toBool());
if(m.contains("mail_notification_email"))
Preferences::setMailNotificationEmail(m["mail_notification_email"].toString());
if(m.contains("mail_notification_smtp"))
Preferences::setMailNotificationSMTP(m["mail_notification_smtp"].toString());
if(m.contains("autorun_enabled"))
Preferences::setAutoRunEnabled(m["autorun_enabled"].toBool());
if(m.contains("autorun_program"))
Preferences::setAutoRunProgram(m["autorun_program"].toString());
if(m.contains("preallocate_all"))
Preferences::preAllocateAllFiles(m["preallocate_all"].toBool());
if(m.contains("queueing_enabled"))
@@ -141,7 +196,7 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
Preferences::setMaxActiveTorrents(m["max_active_torrents"].toInt());
if(m.contains("max_active_uploads"))
Preferences::setMaxActiveUploads(m["max_active_uploads"].toInt());
#ifdef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR > 14
if(m.contains("incomplete_files_ext"))
Preferences::useIncompleteFilesExtension(m["incomplete_files_ext"].toBool());
#endif
@@ -165,6 +220,10 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
// Bittorrent
if(m.contains("dht"))
Preferences::setDHTEnabled(m["dht"].toBool());
if(m.contains("dhtSameAsBT"))
Preferences::setDHTPortSameAsBT(m["dhtSameAsBT"].toBool());
if(m.contains("dht_port"))
Preferences::setDHTPort(m["dht_port"].toInt());
if(m.contains("pex"))
Preferences::setPeXEnabled(m["pex"].toBool());
qDebug("Pex support: %d", (int)m["pex"].toBool());
@@ -172,12 +231,6 @@ void EventManager::setGlobalPreferences(QVariantMap m) const {
Preferences::setLSDEnabled(m["lsd"].toBool());
if(m.contains("encryption"))
Preferences::setEncryptionSetting(m["encryption"].toInt());
if(m.contains("peer_id"))
Preferences::setPeerID(m["peer_id"].toString());
if(m.contains("peer_version"))
Preferences::setClientVersion(m["peer_version"].toString());
if(m.contains("peer_build"))
Preferences::setClientBuild(m["peer_build"].toString());
// Proxy
if(m.contains("proxy_type"))
Preferences::setPeerProxyType(m["proxy_type"].toInt());
@@ -227,14 +280,25 @@ QVariantMap EventManager::getGlobalPreferences() const {
data["save_path"] = Preferences::getSavePath();
data["temp_path_enabled"] = Preferences::isTempPathEnabled();
data["temp_path"] = Preferences::getTempPath();
data["scan_dir_enabled"] = Preferences::isDirScanEnabled();
data["scan_dir"] = Preferences::getScanDir();
data["scan_dirs"] = Preferences::getScanDirs();
QVariantList var_list;
foreach(bool b, Preferences::getDownloadInScanDirs()) {
var_list << b;
}
data["download_in_scan_dirs"] = var_list;
data["export_dir_enabled"] = Preferences::isTorrentExportEnabled();
data["export_dir"] = Preferences::getExportDir();
data["mail_notification_enabled"] = Preferences::isMailNotificationEnabled();
data["mail_notification_email"] = Preferences::getMailNotificationEmail();
data["mail_notification_smtp"] = Preferences::getMailNotificationSMTP();
data["autorun_enabled"] = Preferences::isAutoRunEnabled();
data["autorun_program"] = Preferences::getAutoRunProgram();
data["preallocate_all"] = Preferences::preAllocateAllFiles();
data["queueing_enabled"] = Preferences::isQueueingSystemEnabled();
data["max_active_downloads"] = Preferences::getMaxActiveDownloads();
data["max_active_torrents"] = Preferences::getMaxActiveTorrents();
data["max_active_uploads"] = Preferences::getMaxActiveUploads();
#ifdef LIBTORRENT_0_15
#if LIBTORRENT_VERSION_MINOR > 14
data["incomplete_files_ext"] = Preferences::useIncompleteFilesExtension();
#endif
// Connection
@@ -248,12 +312,11 @@ QVariantMap EventManager::getGlobalPreferences() const {
data["max_uploads_per_torrent"] = Preferences::getMaxUploadsPerTorrent();
// Bittorrent
data["dht"] = Preferences::isDHTEnabled();
data["dhtSameAsBT"] = Preferences::isDHTPortSameAsBT();
data["dht_port"] = Preferences::getDHTPort();
data["pex"] = Preferences::isPeXEnabled();
data["lsd"] = Preferences::isLSDEnabled();
data["encryption"] = Preferences::getEncryptionSetting();
data["peer_id"] = Preferences::getPeerID();
data["peer_version"] = Preferences::getClientVersion();
data["peer_build"] = Preferences::getClientBuild();
// Proxy
data["proxy_type"] = Preferences::getPeerProxyType();
data["proxy_ip"] = Preferences::getPeerProxyIp();
@@ -282,28 +345,30 @@ QVariantMap EventManager::getPropGeneralInfo(QString hash) const {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(h.is_valid() && h.has_metadata()) {
// Save path
data["save_path"] = TorrentPersistentData::getSavePath(hash);
QString p = TorrentPersistentData::getSavePath(hash);
if(p.isEmpty()) p = h.save_path();
data["save_path"] = p;
// Creation date
data["creation_date"] = h.creation_date();
// Comment
data["comment"] = h.comment();
data["total_wasted"] = misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes());
data["total_uploaded"] = misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")";
data["total_downloaded"] = misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")";
data["total_wasted"] = QVariant(misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes()));
data["total_uploaded"] = QVariant(misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")");
data["total_downloaded"] = QVariant(misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")");
if(h.upload_limit() <= 0)
data["up_limit"] = QString::fromUtf8("");
else
data["up_limit"] = misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)");
data["up_limit"] = QVariant(misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)"));
if(h.download_limit() <= 0)
data["dl_limit"] = QString::fromUtf8("");
else
data["dl_limit"] = misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)");
data["dl_limit"] = QVariant(misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)"));
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
if(h.is_seed()) {
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
}
data["time_elapsed"] = elapsed_txt;
data["nb_connections"] = QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")";
data["nb_connections"] = QVariant(QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")");
// Update ratio info
double ratio = BTSession->getRealRatio(h.hash());
if(ratio > 100.)
@@ -330,10 +395,14 @@ void EventManager::modifiedTorrent(QTorrentHandle h)
QVariantMap event;
event["eta"] = QVariant(QString::fromUtf8(""));
if(h.is_paused()) {
if(h.is_seed())
event["state"] = QVariant("pausedUP");
else
event["state"] = QVariant("pausedDL");
if(h.has_error()) {
event["state"] = QVariant("error");
} else {
if(h.is_seed())
event["state"] = QVariant("pausedUP");
else
event["state"] = QVariant("pausedDL");
}
} else {
if(BTSession->isQueueingEnabled() && h.is_queued()) {
if(h.is_seed())

View File

@@ -28,15 +28,16 @@ public:
setColumnCount(1);
QTreeWidgetItem *___qtreewidgetitem = headerItem();
___qtreewidgetitem->setText(0, QApplication::translate("RSS", "RSS feeds", 0, QApplication::UnicodeUTF8));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
unread_item = new QTreeWidgetItem(this);
unread_item->setText(0, tr("Unread") + QString::fromUtf8(" (") + QString::number(rssmanager->getNbUnRead(), 10)+ QString(")"));
unread_item->setData(0,Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/mail-folder-inbox.png")));
itemAdded(unread_item, rssmanager);
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
setCurrentItem(unread_item);
}
~FeedList() {
disconnect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(updateCurrentFeed(QTreeWidgetItem*)));
delete unread_item;
}
@@ -121,19 +122,19 @@ public:
}
RssFile* getRSSItem(QTreeWidgetItem *item) const {
return mapping[item];
return mapping.value(item, 0);
}
RssFile::FileType getItemType(QTreeWidgetItem *item) const {
return mapping[item]->getType();
return mapping.value(item)->getType();
}
QString getItemID(QTreeWidgetItem *item) const {
return mapping[item]->getID();
return mapping.value(item)->getID();
}
QTreeWidgetItem* getTreeItemFromUrl(QString url) const{
return feeds_items[url];
return feeds_items.value(url, 0);
}
RssStream* getRSSItemFromUrl(QString url) const {
@@ -154,7 +155,9 @@ signals:
protected slots:
void updateCurrentFeed(QTreeWidgetItem* new_item) {
if((new_item && getItemType(new_item) == RssFile::STREAM) || new_item == unread_item)
if(!new_item) return;
if(!mapping.contains(new_item)) return;
if((getItemType(new_item) == RssFile::STREAM) || new_item == unread_item)
current_feed = new_item;
}

View File

@@ -32,7 +32,6 @@
#define FEEDDOWNLOADER_H
#include <QString>
#include <QSettings>
#include <QListWidget>
#include <QListWidgetItem>
#include <QInputDialog>
@@ -45,8 +44,9 @@
#include "bittorrent.h"
#include "ui_feeddownloader.h"
#include "qinisettings.h"
#ifdef QT_4_5
#if QT_VERSION >= 0x040500
#include <QHash>
#else
#include <QMap>
@@ -64,11 +64,9 @@ public:
bool matches(QString s) {
QStringList match_tokens = getMatchingTokens();
//qDebug("Checking matching tokens: \"%s\"", getMatchingTokens_str().toLocal8Bit().data());
foreach(const QString& token, match_tokens) {
if(token.isEmpty() || token == "")
continue;
//qDebug("Token: %s", token.toLocal8Bit().data());
QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard);
//reg.setMinimal(false);
if(reg.indexIn(s) < 0) return false;
@@ -107,7 +105,7 @@ public:
QStringList getNotMatchingTokens() const {
QString notmatching = this->value("not", "").toString();
return notmatching.split(" ");
return notmatching.split(QRegExp("[\\s|]"));
}
QString getNotMatchingTokens_str() const {
@@ -170,20 +168,20 @@ public:
}
bool isDownloadingEnabled() const {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QIniSettings 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");
QIniSettings 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");
QIniSettings 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());
}
@@ -224,9 +222,9 @@ public:
}
void save() {
QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QIniSettings 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());
qDebug("Saving filters for feed: %s (%d filters)", qPrintable(feed_url), (*this).size());
all_feeds_filters[feed_url] = *this;
qBTRSS.setValue("feed_filters", all_feeds_filters);
}
@@ -261,7 +259,6 @@ public:
// Restore saved info
enableDl_cb->setChecked(filters.isDownloadingEnabled());
fillFiltersList();
filtersList->sortItems(Qt::AscendingOrder);
if(filters.size() > 0) {
// Select first filter
filtersList->setCurrentItem(filtersList->item(0));
@@ -300,7 +297,7 @@ protected slots:
default_path = QDir::homePath();
}
QString dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
if(!dir.isNull() and QDir(dir).exists()) {
if(!dir.isNull() && QDir(dir).exists()) {
savepath_line->setText(dir);
}
}
@@ -388,7 +385,6 @@ protected slots:
if(selected_filter == current_name)
selected_filter = new_name;
item->setText(new_name);
filtersList->sortItems(Qt::AscendingOrder);
}
}
@@ -442,7 +438,6 @@ protected slots:
}
}while(!validated);
QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList);
filtersList->sortItems(Qt::AscendingOrder);
filtersList->setCurrentItem(it);
//showFilterSettings(it);
}

View File

@@ -2,10 +2,10 @@
#define FILESYSTEMWATCHER_H
#include <QFileSystemWatcher>
#include <QDir>
#ifndef Q_WS_WIN
#include <QTimer>
#include <QDir>
#include <QPointer>
#include <QStringList>
#include <QSet>
@@ -34,12 +34,14 @@
class FileSystemWatcher: public QFileSystemWatcher {
Q_OBJECT
#ifndef Q_WS_WIN
private:
QDir watched_folder;
#ifndef Q_WS_WIN
QList<QDir> watched_folders;
QPointer<QTimer> watch_timer;
#endif
QStringList filters;
#ifndef Q_WS_WIN
protected:
bool isNetworkFileSystem(QString path) {
QString file = path;
@@ -47,10 +49,10 @@ protected:
file += QDir::separator();
file += ".";
struct statfs buf;
if(!statfs(file.toLocal8Bit().data(), &buf)) {
if(!statfs(file.toLocal8Bit().constData(), &buf)) {
return (buf.f_type == (long)CIFS_MAGIC_NUMBER || buf.f_type == (long)NFS_SUPER_MAGIC);
} else {
std::cerr << "Error: statfs() call failed for " << file.toLocal8Bit().data() << ". Supposing it is a local folder..." << std::endl;
std::cerr << "Error: statfs() call failed for " << qPrintable(file) << ". Supposing it is a local folder..." << std::endl;
switch(errno) {
case EACCES:
std::cerr << "Search permission is denied for a component of the path prefix of the path" << std::endl;
@@ -98,13 +100,7 @@ protected:
public:
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
filters << "*.torrent";
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder()));
}
FileSystemWatcher(QString path, QObject *parent): QFileSystemWatcher(parent) {
filters << "*.torrent";
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanFolder()));
addPath(path);
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
}
~FileSystemWatcher() {
@@ -115,33 +111,40 @@ public:
}
QStringList directories() const {
QStringList dirs;
#ifndef Q_WS_WIN
if(watch_timer)
return QStringList(watched_folder.path());
if(watch_timer) {
foreach (const QDir &dir, watched_folders)
dirs << dir.canonicalPath();
}
#endif
return QFileSystemWatcher::directories();
dirs << QFileSystemWatcher::directories();
return dirs;
}
void addPath(const QString & path) {
#ifndef Q_WS_WIN
watched_folder = QDir(path);
if(!watched_folder.exists()) return;
QDir dir(path);
if (!dir.exists())
return;
// Check if the path points to a network file system or not
if(isNetworkFileSystem(path)) {
// Network mode
Q_ASSERT(!watch_timer);
qDebug("Network folder detected: %s", path.toLocal8Bit().data());
qDebug("Network folder detected: %s", qPrintable(path));
qDebug("Using file polling mode instead of inotify...");
watched_folders << dir;
// Set up the watch timer
watch_timer = new QTimer(this);
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanFolder()));
watch_timer->start(5000); // 5 sec
if (!watch_timer) {
watch_timer = new QTimer(this);
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders()));
watch_timer->start(5000); // 5 sec
}
} else {
#endif
// Normal mode
qDebug("FS Watching is watching %s in normal mode", path.toLocal8Bit().data());
qDebug("FS Watching is watching %s in normal mode", qPrintable(path));
QFileSystemWatcher::addPath(path);
scanFolder();
scanLocalFolder(path);
#ifndef Q_WS_WIN
}
#endif
@@ -149,38 +152,65 @@ public:
void removePath(const QString & path) {
#ifndef Q_WS_WIN
if(watch_timer) {
// Network mode
if(QDir(path) == watched_folder) {
delete watch_timer;
QDir dir(path);
for (int i = 0; i < watched_folders.count(); ++i) {
if (QDir(watched_folders.at(i)) == dir) {
watched_folders.removeAt(i);
if (watched_folders.isEmpty())
delete watch_timer;
return;
}
} else {
#endif
// Normal mode
QFileSystemWatcher::removePath(path);
#ifndef Q_WS_WIN
}
#endif
// Normal mode
QFileSystemWatcher::removePath(path);
}
protected slots:
// XXX: Does not detect file size changes to improve performance.
void scanFolder() {
qDebug("Scan folder was called");
void scanLocalFolder(QString path) {
qDebug("scanLocalFolder(%s) called", qPrintable(path));
QStringList torrents;
if(watch_timer) {
torrents = watched_folder.entryList(filters, QDir::Files, QDir::Unsorted);
} else {
torrents = QDir(QFileSystemWatcher::directories().first()).entryList(filters, QDir::Files, QDir::Unsorted);
qDebug("FSWatcher: Polling manually folder %s", QFileSystemWatcher::directories().first().toLocal8Bit().data());
}
if(!torrents.empty())
// Local folders scan
addTorrentsFromDir(QDir(path), torrents);
// Report detected torrent files
if(!torrents.empty()) {
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
emit torrentsAdded(torrents);
}
}
void scanNetworkFolders() {
#ifndef Q_WS_WIN
qDebug("scanNetworkFolders() called");
QStringList torrents;
// Network folders scan
foreach (const QDir &dir, watched_folders) {
//qDebug("FSWatcher: Polling manually folder %s", qPrintable(dir.path()));
addTorrentsFromDir(dir, torrents);
}
// Report detected torrent files
if(!torrents.empty()) {
qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n")));
emit torrentsAdded(torrents);
}
#endif
}
signals:
void torrentsAdded(QStringList &pathList);
private:
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
const QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted);
foreach(const QString &file, files) {
#if defined(Q_WS_WIN) || defined(Q_OS_OS2)
torrents << dir.absoluteFilePath(file).replace("/", "\\");
#else
torrents << dir.absoluteFilePath(file);
#endif
}
}
};
#endif // FILESYSTEMWATCHER_H

View File

@@ -407,9 +407,12 @@ class FilterParserThread : public QThread {
// First, import current filter
ip_filter filter = s->get_ip_filter();
foreach(const QString &ip, IPs) {
qDebug("Manual ban of peer %s", ip.toLocal8Bit().data());
address_v4 addr = address_v4::from_string(ip.toLocal8Bit().data());
filter.add_rule(addr, addr, ip_filter::blocked);
qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData());
boost::system::error_code ec;
address_v4 addr = address_v4::from_string(ip.toLocal8Bit().constData(), ec);
Q_ASSERT(!ec);
if(!ec)
filter.add_rule(addr, addr, ip_filter::blocked);
}
s->set_ip_filter(filter);
}

View File

@@ -40,13 +40,14 @@
using namespace libtorrent;
class GeoIP {
class GeoIP : public QObject {
Q_OBJECT
protected:
#ifdef WITH_GEOIP_EMBEDDED
static QString geoipFolder(bool embedded=false) {
if(embedded)
return ":/geoip/";
return misc::qBittorrentPath()+"geoip"+QDir::separator();
return misc::QDesktopServicesDataLocation()+"geoip"+QDir::separator();
#else
static QString geoipFolder(bool) {
if(QFile::exists("/usr/local/share/GeoIP/GeoIP.dat"))
@@ -68,13 +69,19 @@ protected:
// Create geoip folder is necessary
QDir gfolder(geoipFolder(false));
if(!gfolder.exists()) {
if(!gfolder.mkpath(geoipFolder(false))) return;
if(!gfolder.mkpath(geoipFolder(false))) {
std::cerr << "Failed to create geoip folder at " << qPrintable(geoipFolder(false)) << std::endl;
return;
}
}
// Remove destination files
if(QFile::exists(geoipDBpath(false)))
QFile::remove(geoipDBpath(false));
misc::safeRemove(geoipDBpath(false));
// Copy from executable to hard disk
QFile::copy(geoipDBpath(true), geoipDBpath(false));
qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false)));
if(!QFile::copy(geoipDBpath(true), geoipDBpath(false))) {
std::cerr << "ERROR: Failed to copy geoip.dat from executable to hard disk" << std::endl;
}
qDebug("Local Geoip database was updated");
}
}
@@ -86,9 +93,9 @@ public:
exportEmbeddedDb();
#endif
if(QFile::exists(geoipDBpath(false))) {
qDebug("Loading GeoIP database from %s...", geoipDBpath(false).toLocal8Bit().data());
if(!s->load_country_db(geoipDBpath(false).toLocal8Bit().data())) {
std::cerr << "Failed to load Geoip Database at " << geoipDBpath(false).toLocal8Bit().data() << std::endl;
qDebug("Loading GeoIP database from %s...", qPrintable(geoipDBpath(false)));
if(!s->load_country_db(geoipDBpath(false).toLocal8Bit().constData())) {
std::cerr << "Failed to load Geoip Database at " << qPrintable(geoipDBpath(false)) << std::endl;
}
} else {
qDebug("ERROR: Impossible to find local Geoip Database");
@@ -97,7 +104,7 @@ public:
// TODO: Support more countries
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
static QIcon CountryISOCodeToIcon(char* iso) {
static QIcon CountryISOCodeToIcon(const char* iso, QString &country_name) {
switch(iso[0]) {
case 0:
case '-':
@@ -105,106 +112,107 @@ public:
//qDebug("Not returning any icon because iso is invalid: %s", iso);
return QIcon();
case 'A':
if(iso[1] == 'U') return QIcon(":/Icons/flags/australia.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/argentina.png");
if(iso[1] == 'T') return QIcon(":/Icons/flags/austria.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/united_arab_emirates.png");
if(iso[1] == 'U') { country_name = tr("Australia"); return QIcon(":/Icons/flags/australia.png"); }
if(iso[1] == 'R') { country_name = tr("Argentina"); return QIcon(":/Icons/flags/argentina.png"); }
if(iso[1] == 'T') { country_name = tr("Austria"); return QIcon(":/Icons/flags/austria.png"); }
if(iso[1] == 'E') { country_name = tr("United Arab Emirates"); return QIcon(":/Icons/flags/united_arab_emirates.png"); }
break;
case 'B':
if(iso[1] == 'R') return QIcon(":/Icons/flags/brazil.png");
if(iso[1] == 'G') return QIcon(":/Icons/flags/bulgaria.png");
if(iso[1] == 'Y') return QIcon(":/Icons/flags/belarus.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/belgium.png");
if(iso[1] == 'A') return QIcon(":/Icons/flags/bosnia.png");
if(iso[1] == 'R') { country_name = tr("Brazil"); return QIcon(":/Icons/flags/brazil.png"); }
if(iso[1] == 'G') { country_name = tr("Bulgaria"); return QIcon(":/Icons/flags/bulgaria.png"); }
if(iso[1] == 'Y') { country_name = tr("Belarus"); return QIcon(":/Icons/flags/belarus.png"); }
if(iso[1] == 'E') { country_name = tr("Belgium"); return QIcon(":/Icons/flags/belgium.png"); }
if(iso[1] == 'A') { country_name = tr("Bosnia"); return QIcon(":/Icons/flags/bosnia.png"); }
break;
case 'C':
if(iso[1] == 'A') return QIcon(":/Icons/flags/canada.png");
if(iso[1] == 'Z') return QIcon(":/Icons/flags/czech.png");
if(iso[1] == 'N') return QIcon(":/Icons/flags/china.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/costa_rica.png");
if(iso[1] == 'H') return QIcon(":/Icons/flags/suisse.png");
if(iso[1] == 'A') { country_name = tr("Canada"); return QIcon(":/Icons/flags/canada.png"); }
if(iso[1] == 'Z') { country_name = tr("Czech Republic"); return QIcon(":/Icons/flags/czech.png"); }
if(iso[1] == 'N') { country_name = tr("China"); return QIcon(":/Icons/flags/china.png"); }
if(iso[1] == 'R') { country_name = tr("Costa Rica"); return QIcon(":/Icons/flags/costa_rica.png"); }
if(iso[1] == 'H') { country_name = tr("Switzerland"); return QIcon(":/Icons/flags/suisse.png"); }
break;
case 'D':
if(iso[1] == 'E') return QIcon(":/Icons/flags/germany.png");
if(iso[1] == 'K') return QIcon(":/Icons/flags/denmark.png");
if(iso[1] == 'Z') return QIcon(":/Icons/flags/algeria.png");
if(iso[1] == 'E') { country_name = tr("Germany"); return QIcon(":/Icons/flags/germany.png"); }
if(iso[1] == 'K') { country_name = tr("Denmark"); return QIcon(":/Icons/flags/denmark.png"); }
if(iso[1] == 'Z') { country_name = tr("Algeria"); return QIcon(":/Icons/flags/algeria.png"); }
break;
case 'E':
if(iso[1] == 'S') return QIcon(":/Icons/flags/spain.png");
if(iso[1] == 'G') return QIcon(":/Icons/flags/egypt.png");
if(iso[1] == 'S') { country_name = tr("Spain"); return QIcon(":/Icons/flags/spain.png"); }
if(iso[1] == 'G') { country_name = tr("Egypt"); return QIcon(":/Icons/flags/egypt.png"); }
break;
case 'F':
if(iso[1] == 'I') return QIcon(":/Icons/flags/finland.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/france.png");
if(iso[1] == 'I') { country_name = tr("Finland"); return QIcon(":/Icons/flags/finland.png"); }
if(iso[1] == 'R') { country_name = tr("France"); return QIcon(":/Icons/flags/france.png"); }
break;
case 'G':
if(iso[1] == 'B') return QIcon(":/Icons/flags/united_kingdom.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/greece.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/georgia.png");
if(iso[1] == 'B') { country_name = tr("United Kingdom"); return QIcon(":/Icons/flags/united_kingdom.png"); }
if(iso[1] == 'R') { country_name = tr("Greece"); return QIcon(":/Icons/flags/greece.png"); }
if(iso[1] == 'E') { country_name = tr("Georgia"); return QIcon(":/Icons/flags/georgia.png"); }
break;
case 'H':
if(iso[1] == 'U') return QIcon(":/Icons/flags/hungary.png");
if(iso[1] == 'K') return QIcon(":/Icons/flags/china.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/croatia.png");
if(iso[1] == 'U') { country_name = tr("Hungary"); return QIcon(":/Icons/flags/hungary.png"); }
if(iso[1] == 'K') { country_name = tr("China"); return QIcon(":/Icons/flags/china.png"); }
if(iso[1] == 'R') { country_name = tr("Croatia"); return QIcon(":/Icons/flags/croatia.png"); }
break;
case 'I':
if(iso[1] == 'T') return QIcon(":/Icons/flags/italy.png");
if(iso[1] == 'N') return QIcon(":/Icons/flags/india.png");
if(iso[1] == 'L') return QIcon(":/Icons/flags/israel.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/ireland.png");
if(iso[1] == 'S') return QIcon(":/Icons/flags/iceland.png");
if(iso[1] == 'D') return QIcon(":/Icons/flags/indonesia.png");
if(iso[1] == 'T') { country_name = tr("Italy"); return QIcon(":/Icons/flags/italy.png"); }
if(iso[1] == 'N') { country_name = tr("India"); return QIcon(":/Icons/flags/india.png"); }
if(iso[1] == 'L') { country_name = tr("Israel"); return QIcon(":/Icons/flags/israel.png"); }
if(iso[1] == 'E') { country_name = tr("Ireland"); return QIcon(":/Icons/flags/ireland.png"); }
if(iso[1] == 'S') { country_name = tr("Iceland"); return QIcon(":/Icons/flags/iceland.png"); }
if(iso[1] == 'D') { country_name = tr("Indonesia"); return QIcon(":/Icons/flags/indonesia.png"); }
break;
case 'J':
if(iso[1] == 'P') return QIcon(":/Icons/flags/japan.png");
if(iso[1] == 'P') { country_name = tr("Japan"); return QIcon(":/Icons/flags/japan.png"); }
break;
case 'K':
if(iso[1] == 'R') return QIcon(":/Icons/flags/south_korea.png");
if(iso[1] == 'R') { country_name = tr("South Korea"); return QIcon(":/Icons/flags/south_korea.png"); }
break;
case 'L':
if(iso[1] == 'U') return QIcon(":/Icons/flags/luxembourg.png");
if(iso[1] == 'U') { country_name = tr("Luxembourg"); return QIcon(":/Icons/flags/luxembourg.png"); }
break;
case 'M':
if(iso[1] == 'Y') return QIcon(":/Icons/flags/malaysia.png");
if(iso[1] == 'X') return QIcon(":/Icons/flags/mexico.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/serbia.png");
if(iso[1] == 'A') return QIcon(":/Icons/flags/morocco.png");
if(iso[1] == 'Y') { country_name = tr("Malaysia"); return QIcon(":/Icons/flags/malaysia.png"); }
if(iso[1] == 'X') { country_name = tr("Mexico"); return QIcon(":/Icons/flags/mexico.png"); }
if(iso[1] == 'E') { country_name = tr("Serbia"); return QIcon(":/Icons/flags/serbia.png"); }
if(iso[1] == 'A') { country_name = tr("Morocco"); return QIcon(":/Icons/flags/morocco.png"); }
break;
case 'N':
if(iso[1] == 'L') return QIcon(":/Icons/flags/netherlands.png");
if(iso[1] == 'O') return QIcon(":/Icons/flags/norway.png");
if(iso[1] == 'Z') return QIcon(":/Icons/flags/newzealand.png");
if(iso[1] == 'L') { country_name = tr("Netherlands"); return QIcon(":/Icons/flags/netherlands.png"); }
if(iso[1] == 'O') { country_name = tr("Norway"); return QIcon(":/Icons/flags/norway.png"); }
if(iso[1] == 'Z') { country_name = tr("New Zealand"); return QIcon(":/Icons/flags/newzealand.png"); }
break;
case 'P':
if(iso[1] == 'T') return QIcon(":/Icons/flags/portugal.png");
if(iso[1] == 'L') return QIcon(":/Icons/flags/poland.png");
if(iso[1] == 'K') return QIcon(":/Icons/flags/pakistan.png");
if(iso[1] == 'H') return QIcon(":/Icons/flags/philippines.png");
if(iso[1] == 'T') { country_name = tr("Portugal"); return QIcon(":/Icons/flags/portugal.png"); }
if(iso[1] == 'L') { country_name = tr("Poland"); return QIcon(":/Icons/flags/poland.png"); }
if(iso[1] == 'K') { country_name = tr("Pakistan"); return QIcon(":/Icons/flags/pakistan.png"); }
if(iso[1] == 'H') { country_name = tr("Philippines"); return QIcon(":/Icons/flags/philippines.png"); }
break;
case 'R':
if(iso[1] == 'U') return QIcon(":/Icons/flags/russia.png");
if(iso[1] == 'O') return QIcon(":/Icons/flags/romania.png");
if(iso[1] == 'E') return QIcon(":/Icons/flags/france.png");
if(iso[1] == 'S') return QIcon(":/Icons/flags/serbia.png");
if(iso[1] == 'U') { country_name = tr("Russia"); return QIcon(":/Icons/flags/russia.png"); }
if(iso[1] == 'O') { country_name = tr("Romania"); return QIcon(":/Icons/flags/romania.png"); }
if(iso[1] == 'E') { country_name = tr("France (Reunion Island)"); return QIcon(":/Icons/flags/france.png"); }
if(iso[1] == 'S') { country_name = tr("Serbia"); return QIcon(":/Icons/flags/serbia.png"); }
break;
case 'S':
if(iso[1] == 'E') return QIcon(":/Icons/flags/sweden.png");
if(iso[1] == 'K') return QIcon(":/Icons/flags/slovakia.png");
if(iso[1] == 'G') return QIcon(":/Icons/flags/singapore.png");
if(iso[1] == 'I') return QIcon(":/Icons/flags/slovenia.png");
if(iso[1] == 'A') { country_name = tr("Saudi Arabia"); return QIcon(":/Icons/flags/saoudi_arabia.png"); }
if(iso[1] == 'E') { country_name = tr("Sweden"); return QIcon(":/Icons/flags/sweden.png"); }
if(iso[1] == 'K') { country_name = tr("Slovakia"); return QIcon(":/Icons/flags/slovakia.png"); }
if(iso[1] == 'G') { country_name = tr("Singapore"); return QIcon(":/Icons/flags/singapore.png"); }
if(iso[1] == 'I') { country_name = tr("Slovenia"); return QIcon(":/Icons/flags/slovenia.png"); }
break;
case 'T':
if(iso[1] == 'W') return QIcon(":/Icons/flags/china.png");
if(iso[1] == 'R') return QIcon(":/Icons/flags/turkey.png");
if(iso[1] == 'H') return QIcon(":/Icons/flags/thailand.png");
if(iso[1] == 'W') { country_name = tr("Taiwan"); return QIcon(":/Icons/flags/china.png"); }
if(iso[1] == 'R') { country_name = tr("Turkey"); return QIcon(":/Icons/flags/turkey.png"); }
if(iso[1] == 'H') { country_name = tr("Thailand"); return QIcon(":/Icons/flags/thailand.png"); }
break;
case 'U':
if(iso[1] == 'S') return QIcon(":/Icons/flags/usa.png");
if(iso[1] == 'M') return QIcon(":/Icons/flags/usa.png");
if(iso[1] == 'A') return QIcon(":/Icons/flags/ukraine.png");
if(iso[1] == 'S') { country_name = tr("USA"); return QIcon(":/Icons/flags/usa.png"); }
if(iso[1] == 'M') { country_name = tr("USA"); return QIcon(":/Icons/flags/usa.png"); }
if(iso[1] == 'A') { country_name = tr("Ukraine"); return QIcon(":/Icons/flags/ukraine.png"); }
break;
case 'Z':
if(iso[1] == 'A') return QIcon(":/Icons/flags/south_africa.png");
if(iso[1] == 'A') { country_name = tr("South Africa"); return QIcon(":/Icons/flags/south_africa.png"); }
break;
}
qDebug("Unrecognized country code: %c%c", iso[0], iso[1]);

View File

@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/" >
<file>geoip/GeoIP.dat</file>
</qresource>
</RCC>
<RCC>
<qresource>
<file>geoip/GeoIP.dat</file>
</qresource>
</RCC>

508
src/gpl.html Normal file
View File

@@ -0,0 +1,508 @@
<p>qBittorrent is licensed under the GNU General Public License version 2 with the
addition of the following special exception:</p>
<p>
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.</p>
----------
<h2>GNU General Public License, version 2</h2>
<hr>
<h3>Table of Contents</h3>
<ul>
<li><a name="TOC1" href="#SEC1">GNU GENERAL PUBLIC
LICENSE<!--TRANSLATORS: Don't translate the license; copy msgid's
verbatim!--></a>
<ul>
<li><a name="TOC2" href="#SEC2">Preamble</a></li>
<li><a name="TOC3" href="#SEC3">TERMS AND CONDITIONS
FOR COPYING, DISTRIBUTION AND MODIFICATION</a></li>
<li><a name="TOC4" href="#SEC4">How to Apply These
Terms to Your New Programs</a></li>
</ul></li>
</ul>
<hr>
<h3><a name="SEC1" href="#TOC1">GNU GENERAL PUBLIC LICENSE</a></h3>
<p>
Version 2, June 1991
</p>
<pre>
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
</pre>
<h3><a name="preamble"></a><a name="SEC2" href="#TOC2">Preamble</a></h3>
<p>
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
</p>
<p>
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
</p>
<p>
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
</p>
<p>
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
</p>
<p>
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
</p>
<p>
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
</p>
<p>
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
</p>
<p>
The precise terms and conditions for copying, distribution and
modification follow.
</p>
<h3><a name="terms"></a><a name="SEC3" href="#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a></h3>
<a name="section0"></a><p>
<strong>0.</strong>
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
</p>
<p>
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
</p>
<a name="section1"></a><p>
<strong>1.</strong>
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
</p>
<p>
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
</p>
<a name="section2"></a><p>
<strong>2.</strong>
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
</p>
<dl>
<dt></dt>
<dd>
<strong>a)</strong>
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
</dd>
<dt></dt>
<dd>
<strong>b)</strong>
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
</dd>
<dt></dt>
<dd>
<strong>c)</strong>
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
</dd>
</dl>
<p>
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
</p>
<p>
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
</p>
<p>
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
</p>
<a name="section3"></a><p>
<strong>3.</strong>
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
</p>
<!-- we use this doubled UL to get the sub-sections indented, -->
<!-- while making the bullets as unobvious as possible. -->
<dl>
<dt></dt>
<dd>
<strong>a)</strong>
Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
</dd>
<dt></dt>
<dd>
<strong>b)</strong>
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
</dd>
<dt></dt>
<dd>
<strong>c)</strong>
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
</dd>
</dl>
<p>
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
</p>
<p>
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
</p>
<a name="section4"></a><p>
<strong>4.</strong>
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
</p>
<a name="section5"></a><p>
<strong>5.</strong>
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
</p>
<a name="section6"></a><p>
<strong>6.</strong>
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
</p>
<a name="section7"></a><p>
<strong>7.</strong>
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
</p>
<p>
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
</p>
<p>
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
</p>
<p>
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
</p>
<a name="section8"></a><p>
<strong>8.</strong>
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
</p>
<a name="section9"></a><p>
<strong>9.</strong>
The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
</p>
<p>
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
</p>
<a name="section10"></a><p>
<strong>10.</strong>
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
</p>
<a name="section11"></a><p><strong>NO WARRANTY</strong></p>
<p>
<strong>11.</strong>
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
</p>
<a name="section12"></a><p>
<strong>12.</strong>
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
</p>
<h3>END OF TERMS AND CONDITIONS</h3>
<h3><a name="howto"></a><a name="SEC4" href="#TOC4">How to Apply These Terms to Your New Programs</a></h3>
<p>
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
</p>
<p>
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
</p>
<pre>
<var>one line to give the program's name and an idea of what it does.</var>
Copyright (C) <var>yyyy</var> <var>name of author</var>
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.
</pre>
<p>
Also add information on how to contact you by electronic and paper mail.
</p>
<p>
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
</p>
<pre>
Gnomovision version 69, Copyright (C) <var>year</var> <var>name of author</var>
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
</pre>
<p>
The hypothetical commands <samp>`show w'</samp> and <samp>`show c'</samp> should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than <samp>`show w'</samp> and
<samp>`show c'</samp>; they could even be mouse-clicks or menu items--whatever
suits your program.
</p>
<p>
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
</p>
<pre>
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
<var>signature of Ty Coon</var>, 1 April 1989
Ty Coon, President of Vice
</pre>
<p>
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the
<a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General Public License</a>
instead of this License.
</p>

View File

@@ -33,105 +33,77 @@
#include <QObject>
#include <QCoreApplication>
#include <QLocalServer>
#include <QLocalSocket>
#include "preferences.h"
#include "bittorrent.h"
class HeadlessLoader: QObject {
class HeadlessLoader: public QObject {
Q_OBJECT
private:
QLocalServer *localServer;
Bittorrent *BTSession;
public:
HeadlessLoader(QStringList torrentCmdLine) {
// Enable Web UI
Preferences::setWebUiEnabled(true);
// Instanciate Bittorrent Object
BTSession = new Bittorrent();
connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString)));
// Resume unfinished torrents
BTSession->startUpTorrents();
// Process command line parameters
processParams(torrentCmdLine);
// Use a tcp server to allow only one instance of qBittorrent
localServer = new QLocalServer();
QString uid = QString::number(getuid());
#ifdef Q_WS_X11
if(QFile::exists(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid)) {
// Socket was not closed cleanly
std::cerr << "Warning: Local domain socket was not closed cleanly, deleting file...\n";
QFile::remove(QDir::tempPath()+QDir::separator()+QString("qBittorrent-")+uid);
}
#endif
if (!localServer->listen("qBittorrent-"+uid)) {
std::cerr << "Couldn't create socket, single instance mode won't work...\n";
}
connect(localServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
// Display some information to the user
std::cout << std::endl << "******** " << tr("Information").toLocal8Bit().data() << " ********" << std::endl;
std::cout << tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort())).toLocal8Bit().data() << std::endl;
std::cout << tr("The Web UI administrator user name is: %1").arg(Preferences::getWebUiUsername()).toLocal8Bit().data() << std::endl;
if(Preferences::getWebUiPassword() == "f6fdffe48c908deb0f4c3bd36c032e72") {
std::cout << tr("The Web UI administrator password is still the default one: %1").arg("adminadmin").toLocal8Bit().data() << std::endl;
std::cout << tr("This is a security risk, please consider changing your password from program preferences.").toLocal8Bit().data() << std::endl;
}
public:
HeadlessLoader(QStringList torrentCmdLine) {
// Enable Web UI
Preferences::setWebUiEnabled(true);
// Instanciate Bittorrent Object
BTSession = new Bittorrent();
connect(BTSession, SIGNAL(newConsoleMessage(QString)), this, SLOT(displayConsoleMessage(QString)));
// Resume unfinished torrents
BTSession->startUpTorrents();
// Process command line parameters
processParams(torrentCmdLine);
// Display some information to the user
std::cout << std::endl << "******** " << qPrintable(tr("Information")) << " ********" << std::endl;
std::cout << qPrintable(tr("To control qBittorrent, access the Web UI at http://localhost:%1").arg(QString::number(Preferences::getWebUiPort()))) << std::endl;
std::cout << qPrintable(tr("The Web UI administrator user name is: %1").arg(Preferences::getWebUiUsername())) << std::endl;
if(Preferences::getWebUiPassword() == "f6fdffe48c908deb0f4c3bd36c032e72") {
std::cout << qPrintable(tr("The Web UI administrator password is still the default one: %1").arg("adminadmin")) << std::endl;
std::cout << qPrintable(tr("This is a security risk, please consider changing your password from program preferences.")) << std::endl;
}
}
~HeadlessLoader() {
delete BTSession;
}
~HeadlessLoader() {
delete BTSession;
}
public slots:
// Call this function to exit qBittorrent headless loader
// and return to prompt (object will be deleted by main)
void exit() {
qApp->quit();
}
public slots:
// Call this function to exit qBittorrent headless loader
// and return to prompt (object will be deleted by main)
void exit() {
qApp->quit();
}
void displayConsoleMessage(QString msg) {
std::cout << msg.toLocal8Bit().data() << std::endl;
}
void displayConsoleMessage(QString msg) {
std::cout << qPrintable(msg) << std::endl;
}
// As program parameters, we can get paths or urls.
// This function parse the parameters and call
// the right addTorrent function, considering
// the parameter type.
void processParams(const QStringList& params) {
foreach(QString param, params) {
param = param.trimmed();
if(param.startsWith("--")) continue;
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
BTSession->downloadFromUrl(param);
}else{
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
BTSession->addMagnetUri(param);
} else {
BTSession->addTorrent(param);
}
void processParams(const QString& params_str) {
processParams(params_str.split(" ", QString::SkipEmptyParts));
}
// As program parameters, we can get paths or urls.
// This function parse the parameters and call
// the right addTorrent function, considering
// the parameter type.
void processParams(const QStringList& params) {
foreach(QString param, params) {
param = param.trimmed();
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
BTSession->downloadFromUrl(param);
}else{
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) {
qDebug("Converting bc link to magnet link");
param = misc::bcLinkToMagnet(param);
}
if(param.startsWith("magnet:", Qt::CaseInsensitive)) {
BTSession->addMagnetUri(param);
} else {
BTSession->addTorrent(param);
}
}
}
}
void acceptConnection() {
QLocalSocket *clientConnection = localServer->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(readParamsOnSocket()));
qDebug("accepted connection from another instance");
}
void readParamsOnSocket() {
QLocalSocket *clientConnection = static_cast<QLocalSocket*>(sender());
if(clientConnection) {
QByteArray params = clientConnection->readAll();
if(!params.isEmpty()) {
processParams(QString::fromUtf8(params.data()).split(QString::fromUtf8("\n")));
qDebug("Received parameters from another instance");
}
clientConnection->deleteLater();
}
}
private:
Bittorrent *BTSession;
};

44
src/hidabletabwidget.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* 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 HIDABLETABWIDGET_H
#define HIDABLETABWIDGET_H
#include <QTabWidget>
#include <QTabBar>
class HidableTabWidget : public QTabWidget {
public:
void showTabBar(bool show) {
tabBar()->setVisible(show);
}
};
#endif // HIDABLETABWIDGET_H

View File

@@ -35,6 +35,7 @@
#include "preferences.h"
#include "json.h"
#include "bittorrent.h"
#include "misc.h"
#include <QTcpSocket>
#include <QDateTime>
#include <QStringList>
@@ -46,7 +47,7 @@
#include <QTemporaryFile>
HttpConnection::HttpConnection(QTcpSocket *socket, Bittorrent *BTSession, HttpServer *parent)
: QObject(parent), socket(socket), parent(parent), BTSession(BTSession)
: QObject(parent), socket(socket), parent(parent), BTSession(BTSession)
{
socket->setParent(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(read()));
@@ -103,12 +104,12 @@ void HttpConnection::write()
}
QString HttpConnection::translateDocument(QString data) {
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg", "TrackerList", "TorrentFilesModel", "options_imp", "Preferences"};
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg", "TrackerList", "TorrentFilesModel", "options_imp", "Preferences", "TrackersAdditionDlg", "ScanFoldersModel"};
int i=0;
bool found = false;
do {
found = false;
QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),µ\\-\\.]+)\\)"));
QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),%µ&\\-\\.]+)\\)"));
i = regex.indexIn(data, i);
if(i >= 0) {
//qDebug("Found translatable string: %s", regex.cap(1).toUtf8().data());
@@ -116,9 +117,11 @@ QString HttpConnection::translateDocument(QString data) {
QString translation = word;
int context_index= 0;
do {
translation = qApp->translate(contexts[context_index].c_str(), word.toLocal8Bit().data(), 0, QCoreApplication::UnicodeUTF8, 1);
translation = qApp->translate(contexts[context_index].c_str(), word.toLocal8Bit().constData(), 0, QCoreApplication::UnicodeUTF8, 1);
++context_index;
}while(translation == word && context_index < 11);
}while(translation == word && context_index < 13);
// Remove keyboard shortcuts
translation = translation.replace("&", "");
//qDebug("Translation is %s", translation.toUtf8().data());
data = data.replace(i, regex.matchedLength(), translation);
i += translation.length();
@@ -130,26 +133,36 @@ QString HttpConnection::translateDocument(QString data) {
void HttpConnection::respond() {
//qDebug("Respond called");
int nb_fail = parent->client_failed_attempts.value(socket->peerAddress().toString(), 0);
if(nb_fail > 4) {
const QString peer_ip = socket->peerAddress().toString();
const int nb_fail = parent->NbFailedAttemptsForIp(peer_ip);
if(nb_fail >= MAX_AUTH_FAILED_ATTEMPTS) {
generator.setStatusLine(403, "Forbidden");
generator.setMessage(tr("Your IP address has been banned after too many failed authentication attempts."));
write();
return;
}
QString auth = parser.value("Authorization");
if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth.toLocal8Bit(), parser.method())) {
// Update failed attempt counter
parent->client_failed_attempts.insert(socket->peerAddress().toString(), nb_fail+1);
qDebug("client IP: %s (%d failed attempts)", socket->peerAddress().toString().toLocal8Bit().data(), nb_fail);
if(auth.isEmpty()) {
// Return unauthorized header
qDebug("Auth is Empty...");
generator.setStatusLine(401, "Unauthorized");
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", algorithm=\"MD5\", qop=\"auth\"");
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", opaque=\""+parent->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\"");
write();
return;
}
// Client sucessfuly authenticated, reset number of failed attempts
parent->client_failed_attempts.remove(socket->peerAddress().toString());
//qDebug("Auth: %s", qPrintable(auth.split(" ").first()));
if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth.toLocal8Bit(), parser.method())) {
// Update failed attempt counter
parent->increaseNbFailedAttemptsForIp(peer_ip);
qDebug("client IP: %s (%d failed attempts)", qPrintable(peer_ip), nb_fail+1);
// Return unauthorized header
generator.setStatusLine(401, "Unauthorized");
generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", opaque=\""+parent->generateNonce()+"\", stale=\"false\", algorithm=\"MD5\", qop=\"auth\"");
write();
return;
}
// Client successfully authenticated, reset number of failed attempts
parent->resetNbFailedAttemptsForIp(peer_ip);
QString url = parser.url();
// Favicon
if(url.endsWith("favicon.ico")) {
@@ -202,6 +215,10 @@ void HttpConnection::respond() {
} else {
if(list[1] == "preferences") {
respondPreferencesJson();
} else {
if(list[1] == "transferInfo") {
respondGlobalTransferInfoJson();
}
}
}
}
@@ -219,10 +236,10 @@ void HttpConnection::respond() {
else
list.prepend("webui");
url = ":/" + list.join("/");
//qDebug("Resource URL: %s", url.toLocal8Bit().data());
QFile file(url);
if(!file.open(QIODevice::ReadOnly))
{
qDebug("File %s was not found!", qPrintable(url));
respondNotFound();
return;
}
@@ -255,7 +272,6 @@ void HttpConnection::respondJson()
QString string = json::toJson(manager->getEventList());
generator.setStatusLine(200, "OK");
generator.setContentTypeByExt("js");
//qDebug("JSON: %s", string.toLocal8Bit().data());
generator.setMessage(string);
write();
}
@@ -284,7 +300,6 @@ void HttpConnection::respondFilesPropertiesJson(QString hash) {
generator.setStatusLine(200, "OK");
generator.setContentTypeByExt("js");
generator.setMessage(string);
//qDebug("JSON: %s", string.toLocal8Bit().data());
write();
}
@@ -297,6 +312,18 @@ void HttpConnection::respondPreferencesJson() {
write();
}
void HttpConnection::respondGlobalTransferInfoJson() {
QVariantMap info;
session_status sessionStatus = BTSession->getSessionStatus();
info["DlInfos"] = tr("D: %1/s - T: %2", "Download speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_download_rate)).arg(misc::friendlyUnit(sessionStatus.total_payload_download));
info["UpInfos"] = tr("U: %1/s - T: %2", "Upload speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_upload_rate)).arg(misc::friendlyUnit(sessionStatus.total_payload_upload));
QString string = json::toJson(info);
generator.setStatusLine(200, "OK");
generator.setContentTypeByExt("js");
generator.setMessage(string);
write();
}
void HttpConnection::respondCommand(QString command)
{
if(command == "download")
@@ -306,6 +333,10 @@ void HttpConnection::respondCommand(QString command)
foreach(QString url, list){
url = url.trimmed();
if(!url.isEmpty()){
if(url.startsWith("bc://bt/", Qt::CaseInsensitive)) {
qDebug("Converting bc link to magnet link");
url = misc::bcLinkToMagnet(url);
}
if(url.startsWith("magnet:", Qt::CaseInsensitive)) {
emit MagnetReadyToBeDownloaded(url);
} else {
@@ -316,6 +347,20 @@ void HttpConnection::respondCommand(QString command)
}
return;
}
if(command == "addTrackers") {
QString hash = parser.post("hash");
if(!hash.isEmpty()) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(h.is_valid() && h.has_metadata()) {
QString urls = parser.post("urls");
QStringList list = urls.split('\n');
foreach(QString url, list) {
announce_entry e(url.toStdString());
h.add_tracker(e);
}
}
}
}
if(command == "upload")
{
QByteArray torrentfile = parser.torrent();
@@ -359,7 +404,6 @@ void HttpConnection::respondCommand(QString command)
}
if(command == "setPreferences") {
QString json_str = parser.post("json");
//qDebug("setPreferences, json: %s", json_str.toLocal8Bit().data());
EventManager* manager = parent->eventManager();
manager->setGlobalPreferences(json::fromJson(json_str));
}
@@ -422,6 +466,18 @@ void HttpConnection::respondCommand(QString command)
h.set_download_limit(limit);
}
}
if(command == "setGlobalUpLimit") {
qlonglong limit = parser.post("limit").toLongLong();
if(limit == 0) limit = -1;
BTSession->getSession()->set_upload_rate_limit(limit);
Preferences::setGlobalUploadLimit(limit/1024.);
}
if(command == "setGlobalDlLimit") {
qlonglong limit = parser.post("limit").toLongLong();
if(limit == 0) limit = -1;
BTSession->getSession()->set_download_rate_limit(limit);
Preferences::setGlobalDownloadLimit(limit/1024.);
}
if(command == "pause") {
emit pauseTorrent(parser.post("hash"));
return;
@@ -444,6 +500,16 @@ void HttpConnection::respondCommand(QString command)
if(h.is_valid()) h.queue_position_down();
return;
}
if(command == "topPrio") {
QTorrentHandle h = BTSession->getTorrentHandle(parser.post("hash"));
if(h.is_valid()) h.queue_position_top();
return;
}
if(command == "bottomPrio") {
QTorrentHandle h = BTSession->getTorrentHandle(parser.post("hash"));
if(h.is_valid()) h.queue_position_bottom();
return;
}
if(command == "recheck"){
recheckTorrent(parser.post("hash"));
return;

View File

@@ -60,6 +60,7 @@ class HttpConnection : public QObject
void respondTrackersPropertiesJson(QString hash);
void respondFilesPropertiesJson(QString hash);
void respondPreferencesJson();
void respondGlobalTransferInfoJson();
void respondCommand(QString command);
void respondNotFound();
void processDownloadedFile(QString, QString);

View File

@@ -39,7 +39,8 @@ void HttpResponseGenerator::setMessage(const QByteArray message)
void HttpResponseGenerator::setMessage(const QString message)
{
setMessage(message.QString::toLocal8Bit());
// This must be UTF-8!
setMessage(message.toUtf8());
}
void HttpResponseGenerator::stripMessage()

View File

@@ -37,6 +37,48 @@
#include <QCryptographicHash>
#include <QTime>
#include <QRegExp>
#include <QTimer>
const int BAN_TIME = 3600000; // 1 hour
class UnbanTimer: public QTimer {
public:
UnbanTimer(QObject *parent, QString peer_ip): QTimer(parent), peer_ip(peer_ip){
setSingleShot(true);
setInterval(BAN_TIME);
}
~UnbanTimer() {
qDebug("||||||||||||Deleting ban timer|||||||||||||||");
}
QString peer_ip;
};
void HttpServer::UnbanTimerEvent() {
UnbanTimer* ubantimer = static_cast<UnbanTimer*>(sender());
qDebug("Ban period has expired for %s", qPrintable(ubantimer->peer_ip));
client_failed_attempts.remove(ubantimer->peer_ip);
ubantimer->deleteLater();
}
int HttpServer::NbFailedAttemptsForIp(QString ip) const {
return client_failed_attempts.value(ip, 0);
}
void HttpServer::increaseNbFailedAttemptsForIp(QString ip) {
const int nb_fail = client_failed_attempts.value(ip, 0);
client_failed_attempts.insert(ip, nb_fail+1);
if(nb_fail == MAX_AUTH_FAILED_ATTEMPTS-1) {
// Max number of failed attempts reached
// Start ban period
UnbanTimer* ubantimer = new UnbanTimer(this, ip);
connect(ubantimer, SIGNAL(timeout()), this, SLOT(UnbanTimerEvent()));
ubantimer->start();
}
}
void HttpServer::resetNbFailedAttemptsForIp(QString ip) {
client_failed_attempts.remove(ip);
}
HttpServer::HttpServer(Bittorrent *_BTSession, int msec, QObject* parent) : QTcpServer(parent) {
username = Preferences::getWebUiUsername().toLocal8Bit();
@@ -132,26 +174,22 @@ void HttpServer::setAuthorization(QString _username, QString _password_ha1) {
password_ha1 = _password_ha1.toLocal8Bit();
}
// AUTH string is: Digest username="chris",
// realm="Web UI Access",
// nonce="570d04de93444b7fd3eaeaecb00e635e",
// uri="/", algorithm=MD5,
// response="ba886766d19b45313c0e2195e4344264",
// qop=auth, nc=00000001, cnonce="e8ac970779c17075"
// Parse HTTP AUTH string
// http://tools.ietf.org/html/rfc2617
bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
qDebug("AUTH string is %s", auth.data());
//qDebug("AUTH string is %s", auth.data());
// Get user name
QRegExp regex_user(".*username=\"([^\"]+)\".*");
QRegExp regex_user(".*username=\"([^\"]+)\".*"); // Must be a quoted string
if(regex_user.indexIn(auth) < 0) return false;
QString prop_user = regex_user.cap(1);
qDebug("AUTH: Proposed username is %s, real username is %s", prop_user.toLocal8Bit().data(), username.data());
//qDebug("AUTH: Proposed username is %s, real username is %s", prop_user.toLocal8Bit().data(), username.data());
if(prop_user != username) {
// User name is invalid, we can reject already
qDebug("AUTH-PROB: Username is invalid");
return false;
}
// Get realm
QRegExp regex_realm(".*realm=\"([^\"]+)\".*");
QRegExp regex_realm(".*realm=\"([^\"]+)\".*"); // Must be a quoted string
if(regex_realm.indexIn(auth) < 0) {
qDebug("AUTH-PROB: Missing realm");
return false;
@@ -162,7 +200,7 @@ bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
return false;
}
// get nonce
QRegExp regex_nonce(".*nonce=\"([^\"]+)\".*");
QRegExp regex_nonce(".*nonce=[\"]?([\\w=]+)[\"]?.*");
if(regex_nonce.indexIn(auth) < 0) {
qDebug("AUTH-PROB: missing nonce");
return false;
@@ -178,7 +216,7 @@ bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
QByteArray prop_uri = regex_uri.cap(1).toLocal8Bit();
qDebug("prop uri is: %s", prop_uri.data());
// get response
QRegExp regex_response(".*response=\"([^\"]+)\".*");
QRegExp regex_response(".*response=[\"]?([\\w=]+)[\"]?.*");
if(regex_response.indexIn(auth) < 0) {
qDebug("AUTH-PROB: Missing response");
return false;
@@ -193,21 +231,21 @@ bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
if(auth.contains("qop=")) {
QCryptographicHash md5_ha(QCryptographicHash::Md5);
// Get nc
QRegExp regex_nc(".*nc=(\\w+).*");
QRegExp regex_nc(".*nc=[\"]?([\\w=]+)[\"]?.*");
if(regex_nc.indexIn(auth) < 0) {
qDebug("AUTH-PROB: qop but missing nc");
return false;
}
QByteArray prop_nc = regex_nc.cap(1).toLocal8Bit();
qDebug("prop nc is: %s", prop_nc.data());
QRegExp regex_cnonce(".*cnonce=\"([^\"]+)\".*");
QRegExp regex_cnonce(".*cnonce=[\"]?([\\w=]+)[\"]?.*");
if(regex_cnonce.indexIn(auth) < 0) {
qDebug("AUTH-PROB: qop but missing cnonce");
return false;
}
QByteArray prop_cnonce = regex_cnonce.cap(1).toLocal8Bit();
qDebug("prop cnonce is: %s", prop_cnonce.data());
QRegExp regex_qop(".*qop=(\\w+).*");
QRegExp regex_qop(".*qop=[\"]?(\\w+)[\"]?.*");
if(regex_qop.indexIn(auth) < 0) {
qDebug("AUTH-PROB: missing qop");
return false;
@@ -221,7 +259,7 @@ bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
md5_ha.addData(password_ha1+":"+prop_nonce+":"+ha2);
response = md5_ha.result().toHex();
}
qDebug("AUTH: comparing reponses");
qDebug("AUTH: comparing reponses: (%d)", static_cast<int>(prop_response == response));
return prop_response == response;
}

View File

@@ -42,28 +42,34 @@ class Bittorrent;
class QTimer;
class EventManager;
const int MAX_AUTH_FAILED_ATTEMPTS = 5;
class HttpServer : public QTcpServer {
Q_OBJECT
Q_OBJECT
private:
QByteArray username;
QByteArray password_ha1;
Bittorrent *BTSession;
EventManager *manager;
QTimer *timer;
public:
HttpServer(Bittorrent *BTSession, int msec, QObject* parent = 0);
~HttpServer();
void setAuthorization(QString username, QString password_ha1);
bool isAuthorized(QByteArray auth, QString method) const;
EventManager *eventManager() const;
QString generateNonce() const;
int NbFailedAttemptsForIp(QString ip) const;
void increaseNbFailedAttemptsForIp(QString ip);
void resetNbFailedAttemptsForIp(QString ip);
public:
HttpServer(Bittorrent *BTSession, int msec, QObject* parent = 0);
~HttpServer();
void setAuthorization(QString username, QString password_ha1);
bool isAuthorized(QByteArray auth, QString method) const;
EventManager *eventManager() const;
QString generateNonce() const;
QHash<QString, int> client_failed_attempts;
private slots:
void newHttpConnection();
void onTimer();
void UnbanTimerEvent();
private slots:
void newHttpConnection();
void onTimer();
private:
QByteArray username;
QByteArray password_ha1;
Bittorrent *BTSession;
EventManager *manager;
QTimer *timer;
QHash<QString, int> client_failed_attempts;
};
#endif

View File

@@ -1,177 +1,183 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>Icons/rss32.png</file>
<file>Icons/sphere2.png</file>
<file>Icons/downarrow.png</file>
<file>Icons/url.png</file>
<file>Icons/locale.png</file>
<file>Icons/loading.png</file>
<file>Icons/magnet.png</file>
<file>Icons/sphere.png</file>
<file>Icons/uparrow.png</file>
<file>Icons/rss16.png</file>
<file>Icons/skin/checkingUP.png</file>
<file>Icons/skin/bg-handle-horizontal.gif</file>
<file>Icons/skin/play.png</file>
<file>Icons/skin/qbittorrent22.png</file>
<file>Icons/skin/queuedDL.png</file>
<file>Icons/skin/new.png</file>
<file>Icons/skin/queuedUP.png</file>
<file>Icons/skin/preview.png</file>
<file>Icons/skin/stalled.png</file>
<file>Icons/skin/delete.png</file>
<file>Icons/skin/handle-icon-horizontal.gif</file>
<file>Icons/skin/handle-icon.gif</file>
<file>Icons/skin/knob.gif</file>
<file>Icons/skin/url.png</file>
<file>Icons/skin/stalledUP.png</file>
<file>Icons/rss32.png</file>
<file>Icons/3-state-checkbox.gif</file>
<file>Icons/uparrow.png</file>
<file>Icons/sphere.png</file>
<file>Icons/downarrow.png</file>
<file>Icons/slow_off.png</file>
<file>Icons/sphere2.png</file>
<file>Icons/magnet.png</file>
<file>Icons/slow.png</file>
<file>Icons/L.gif</file>
<file>Icons/skin/delete_perm22.png</file>
<file>Icons/skin/filteractive.png</file>
<file>Icons/skin/connected.png</file>
<file>Icons/skin/pausedDL.png</file>
<file>Icons/skin/mascot.png</file>
<file>Icons/skin/pausedUP.png</file>
<file>Icons/skin/seeding.png</file>
<file>Icons/skin/increase.png</file>
<file>Icons/skin/qbittorrent32.png</file>
<file>Icons/skin/paused.png</file>
<file>Icons/skin/toolbox-divider.gif</file>
<file>Icons/skin/stalledDL.png</file>
<file>Icons/skin/qb_question.png</file>
<file>Icons/skin/download.png</file>
<file>Icons/skin/open.png</file>
<file>Icons/skin/play22.png</file>
<file>Icons/skin/qbittorrent16.png</file>
<file>Icons/skin/slider-area.gif</file>
<file>Icons/skin/downloading.png</file>
<file>Icons/skin/filterinactive.png</file>
<file>Icons/skin/pause22.png</file>
<file>Icons/skin/pause_all.png</file>
<file>Icons/skin/delete22.png</file>
<file>Icons/skin/play_all.png</file>
<file>Icons/skin/pause.png</file>
<file>Icons/skin/firewalled.png</file>
<file>Icons/skin/properties.png</file>
<file>Icons/skin/info.png</file>
<file>Icons/skin/tabs.gif</file>
<file>Icons/skin/delete_perm.png</file>
<file>Icons/skin/checkingDL.png</file>
<file>Icons/skin/settings.png</file>
<file>Icons/skin/exit.png</file>
<file>Icons/skin/delete_all.png</file>
<file>Icons/skin/splash.png</file>
<file>Icons/skin/preview.png</file>
<file>Icons/skin/tabs.gif</file>
<file>Icons/skin/delete.png</file>
<file>Icons/skin/increase.png</file>
<file>Icons/skin/qbittorrent16.png</file>
<file>Icons/skin/connected.png</file>
<file>Icons/skin/url.png</file>
<file>Icons/skin/qbittorrent22.png</file>
<file>Icons/skin/disconnected.png</file>
<file>Icons/skin/decrease.png</file>
<file>Icons/skin/uploading.png</file>
<file>Icons/skin/mascot.png</file>
<file>Icons/skin/info.png</file>
<file>Icons/skin/paused.png</file>
<file>Icons/skin/slider-area.gif</file>
<file>Icons/skin/pause22.png</file>
<file>Icons/skin/stalledDL.png</file>
<file>Icons/skin/play.png</file>
<file>Icons/skin/delete_all.png</file>
<file>Icons/skin/delete_perm.png</file>
<file>Icons/skin/qb_question.png</file>
<file>Icons/skin/error.png</file>
<file>Icons/skin/settings.png</file>
<file>Icons/skin/handle-icon-horizontal.gif</file>
<file>Icons/skin/pause.png</file>
<file>Icons/skin/qbittorrent32.png</file>
<file>Icons/skin/exit.png</file>
<file>Icons/skin/knob.gif</file>
<file>Icons/skin/open.png</file>
<file>Icons/skin/pause_all.png</file>
<file>Icons/skin/filterall.png</file>
<file>Icons/flags/czech.png</file>
<file>Icons/flags/serbia.png</file>
<file>Icons/flags/iceland.png</file>
<file>Icons/flags/china.png</file>
<file>Icons/flags/luxembourg.png</file>
<file>Icons/flags/newzealand.png</file>
<file>Icons/flags/austria.png</file>
<file>Icons/flags/indonesia.png</file>
<file>Icons/flags/united_arab_emirates.png</file>
<file>Icons/flags/norway.png</file>
<file>Icons/flags/india.png</file>
<file>Icons/flags/finland.png</file>
<file>Icons/flags/australia.png</file>
<file>Icons/skin/uploading.png</file>
<file>Icons/skin/queued.png</file>
<file>Icons/skin/checking.png</file>
<file>Icons/skin/handle-icon.gif</file>
<file>Icons/skin/arrow-right.gif</file>
<file>Icons/skin/filterinactive.png</file>
<file>Icons/skin/decrease.png</file>
<file>Icons/skin/play22.png</file>
<file>Icons/skin/firewalled.png</file>
<file>Icons/skin/delete22.png</file>
<file>Icons/skin/new.png</file>
<file>Icons/skin/downloading.png</file>
<file>Icons/skin/play_all.png</file>
<file>Icons/skin/toolbox-divider.gif</file>
<file>Icons/skin/stalledUP.png</file>
<file>Icons/skin/filteractive.png</file>
<file>Icons/skin/bg-handle-horizontal.gif</file>
<file>Icons/skin/download.png</file>
<file>Icons/flags/pakistan.png</file>
<file>Icons/flags/argentina.png</file>
<file>Icons/flags/netherlands.png</file>
<file>Icons/flags/south_africa.png</file>
<file>Icons/flags/belarus.png</file>
<file>Icons/flags/georgia.png</file>
<file>Icons/flags/taiwan.png</file>
<file>Icons/flags/sweden.png</file>
<file>Icons/flags/spain_catalunya.png</file>
<file>Icons/flags/ireland.png</file>
<file>Icons/flags/singapore.png</file>
<file>Icons/flags/israel.png</file>
<file>Icons/flags/belgium.png</file>
<file>Icons/flags/usa.png</file>
<file>Icons/flags/costa_rica.png</file>
<file>Icons/flags/romania.png</file>
<file>Icons/flags/suisse.png</file>
<file>Icons/flags/australia.png</file>
<file>Icons/flags/finland.png</file>
<file>Icons/flags/croatia.png</file>
<file>Icons/flags/mexico.png</file>
<file>Icons/flags/indonesia.png</file>
<file>Icons/flags/greece.png</file>
<file>Icons/flags/belarus.png</file>
<file>Icons/flags/morocco.png</file>
<file>Icons/flags/portugal.png</file>
<file>Icons/flags/egypt.png</file>
<file>Icons/flags/georgia.png</file>
<file>Icons/flags/costa_rica.png</file>
<file>Icons/flags/denmark.png</file>
<file>Icons/flags/hungary.png</file>
<file>Icons/flags/slovenia.png</file>
<file>Icons/flags/ukraine.png</file>
<file>Icons/flags/bosnia.png</file>
<file>Icons/flags/newzealand.png</file>
<file>Icons/flags/serbia.png</file>
<file>Icons/flags/singapore.png</file>
<file>Icons/flags/italy.png</file>
<file>Icons/flags/brazil.png</file>
<file>Icons/flags/taiwan.png</file>
<file>Icons/flags/south_korea.png</file>
<file>Icons/flags/turkey.png</file>
<file>Icons/flags/algeria.png</file>
<file>Icons/flags/greece.png</file>
<file>Icons/flags/morocco.png</file>
<file>Icons/flags/argentina.png</file>
<file>Icons/flags/spain.png</file>
<file>Icons/flags/portugal.png</file>
<file>Icons/flags/russia.png</file>
<file>Icons/flags/united_kingdom.png</file>
<file>Icons/flags/thailand.png</file>
<file>Icons/flags/poland.png</file>
<file>Icons/flags/germany.png</file>
<file>Icons/flags/bulgaria.png</file>
<file>Icons/flags/canada.png</file>
<file>Icons/flags/brazil.png</file>
<file>Icons/flags/france.png</file>
<file>Icons/flags/slovakia.png</file>
<file>Icons/flags/pakistan.png</file>
<file>Icons/flags/egypt.png</file>
<file>Icons/flags/italy.png</file>
<file>Icons/flags/south_korea.png</file>
<file>Icons/flags/bosnia.png</file>
<file>Icons/flags/japan.png</file>
<file>Icons/flags/malaysia.png</file>
<file>Icons/flags/luxembourg.png</file>
<file>Icons/flags/poland.png</file>
<file>Icons/flags/iceland.png</file>
<file>Icons/flags/spain.png</file>
<file>Icons/flags/saoudi_arabia.png</file>
<file>Icons/flags/norway.png</file>
<file>Icons/flags/russia.png</file>
<file>Icons/flags/slovakia.png</file>
<file>Icons/flags/philippines.png</file>
<file>Icons/oxygen/mail-queue.png</file>
<file>Icons/oxygen/view-refresh.png</file>
<file>Icons/oxygen/file.png</file>
<file>Icons/oxygen/folder-remote16.png</file>
<file>Icons/oxygen/mail-folder-inbox.png</file>
<file>Icons/oxygen/edit-find.png</file>
<file>Icons/oxygen/folder-new.png</file>
<file>Icons/oxygen/folder-remote.png</file>
<file>Icons/oxygen/edit-paste.png</file>
<file>Icons/oxygen/run-build.png</file>
<file>Icons/oxygen/proxy.png</file>
<file>Icons/oxygen/services.png</file>
<file>Icons/oxygen/user-group-delete.png</file>
<file>Icons/oxygen/user-group-new.png</file>
<file>Icons/oxygen/log.png</file>
<file>Icons/oxygen/unavailable.png</file>
<file>Icons/oxygen/button_ok.png</file>
<file>Icons/oxygen/button_cancel.png</file>
<file>Icons/oxygen/edit-clear.png</file>
<file>Icons/oxygen/filter.png</file>
<file>Icons/oxygen/encrypted.png</file>
<file>Icons/oxygen/edit_clear.png</file>
<file>Icons/oxygen/download.png</file>
<file>Icons/oxygen/gear.png</file>
<file>Icons/oxygen/remove.png</file>
<file>Icons/oxygen/dialog-warning.png</file>
<file>Icons/flags/thailand.png</file>
<file>Icons/flags/israel.png</file>
<file>Icons/flags/bulgaria.png</file>
<file>Icons/flags/czech.png</file>
<file>Icons/flags/usa.png</file>
<file>Icons/flags/malaysia.png</file>
<file>Icons/flags/belgium.png</file>
<file>Icons/flags/south_africa.png</file>
<file>Icons/flags/slovenia.png</file>
<file>Icons/flags/china.png</file>
<file>Icons/flags/germany.png</file>
<file>Icons/flags/ukraine.png</file>
<file>Icons/flags/india.png</file>
<file>Icons/flags/spain_catalunya.png</file>
<file>Icons/flags/romania.png</file>
<file>Icons/flags/united_kingdom.png</file>
<file>Icons/flags/united_arab_emirates.png</file>
<file>Icons/flags/sweden.png</file>
<file>Icons/flags/canada.png</file>
<file>Icons/flags/mexico.png</file>
<file>Icons/flags/hungary.png</file>
<file>Icons/flags/france.png</file>
<file>Icons/flags/ireland.png</file>
<file>Icons/flags/austria.png</file>
<file>Icons/flags/suisse.png</file>
<file>Icons/oxygen/peer.png</file>
<file>Icons/oxygen/browse.png</file>
<file>Icons/oxygen/unsubscribe16.png</file>
<file>Icons/oxygen/unavailable.png</file>
<file>Icons/oxygen/subscribe.png</file>
<file>Icons/oxygen/edit-copy.png</file>
<file>Icons/oxygen/bt_settings.png</file>
<file>Icons/oxygen/document-new.png</file>
<file>Icons/oxygen/preferences-desktop.png</file>
<file>Icons/oxygen/tab-close.png</file>
<file>Icons/oxygen/wallet.png</file>
<file>Icons/oxygen/webui.png</file>
<file>Icons/oxygen/list-remove.png</file>
<file>Icons/oxygen/connection.png</file>
<file>Icons/oxygen/bug.png</file>
<file>Icons/oxygen/help-about.png</file>
<file>Icons/oxygen/list-add.png</file>
<file>Icons/oxygen/network-server.png</file>
<file>Icons/oxygen/dialog-warning.png</file>
<file>Icons/oxygen/mail-folder-inbox.png</file>
<file>Icons/oxygen/folder.png</file>
<file>Icons/oxygen/urlseed.png</file>
<file>Icons/oxygen/edit-copy.png</file>
<file>Icons/oxygen/folder-documents.png</file>
<file>Icons/oxygen/urlseed.png</file>
<file>Icons/oxygen/go-up.png</file>
<file>Icons/oxygen/edit-cut.png</file>
<file>Icons/oxygen/gear32.png</file>
<file>Icons/oxygen/go-bottom.png</file>
<file>Icons/oxygen/user-group-delete.png</file>
<file>Icons/oxygen/unsubscribe.png</file>
<file>Icons/oxygen/tab-close.png</file>
<file>Icons/oxygen/file.png</file>
<file>Icons/oxygen/services.png</file>
<file>Icons/oxygen/view-refresh.png</file>
<file>Icons/oxygen/feed-subscribe.png</file>
<file>Icons/oxygen/remove.png</file>
<file>Icons/oxygen/chronometer.png</file>
<file>Icons/oxygen/filter.png</file>
<file>Icons/oxygen/run-build.png</file>
<file>Icons/oxygen/button_ok.png</file>
<file>Icons/oxygen/user-group-new.png</file>
<file>Icons/oxygen/cookies.png</file>
<file>Icons/oxygen/network-server.png</file>
<file>Icons/oxygen/unsubscribe16.png</file>
<file>Icons/oxygen/encrypted32.png</file>
<file>Icons/oxygen/list-add.png</file>
<file>Icons/oxygen/edit-paste.png</file>
<file>Icons/oxygen/folder-remote.png</file>
<file>Icons/oxygen/help-about.png</file>
<file>Icons/oxygen/encrypted.png</file>
<file>Icons/oxygen/folder-remote16.png</file>
<file>Icons/oxygen/go-top.png</file>
<file>Icons/oxygen/edit_clear.png</file>
<file>Icons/oxygen/bug.png</file>
<file>Icons/oxygen/gear.png</file>
<file>Icons/oxygen/connection.png</file>
<file>Icons/oxygen/document-new.png</file>
<file>Icons/oxygen/browse.png</file>
<file>Icons/oxygen/proxy.png</file>
<file>Icons/oxygen/button_cancel.png</file>
<file>Icons/oxygen/preferences-desktop.png</file>
<file>Icons/oxygen/bt_settings.png</file>
<file>Icons/oxygen/go-down.png</file>
<file>Icons/oxygen/subscribe16.png</file>
<file>Icons/oxygen/download.png</file>
<file>Icons/oxygen/log.png</file>
<file>Icons/oxygen/edit-find.png</file>
<file>Icons/oxygen/edit-clear.png</file>
<file>Icons/oxygen/webui.png</file>
<file>Icons/oxygen/folder-new.png</file>
</qresource>
</RCC>

View File

@@ -41,15 +41,23 @@ namespace json {
return "null";
switch(v.type())
{
case QVariant::Bool:
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
case QVariant::UInt:
case QVariant::ULongLong:
case QMetaType::Float:
case QVariant::Bool:
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
case QVariant::UInt:
case QVariant::ULongLong:
//case QMetaType::Float:
return v.value<QString>();
case QVariant::String:
case QVariant::StringList:
case QVariant::List: {
QStringList strList;
foreach(const QVariant &var, v.toList()) {
strList << toJson(var);
}
return "["+strList.join(",")+"]";
}
case QVariant::String:
{
QString s = v.value<QString>();
QString result = "\"";
@@ -58,35 +66,35 @@ namespace json {
QChar ch = s[i];
switch(ch.toAscii())
{
case '\b':
case '\b':
result += "\\b";
break;
case '\f':
case '\f':
result += "\\f";
break;
case '\n':
case '\n':
result += "\\n";
break;
case '\r':
case '\r':
result += "\\r";
break;
case '\t':
case '\t':
result += "\\t";
break;
case '\"':
case '\'':
case '\\':
case '&':
case '\"':
case '\'':
case '\\':
case '&':
result += '\\';
case '\0':
default:
case '\0':
default:
result += ch;
}
}
result += "\"";
return result;
}
default:
default:
qDebug("Unknown QVariantType: %d", (int)v.type());
return "undefined";
}
@@ -101,11 +109,30 @@ namespace json {
}
QVariantMap fromJson(QString json) {
qDebug("JSON is %s", qPrintable(json));
QVariantMap m;
if(json.startsWith("{") && json.endsWith("}")) {
json.chop(1);
json = json.replace(0, 1, "");
QStringList couples = json.split(",");
QStringList couples;
QString tmp = "";
bool in_list = false;
foreach(QChar c, json) {
if(c == ',' && !in_list) {
couples << tmp;
tmp = "";
} else {
if(c == '[') {
in_list = true;
} else {
if(c == ']') {
in_list = false;
}
}
tmp += c;
}
}
if(!tmp.isEmpty()) couples << tmp;
foreach(QString couple, couples) {
QStringList parts = couple.split(":");
if(parts.size() != 2) continue;
@@ -116,12 +143,29 @@ namespace json {
}
QString value_str = parts.last();
QVariant value;
if(value_str.startsWith("\"") && value_str.endsWith("\"")) {
if(value_str.startsWith("[") && value_str.endsWith("]")) {
value_str.chop(1);
value_str = value_str.replace(0, 1, "");
value = value_str;
value_str.replace(0, 1, "");
QStringList list_elems = value_str.split(",", QString::SkipEmptyParts);
QVariantList varlist;
foreach(QString list_val, list_elems) {
if(list_val.startsWith("\"") && list_val.endsWith("\"")) {
list_val.chop(1);
list_val = list_val.replace(0, 1, "");
varlist << list_val;
} else {
varlist << list_val.toInt();
}
}
value = varlist;
} else {
value = value_str.toInt();
if(value_str.startsWith("\"") && value_str.endsWith("\"")) {
value_str.chop(1);
value_str = value_str.replace(0, 1, "");
value = value_str;
} else {
value = value_str.toInt();
}
}
m.insert(key,value);
qDebug("%s:%s", key.toLocal8Bit().data(), value_str.toLocal8Bit().data());

View File

@@ -1,32 +1,34 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>lang/qbittorrent_es.qm</file>
<file>lang/qbittorrent_sk.qm</file>
<file>lang/qbittorrent_zh_TW.qm</file>
<file>lang/qbittorrent_pt.qm</file>
<file>lang/qbittorrent_sv.qm</file>
<file>lang/qbittorrent_pl.qm</file>
<file>lang/qbittorrent_it.qm</file>
<file>lang/qbittorrent_ko.qm</file>
<file>lang/qbittorrent_en.qm</file>
<file>lang/qbittorrent_ro.qm</file>
<file>lang/qbittorrent_bg.qm</file>
<file>lang/qbittorrent_ru.qm</file>
<file>lang/qbittorrent_nl.qm</file>
<file>lang/qbittorrent_nb.qm</file>
<file>lang/qbittorrent_hu.qm</file>
<file>lang/qbittorrent_ru.qm</file>
<file>lang/qbittorrent_zh_TW.qm</file>
<file>lang/qbittorrent_tr.qm</file>
<file>lang/qbittorrent_fi.qm</file>
<file>lang/qbittorrent_uk.qm</file>
<file>lang/qbittorrent_cs.qm</file>
<file>lang/qbittorrent_pt_BR.qm</file>
<file>lang/qbittorrent_sk.qm</file>
<file>lang/qbittorrent_ja.qm</file>
<file>lang/qbittorrent_el.qm</file>
<file>lang/qbittorrent_ca.qm</file>
<file>lang/qbittorrent_sr.qm</file>
<file>lang/qbittorrent_hu.qm</file>
<file>lang/qbittorrent_da.qm</file>
<file>lang/qbittorrent_de.qm</file>
<file>lang/qbittorrent_zh.qm</file>
<file>lang/qbittorrent_ja.qm</file>
<file>lang/qbittorrent_tr.qm</file>
<file>lang/qbittorrent_pt.qm</file>
<file>lang/qbittorrent_it.qm</file>
<file>lang/qbittorrent_fr.qm</file>
<file>lang/qbittorrent_uk.qm</file>
<file>lang/qbittorrent_zh.qm</file>
<file>lang/qbittorrent_ko.qm</file>
<file>lang/qbittorrent_nb.qm</file>
<file>lang/qbittorrent_sv.qm</file>
<file>lang/qbittorrent_de.qm</file>
<file>lang/qbittorrent_sr.qm</file>
<file>lang/qbittorrent_pt_BR.qm</file>
<file>lang/qbittorrent_da.qm</file>
<file>lang/qbittorrent_cs.qm</file>
<file>lang/qbittorrent_pl.qm</file>
<file>lang/qbittorrent_bg.qm</file>
<file>lang/qbittorrent_ar.qm</file>
<file>lang/qbittorrent_es.qm</file>
<file>lang/qbittorrent_en.qm</file>
<file>lang/qbittorrent_hr.qm</file>
<file>lang/qbittorrent_ro.qm</file>
</qresource>
</RCC>

BIN
src/lang/qbittorrent_ar.qm Normal file

Binary file not shown.

5056
src/lang/qbittorrent_ar.ts Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More