Compare commits

..

541 Commits

Author SHA1 Message Date
Christophe Dumez
b2ffb4c7c5 - Tagged rc5 release 2007-10-13 09:38:32 +00:00
Christophe Dumez
b7fd7d9837 - Fixed memory leak in GUI 2007-08-30 22:42:02 +00:00
Christophe Dumez
89670af7c9 - Updated Romanian translation 2007-08-30 18:51:05 +00:00
Christophe Dumez
10a13195b3 - Updated dutch translation 2007-08-30 13:46:42 +00:00
Christophe Dumez
0f34a98350 - Updated dutch translator 2007-08-30 13:36:47 +00:00
Christophe Dumez
59279aa43a - Ok. Jarek confirmed that Qt4.2 compatibility is back :) 2007-08-30 11:04:51 +00:00
Christophe Dumez
11198208eb - Updated TODO 2007-08-30 10:36:46 +00:00
Christophe Dumez
4a2c7efb27 FEATURE: Replaced Meganova search engine by TorrentReactor 2007-08-30 10:25:27 +00:00
Christophe Dumez
3ea344cb2e attempt to fix toolbar with Qt4.2 2007-08-30 06:48:47 +00:00
Christophe Dumez
dff33dbfb1 - Should fix a layout problem with the infoBar and Qt4.2 (need confirmation) 2007-08-29 19:03:53 +00:00
Christophe Dumez
ed6cad6d1b - Updated TODO 2007-08-29 16:24:47 +00:00
Christophe Dumez
b582ec9480 - BUGFIX: Do not store and calculate ETA values for paused torrents 2007-08-29 16:23:37 +00:00
Christophe Dumez
b5ccf05541 - BUGFIX: Do not store and calculate ETA values for finished torrents 2007-08-29 16:15:11 +00:00
Christophe Dumez
b3c5e6cfa2 - Store less ETA values for each torrent in order to save memory 2007-08-29 16:11:24 +00:00
Christophe Dumez
229927bbe9 - BUGFIX: Fixed file preview and improved previewable files detection 2007-08-29 16:07:37 +00:00
Christophe Dumez
495d6f2bab - Save less trackers errors to save memory 2007-08-29 15:13:20 +00:00
Christophe Dumez
a9f1bd4f74 - Refresh list every 1500ms instead of 2000ms 2007-08-29 15:05:57 +00:00
Christophe Dumez
73c247fe10 BUGFIX: Fixed pause state toggle for paused and checking torrents 2007-08-29 15:04:30 +00:00
Christophe Dumez
bd84cb197f - little optimization for torrentstopauseafterchecking 2007-08-29 15:00:31 +00:00
Christophe Dumez
57309c7d82 - Do not save paused torrents in a list anymore to save some memory 2007-08-29 14:54:03 +00:00
Christophe Dumez
27e76962d1 - Found a way not to use FullAllocationMode list in order to save memory in cpu 2007-08-29 14:30:30 +00:00
Christophe Dumez
db6180b737 - Little hint for windows 2007-08-29 14:05:59 +00:00
Christophe Dumez
6918aba90c - Use "Magick++-config --libs" to get linking libs instead of pkg-config because some distros (like Mandriva) do not provide ImageMagick++.pc 2007-08-29 14:04:45 +00:00
Christophe Dumez
17b8f76dda - UpdateRatio only when it is displayed
- Resample favicon to 16x16 before displaying it for better quality
- Updated TODO
2007-08-29 13:45:51 +00:00
Christophe Dumez
ea3a635d49 - Updated Greek translation 2007-08-29 12:57:00 +00:00
Christophe Dumez
2ddcaf008b - Improved ImageMagick detection and it should be able to build without it too now 2007-08-29 10:20:39 +00:00
Christophe Dumez
99268bfc06 - Added .ico support, which is really useful for RSS favicons. We use libMagick++ in order to convert ICO icons to PNG. If this library is not installed, qBittorrent will still compile but this feature will be disabled. 2007-08-29 09:22:21 +00:00
Christophe Dumez
19c606e067 - Removed outdated define 2007-08-29 06:35:47 +00:00
Christophe Dumez
057029787a - Added some asserts to check for overflows
- Removed a useless functions (was used for debug)
- Fixed 2 warnings in createTorrent.ui
- Improved CXX_FLAGS in src.pro
2007-08-29 06:33:27 +00:00
Christophe Dumez
06cb5ff4c6 - Second attempt to fix Qt4.2 COMPATIBILITY 2007-08-29 03:58:01 +00:00
Christophe Dumez
f67eb47f8c - Updated TODO 2007-08-28 19:37:30 +00:00
Christophe Dumez
7921adbcf9 - Cleaned torrent progress asserts 2007-08-28 19:22:05 +00:00
Christophe Dumez
63334ea6fb - Optimized a lot torrent real size calculation 2007-08-28 19:10:35 +00:00
Christophe Dumez
cdfaed4fb4 BUGFIX: ETA was wrong for torrents with filtered files 2007-08-28 18:49:45 +00:00
Christophe Dumez
21908e0a03 - Optimized function that transform a number of seconds to a duration(days, hours, minutes, secs)
- Improved ETA calculation to avoid overflows (Added asserts to make sure it doesn't happen)
2007-08-28 18:44:54 +00:00
Christophe Dumez
105563ac5a - Fixed a bug in last commit in qBittorrentPath()
- Optimized float to string conversions
2007-08-28 18:05:20 +00:00
Christophe Dumez
c064e5877c - Optimised GUI class a little 2007-08-28 17:33:00 +00:00
Christophe Dumez
29a290264e - updated resources files 2007-08-28 17:05:12 +00:00
Christophe Dumez
08a57d267b - some optimizations 2007-08-28 17:03:55 +00:00
Christophe Dumez
01df4d3c81 - Use int instead of short where possible 2007-08-28 16:55:14 +00:00
Christophe Dumez
6ecb45d661 - Code optimization using initialization lists
- Removed Traditional Chinese translation because we lost our translator and translation is outdated
2007-08-28 16:17:32 +00:00
Christophe Dumez
c6b25e5f79 - Should fix compatibility with Qt4.2 2007-08-28 14:49:57 +00:00
Christophe Dumez
39feb335a4 BUGFIX: Display the torrent that are being checked as 'checking' in seeding list 2007-08-28 14:30:24 +00:00
Christophe Dumez
b90012e431 - Updated TODO 2007-08-28 14:18:31 +00:00
Christophe Dumez
71599c0f9f - Made finished list menu more similar to the download list one
- Fixed Start/Pause actions in lists context menus
2007-08-28 14:18:09 +00:00
Christophe Dumez
20a8b3f418 - Updated language files 2007-08-27 18:28:13 +00:00
Christophe Dumez
3b03b385f3 - removed some useless includes 2007-08-27 13:34:41 +00:00
Christophe Dumez
c7592a6dc8 - prevent downloadFromUrl flooding 2007-08-27 10:06:13 +00:00
Christophe Dumez
8f7de730cc - Added some more torrent_handle checking to be sure we don't use invalid ones 2007-08-27 09:24:22 +00:00
Christophe Dumez
e4795cd64b - removed bad assert 2007-08-27 08:39:04 +00:00
Christophe Dumez
fd2ee35e92 - Do not save torrent related info in class destruction, this is too dangerous 2007-08-26 19:58:41 +00:00
Christophe Dumez
8404eec301 - Force progress update in download list before calling sort function to make it more reliable 2007-08-26 19:52:10 +00:00
Christophe Dumez
cc252fc70a - Fix progress column delayed sorting 2007-08-26 19:33:08 +00:00
Christophe Dumez
89ecdca5e7 Compile with -O2 in release mode and -O1 in debug mode 2007-08-26 19:30:27 +00:00
Christophe Dumez
1bfc181cb2 - Better handing of .finished files (bittorrent class level instead of GUI level) 2007-08-26 19:17:50 +00:00
Christophe Dumez
124fa3c8ed BUGFIX: Showing checking progress for paused torrents too 2007-08-26 18:59:27 +00:00
Christophe Dumez
28294efadf - Check if the hash read from the filename and from the torrent are the same and don't add it if it is different. Safer 2007-08-26 18:50:51 +00:00
Christophe Dumez
829c358f10 - fixed some bugs introduced recently
- improved debug output
2007-08-26 18:41:45 +00:00
Christophe Dumez
35a9fab3b4 - Check if priorities file exists before trying to read it to avoid a warning message 2007-08-26 17:48:38 +00:00
Christophe Dumez
4e2ebe5a69 - Fixed torrent switching to finished tab 2007-08-26 17:25:37 +00:00
Christophe Dumez
366d5108c4 - I thought there was a memory leak here but it crashes when I delete it so.. 2007-08-26 16:30:52 +00:00
Christophe Dumez
7dc7cea31b - Updated TODO. GUI splitting was planned for v1.1.0 but it is already in v1.0.0beta6 after all :) 2007-08-26 16:29:06 +00:00
Christophe Dumez
32c330092a - Merged splitGUI branch, GUI and download tab are now splitted. Code is a lot cleaner and easier to understand. I also fixed some bugs I found on the way :) 2007-08-26 16:25:22 +00:00
Christophe Dumez
36e2cb6f68 - Updated TODO 2007-08-26 16:21:16 +00:00
Christophe Dumez
cebb5fc1fe - dropped Threaded branch
- Added a function to torrent_handle wrapper for debug use
2007-08-24 12:25:52 +00:00
Christophe Dumez
1ad2495896 - Updated polish translation 2007-08-23 15:49:39 +00:00
Christophe Dumez
e82cb2188e - Made torrent deletion from hard-drive safer 2007-08-23 14:04:53 +00:00
Christophe Dumez
680f6409d8 - beta5 release 2007-08-23 04:01:17 +00:00
Christophe Dumez
cfacac7dbf - Add torrents in pause before applying settings to avoid race conditions
- Started to work on a new function to delete torrents permanently that is safer. Not used yet because it is buggy : it works only for simple cases and I'm not sure I can do better right now with the info libtorrent is providing.
2007-08-22 18:26:00 +00:00
Christophe Dumez
8ce1a4c3df - Updated Korean translation 2007-08-22 03:58:05 +00:00
Christophe Dumez
6ee9152b21 - Handling progress bar text painting ourselves because some styles really don't handle it well (cleanlooks...) 2007-08-21 17:33:06 +00:00
Christophe Dumez
d8dd509a7b - Updated Russian translation 2007-08-21 07:17:13 +00:00
Christophe Dumez
4c5c1d49c2 - Updated german translation 2007-08-20 11:47:26 +00:00
Christophe Dumez
8ba1cb329d - Improved unicode support a bit 2007-08-20 07:03:41 +00:00
Christophe Dumez
a28160bcaa - Fixed a bug when deleting a torrent from finished list (just introduced) 2007-08-20 06:41:36 +00:00
Christophe Dumez
c9925eddb6 - Big code cleanup
- Added a Qwrapper for torrent_handle to make code more readable
2007-08-20 06:29:18 +00:00
Christophe Dumez
5946f20783 - Updated beta5 changelog 2007-08-19 16:51:23 +00:00
Christophe Dumez
a4a98e3ada - Added some checking before adding torrents to finished/download lists to avoid duplicate in some circumstances 2007-08-19 16:50:05 +00:00
Christophe Dumez
a01c7e2c60 - Improved finished torrents code a little 2007-08-19 16:45:05 +00:00
Christophe Dumez
2bf0aba48a - improved some asserts for progress checking 2007-08-19 16:33:37 +00:00
Christophe Dumez
7030f85826 - Added an assert to check that progress value is < 100%
- Modified a test due to a bug in libtorrent for #133480
2007-08-19 14:48:16 +00:00
Christophe Dumez
5066819c58 - Added some more assert to be sure progress value is under 100% 2007-08-19 14:39:40 +00:00
Christophe Dumez
5231f5a22b - Rewrote a lot of code concerning finishedTorrents code. It was optimized and should be safer too 2007-08-19 14:20:54 +00:00
Christophe Dumez
de8c3158fe - Make use of qDeleteAll() function from Qt4 2007-08-19 13:00:51 +00:00
Christophe Dumez
04352cce3c - Fixed bad assert
- Little checking before saving url seeds list
- Little optimization to make fastresume data saving faster
2007-08-19 08:45:24 +00:00
Christophe Dumez
5315ba7894 - Fixed french translation 2007-08-18 12:50:48 +00:00
Christophe Dumez
2ce097ec77 - Fixed keyboard shortcuts for third tab (closes #127942) 2007-08-18 12:43:21 +00:00
Christophe Dumez
d025a2ea36 - Updated TODO (preview is working in seeding list now) 2007-08-18 06:00:18 +00:00
Christophe Dumez
a4d24fd4a7 - Updated TODO
- Last commit allows to remove url seeds now too (forgot)
2007-08-18 05:56:59 +00:00
Christophe Dumez
b2867e97bf - Updated spanish translation 2007-08-18 05:55:09 +00:00
Christophe Dumez
98159eaa1b - Updated TODO 2007-08-17 04:10:23 +00:00
Christophe Dumez
b4fbaaa47c BUGFIX: Improved incremental download 2007-08-17 02:22:04 +00:00
Christophe Dumez
df8c591edd - Updated todo 2007-08-17 02:14:37 +00:00
Christophe Dumez
13f21ef6cd - Make use of new torrent_checked_alert that was just included in libtorrent. This allowed to improve torrent that just finished checking handling and progress column sorting. Also allowed to optimize cpu/memory usage a little. 2007-08-17 02:03:13 +00:00
Christophe Dumez
55834ba5db - Fixed session ratio value: was either 10. or 1. (closes #133026) 2007-08-16 23:46:45 +00:00
Christophe Dumez
417d8a777b - Updated portuguese and brazilian translations 2007-08-16 08:59:31 +00:00
Christophe Dumez
38b008a2ac - Updated slovak translation 2007-08-16 08:54:49 +00:00
Christophe Dumez
38283882e9 - Updated Japanese translation 2007-08-16 04:09:39 +00:00
Christophe Dumez
85055c1ef9 - Updated ToDO 2007-08-15 19:59:17 +00:00
Christophe Dumez
36e87952fa - BUGFIX: Wait for torrent_paused_alert before reloading a torrent for full allocation mode 2007-08-15 19:41:12 +00:00
Christophe Dumez
d5fa6cefe4 - Removed some debug
- Updated Changelog (now libtorrent supports Bittorrent FAST extension)
2007-08-15 19:17:17 +00:00
Christophe Dumez
12fd87ab85 - Removed some debug (didn't mean to commit that) 2007-08-11 14:54:24 +00:00
Christophe Dumez
47b42c1c90 - Updated TODO (changelog beta5) 2007-08-11 14:50:29 +00:00
Christophe Dumez
31abae33a1 - Improved the way menu icons are installed to avoid problems on some systems (Thanks JanCR for reporting this)
- Fixed version in desktop file
2007-08-11 14:47:52 +00:00
Christophe Dumez
7b8722df34 - Updated TODO 2007-08-09 06:59:21 +00:00
Christophe Dumez
eda115249a - Updated Italian translator 2007-08-09 06:43:42 +00:00
Christophe Dumez
aa4c53ec43 - Fixed assert so that it doesn't crash when we toggle paused state of a torrent several times and quickly 2007-08-09 05:10:39 +00:00
Christophe Dumez
44d61e0b9d - Fixed overflow that caused ratio to become negative
- Added some more asserts so that it doesn't happen again
- Fixed waiting for paused_alert on exit in the case where a torrent was paused then resumed before we received torrent_paused_alert
2007-08-09 05:03:06 +00:00
Christophe Dumez
c51abd9096 - Updated TODO 2007-08-08 12:43:58 +00:00
Christophe Dumez
320c125d17 - Added some more debug 2007-08-08 07:35:57 +00:00
Christophe Dumez
8b26b7fd48 - BUGFIX: Fixed progress column delayed sorting (after torrent finished checking) 2007-08-07 23:15:46 +00:00
Christophe Dumez
f9c357b52d - Wait for torrent_paused_alert before saving fast resume data 2007-08-07 23:00:51 +00:00
Christophe Dumez
3494702437 - Fixed include again 2007-08-07 22:29:46 +00:00
Christophe Dumez
3100c4afc9 - Added missing include 2007-08-07 22:26:58 +00:00
Christophe Dumez
60923e81c6 - Updated TODO
- Removed useless include in downloadThread
2007-08-07 22:14:23 +00:00
Christophe Dumez
06a2f2ad1f - Updated polish translation 2007-08-07 10:25:36 +00:00
Christophe Dumez
d02edebb58 - Fixed italian trannslation 2007-08-05 17:36:26 +00:00
Christophe Dumez
a9692dbe60 - Changed the way progress bars are rendered 2007-08-04 22:14:17 +00:00
Christophe Dumez
bee1dbeea4 BUGFIX: Finished torrents were still displayed as checking when paused by libtorrent on full disk (hit an assert) 2007-08-04 18:26:42 +00:00
Christophe Dumez
9ba0c7ebba - Updated Italian translation 2007-08-04 11:32:19 +00:00
Christophe Dumez
b702bea806 - beta4 release 2007-08-04 06:23:44 +00:00
Christophe Dumez
ff756a2b1f - Some fixes in bandwidth allocation per torrent dialog 2007-08-04 05:29:35 +00:00
Christophe Dumez
8e6b1be322 - updated TODO 2007-08-03 18:24:36 +00:00
Christophe Dumez
d74a095186 - Updated TODO with beta3->beta4 changelog 2007-08-03 18:20:01 +00:00
Christophe Dumez
037fc69c34 - Updated language files 2007-08-03 15:37:42 +00:00
Christophe Dumez
969d9d5f69 - Fixed debug output 2007-08-03 15:17:34 +00:00
Christophe Dumez
db9bc24b5f - rss feeds are now updated automatically every 10 minutes 2007-08-03 15:16:42 +00:00
Christophe Dumez
86d38efcb2 - Allow to delete rss streams using "Del" key 2007-08-03 15:02:16 +00:00
Christophe Dumez
533aeb3f8b - Allow to select multiple rss feeds at once
- Fixed an icon problem when a feed refreshing fails
2007-08-03 14:51:32 +00:00
Christophe Dumez
dcb6642394 - Mostly rewritten RSS part
* Fixed a lot of bugs
	* Improved CPU & memory usage
	* Improved usability
Please report any bug you may experience.
2007-08-03 14:37:56 +00:00
Christophe Dumez
2589d4e682 - Fixed layout again for about 2007-08-02 18:20:13 +00:00
Christophe Dumez
b2eec9a765 - Fied layout a little (broken by arnaud) 2007-08-02 18:10:31 +00:00
Christophe Dumez
e569fdd2c0 - Added arnaud to thanks page 2007-08-02 18:03:47 +00:00
Arnaud Demaiziere
fff4ad529c port properties.ui to qt 4.2 2007-08-02 17:51:45 +00:00
Christophe Dumez
ab63fa62ea - Fixed ambiguous keyboard shortcut for options 2007-08-02 16:47:29 +00:00
Christophe Dumez
30fef7d1fc - A fix for the thanks page 2007-08-02 15:34:35 +00:00
Christophe Dumez
6d7c15aa33 - Improved about dialog a lot. (broke compatibility with Qt4.2, arnaud will fix this soon)
- Added a missing file for brazilian translation
2007-08-02 15:24:52 +00:00
Christophe Dumez
be11acb31b - Fixed scrolling problem in about window 2007-08-02 14:52:38 +00:00
Christophe Dumez
a9cd4fd3f4 - Fixed a utf8 problem in our dear graphist's name 2007-08-02 14:23:15 +00:00
Christophe Dumez
1c0e890252 - Fixed columns width in transfers list (problem was caused by the hidden "hash" column that didn't have a null size) 2007-08-02 14:12:22 +00:00
Christophe Dumez
190dc793ac - Should fix building with boost 1.33.1 2007-08-01 20:01:06 +00:00
Christophe Dumez
0c18f44a34 - Updated TODO 2007-08-01 19:43:21 +00:00
Christophe Dumez
0280158138 - Updated hungarian translation 2007-08-01 19:40:49 +00:00
Christophe Dumez
265458ae98 - deleteThread: check if a path exists before trying to delete it 2007-08-01 19:25:11 +00:00
Christophe Dumez
a98a21196f - Updated Chinese (Simplified) translation 2007-08-01 18:15:24 +00:00
Christophe Dumez
66c8a21a66 - refresh list was refreshed even though the main window was hidden or minimized. This hitted an assert 2007-08-01 18:08:49 +00:00
Christophe Dumez
4ce1a7eda2 - Fixed deleteThread connect slot 2007-08-01 18:03:58 +00:00
Christophe Dumez
83b0cd5706 - Updated TODO 2007-08-01 10:10:20 +00:00
Christophe Dumez
1a1219448a - Beta 3 release 2007-08-01 10:09:43 +00:00
Christophe Dumez
f4465dcea2 - Updated unkrainian translation 2007-08-01 09:11:38 +00:00
Christophe Dumez
fc0a41e7f8 - Partially updated italian translation 2007-08-01 09:08:42 +00:00
Christophe Dumez
7469f97953 - Really enable UPnP/LSD/NAT-PMP (recently disabled as a default in libtorrent) 2007-08-01 08:47:58 +00:00
Christophe Dumez
80fa44f8bb - It is not possible to pause torrents in finished tab (closes #129498) 2007-08-01 08:43:00 +00:00
Christophe Dumez
6eae7bd201 - Forgot this one 2007-08-01 07:22:27 +00:00
Christophe Dumez
5879df7d5f - Should fix compiling errors with Qt 4.2 2007-08-01 07:19:44 +00:00
Christophe Dumez
57b4a7150a - Prevent users from filtering all the files in a torrent using right-click menu (combobox was ok) 2007-07-31 15:37:14 +00:00
Christophe Dumez
58dc75fbcf - Fixed some slots connects in new deleteThread
- Added some debug when pausing torrents
2007-07-31 14:28:17 +00:00
Christophe Dumez
d04b9a7f02 - Fixed color when filtering files using right-click menu in torrent properties and torrent addition dialog 2007-07-31 13:59:03 +00:00
Christophe Dumez
c2450cd41e - updated TODO 2007-07-31 11:22:05 +00:00
Christophe Dumez
4922eb3dc5 - Improved preview list delegate
- All delegates are now good :)
2007-07-31 11:12:41 +00:00
Christophe Dumez
34d94cd2bb - Improved search list delegate 2007-07-31 11:06:54 +00:00
Christophe Dumez
9bd3647f36 - Improved property list delegate 2007-07-31 11:02:53 +00:00
Christophe Dumez
79e2d253d4 - Improved finishedList delegate 2007-07-31 10:48:17 +00:00
Christophe Dumez
9b08b0ff8c - little improvement in download list delegate
- Disabled editor in finished list
2007-07-31 10:42:45 +00:00
Christophe Dumez
b0f3cdad5d - Improved a lot the download list delegate
- Replaced Qt::TextColorRole by Qt::ForegroundRole because it is deprecated
2007-07-31 10:39:03 +00:00
Christophe Dumez
0561206d91 - Started to improve download & finished list rendering (filename column) 2007-07-31 09:41:47 +00:00
Christophe Dumez
99530728c5 Update torrent progress when its content changed (filtered files) 2007-07-31 09:25:54 +00:00
Christophe Dumez
99a58b9208 - Removed a useless function
- Stop resfreshing trackers errors in torrent properties because this is annoying when you're trying to read them
2007-07-31 09:17:59 +00:00
Christophe Dumez
816a3c8784 - Paused torrents are displayed as paused, even if they are checking (to display their progress). This is less confusing. 2007-07-31 08:56:24 +00:00
Christophe Dumez
570296c29e - Multithreaded deletionThread (harmonized with deleteThread) 2007-07-31 08:52:04 +00:00
Christophe Dumez
5518144b26 - Improved resumeUnfinishedTorrents using a "*.torrent" filter 2007-07-31 08:21:51 +00:00
Christophe Dumez
e66af5b271 - Improved files deletion in BT_backup (no more hard-coded extensions that are annoying when adding new ones)
- Improved directory scanning for torrents using a "*.torrent" filter
2007-07-31 08:13:38 +00:00
Christophe Dumez
7b9da8d941 - Fixed [Bug 129286] Priority is not saved while using the context menu 2007-07-30 18:43:00 +00:00
Christophe Dumez
05a7ba4e38 - Fixed some bugs in italian translation 2007-07-30 16:57:28 +00:00
Christophe Dumez
f07b0eed61 - Removed useless function 2007-07-30 14:01:14 +00:00
Christophe Dumez
8fdc59c37c - Optimized Bittorrent class for faster compilation 2007-07-30 13:56:31 +00:00
Christophe Dumez
58b5d4378d - finished GUI class cleanup 2007-07-30 13:47:16 +00:00
Christophe Dumez
bd8ec01add - Removed bad assert
- Improved updateDlList function a little
2007-07-30 10:37:13 +00:00
Christophe Dumez
c0e4b0bbff removed a function that is not used anymore 2007-07-30 10:30:43 +00:00
Christophe Dumez
b0bbbf0305 - removed useless function (not used anymore) 2007-07-30 10:29:19 +00:00
Christophe Dumez
6dd78d33ab - Improved download list popup menu code
- Added some asserts
- bit of code improvement/clean up
2007-07-30 10:27:56 +00:00
Christophe Dumez
d2983fa5aa - Updated Slovak translation 2007-07-30 10:06:46 +00:00
Christophe Dumez
d680be3626 FEATURE: Allow to drag 'n drop urls on the main window 2007-07-30 09:30:07 +00:00
Christophe Dumez
0043edc85f - Updated changelog 2007-07-29 15:40:56 +00:00
Christophe Dumez
a00ea9af99 - Added a different icon for torrents being checking so that we can differenciate them from finished torrents 2007-07-29 15:40:11 +00:00
Christophe Dumez
57376ae875 - Fixed deletion message when deleting from finished list
- Added some more asserts (let's kill all those bugs time)
2007-07-29 15:32:27 +00:00
Christophe Dumez
7f89b30190 - Fixed a compiling error 2007-07-29 15:20:05 +00:00
Christophe Dumez
6951619c04 - Improved updateDlList code
- Added some ASSERTS
2007-07-29 15:17:50 +00:00
Christophe Dumez
c19937cf98 - removed some useless debug 2007-07-29 14:58:18 +00:00
Christophe Dumez
dbc084dd66 - Improved debug output
- code clean up
- Moved some bittorrent code from GUI class to Bittorrent one
2007-07-29 14:54:39 +00:00
Christophe Dumez
3cb0612cc6 - Added some ASSERTS
- Improved session ratio calculation in main window
2007-07-29 14:41:47 +00:00
Christophe Dumez
c6285d8f67 - Improved start/Pause & start_all/pause_all functions 2007-07-29 14:14:57 +00:00
Christophe Dumez
0a144708d8 - Updated swedish translation 2007-07-29 08:59:23 +00:00
Christophe Dumez
410bbcf003 - Updated Japanese translation 2007-07-29 04:32:01 +00:00
Christophe Dumez
c4a1f30b70 - Prepare for brazilian translation by Nick Manrinho 2007-07-29 03:51:42 +00:00
Christophe Dumez
269b59f8a2 - Updated french translation 2007-07-29 03:23:03 +00:00
Christophe Dumez
ffc1479b1f - Added a little more debug (tested progress column sorting : it works fine now) 2007-07-29 02:03:16 +00:00
Christophe Dumez
9683916d88 - Should fix progress column sorting 2007-07-29 01:55:59 +00:00
Christophe Dumez
74b2b955c9 - Added some more debug in pause function 2007-07-29 01:46:31 +00:00
Christophe Dumez
620deb3b6a - Fixed a problem that happened sometimes with torrents to pause after checking 2007-07-29 01:44:49 +00:00
Arnaud Demaiziere
e4fbf2107d port properties.ui to qt 4.2 2007-07-27 18:43:57 +00:00
Christophe Dumez
1db4af50dd - Reverted changes to MainWindow.ui (broke compatibility with Qt4.2) 2007-07-27 16:17:21 +00:00
Christophe Dumez
a5ac742c1f - Fixed (workaround, maybe Qt's bug?) for transfers list background painting problem. 2007-07-27 16:10:50 +00:00
Christophe Dumez
183544b959 - Updated language files 2007-07-27 15:39:03 +00:00
Christophe Dumez
897ab4d782 - Updated TODO (url seeds are documented on wiki) 2007-07-27 15:04:08 +00:00
Christophe Dumez
3e36cd3c46 - Update trackers edition code
- current tracker is now updated regularly when properties are displayed
2007-07-27 14:43:42 +00:00
Christophe Dumez
f839d6fe41 - Improved trackers errors code a lot and moved it to Bittorrent class
- When using startAll() command and when only some torrents are paused : already started torrents are not displayed as connecting untill next refresh anymore (they keep their current state).
2007-07-27 13:58:12 +00:00
Christophe Dumez
ff9b9d7148 - Updated language files 2007-07-27 10:07:05 +00:00
Christophe Dumez
b4537c52c1 - Fixed typo in changelog 2007-07-27 10:04:43 +00:00
Christophe Dumez
9cbab8d63e -FEATURE: Url seeds are now displayed in torrent properties and are editable
- Broke compatibility with Qt4.2. Will fix this a bit later (in the meantime, edit properties.ui)
2007-07-27 09:53:55 +00:00
Christophe Dumez
676f30d9a1 - Fixed ipv4 compilation warning with latest g++
- Paused torrents that are checking are now displayed as paused (not checking) -> less confusing
- Updated TODO (libtorrent fixed ipfilter bug)
2007-07-26 15:43:27 +00:00
Christophe Dumez
d3f917b408 - Fixed delete functions for finished list 2007-07-26 12:25:46 +00:00
Christophe Dumez
faf6f155ca - Improved a lot delete functions 2007-07-25 14:32:09 +00:00
Christophe Dumez
4e4b0ed9ff - Reverted a previous commit. Transfer lists refreshers aren't in separate threads anymore: too buggy 2007-07-25 14:14:38 +00:00
Christophe Dumez
95fc9e3a72 Fix last commit 2007-07-25 14:03:04 +00:00
Christophe Dumez
3ba3e12f93 - Fixed removing from finished list 2007-07-25 14:01:48 +00:00
Christophe Dumez
2ab7f6f923 - Transfer lists refreshers were moved to separate threads to improve GUI responsiveness. Please report any problem (like mutex deadlocks in console output) or crashes. 2007-07-25 09:03:22 +00:00
Christophe Dumez
d43d68122b BUGFIX: The number of search results was not reset when clicking on 'Clear' button 2007-07-25 07:22:32 +00:00
Christophe Dumez
03fae3953f - Made error message clearer when libcommoncpp2 is not installed. 2007-07-25 07:00:14 +00:00
Christophe Dumez
102c5ee81e - Updated polish translation 2007-07-25 06:46:37 +00:00
Christophe Dumez
f27e913f67 - updated changelog 2007-07-24 08:33:00 +00:00
Christophe Dumez
4ef72c6c8f - Fixed new lines in search engine update changelog 2007-07-24 08:32:17 +00:00
Christophe Dumez
a370503eb3 search plugin update - do not display only last version changelog 2007-07-24 08:22:12 +00:00
Christophe Dumez
e9126aedc3 - Improved mininova search engine support 2007-07-24 07:58:31 +00:00
Christophe Dumez
e493776a73 - User is now warned when fast resume data was rejected 2007-07-24 07:30:33 +00:00
Christophe Dumez
a0e32fefd7 - Fixed compilation warnings
- Started work on fastresume reject alerts
2007-07-24 07:13:40 +00:00
Christophe Dumez
e606d04098 - added doc url in INSTALL file 2007-07-24 06:20:32 +00:00
Christophe Dumez
5713af7375 - Workaround to build on fedora system (pkg-config problem) 2007-07-24 05:08:02 +00:00
Christophe Dumez
1e64d0a3e4 - Added a lot of supported media extensions for preview (tried to be exhaustive but the best way would probably be to use mime types) 2007-07-23 15:55:12 +00:00
Christophe Dumez
e4ab5ceb43 - Compile with -O2 optimization
- Added some media extensions supported
2007-07-23 15:31:30 +00:00
Christophe Dumez
ce5baa93b7 - Ok, includes look fine now 2007-07-23 12:56:57 +00:00
Christophe Dumez
042323a1a8 - Improved rss includes a little and fix a memory leak I just introduced 2007-07-23 12:52:25 +00:00
Christophe Dumez
93938d8597 - still optimizing includes 2007-07-23 12:46:36 +00:00
Christophe Dumez
0db60065c0 - Removed useless mutex in GUI
- started to optimize headers includes for compilation speed
2007-07-23 12:12:55 +00:00
Christophe Dumez
c8c53e2812 - Use pkgconfig for GNU common c++ 2007-07-23 09:48:51 +00:00
Christophe Dumez
737bdadbd0 - Updated TODO 2007-07-23 08:41:23 +00:00
Christophe Dumez
53d2bc34fc - fixed minor code error in finishedList 2007-07-23 08:32:06 +00:00
Christophe Dumez
5cc6e6e8f4 - sometimes, rss feeds had a red cross icon although their download succeeded : fixed 2007-07-23 07:55:06 +00:00
Christophe Dumez
a27e7e1b9e - Lightened finished list code
- Fixed properties slots connects in finished list
- Fixed columns width in finished list
2007-07-23 07:44:58 +00:00
Christophe Dumez
2ba45ef9ad - Updated french translation 2007-07-23 05:11:11 +00:00
Christophe Dumez
59d35b9f8a - beta2 release 2007-07-23 04:57:28 +00:00
Christophe Dumez
cf6a91e850 - BUGFIX: DHT settings were not saved correctly 2007-07-23 04:51:29 +00:00
Christophe Dumez
4e0ed1ec4c - Optimized downloadThread memory usage 2007-07-22 15:48:34 +00:00
Christophe Dumez
2ad1c56933 - Create urlstream for subdownloadthreads only 2007-07-22 15:18:09 +00:00
Christophe Dumez
4f17339820 - URLStream is now constructed in downloadThread constructor 2007-07-22 15:13:11 +00:00
Christophe Dumez
c019b0d72c - Added some debug in rss 2007-07-22 15:02:19 +00:00
Christophe Dumez
0fb78727d5 - Added more debug in rss 2007-07-22 14:14:05 +00:00
Christophe Dumez
2c48968a31 - a search request can now be terminated by another 2007-07-22 13:42:09 +00:00
Christophe Dumez
f4adf173a2 - Multithreaded downloadThread for performance 2007-07-22 13:21:04 +00:00
Christophe Dumez
c086558597 - Updated TODO
- Load torrents before loading rss and sreach engine on startup
2007-07-22 12:46:03 +00:00
Christophe Dumez
7c48afd6eb - Improved downloadThread aborting support 2007-07-22 12:08:16 +00:00
Christophe Dumez
e6554db498 - Updated language files 2007-07-22 12:00:14 +00:00
Christophe Dumez
d25776ddda - Quite a few improvements in rss interface 2007-07-22 11:53:43 +00:00
Christophe Dumez
325a588526 - Fixed some signals/slots (safer)
- Forgot to remove temp file when the file was downloaded from an url (rare occasions)
2007-07-22 09:47:27 +00:00
Christophe Dumez
8c05caba3a - Improved rss favicon handling a little 2007-07-22 09:12:50 +00:00
Christophe Dumez
d3793d180c - Removed some useless debug in downloadThread and added a little more interesting one
- Updated TODO
2007-07-22 04:14:44 +00:00
Christophe Dumez
e1e28fa9ff - Updated TODO 2007-07-22 03:41:53 +00:00
Christophe Dumez
e3e559d857 - Fixed typo in last commit 2007-07-22 03:21:41 +00:00
Christophe Dumez
708e802570 - trying to fix gtsould's work... 2007-07-22 03:07:59 +00:00
Christophe Dumez
a74dc5ee35 - GTSOUL, wtf you're doing??? Committing back the new downloadThread.h 2007-07-22 03:04:47 +00:00
Arnaud Demaiziere
7edc89638f rss : show the number of NONREAD news (local test succeeded, need tests)
rss : clean the file rss.h
rss : display the site favicon (local test succeeded, need tests)

bug that i've noticed but not fixed :
_ something create qt_temp files without delete them
_ in dl list, columns disappear
2007-07-21 19:37:10 +00:00
Christophe Dumez
e4915260e7 - Updated language files 2007-07-20 21:39:21 +00:00
Christophe Dumez
92ae8de58e - Updated TODO list 2007-07-20 21:23:35 +00:00
Christophe Dumez
f81e431032 - Added rss download failure handling (display red cross next to the stream name) 2007-07-20 21:06:50 +00:00
Christophe Dumez
2789316e38 - Fixed a connect in last commit 2007-07-20 20:58:20 +00:00
Christophe Dumez
f4250d812f - Added search plugin download error handling (Fallback on secondary server and then warn the user if both failed) 2007-07-20 20:30:33 +00:00
Christophe Dumez
1fb848e9ed - Added download from url handling in GUI (still missing: search plugin update and rss) 2007-07-20 20:18:18 +00:00
Christophe Dumez
2fd0de082c - Updated configure file to check for libcommoncpp2 instead of libcurl
- Used downloadThread in search plugin update instead of libcurl (no more gui freeze by the same occasion)
- Still need to handle download from urls errors and use fallback url in search plugin update (before beta2)
2007-07-20 17:11:02 +00:00
Christophe Dumez
7c8677d787 - Improved a lot downloading from url using libcommoncpp2 instead of libcurl
- TODO soon:
  - Updated configure file
	- Add url download error handling
2007-07-20 15:55:50 +00:00
Christophe Dumez
347b03d699 - Updated TODO 2007-07-20 14:05:39 +00:00
Christophe Dumez
4c9d1db9d5 - Fixed popup menu position in last commit 2007-07-20 13:30:30 +00:00
Christophe Dumez
8fdd614673 - Added popup menu for file priorities in torrent addition dialog too 2007-07-20 13:21:46 +00:00
Christophe Dumez
0bdb10cdbe - Prepare this dialog for popup menu 2007-07-20 13:10:06 +00:00
Christophe Dumez
60c0049bef - Added a popup menu to set priority for multiple files at once 2007-07-20 13:07:34 +00:00
Christophe Dumez
a40c2bfc8f - Fixed an ambiguous shortcut in french translation 2007-07-20 12:48:06 +00:00
Christophe Dumez
a6b037d663 - Fixed last commit 2007-07-20 12:39:20 +00:00
Christophe Dumez
e079c87f5c - Simplified keyboard shortcuts code 2007-07-20 12:22:28 +00:00
Christophe Dumez
22a80fe1c3 - Updated french translation 2007-07-19 14:44:08 +00:00
Christophe Dumez
d762f094f2 - Updated TODO: Keyboard shortcuts are now documented 2007-07-19 13:36:27 +00:00
Christophe Dumez
e916300a6e - Improved keyboard shortcuts 2007-07-19 13:07:52 +00:00
Christophe Dumez
99959b1aa3 - Added keyboard shortcuts for main actions (thanks Alexander Kuzmenkov) 2007-07-19 12:58:45 +00:00
Christophe Dumez
38c6c63924 - Improved debug output 2007-07-18 08:05:15 +00:00
Christophe Dumez
3d7540dafe - Updated translation files 2007-07-18 07:46:06 +00:00
Christophe Dumez
86a0e68f46 - Added ratio column 2007-07-18 07:44:52 +00:00
Christophe Dumez
eb3db365e7 - Can't set a limit for a torrent superior to the global limit in program preferences 2007-07-17 11:45:36 +00:00
Christophe Dumez
2dea5f2ff8 - Fixed a bug in speed allocation per torrent. Libtorrent works better too but I'm still hitting an assert. 2007-07-17 11:26:49 +00:00
Christophe Dumez
766be4b381 - Fixed hungarian translation 2007-07-17 01:08:44 +00:00
Arnaud Demaiziere
d0bf8b5b04 save mainwindows to qt 4.2 2007-07-14 20:24:45 +00:00
Christophe Dumez
8df61db644 - Rollback to GNU GPLv2 because Qt4 is not compatible with GPLv3 :( 2007-07-14 14:31:59 +00:00
Christophe Dumez
f0353e50b2 - Upload/download limits per torrent are now saved on restart. I can't test this feature yet though because libtorrent is crashing when I try to use it :) 2007-07-14 13:38:29 +00:00
Christophe Dumez
28ea505088 - qBittorrent is not exiting anymore when Main window is hidden and a dialog is closed (nasty long-standing bug...) 2007-07-14 12:35:04 +00:00
Christophe Dumez
8c5d38400a - Allow to set global upload/download bandwidth limit from tray icon menu
- Fixed a bug in bandwidth limitation per torrent (confused bytes with kbytes)
- Fixed a bug with paused torrents still displayed as checking
2007-07-14 10:50:38 +00:00
Christophe Dumez
eed49c10ce - Peer blocked are now added in the right box (not log) 2007-07-14 04:22:57 +00:00
Christophe Dumez
0a2ab16e4c - little translation for hungarian 2007-07-14 04:18:26 +00:00
Christophe Dumez
dda4ffed08 - Added hungarian translation 2007-07-13 12:28:18 +00:00
Christophe Dumez
54f9375b32 - Update to GNU GPL v3 2007-07-13 06:55:51 +00:00
Christophe Dumez
8d667310e3 - Fixed signal connect 2007-07-13 01:28:08 +00:00
Christophe Dumez
a4371e7f55 - Removed some debug
- Updated TODO
2007-07-12 13:38:40 +00:00
Arnaud Demaiziere
a5b8d3c730 bug fix in ipfilter 2007-07-10 18:16:07 +00:00
Arnaud Demaiziere
09c97decb6 ipfilter : ipv6 support 2007-07-09 22:09:21 +00:00
Christophe Dumez
c2fc03b0d7 - Updated french translation 2007-07-07 01:29:32 +00:00
Christophe Dumez
5622fd0991 - Updated French translation 2007-07-05 13:02:04 +00:00
Arnaud Demaiziere
1712a7c776 * port interfaces to qt 4.2
* fix size bug
2007-07-05 11:31:33 +00:00
Christophe Dumez
9f3b9da24a - fixed a bug with full allocation mode, introduced yesterday 2007-07-05 00:07:45 +00:00
Christophe Dumez
18ec98c3fb - Reloading a torrent only when necessary (properties, when files are filtered but full allocation mode is disabled) 2007-07-04 10:06:22 +00:00
Christophe Dumez
c8e4894d85 - Fixed size update when filtering files in a torrent (broken in svn) 2007-07-04 08:10:44 +00:00
Christophe Dumez
4657ee9087 Fixed a crash when filtering all the files in a torrent 2007-07-04 07:28:51 +00:00
Christophe Dumez
97aed61fc8 ** first beta ** 2007-07-04 06:48:38 +00:00
Christophe Dumez
c11e5e8b12 - Blocked users (by ipfilter) are now logged in GUI 2007-07-04 06:42:36 +00:00
Christophe Dumez
3a727dea28 - improved tabs at the bottom 2007-07-03 22:53:10 +00:00
Christophe Dumez
107d2c8e7b Fixed file filtering in a torrent 2007-07-03 22:39:49 +00:00
Christophe Dumez
b1ed521d6b Fixed downloadFromUrl 2007-07-03 09:04:04 +00:00
Christophe Dumez
e2427a4ce2 - Delete torrent permanently from hard drive used to delete parent folder if empty (fixed) 2007-06-30 19:19:09 +00:00
Christophe Dumez
d12e510fad Improved start_All and resume_All functions to detect if a torrent's state changed or not. This way, it doesn't flood the GUI if the user keeps on clicking on those buttons 2007-06-30 18:56:49 +00:00
Christophe Dumez
9bde00b7de Improved ETA calculation 2007-06-29 16:49:45 +00:00
Christophe Dumez
611b9424ee updated version 2007-06-29 15:50:55 +00:00
Christophe Dumez
0ec6af03c0 Fixed possible division by 0 2007-06-29 15:37:59 +00:00
Christophe Dumez
80f61880b7 made ETA calculation more reliable 2007-06-29 15:23:15 +00:00
Arnaud Demaiziere
92541b779c fixed sort bug (made by chris) 2007-06-29 14:23:15 +00:00
Christophe Dumez
f5a4190e4b attempt to fix progress column sorting 2007-06-29 14:13:50 +00:00
Christophe Dumez
6ae1564136 fixed a deadlock 2007-06-29 14:11:31 +00:00
Christophe Dumez
e361ef5543 Oops forgot a mutex locker in progress column sorting 2007-06-29 14:06:34 +00:00
Christophe Dumez
dfa9965ed3 use a mutex for download list access (should fix sorting) 2007-06-29 14:00:17 +00:00
Arnaud Demaiziere
dcc54a7f35 fixed addtorrent signal, add bool onstartup to connect methods 2007-06-29 13:42:10 +00:00
Christophe Dumez
478a275bb5 - Updated german translation 2007-06-29 12:42:05 +00:00
Christophe Dumez
8c30ee3403 - Updated changelog in search engine 2007-06-29 12:24:50 +00:00
Christophe Dumez
cf002e5ab2 fixed mininova search engine 2007-06-29 12:22:55 +00:00
Christophe Dumez
09ca6e97b8 Fixed addTorrent slot 2007-06-29 10:34:10 +00:00
Christophe Dumez
dfa58f909b Fixed addtorrent slot 2007-06-29 10:30:00 +00:00
Arnaud Demaiziere
d925efb928 save options.ui with qt 4.2 2007-06-29 10:18:27 +00:00
Christophe Dumez
1910ee20dd Real time sorting of progress column was broken by ealier patch -> Fixed 2007-06-29 08:14:43 +00:00
Christophe Dumez
faaa700270 Updated polish translator 2007-06-28 23:10:57 +00:00
Christophe Dumez
d0e2e9c85f - Updating polish translation (Thanks Jarek) 2007-06-28 23:07:16 +00:00
Christophe Dumez
55538934e0 A better fix for progress column sorting on restart (still untested, gtsoul please check) 2007-06-28 22:58:43 +00:00
Christophe Dumez
ee4a4c81bf Attempt to fix the sorting of the progress column on restart (anyone can confirm? my Qt4.3 is buggy and columns won't sort) 2007-06-28 22:13:01 +00:00
Christophe Dumez
568b2ddf75 Progress of paused torrents is now correct on restart 2007-06-28 21:54:07 +00:00
Christophe Dumez
8755ebba01 Added an icon for the new encryption option 2007-06-28 21:03:52 +00:00
Christophe Dumez
18b41d07bd - Updated TODO 2007-06-19 15:58:53 +00:00
Arnaud Demaiziere
614606e3be update main menu items'order 2007-06-19 15:19:23 +00:00
Christophe Dumez
0aa4651657 - added documentation icon 2007-06-19 15:11:02 +00:00
Arnaud Demaiziere
841e6549c0 interface ported to qt 4.2, resize of the log windows 2007-06-19 14:53:58 +00:00
Christophe Dumez
3ec647cfda -legal notice in red 2007-06-17 18:36:04 +00:00
Christophe Dumez
e6fca96d0d - Added Documentation entry in Help menu 2007-06-17 15:09:00 +00:00
Christophe Dumez
5e73539393 - fixed delete permanently in finished list 2007-06-17 12:15:04 +00:00
Christophe Dumez
68b867e480 - Fixed a few other bugs in translatable strings
- French translation is up to date!
2007-06-15 23:51:10 +00:00
Christophe Dumez
4a671dba9e - Fixed a lot of bugs in translatable strings
- Started to update french translation
2007-06-15 23:40:33 +00:00
Christophe Dumez
ef1f030076 - Added some debug in bittorrent.cpp
- Added Legal Notice on qBittorrent startup "Be careful, sharing copyrighted material without permission is against the law." because of new DADVSI law.
2007-06-15 23:02:35 +00:00
Christophe Dumez
341225aff4 - Updated TODO 2007-06-15 22:47:55 +00:00
Christophe Dumez
2d9f688d56 Updated TODO 2007-06-15 22:29:11 +00:00
Christophe Dumez
3b63d34f34 Allow only rc4 for encryption, no plaintext 2007-06-15 20:43:31 +00:00
Christophe Dumez
c39da36cca - Added Encryption support!
- Removed old UPnP code
- Removed UPnP in options since libtorrent doesn't allow to disable it. Thus, UPnP is always enabled
- Made options window a bit larger
- Added Arnaud Demaiziere to developpers list
- Updated TODO & Changelog
2007-06-15 20:35:07 +00:00
Christophe Dumez
c4b49a6d96 Added a way to build statically against libtorrent (see ./configure --help) 2007-06-15 11:29:00 +00:00
Christophe Dumez
68e78a7d24 Updated TODO 2007-06-15 09:04:39 +00:00
Christophe Dumez
8b9a15d4f2 Updated TODO 2007-06-14 22:10:48 +00:00
Christophe Dumez
71dd59f5bc Added Kdevelop project file 2007-06-14 20:14:06 +00:00
Christophe Dumez
4b03220064 Updated TODO 2007-06-14 19:57:34 +00:00
Christophe Dumez
7fad742e99 - Fixed compiling with latest libtorrent svn 2007-06-13 14:04:29 +00:00
Christophe Dumez
fe70d5ecaa - Oops was in v0.9.3 already 2007-06-12 18:30:59 +00:00
Christophe Dumez
89022a5065 - Updated Changelog (forgot this one) 2007-06-12 18:28:27 +00:00
Christophe Dumez
a0d107a0e8 - Updated changelog 2007-06-12 18:24:15 +00:00
Christophe Dumez
e71252306a - Fixed a bug in polish translation 2007-06-12 18:19:16 +00:00
Christophe Dumez
f86037865d - Updated TODO 2007-06-12 12:40:10 +00:00
Christophe Dumez
1cff97f65d - Bugfix: User can't empty the trackers list 2007-05-16 18:55:34 +00:00
Christophe Dumez
e3228a9699 - Updated Japanese translation (Thanks Nardog) 2007-05-14 07:58:18 +00:00
Christophe Dumez
407ae8d01b - Updated translation files 2007-05-13 20:08:42 +00:00
Christophe Dumez
b3b1bcc60c - Updated TODO 2007-05-13 20:05:30 +00:00
Christophe Dumez
2196fcc911 - Supports SOCKS5 proxies as well as HTTP ones
- Allow to use Proxy for Trackers / Peers / Web seeds / DHT connections
- Redesigned Proxy options a little (for new features)
2007-05-13 20:02:30 +00:00
Christophe Dumez
2985fa921a remember sorted columns in download list 2007-05-07 21:20:35 +00:00
Christophe Dumez
9808e5a37a - Fixes in Slovak translation 2007-05-07 20:10:23 +00:00
Christophe Dumez
ff70dc7c83 - Updated changelog 2007-05-02 14:04:11 +00:00
Christophe Dumez
9093f8e44a - Proxy is now used for tracker / web seeds / peers connections
- Fixed the compiling errors with latest libtorrent svn
2007-05-02 13:52:29 +00:00
Christophe Dumez
f8eea3b779 - Updated TODO (search plugin update improvement to come) 2007-04-16 07:10:54 +00:00
Arnaud Demaiziere
85fa92ca12 rss : bug fixes 2007-04-15 21:43:58 +00:00
Christophe Dumez
44bfb1e376 - Fixed a small error in the german translation 2007-04-15 21:37:22 +00:00
Arnaud Demaiziere
06378e09be rss : improvements of the qtreeview 2007-04-15 21:31:32 +00:00
Arnaud Demaiziere
2c6b66a834 rss : from qlistwidget to qtreewidget 2007-04-15 19:06:19 +00:00
Christophe Dumez
9a4466e74f - Improved right click menu in RSS streams list 2007-04-15 18:53:53 +00:00
Christophe Dumez
f482496a61 - Updated smileys 2007-04-15 18:38:32 +00:00
Christophe Dumez
6802e22f7e - Improved a lot switching between tabs 2007-04-15 18:15:22 +00:00
Christophe Dumez
79253c76f1 - Now finished torrents are moved correctly to download tab if for some reason the files disapear from the hard-drive :) 2007-04-15 17:42:43 +00:00
Christophe Dumez
5fc754520a - small fix in finished list 2007-04-15 17:00:16 +00:00
Christophe Dumez
43bced2e04 - Improved refresh icon
- Added tooltips on rss buttons
- Fixed a compiling warning
2007-04-15 14:53:38 +00:00
Christophe Dumez
65468d7826 - Improved add/remove icons 2007-04-15 14:43:12 +00:00
Arnaud Demaiziere
1a553b00b0 rss : download icon fix, don't work so i commented it 2007-04-15 12:05:14 +00:00
Christophe Dumez
79a3d2e81b - Updated splash screen 2007-04-15 09:56:50 +00:00
Christophe Dumez
4ed6f12374 - Added a text to help using the rss 2007-04-14 21:08:33 +00:00
Christophe Dumez
4d6afaacfd - Should fix the problem of finished torrents in download list (Thx heavyjoos) 2007-04-14 21:06:00 +00:00
Arnaud Demaiziere
7d8d4e7ee5 rss : try to download streams' favicon 2007-04-14 18:04:47 +00:00
Arnaud Demaiziere
3fa88436c3 rss : try to use dynamic icon before streams names 2007-04-14 12:41:42 +00:00
Arnaud Demaiziere
191ac5eeac rss : another improvements 2007-04-13 12:13:27 +00:00
Arnaud Demaiziere
2ce51400aa rss : work to improve algorithm & memory
implements some color
2007-04-13 12:07:14 +00:00
Arnaud Demaiziere
d5aea98f80 rss : color try 2007-04-12 23:53:15 +00:00
Christophe Dumez
85fd33a619 - Updated to v1.0.0alpha8 (not a v0.10 after all)
- Added a new splash screen by our graphist but still unfinished
2007-04-12 22:17:33 +00:00
Christophe Dumez
ada614a956 - Updated Changelog 2007-04-12 21:43:33 +00:00
Christophe Dumez
45d51e1d44 - The torrent size displayed now takes filtered files into consideration 2007-04-12 21:28:15 +00:00
Christophe Dumez
9c83c195e3 - Fixed some slots bindings in finished list 2007-04-12 21:10:44 +00:00
Christophe Dumez
ec3f878372 - Updated alpha version 2007-04-12 20:36:27 +00:00
Christophe Dumez
9885169baf - Updated translation files
- Fixed column width in torrent addition dialog
2007-04-12 20:28:10 +00:00
Christophe Dumez
00afd6b635 - Implemented files prioritizing in torrent addition dialog 2007-04-12 20:22:42 +00:00
Christophe Dumez
ff3575c7ac - Implemented files prioritizing in a torrent (Part I: Torrent Properties), still need to work on torrent addition dialog 2007-04-12 19:51:39 +00:00
Arnaud Demaiziere
66201a2853 rss : bugs fixes, better refresh 2007-04-12 19:24:05 +00:00
Christophe Dumez
eb85389c0a - UPnP is on as a default, display the display message 2007-04-12 17:25:47 +00:00
Christophe Dumez
f7c4411c9a - UPnP is enabled as a default and there is no way to disable it at the moment (libtorrent API) 2007-04-12 17:21:30 +00:00
Christophe Dumez
36d073d597 - Removing our UPnP code because libtorrent svn does it 2007-04-12 17:19:12 +00:00
Christophe Dumez
658771612a - Upgraded to libtorrent svn (0.13) 2007-04-12 17:17:04 +00:00
Christophe Dumez
7f7fb2354f - Added some scripts that might be useful in the future 2007-04-12 13:26:06 +00:00
Christophe Dumez
c146f6d0d9 - Added experimental windows build url to TODO 2007-04-12 09:27:05 +00:00
Christophe Dumez
923bba95b4 - Updated TODO 2007-04-11 21:13:34 +00:00
Christophe Dumez
ee594400dc - Fixed togglepausedstate() on double click in download list 2007-04-11 20:50:41 +00:00
Arnaud Demaiziere
77b998c438 rss : bug fixes and refresh algorithm improved and better use of
signals&memory
2007-04-11 20:24:41 +00:00
Christophe Dumez
cf2bc1e980 - removed ETA & DL speed columns in finished torrents list 2007-04-11 18:31:21 +00:00
Christophe Dumez
ab4ad0b114 - Use a standard QDialogButtonBox in options for better systems integration 2007-04-11 18:19:20 +00:00
Christophe Dumez
dc4acc83a5 - Allow multiple selection in finished list 2007-04-11 18:06:54 +00:00
Christophe Dumez
7263867f14 - Display torrent properties on double click in finished torrents list (togglepausedstate() was useless here)
- Fixed default tab selected in torrent properties
- Updated TODO
2007-04-11 13:23:17 +00:00
Christophe Dumez
cfe979c8dd - Updated changelog
- Made sorting work in the finished torrents list
2007-04-11 13:19:58 +00:00
Christophe Dumez
762df4b914 - Columns width are now remembered on restart for the finished torrent list 2007-04-11 13:10:13 +00:00
Christophe Dumez
4a57037c47 - Fixed typo and redesigned rss code a little 2007-04-11 12:59:55 +00:00
Christophe Dumez
bfe7010350 - Fixed right click menu disposition in RSS
- Improved some sentences in dialogs
2007-04-11 12:33:41 +00:00
Christophe Dumez
76708c96df - Updated TODO 2007-04-11 10:41:33 +00:00
Arnaud Demaiziere
e0261295db rss : bug fix 2007-04-11 09:45:00 +00:00
Christophe Dumez
953a99ee90 - Updated turkish translation 2007-04-10 20:57:35 +00:00
Christophe Dumez
e3f3293461 - Updated TODO 2007-04-10 15:26:44 +00:00
Christophe Dumez
8e8ffae57a - Disabled MainWindow context menu, more annoying than useful 2007-04-10 10:54:22 +00:00
Christophe Dumez
30d328774f - Fixed compiling error in finishedTorrents.cpp
- Added icons for bandwidth allocation actions
2007-04-10 10:50:34 +00:00
Christophe Dumez
e1660e592b - Added Upload limit per torrent in finished list 2007-04-10 10:11:36 +00:00
Christophe Dumez
6428fd4ae0 - Added bandwidth allocation to the right click menu on torrents 2007-04-10 10:05:04 +00:00
Christophe Dumez
b08d08512f - Bandwidth allocation per torrent class should be almost ready now 2007-04-10 09:43:26 +00:00
Christophe Dumez
a25cc14af4 - Fixed a crash when stopping a search (introduced when splitting search engine from GUI recently) 2007-04-10 09:35:34 +00:00
Christophe Dumez
30aa59f582 - Kept on working on bandwidth allocation per torrent
- Fixed a crash in search engine when systray integration was disabled
2007-04-10 09:31:25 +00:00
Christophe Dumez
3933d78da2 - Started to work on bandwidth allocation per torrent 2007-04-10 09:07:33 +00:00
Christophe Dumez
a9ed013ca3 - Code optimization in for loops tests 2007-04-10 08:05:27 +00:00
Christophe Dumez
b198494900 - Code cleanup using autoconnect slots 2007-04-10 07:54:06 +00:00
Christophe Dumez
216e9a9785 - Updated TODO 2007-04-10 07:21:56 +00:00
Christophe Dumez
c627c9b540 - Fixed the name of the protuguese translator 2007-04-09 19:01:56 +00:00
Christophe Dumez
359dcd3b99 - Added Japanese translator 2007-04-09 17:12:36 +00:00
Christophe Dumez
0eaa592086 - Disabled context menu in toolbar 2007-04-08 18:21:26 +00:00
Christophe Dumez
62b61750d1 - Translated "Japanese" into japanese in options 2007-04-07 13:58:23 +00:00
Christophe Dumez
3e1f7d2193 - Improved icons in torrent creation dialog for add_older and add_file 2007-04-07 13:54:59 +00:00
Christophe Dumez
8980905c24 - Fixed a typo 2007-04-07 07:48:06 +00:00
Christophe Dumez
f3f71e5d14 - Added Japanese translation 2007-04-07 07:43:57 +00:00
Arnaud Demaiziere
2a9d2a4910 about rss : new streams are aliased by their title 2007-04-06 12:57:41 +00:00
Christophe Dumez
59c6f469a0 - use PKGCONFIG again for libtorrent in configure 2007-04-05 22:58:12 +00:00
Christophe Dumez
4473b7917b - Fixed some bugs in rss 2007-04-05 22:38:46 +00:00
Christophe Dumez
3dbb958bde - Doesn't display that a torrent has finished on start when it finished during last session 2007-04-05 22:29:09 +00:00
Christophe Dumez
f81481c50f - Still cleaning up rss 2007-04-05 22:10:55 +00:00
Christophe Dumez
485c6b80af - Added a TODO in rss.h 2007-04-05 22:02:04 +00:00
Christophe Dumez
b8d5793ab7 - cleaned up rss.h 2007-04-05 20:29:30 +00:00
Christophe Dumez
933957282b - gtsoul commited some files he shouldn't have ;) 2007-04-05 19:43:11 +00:00
Christophe Dumez
381ae195b9 - Fixed a bug in the number of finished torrents initial display
- Started to clean up rss.h
2007-04-05 19:42:39 +00:00
Arnaud Demaiziere
d323dcd4e0 add svn_imp 2007-04-05 19:26:30 +00:00
Arnaud Demaiziere
1ae635a8b5 work on rss, right-click menu, refresh functions, and anticrash methods 2007-04-05 18:30:20 +00:00
Christophe Dumez
d3eda2e8be - Added Comboboxes in torrent properties. No usable yet but it will be very useful when we will support pieces prioritization 2007-04-05 15:55:05 +00:00
Arnaud Demaiziere
adf91c95d3 some work on rss, direct open & add stream function 2007-04-05 13:07:46 +00:00
Arnaud Demaiziere
eddee2a0d5 some work on rss, refresh & autoopenbrowser 2007-04-05 12:39:42 +00:00
Christophe Dumez
ff0dd88ee1 - Improved a lot the torrent creation module 2007-04-04 18:55:38 +00:00
Christophe Dumez
81d05a67b3 - Window can now stay maximized on exit 2007-04-04 14:53:00 +00:00
Christophe Dumez
a0743c0713 - Preview from finished list should now be working 2007-04-04 14:36:47 +00:00
Christophe Dumez
8c9ce5dd45 - Improved popup menu in finished list 2007-04-04 14:29:59 +00:00
Christophe Dumez
4727cd57ed - Removed pause/start in finished list (useless) 2007-04-04 14:25:56 +00:00
Christophe Dumez
775afd6ac2 - Implemented Start/Pause in finished list 2007-04-04 13:58:38 +00:00
Christophe Dumez
a615038498 - Added a popu menu in finished list 2007-04-04 13:12:11 +00:00
Christophe Dumez
cd70dcc3ba - Allow the user to display torrent properties in finished list 2007-04-04 12:52:50 +00:00
Christophe Dumez
5c53c457e5 - Implemented delete from finished list 2007-04-04 12:41:47 +00:00
Christophe Dumez
6d0b550f5d - Implemented DeleteFromHardDrive & finishedList 2007-04-04 12:33:53 +00:00
Christophe Dumez
37027c0480 - A lot of work on "Finished torrents are moved to a new tab". It still needs improvements but most of it is working
- Fixed pressing return in search field to launch search
2007-04-04 12:01:32 +00:00
Christophe Dumez
13aa2cfa6e - Added a new tab for finished torrents (WIP, not used yet) 2007-04-04 01:36:55 +00:00
Christophe Dumez
c832d91f79 - Ask for exit confirmation only if the download list is not empty 2007-04-04 00:47:26 +00:00
Christophe Dumez
c6c4bc1277 - FEATURE: Search engine is now using one thread per website for faster results 2007-04-03 23:55:21 +00:00
Christophe Dumez
2ab2e5a40f - Fixed configure files 2007-04-03 21:51:26 +00:00
Christophe Dumez
732cc41be4 - qConf is buggy and the configure file was not working properly. I had to rewrite most of the configure code to get it working. 2007-04-03 21:49:52 +00:00
Christophe Dumez
2f0bee3b19 - Updated splash screen to v0.10.0 2007-04-03 12:24:12 +00:00
Christophe Dumez
ab1d664f07 - Updated Changelog / Todo
- Fixed a title boldness in torrent properties
2007-04-02 13:22:48 +00:00
Christophe Dumez
95bc8e513a - Optimized friendlyUnit() function a little 2007-03-30 12:47:57 +00:00
Christophe Dumez
da2602a632 - Updated INSTALL file 2007-03-29 20:43:35 +00:00
Christophe Dumez
178a2046dc - Updated TODO
- Updated dependencies
2007-03-29 20:40:39 +00:00
Christophe Dumez
d90e4286e3 - Bring the window to foreround on exit when it was minimized 2007-03-29 20:21:17 +00:00
Christophe Dumez
5d0e466d6d - Allow the user to disable systray integration 2007-03-29 19:54:45 +00:00
Christophe Dumez
622fb85f60 - Updated TODO 2007-03-29 18:49:58 +00:00
Christophe Dumez
0ebdd34df3 Bring mainWindow to foreground when asking for exit confirmation 2007-03-29 18:46:50 +00:00
Christophe Dumez
81eee7bba2 - Style is now applied instantly, no need to restart qBT
- Fixed a typo in WIndowsXP Style
2007-03-29 18:43:04 +00:00
Christophe Dumez
5ddc3467f8 - Added some more debug in upnp code 2007-03-29 18:14:45 +00:00
Christophe Dumez
76d9a230c0 - Added all missing icons in RSS tab 2007-03-29 16:09:21 +00:00
Christophe Dumez
b3e6f341ff - Added RSS icon on its tab 2007-03-29 16:02:34 +00:00
Arnaud Demaiziere
6c8f0bff13 - Added a rss tab (still not functional) 2007-03-29 15:43:08 +00:00
Arnaud Demaiziere
456f57e32f - Added RSS support header 2007-03-29 15:27:40 +00:00
Christophe Dumez
4ca852c2b3 - Added a message log when an UPnP WAN service is detected 2007-03-29 14:49:01 +00:00
Christophe Dumez
3ff075c048 - Display more log messages 2007-03-29 14:31:43 +00:00
Christophe Dumez
ebc9d62f69 - Added a signal in upnp to display an error on GUI when no wan service is detected (still unused) 2007-03-29 14:12:26 +00:00
Christophe Dumez
fd3e60bce1 - Updated dutch translation 2007-03-29 13:55:38 +00:00
Christophe Dumez
3f01be8d6e - Fixed an error when disabling upnp
- upnp is now disabled as a default
2007-03-29 13:51:15 +00:00
Christophe Dumez
3ea7685405 - cleaning up upnp code 2007-03-29 13:31:10 +00:00
Christophe Dumez
fa2815df49 - Started to clean up upnp code 2007-03-29 13:28:11 +00:00
Christophe Dumez
01dd57a5fb - Reworked UPnP code a little 2007-03-29 12:52:14 +00:00
Christophe Dumez
a5ebc85bdb - Added some more debug in UPnP 2007-03-29 10:10:28 +00:00
Christophe Dumez
04a716ac91 - Fixed a mutex lock in UPnP code 2007-03-29 10:06:55 +00:00
Christophe Dumez
fc10f3c4cd - Forgot to remove this include 2007-03-29 09:55:53 +00:00
Christophe Dumez
682196543f - Move our own UPnP to a branch because it is taking too long 2007-03-29 09:55:17 +00:00
Christophe Dumez
2772a41917 - Added some missing functions body :) **WIP** but I need to sleep now. Will resume tomorrow :) 2007-03-28 22:29:23 +00:00
Christophe Dumez
0dc4bdd646 - some fixes in new UPnP (still unfinished) 2007-03-28 22:14:38 +00:00
Christophe Dumez
78916bba41 - Added debug in UPnP
- Started to rewrite qBT's own UPnP support instead of using aMule CVS code : (not usable yet)
2007-03-28 21:59:21 +00:00
Arnaud Demaiziere
e8e40c7bcf - Fixed compiling errors when upnp is disabled (chris) 2007-03-28 11:45:32 +00:00
Christophe Dumez
47db3386aa - Updated Italian translation 2007-03-28 11:19:30 +00:00
Christophe Dumez
92f840519c - Allow to change UPnP port while it is enabled
- Allow to change qBT style! (GTK people should like Cleanlooks style)
2007-03-28 08:05:37 +00:00
Christophe Dumez
e0a0a0beb1 - fix for UPnP option 2007-03-27 21:12:33 +00:00
Christophe Dumez
d778766e29 - UPnP option should now be working 2007-03-27 21:08:07 +00:00
Christophe Dumez
371dcb0a45 - Disable UPnP in options if qBT isn't compiled with UPnP support 2007-03-27 20:33:00 +00:00
Christophe Dumez
9408e8006d - Redesigned options
- Updated TODO
- Added UPnP option entry (but still not taken into consideration nor saved)
2007-03-27 20:26:07 +00:00
Christophe Dumez
2e4b7b375b - Removed option 'Automatically clear finished torrents' <- Decided it wasn't good for the network :) 2007-03-27 19:27:42 +00:00
Christophe Dumez
868d7cee4a - Removed some unused headers 2007-03-27 19:22:53 +00:00
Christophe Dumez
e8cc751f22 - Splitted search engine code from MainWindow part because GUI.cpp was getting too big and we are going to add a RSS tab soon
- Removed some unnecessary includes
2007-03-27 18:49:29 +00:00
Christophe Dumez
26e0c5d4ea - Updated TODO 2007-03-26 14:51:01 +00:00
Christophe Dumez
ef71b122df - Made ipfilter.dat parser less sensitive to errors 2007-03-26 14:48:01 +00:00
Christophe Dumez
98ecb97790 - Made ipfilter.dat parser less sensitive to errors 2007-03-26 14:45:09 +00:00
Christophe Dumez
86cfe82b89 - Updated version in desktop file 2007-03-26 07:49:34 +00:00
Christophe Dumez
1502bcb5d4 - Updated TODO
- Added a message box to display errors for torrent creation
2007-03-25 23:22:10 +00:00
Christophe Dumez
d2d3968b8b - Finished trackers edition 2007-03-25 18:39:27 +00:00
Christophe Dumez
1256da9bd5 - Remember edited trackers on restart 2007-03-25 16:18:57 +00:00
Christophe Dumez
1f6948d260 - Keep on working on trackers edition 2007-03-25 13:45:20 +00:00
Christophe Dumez
ab18594e00 - Updated Portuguese translation 2007-03-25 10:51:43 +00:00
Christophe Dumez
3467d68020 - Keep on working on trackers edition 2007-03-24 21:36:22 +00:00
Christophe Dumez
db7c7bd21a - Added missing icons in trackers tab (torrent properties) -> still unfinished 2007-03-24 20:55:15 +00:00
Christophe Dumez
f785888213 - Updated Changelog 2007-03-24 17:52:51 +00:00
Christophe Dumez
a346d49b60 - Displaying more infos about the torrent in its properties (hash, creator, comment)
- Preparing GUI to allow trackers list edition (Unfinished)
2007-03-24 17:50:53 +00:00
Christophe Dumez
5dacf4755e - Updated Ukrainian translation 2007-03-24 15:30:52 +00:00
Christophe Dumez
3e5f36dc97 - changed Danish to Dansk 2007-03-23 17:59:44 +00:00
Christophe Dumez
db55b72d87 - Updated TODO 2007-03-23 14:35:45 +00:00
Christophe Dumez
95844ce045 - Added option entry to select new Danish translation 2007-03-23 14:24:36 +00:00
Christophe Dumez
4bf4ed0f00 - Added Danish translation 2007-03-23 14:11:15 +00:00
Christophe Dumez
1d2d91d091 - Added a message saying if upnp is enabled or not 2007-03-23 14:10:16 +00:00
Christophe Dumez
40239f5cb2 - Updated spanish translation 2007-03-22 08:35:56 +00:00
Christophe Dumez
488e9d77b8 - Updated Bulgarian & greek translations 2007-03-19 21:54:33 +00:00
Christophe Dumez
85a5041a35 - Updated simplified chinese translation & translator 2007-03-19 21:21:01 +00:00
Christophe Dumez
fd2d2ddc0b - Added UPnP support (experimental) - taken from aMule CVS 2007-03-19 21:15:29 +00:00
Christophe Dumez
f8e7687551 - Added CONFIG += thread 2007-03-19 15:51:31 +00:00
Christophe Dumez
5140f42cb1 Update application style according to the system (WindowsXP, MacOS, X11) 2007-03-19 14:45:17 +00:00
Christophe Dumez
59e1e0bbf0 - Fixed a memory leak in options
- Removed unneeded QTranslator object in options.
2007-03-19 14:31:08 +00:00
Christophe Dumez
d53e85a232 - Updated TODO 2007-03-19 14:30:26 +00:00
Christophe Dumez
cf36db16ba - Updated korean translation 2007-03-17 13:56:59 +00:00
Christophe Dumez
5adf3f023d - Removing empty doc folders (moved) 2007-03-15 16:28:40 +00:00
Christophe Dumez
a0e49f8162 - bump version to v0.10.0alpha1 because now there is a branch for v0.9.x 2007-03-15 15:59:05 +00:00
Christophe Dumez
92eed29ded - Updated slovak translation 2007-03-15 15:54:06 +00:00
188 changed files with 82942 additions and 22690 deletions

View File

@@ -1 +1,5 @@
Christophe Dumez <chris@qbittorrent.org>
Author:
* Christophe Dumez <chris@qbittorrent.org>
Contributors:
* Arnaud Demaizière <arnaud@qbittorrent.org>

View File

@@ -1,18 +1,92 @@
* Unknown - Christophe Dumez <chris@qbittorrent.org> - v1.0.0
- FEATURE: Based on new libtorrent v0.13
- FEATURE: Added UPnP / NAT-PMP port forwarding support
- FEATURE: Added encryption support (compatible with Azureus)
- FEATURE: Bittorrent FAST extension support
- FEATURE: Added RSS support
- FEATURE: Support files prioritizing in a torrent
- FEATURE: Brand new search engine plugins system
- FEATURE: Filtered files don't appear on hard disk anymore
- FEATURE: Finished torrents are now moved to another tab for seeding
- FEATURE: Display more infos about the torrent in its properties
- FEATURE: Allow the user to edit torrents' trackers
- FEATURE: Allow user to change qBT's style (Plastique, Cleanlooks, Motif, CDE, MacOSX, WinXP)
- FEATURE: Allow the user to disable system tray integration
- FEATURE: Search engine is now using one thread per website for faster results
- FEATURE: Improved a lot the torrent creation module
- FEATURE: Allow to set upload/download limit per torrent (right click)
- FEATURE: Ask for exit confirmation only if download list is not empty
- FEATURE: Allow to use a proxy for trackers / web seeds / peers / DHT connections
- FEATURE: Supports SOCKS5 proxies as well as HTTP ones
- FEATURE: Better systems integration (buttons, dialogs...)
- FEATURE: Filtered files are not allocated on the hard-drive anymore (sparse file support)
- FEATURE: IPs blocked by filter are now logged in GUI
- FEATURE: Added a way to link against static libtorrent (useful for deb packages)
- FEATURE: Allow to set global upload/download limits from tray icon menu
- FEATURE: IPv6 is now fully supported
- FEATURE: Real torrent share ratio is now displayed in transfer list
- FEATURE: Added keyboard shortcuts for main actions (see wiki)
- FEATURE: Added a popup menu to set priority for multiple files at once
- FEATURE: Improved a lot downloading from urls (using libcommoncpp2 instead of libcurl)
- FEATURE: A search request can now be terminated by another
- FEATURE: User is now warned when fast resume data was rejected
- FEATURE: Url seeds are now displayed in torrent properties and are editable
- FEATURE: Allow to drag 'n drop urls on the main window
- FEATURE: Improved search engine (multipage support in all plugins)
- FEATURE: Added BTJunkie search engine plugin
- FEATURE: Added an option to force full disk allocation for all torrents
- FEATURE: Added an option to add torrents in paused state
- FEATURE: Added an option to set the max number of connections per torrent
- FEATURE: Added an option to set the max number of uploads per torrent
- FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0)
- FEATURE: Added an option to display current transfer speeds in title bar
- FEATURE: Torrent content is now displayed as a tree
- I18N: Added Hungarian translation
- I18N: Added Brazilian translation
- BUGFIX: Progress of paused torrents is now correct on restart
- BUGFIX: Progress column gets sorted on restart it is was during last execution
- BUGFIX: Made ETA more reliable using stats instead of instant values
- BUGFIX: Remove torrent from hard drive used to delete parent folder if empty
- BUGFIX: Fixed a crash when filtering all the files in a torrent
- BUGFIX: Reload torrent only when necessary (properties)
- BUGFIX: qBittorrent is not exiting anymore when a dialog is closed and main window is hidden
- BUGFIX: Search plugin update is not making the GUI freeze anymore (moved to a thread)
- BUGFIX: DHT settings were not saved correctly
- BUGFIX: Workaround to build on Fedora system (pkg-config problem)
- BUGFIX: search plugin update - do not display only last version changelog
- BUGFIX: Search plugin update - fixed missing new lines in changelog
- BUGFIX: The number of search results was not reset when clicking on 'Clear' button
- BUGFIX: Update torrent progress when its content changed (filtered files)
- BUGFIX: Improved the way menu icons are installed to avoid problems on some systems
- BUGFIX: Improved incremental download
- BUGFIX: Improved unicode support
- BUGFIX: Made torrent deletion from hard-drive safer
- BUGFIX: Prevent downloadFromUrl flooding
- BUGFIX: ETA was wrong for torrents with filtered files
- BUGFIX: Fixed drag'n drop on non-KDE systems
- COSMETIC: Redesigned torrent properties a little
- COSMETIC: Totally redesigned program preferences
- COSMETIC: Display more logs messages concerning features
- COSMETIC: Improved lists renderers
- COSMETIC: Use a different icon for torrents being checked and for connecting ones
- COSMETIC: Improved some icons
- COSMETIC: Improved systray tooltip style
* Mon May 07 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.3
- BUGFIX: Fixed pause toggle on double-click in download list
- BUGFIX: The torrent size displayed now only takes unfiltered files into account
- BUGFIX: Fixed compiling errors with libtorrent svn (future v0.13 with UPnP enabled)
- BUGFIX: Remember sorted column in download list on restart
- BUGFIX: Small fix in the german translation
- BUGFIX: Some fixes in slovak translation
- BUGFIX: Fixed pause toggle on double-click in download list
- BUGFIX: The torrent size displayed now only takes unfiltered files into account
- BUGFIX: Fixed compiling errors with libtorrent svn (future v0.13 with UPnP enabled)
- BUGFIX: Remember sorted column in download list on restart
- BUGFIX: Small fix in the german translation
- BUGFIX: Some fixes in slovak translation
* Tue Apr 10 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.2
- BUGFIX: Window can now stay maximized on exit
- BUGFIX: Use PKGCONFIG again for configuring libtorrent
- BUGFIX: Allow to compile with libtorrent v0.11
- BUGFIX: Disabled main window context menu (annoying)
- I18N: Added Japanese translation
- I18N: Updated Turkish translation
- BUGFIX: Window can now stay maximized on exit
- BUGFIX: Use PKGCONFIG again for configuring libtorrent
- BUGFIX: Allow to compile with libtorrent v0.11
- BUGFIX: Disabled main window context menu (annoying)
- I18N: Added Japanese translation
- I18N: Updated Turkish translation
* Wed Apr 04 2007 - Christophe Dumez <chris@qbittorrent.org> - v0.9.1
- BUGFIX: A lot of fixes in configure file

28
INSTALL
View File

@@ -1,4 +1,4 @@
qBittorrent - A BitTorrent client in C++ / Qt4.2
qBittorrent - A BitTorrent client in C++ / Qt4
------------------------------------------
*** Necessary if qt3 is default on your system ***
@@ -14,23 +14,33 @@ qbittorrent
will install and execute qBittorrent hopefully without any problems.
Dependencies:
- Qt >= 4.2 (libqt-devel, libqtgui, libqtcore, libqtnetwork)
- Qt >= 4.3.0 (libqt-devel, libqtgui, libqtcore, libqtnetwork, libqtxml)
- libtorrent by Arvid Norberg (>= v0.11 REQUIRED, >= 0.12 ADVISED)
-> http://libtorrent.sf.net
Be carefull: another library (the one used by rtorrent) use the same name.
- rblibtorrent by Arvid Norberg (>= v0.13 REQUIRED)
-> http://www.qbittorrent.org/download.php (advised)
-> http://www.libtorrent.net
Be careful: another library (the one used by rTorrent) use the same name.
These are TWO different libraries and qBittorrent will only work with the one provided
on sourceforge (created by Arvid Norberg). The two libraries conflicts with each other.
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
- libcurl
- libcommoncpp2
- python >= 2.3 (previous might work - not tested): needed by search engine.
- python >= 2.3 (needed by search engine)
NOTE FOR GNOME USERS:
- qt4-qtconfig package is advised or qBittorrent interface will be ugly
- libmagick++ (advised, not required)
* Needed for favicons support (RSS / Search plugins)
- libzzip (advised, not required)
* Needed for zip support (Search plugins)
NOTE FOR NON-KDE USERS:
- qt4-qtconfig package is advised when using other systems than KDE.
You can also change qBittorrent style to Cleanlooks (GNOME like)
DOCUMENTATION:
Please note that there is a documentation with a "compiling howto" at http://wiki.qbittorrent.org.
------------------------------------------
Christophe Dumez <chris@qbittorrent.org>

16
README
View File

@@ -1,32 +1,32 @@
qBittorrent - A BitTorrent client in Qt4.2
qBittorrent - A BitTorrent client in Qt4
------------------------------------------
Description:
********************************
qBittorrent is a bittorrent client programmed in C++ / Qt4.2 that use
libtorrent (sometimes called rb_libtorrent) by Arvid Norberg.
qBittorrent is a bittorrent client programmed in C++ / Qt4 that uses
libtorrent (sometimes called rblibtorrent) by Arvid Norberg.
It aims to be a good alternative to all other bittorrent clients
out there. qBittorrent is fast, stable and provides unicode
support.
support as well as many features.
Installation:
********************************
For installation follow the instructions from INSTALL file, but simple
For installation, follow the instructions from INSTALL file, but simple:
./configure
make && make install
qbittorrent
will install and execute qBittorrent hopefully without any problems.
will install and execute qBittorrent hopefully without any problem.
For more information please visit:
http://www.qbittorrent.org
Please report any bug (or feature requests) to:
Please report any bug (or feature request) to:
http://bugs.qbittorrent.org
You can also meet me on IRC:
You can also meet me (chris-qBT) on IRC:
#qbittorrent on irc.freenode.net
------------------------------------------

75
TODO
View File

@@ -1,38 +1,67 @@
// Easy
- Write documentation
- Translations into as many languages as possible
- Improve man page
- Add more keyboard shortcuts
- Use Launchpad/Rosetta for translations once it supports TS files
// Intermediate
- Port on MacOS, Windows (and create an installer for Windows) - Progressing
- Add some transparency (menus,...)
- Add upnp port forwarding support
- Port on MacOS, Windows (and create an installer for Windows) - Slow progress
- Add some transparency (menus,...), improve look / usabilty
- Skins support? (contact Mateusz)
// Harder
- Allow user to organize the downloads into categories/folders
- Display new searches in new tabs
- Display a progress bar that really displays the pieces we have (like in eMule)
- Display a progress bar that really represents the pieces we have (like in eMule)
- Torrent scheduler ala µtorrent/Bitcomet
// Waiting for libtorrent
- Encryption support (v0.13?)
- File selection in a torrent in compact mode
- Allow to prioritize files within a torrent
- Allow to prioritize torrents
- Allow to prioritize torrents (may code this in qBittorrent?)
// Unsure
- Display the peers we are connected to for each torrent with infos (like flag, dl/up speeds, ...)
- Azureus spoofing to prevent ban from trackers?
- Web interface?
- Use downloader class to download search plugin updates
- Allow to set upload limit for each torrent
- Option to shutdown computer when downloads are finished
- Add a torrent scheduler
- NAT checker/Tester
- Display hard drive space left?
- Make use of dbus on Linux for the single instance instead of socket communication?
(http://techbase.kde.org/Development/Tutorials/D-Bus/Accessing_Interfaces)
- When favicon can't be downloaded, try to parse the webpage for:
<link rel="icon" href="http://example.com/favicon.ico" type="image/vnd.microsoft.icon">
* Be carefull, the link can be relative
// in v1.0.0 (partial)
- Download from RSS feeds (WIP by gtsoul)
- Move finished torrent to another tab and keep on seeding them even after restart
- Allow to edit the trackers for a torrent
- Improve torrent creation dialog (look & features)
- Add IPv6 support (at least start working on it)
- UPnP support?
// in v1.2.0
- Allow user to organize the downloads into categories/folders?
// in v1.1.0
- Tabs support in search
- Allow to hide columns?
- Allow to scan multiple directories? (useful?)
- Web interface (turbogears? php? python?)
* Webserver? Try to write a webserver as a plugin for qBittorrent in Python
* http://fragments.turtlemeat.com/pythonwebserver.php
- improve and test tracker authentication code (remember login/pass) (need a tracker to test this)
- support zipped torrents? (useful?)
- Allow to limit the number of downloading torrents simultaneously (other are paused until a download finishes)
- Improve search plugin install (choose in a list taken from plugins.qbittorrent.org)
- Display the number of DHT node if possible
- When adding a duplicate torrent, check if the trackers are different from the existing one and ask the user if he wants to add them
- Display in torrent addition dialog:
* free disk space on selected drive
* free disk space after torrent download (and/or torrent size)
- Allow to change action on double-click
-> in download list
-> in seeding list
// in v1.0.0 - FEATURE FREEZE
- Fix all (or almost all) opened bugs in bug tracker
- Recheck doc
- Translations update (IN PROGRESS)
- add qt4-qtconfig as package dependency
rc4->rc5 changelog:
- BUGFIX: Now filtered don't appear on hard drive anymore (libtorrent >= r1659)
- BUGFIX: AddInPause setting doesn't pause downloads on startup anymore
- BUGFIX: Fixed an ETA calculation problem when the torrent has filtered files
- BUGFIX: Fixed possible overflow in ETA calculation
- BUGFIX: Fixed "Missing Input path" error when creating a torrent
- BUGFIX: Fixed some notification messages for torrent addition dialog
- BUGFIX: Fixed "Automatically start seeding" feature in torrent creation tool
- COSMETIC: Improved progress bar text rendering

474
configure vendored
View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# Generated by qconf 1.3 ( http://delta.affinix.com/qconf/ )
# Generated by qconf 1.4 ( http://delta.affinix.com/qconf/ )
#
show_usage() {
@@ -18,11 +18,18 @@ Main options:
--help This help text.
Dependency options:
--with-libtorrent-inc=[path] Path to libtorrent include files
--with-libtorrent-lib=[path] Path to libtorrent library files
--with-libboost-inc=[path] Path to libboost include files
--with-libcurl-inc=[path] Path to libcurl include files
--with-libcurl-lib=[path] Path to libcurl library files
--with-libtorrent-inc=[path] Path to libtorrent include files
--with-libtorrent-lib=[path] Path to libtorrent library files
--with-libtorrent-static-lib=[path] Path to libtorrent .a file
--with-libboost-inc=[path] Path to libboost include files
--with-libcommoncpp2-inc=[path] Path to libcommoncpp2 include files
--with-libcommoncpp2-lib=[path] Path to libcommoncpp2 library files
--disable-libmagick Disable use of libmagick
--with-libmagick-inc=[path] Path to libmagick++ include files
--with-libmagick-lib=[path] Path to libmagick++ library files
--disable-libzzip Disable use of libzzip
--with-libzzip-inc=[path] Path to libzzip++ include files
--with-libzzip-lib=[path] Path to libzzip++ library files
EOT
}
@@ -149,23 +156,58 @@ while [ $# -gt 0 ]; do
shift
;;
--with-libtorrent-static-lib=*)
QC_WITH_LIBTORRENT_STATIC_LIB=$optarg
shift
;;
--with-libboost-inc=*)
QC_WITH_LIBBOOST_INC=$optarg
shift
;;
--with-libcurl-inc=*)
QC_WITH_LIBCURL_INC=$optarg
--with-libcommoncpp2-inc=*)
QC_WITH_LIBCOMMONCPP2_INC=$optarg
shift
;;
--with-libcurl-lib=*)
QC_WITH_LIBCURL_LIB=$optarg
--with-libcommoncpp2-lib=*)
QC_WITH_LIBCOMMONCPP2_LIB=$optarg
shift
;;
--disable-libmagick)
QC_DISABLE_libmagick="Y"
shift
;;
--with-libmagick-inc=*)
QC_WITH_LIBMAGICK_INC=$optarg
shift
;;
--with-libmagick-lib=*)
QC_WITH_LIBMAGICK_LIB=$optarg
shift
;;
--disable-libzzip)
QC_DISABLE_libzzip="Y"
shift
;;
--with-libzzip-inc=*)
QC_WITH_LIBZZIP_INC=$optarg
shift
;;
--with-libzzip-lib=*)
QC_WITH_LIBZZIP_LIB=$optarg
shift
;;
--verbose)
QC_DEBUG="Y"
QC_VERBOSE="Y"
shift
;;
--help) show_usage; exit ;;
@@ -179,7 +221,7 @@ DATADIR=${DATADIR:-$PREFIX/share}
echo "Configuring qbittorrent ..."
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo
echo PREFIX=$PREFIX
echo BINDIR=$BINDIR
@@ -187,39 +229,65 @@ echo DATADIR=$DATADIR
echo EX_QTDIR=$EX_QTDIR
echo QC_WITH_LIBTORRENT_INC=$QC_WITH_LIBTORRENT_INC
echo QC_WITH_LIBTORRENT_LIB=$QC_WITH_LIBTORRENT_LIB
echo QC_WITH_LIBTORRENT_STATIC_LIB=$QC_WITH_LIBTORRENT_STATIC_LIB
echo QC_WITH_LIBBOOST_INC=$QC_WITH_LIBBOOST_INC
echo QC_WITH_LIBCURL_INC=$QC_WITH_LIBCURL_INC
echo QC_WITH_LIBCURL_LIB=$QC_WITH_LIBCURL_LIB
echo QC_WITH_LIBCOMMONCPP2_INC=$QC_WITH_LIBCOMMONCPP2_INC
echo QC_WITH_LIBCOMMONCPP2_LIB=$QC_WITH_LIBCOMMONCPP2_LIB
echo QC_DISABLE_libmagick=$QC_DISABLE_libmagick
echo QC_WITH_LIBMAGICK_INC=$QC_WITH_LIBMAGICK_INC
echo QC_WITH_LIBMAGICK_LIB=$QC_WITH_LIBMAGICK_LIB
echo QC_DISABLE_libzzip=$QC_DISABLE_libzzip
echo QC_WITH_LIBZZIP_INC=$QC_WITH_LIBZZIP_INC
echo QC_WITH_LIBZZIP_LIB=$QC_WITH_LIBZZIP_LIB
echo
fi
printf "Verifying Qt 4 build environment ... "
if [ "$QC_DEBUG" = "Y" ]; then
# run qmake -v and check version
qmake_check_v4() {
if [ -x "$1" ]; then
if echo `$1 -v 2>&1` | grep "Qt version 4\." >/dev/null 2>&1; then
return 0
elif [ "$QC_VERBOSE" = "Y" ]; then
echo "Warning: $1 not for Qt 4"
fi
fi
return 1
}
if [ "$QC_VERBOSE" = "Y" ]; then
echo
fi
qm=""
names="qmake-qt4 qmake4 qmake"
# qt4 check: --qtdir
if [ -z "$qm" ]; then
qstr=$EX_QTDIR/bin/qmake
if [ -x "$qstr" ]; then
qm=$qstr
fi
if [ -z "$qm" ] && [ ! -z "$EX_QTDIR" ]; then
for n in $names; do
qstr=$EX_QTDIR/bin/$n
if qmake_check_v4 "$qstr"; then
qm=$qstr
break;
fi
done
fi
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
echo "Warning: qmake not found via --qtdir"
fi
# qt4 check: QTDIR
if [ -z "$qm" ]; then
qstr=$QTDIR/bin/qmake
if [ -x "$qstr" ]; then
qm=$qstr
fi
if [ -z "$qm" ] && [ ! -z "$QTDIR" ]; then
for n in $names; do
qstr=$QTDIR/bin/$n
if qmake_check_v4 "$qstr"; then
qm=$qstr
break;
fi
done
fi
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
echo "Warning: qmake not found via \$QTDIR"
fi
@@ -227,60 +295,66 @@ fi
if [ -z "$qm" ]; then
str=`pkg-config QtCore --variable=exec_prefix 2>/dev/null`
if [ ! -z "$str" ]; then
qstr=$str/bin/qmake
if [ -x "$qstr" ]; then
qm=$qstr
fi
for n in $names; do
qstr=$str/bin/$n
if qmake_check_v4 "$qstr"; then
qm=$qstr
break;
fi
done
fi
fi
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
echo "Warning: qmake not found via pkg-config"
fi
# qt4 check: PATH
if [ -z "$qm" ]; then
qstr=`$WHICH qmake 2>/dev/null`
if [ -x "$qstr" ]; then
qm=$qstr
fi
for n in $names; do
qstr=`$WHICH $n 2>/dev/null`
if qmake_check_v4 "$qstr"; then
qm=$qstr
break;
fi
done
fi
if [ -z "$qm" ] && [ "$QC_DEBUG" = "Y" ]; then
if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
echo "Warning: qmake not found via \$PATH"
fi
if [ -z "$qm" ]; then
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo " -> fail"
else
echo "fail"
fi
printf "\n"
printf "Reason: Unable to find the 'qmake' tool.\n"
printf "Reason: Unable to find the 'qmake' tool for Qt 4.\n"
printf "\n"
show_qt_info
exit 1;
fi
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo qmake found in $qm
fi
gen_files() {
cat >$1/modules.cpp <<EOT
#line 1 "qt42.qcm"
#line 1 "qt4.qcm"
/*
-----BEGIN QCMOD-----
name: Qt >= 4.2
name: Qt >= 4.3
-----END QCMOD-----
*/
class qc_qt42 : public ConfObj
class qc_qt4 : public ConfObj
{
public:
qc_qt42(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.2"; }
QString shortname() const { return "qt42"; }
qc_qt4(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.3"; }
QString shortname() const { return "Qt 4.3"; }
bool exec()
{
return(QT_VERSION >= 0x040200);
return(QT_VERSION >= 0x040300);
}
};
#line 1 "libtorrent.qcm"
@@ -289,51 +363,46 @@ public:
name: libtorrent
arg: with-libtorrent-inc=[path], Path to libtorrent include files
arg: with-libtorrent-lib=[path], Path to libtorrent library files
arg: with-libtorrent-static-lib=[path], Path to libtorrent .a file
-----END QCMOD-----
*/
class qc_libtorrent : public ConfObj
{
public:
qc_libtorrent(Conf *c) : ConfObj(c) {}
QString name() const { return "libtorrent >= 0.11 (>= 0.12 ADVISED)"; }
QString name() const { return "libtorrent >= 0.13"; }
QString shortname() const { return "libtorrent"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
return false;
}
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")) {
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
conf->addDefine("NO_PEX");
}
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
conf->addDefine("V_0_13");
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
found = true;
break;
}
}
if(!found) return false;
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")){
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
conf->addDefine("NO_PEX");
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
found = true;
break;
}
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
conf->addDefine("V_0_13");
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
conf->addIncludePath(s+QDir::separator()+"libtorrent");
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
conf->addLib(s);
return true;
}
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "torrent")) {
@@ -354,7 +423,16 @@ public:
if(!found) return false;
conf->addLib(QString("-L") + s);
}
//conf->addLib("-ltorrent");
// BUGFIX for Fedora (doesn't support pkg-config?)
QFile issue_file("/etc/issue");
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString content = issue_file.readAll();
issue_file.close();
if(content.indexOf("Fedora") != -1){
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
conf->addLib("-lssl -lcrypto -lboost_date_time -lboost_filesystem -lboost_thread -lz -ltorrent");
}
}
return true;
}
};
@@ -415,65 +493,225 @@ public:
return true;
}
};
#line 1 "libcurl.qcm"
#line 1 "libcommoncpp2.qcm"
/*
-----BEGIN QCMOD-----
name: libcurl
arg: with-libcurl-inc=[path], Path to libcurl include files
arg: with-libcurl-lib=[path], Path to libcurl library files
name: libcommoncpp2
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
-----END QCMOD-----
*/
class qc_libcurl : public ConfObj
class qc_libcommoncpp2 : public ConfObj
{
public:
qc_libcurl(Conf *c) : ConfObj(c) {}
QString name() const { return "libcurl"; }
QString shortname() const { return "libcurl"; }
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
QString shortname() const { return "libcommoncpp2"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBCURL_INC");
QString s;
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "curl/curl.h")) {
if(!conf->checkHeader(s, "cc++/url.h")) {
return false;
}
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "curl/curl.h")){
if(conf->checkHeader(s, "cc++/url.h")){
found = true;
break;
}
}
if(!found) {
return false;
}
}
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBCURL_LIB");
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "curl")) {
return false;
}
conf->addLib(QString("-L") + s);
if(!QFile::exists(s+QString("libccext2.so")))
return false;
if(!QFile::exists(s+QString("libccgnu2.so")))
return false;
conf->addLib(QString("-L") + s);
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "curl")){
found = true;
break;
if(QFile::exists(s+QString("libccext2.so"))){
if(QFile::exists(s+QString("libccgnu2.so"))){
found = true;
break;
}
}
}
if(!found) return false;
conf->addLib(QString("-L") + s);
}
conf->addLib("-lcurl");
// BUGFIX for Fedora (doesn't support pkg-config?)
QFile issue_file("/etc/issue");
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString content = issue_file.readAll();
issue_file.close();
if(content.indexOf("Fedora") != -1){
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
conf->addLib("-pthread -lccext2 -lz -lccgnu2 -ldl -lrt");
}
}
return true;
}
};
#line 1 "libmagick.qcm"
/*
-----BEGIN QCMOD-----
name: libmagick
arg: with-libmagick-inc=[path], Path to libmagick++ include files
arg: with-libmagick-lib=[path], Path to libmagick++ library files
-----END QCMOD-----
*/
#include <QProcess>
class qc_libmagick : public ConfObj
{
public:
qc_libmagick(Conf *c) : ConfObj(c) {}
QString name() const { return "ImageMagick library (libmagick++)"; }
QString shortname() const { return "libmagick++"; }
QString checkString() const {
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return "";
return ConfObj::checkString();
}
bool exec(){
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return false;
QString s;
s = conf->getenv("QC_WITH_LIBMAGICK_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "Magick++.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "Magick++.h")){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("libMagick++.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libMagick++.so"))){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addLib(QString("-L") + s);
QProcess magickConfig;
QStringList params;
params << "--libs";
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
magickConfig.waitForStarted();
magickConfig.waitForFinished();
QByteArray result = magickConfig.readAll();
result = result.replace("\n", "");
conf->addLib(result.data());
conf->addDefine("HAVE_MAGICK");
return true;
}
};
#line 1 "libzzip.qcm"
/*
-----BEGIN QCMOD-----
name: libzzip
arg: with-libzzip-inc=[path], Path to libzzip++ include files
arg: with-libzzip-lib=[path], Path to libzzip++ library files
-----END QCMOD-----
*/
#include <QProcess>
class qc_libzzip : public ConfObj
{
public:
qc_libzzip(Conf *c) : ConfObj(c) {}
QString name() const { return "Zzip library (libzzip)"; }
QString shortname() const { return "libzzip"; }
QString checkString() const {
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
return "";
return ConfObj::checkString();
}
bool exec(){
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
return false;
QString s;
s = conf->getenv("QC_WITH_LIBZZIP_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "zzip/zzip.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "zzip/zzip.h")){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBZZIP_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("libzzip.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libzzip.so"))){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addLib(QString("-L") + s);
conf->addLib("-lzzip");
conf->addDefine("HAVE_ZZIP");
return true;
}
};
@@ -500,7 +738,7 @@ public:
EOT
cat >$1/modules_new.cpp <<EOT
o = new qc_qt42(conf);
o = new qc_qt4(conf);
o->required = true;
o->disabled = false;
o = new qc_libtorrent(conf);
@@ -509,15 +747,23 @@ cat >$1/modules_new.cpp <<EOT
o = new qc_libboost(conf);
o->required = true;
o->disabled = false;
o = new qc_libcurl(conf);
o = new qc_libcommoncpp2(conf);
o->required = true;
o->disabled = false;
o = new qc_libmagick(conf);
o->required = false;
o->disabled = false;
o = new qc_libzzip(conf);
o->required = false;
o->disabled = false;
o = new qc_python(conf);
o->required = true;
o->disabled = false;
EOT
cat >$1/conf4.h <<EOT
// For license information, see the COPYING file in the qconf base directory.
#ifndef QC_CONF4_H
#define QC_CONF4_H
@@ -622,6 +868,8 @@ private:
EOT
cat >$1/conf4.cpp <<EOT
// For license information, see the COPYING file in the qconf base directory.
#include "conf4.h"
#include <stdio.h>
@@ -772,6 +1020,18 @@ void qc_splitcflags(const QString &cflags, QStringList *incs, QStringList *other
}
}
QString qc_escapeArg(const QString &str)
{
QString out;
for(int n = 0; n < (int)str.length(); ++n) {
if(str[n] == '-')
out += '_';
else
out += str[n];
}
return out;
}
//----------------------------------------------------------------------------
// ConfObj
//----------------------------------------------------------------------------
@@ -888,14 +1148,14 @@ bool Conf::exec()
// if this was a disabled-by-default option, check if it was enabled
if(o->disabled)
{
QString v = QString("QC_ENABLE_") + o->shortname();
QString v = QString("QC_ENABLE_") + qc_escapeArg(o->shortname());
if(getenv(v) != "Y")
continue;
}
// and the opposite?
else
{
QString v = QString("QC_DISABLE_") + o->shortname();
QString v = QString("QC_DISABLE_") + qc_escapeArg(o->shortname());
if(getenv(v) == "Y")
continue;
}
@@ -1322,7 +1582,7 @@ int main()
# include"modules_new.cpp"
#endif
conf->debug_enabled = (qc_getenv("QC_DEBUG") == "Y") ? true: false;
conf->debug_enabled = (qc_getenv("QC_VERBOSE") == "Y") ? true: false;
if(conf->debug_enabled)
printf(" -> ok\n");
else
@@ -1378,6 +1638,9 @@ int main()
var = qc_getenv("BINDIR");
if(!var.isEmpty())
str += QString("BINDIR = %1\n").arg(var);
var = qc_getenv("INCDIR");
if(!var.isEmpty())
str += QString("INCDIR = %1\n").arg(var);
var = qc_getenv("LIBDIR");
if(!var.isEmpty())
str += QString("LIBDIR = %1\n").arg(var);
@@ -1443,10 +1706,17 @@ export DATADIR
export EX_QTDIR
export QC_WITH_LIBTORRENT_INC
export QC_WITH_LIBTORRENT_LIB
export QC_WITH_LIBTORRENT_STATIC_LIB
export QC_WITH_LIBBOOST_INC
export QC_WITH_LIBCURL_INC
export QC_WITH_LIBCURL_LIB
export QC_DEBUG
export QC_WITH_LIBCOMMONCPP2_INC
export QC_WITH_LIBCOMMONCPP2_LIB
export QC_DISABLE_libmagick
export QC_WITH_LIBMAGICK_INC
export QC_WITH_LIBMAGICK_LIB
export QC_DISABLE_libzzip
export QC_WITH_LIBZZIP_INC
export QC_WITH_LIBZZIP_LIB
export QC_VERBOSE
rm -rf .qconftemp
(
mkdir .qconftemp
@@ -1459,7 +1729,7 @@ rm -rf .qconftemp
if [ "$?" != "0" ]; then
rm -rf .qconftemp
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo " -> fail"
else
echo "fail"
@@ -1468,7 +1738,7 @@ if [ "$?" != "0" ]; then
printf "Reason: There was an error compiling 'conf'. See conf.log for details.\n"
printf "\n"
show_qt_info
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo "conf.log:"
cat conf.log
fi
@@ -1492,7 +1762,7 @@ if [ "$ret" = "1" ]; then
else
if [ "$ret" != "0" ]; then
rm -rf .qconftemp
if [ "$QC_DEBUG" = "Y" ]; then
if [ "$QC_VERBOSE" = "Y" ]; then
echo " -> fail"
else
echo "fail"

Binary file not shown.

200
qBittorrent.kdevelop Normal file
View File

@@ -0,0 +1,200 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Christophe Dumez</author>
<email>chris@qbittorrent.org</email>
<version>1.0.0</version>
<projectmanagement>KDevTrollProject</projectmanagement>
<primarylanguage>C++</primarylanguage>
<keywords>
<keyword>Qt</keyword>
</keywords>
<projectname>qBittorrent</projectname>
<ignoreparts/>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
<defaultencoding/>
<versioncontrol>kdevsubversion</versioncontrol>
</general>
<kdevfileview>
<groups>
<group pattern="*.cpp;*.cxx;*.h" name="Sources" />
<group pattern="*.ui" name="User Interface" />
<group pattern="*.png" name="Icons" />
<group pattern="*" name="Others" />
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
<showvcsfields>false</showvcsfields>
</tree>
</kdevfileview>
<kdevdoctreeview>
<ignoretocs>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>w3c-dom-level2-html</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>stl</toc>
<toc>w3c-svg</toc>
<toc>sw</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevdebugger>
<general>
<dbgshell/>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
</general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger>
<kdevcppsupport>
<qt>
<version>4</version>
<used>true</used>
<includestyle>4</includestyle>
<designerintegration>ExternalDesigner</designerintegration>
<root>/usr/lib/qt4</root>
<qmake>/usr/bin/qmake-qt4</qmake>
<designer>/usr/bin/designer-qt4</designer>
<designerpluginpaths/>
</qt>
<references>
<pcs>automatic_%2Fhome%2Fchris%2Fqbittorrent_svn%2Ftrunk</pcs>
<pcs>Qt4</pcs>
</references>
<codecompletion>
<automaticCodeCompletion>true</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
<completionBoxItemOrder>0</completionBoxItemOrder>
<howEvaluationContextMenu>true</howEvaluationContextMenu>
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
<processPrimaryTypes>true</processPrimaryTypes>
<processFunctionArguments>true</processFunctionArguments>
<preProcessAllHeaders>true</preProcessAllHeaders>
<parseMissingHeadersExperimental>true</parseMissingHeadersExperimental>
<resolveIncludePathsUsingMakeExperimental>true</resolveIncludePathsUsingMakeExperimental>
<alwaysParseInBackground>true</alwaysParseInBackground>
<usePermanentCaching>true</usePermanentCaching>
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
<includePaths>.;</includePaths>
</codecompletion>
<creategettersetter>
<prefixGet>get</prefixGet>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
<splitheadersource>
<enabled>false</enabled>
<synchronize>true</synchronize>
<orientation>Vertical</orientation>
</splitheadersource>
</kdevcppsupport>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="ui" />
<type ext="cpp" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevtrollproject>
<general>
<activedir></activedir>
</general>
<run>
<directoryradio>executable</directoryradio>
<mainprogram>/home/chris/qbittorrent_svn/trunk/src/qbittorrent</mainprogram>
<programargs/>
<globaldebugarguments/>
<globalcwd>/home/chris/qbittorrent_svn/trunk</globalcwd>
<useglobalprogram>true</useglobalprogram>
<terminal>false</terminal>
<autocompile>true</autocompile>
<autoinstall>false</autoinstall>
<autokdesu>false</autokdesu>
<envvars/>
</run>
<make>
<abortonerror>true</abortonerror>
<runmultiplejobs>false</runmultiplejobs>
<numberofjobs>1</numberofjobs>
<dontact>false</dontact>
<makebin/>
<prio>0</prio>
<envvars/>
</make>
<qmake>
<savebehaviour>2</savebehaviour>
<replacePaths>false</replacePaths>
<disableDefaultOpts>true</disableDefaultOpts>
</qmake>
</kdevtrollproject>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
<ctagspart>
<customArguments/>
<customTagfilePath>/home/chris/qbittorrent_svn/trunk/tags</customTagfilePath>
<activeTagsFiles/>
</ctagspart>
<kdevdocumentation>
<projectdoc>
<docsystem/>
<docurl/>
<usermanualurl/>
</projectdoc>
</kdevdocumentation>
</kdevelop>

View File

@@ -2,7 +2,8 @@
<name>qbittorrent</name>
<profile>qbittorrent.pro</profile>
<moddir>qcm</moddir>
<dep type='qt42'>
<datadir/>
<dep type='qt4'>
<required/>
</dep>
<dep type='libtorrent'>
@@ -11,9 +12,11 @@
<dep type='libboost'>
<required/>
</dep>
<dep type='libcurl'>
<dep type='libcommoncpp2'>
<required/>
</dep>
<dep type='libmagick'/>
<dep type='libzzip'/>
<dep type='python'>
<required/>
</dep>

73
qcm/libcommoncpp2.qcm Normal file
View File

@@ -0,0 +1,73 @@
/*
-----BEGIN QCMOD-----
name: libcommoncpp2
arg: with-libcommoncpp2-inc=[path], Path to libcommoncpp2 include files
arg: with-libcommoncpp2-lib=[path], Path to libcommoncpp2 library files
-----END QCMOD-----
*/
class qc_libcommoncpp2 : public ConfObj
{
public:
qc_libcommoncpp2(Conf *c) : ConfObj(c) {}
QString name() const { return "GNU Common C++ library (libcommoncpp2)"; }
QString shortname() const { return "libcommoncpp2"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "cc++/url.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "cc++/url.h")){
found = true;
break;
}
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBCOMMONCPP2_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("libccext2.so")))
return false;
if(!QFile::exists(s+QString("libccgnu2.so")))
return false;
conf->addLib(QString("-L") + s);
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libccext2.so"))){
if(QFile::exists(s+QString("libccgnu2.so"))){
found = true;
break;
}
}
}
if(!found) return false;
conf->addLib(QString("-L") + s);
}
// BUGFIX for Fedora (doesn't support pkg-config?)
QFile issue_file("/etc/issue");
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString content = issue_file.readAll();
issue_file.close();
if(content.indexOf("Fedora") != -1){
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
conf->addLib("-pthread -lccext2 -lz -lccgnu2 -ldl -lrt");
}
}
return true;
}
};

View File

@@ -1,61 +0,0 @@
/*
-----BEGIN QCMOD-----
name: libcurl
arg: with-libcurl-inc=[path], Path to libcurl include files
arg: with-libcurl-lib=[path], Path to libcurl library files
-----END QCMOD-----
*/
class qc_libcurl : public ConfObj
{
public:
qc_libcurl(Conf *c) : ConfObj(c) {}
QString name() const { return "libcurl"; }
QString shortname() const { return "libcurl"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBCURL_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "curl/curl.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "curl/curl.h")){
found = true;
break;
}
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBCURL_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "curl")) {
return false;
}
conf->addLib(QString("-L") + s);
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(conf->checkLibrary(s, "curl")){
found = true;
break;
}
}
if(!found) return false;
conf->addLib(QString("-L") + s);
}
conf->addLib("-lcurl");
return true;
}
};

77
qcm/libmagick.qcm Normal file
View File

@@ -0,0 +1,77 @@
/*
-----BEGIN QCMOD-----
name: libmagick
arg: with-libmagick-inc=[path], Path to libmagick++ include files
arg: with-libmagick-lib=[path], Path to libmagick++ library files
-----END QCMOD-----
*/
#include <QProcess>
class qc_libmagick : public ConfObj
{
public:
qc_libmagick(Conf *c) : ConfObj(c) {}
QString name() const { return "ImageMagick library (libmagick++)"; }
QString shortname() const { return "libmagick++"; }
QString checkString() const {
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return "";
return ConfObj::checkString();
}
bool exec(){
if(!conf->getenv("QC_DISABLE_libmagick").isEmpty())
return false;
QString s;
s = conf->getenv("QC_WITH_LIBMAGICK_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "Magick++.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "Magick++.h")){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBMAGICK_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("libMagick++.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libMagick++.so"))){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addLib(QString("-L") + s);
QProcess magickConfig;
QStringList params;
params << "--libs";
magickConfig.start("Magick++-config", params, QIODevice::ReadOnly);
magickConfig.waitForStarted();
magickConfig.waitForFinished();
QByteArray result = magickConfig.readAll();
result = result.replace("\n", "");
conf->addLib(result.data());
conf->addDefine("HAVE_MAGICK");
return true;
}
};

View File

@@ -3,51 +3,46 @@
name: libtorrent
arg: with-libtorrent-inc=[path], Path to libtorrent include files
arg: with-libtorrent-lib=[path], Path to libtorrent library files
arg: with-libtorrent-static-lib=[path], Path to libtorrent .a file
-----END QCMOD-----
*/
class qc_libtorrent : public ConfObj
{
public:
qc_libtorrent(Conf *c) : ConfObj(c) {}
QString name() const { return "libtorrent >= 0.11 (>= 0.12 ADVISED)"; }
QString name() const { return "libtorrent >= 0.13"; }
QString shortname() const { return "libtorrent"; }
bool exec(){
QString s;
s = conf->getenv("QC_WITH_LIBTORRENT_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
if(!conf->checkHeader(s, "libtorrent/lsd.hpp")) {
return false;
}
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")) {
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
conf->addDefine("NO_PEX");
}
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
conf->addDefine("V_0_13");
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "libtorrent/kademlia/node.hpp")){
found = true;
break;
}
}
if(!found) return false;
if(!conf->checkHeader(s, "libtorrent/extensions/ut_pex.hpp")){
qWarning("Libtorrent >= v0.12 was not detected, PeX will be disabled.");
conf->addDefine("NO_PEX");
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
found = true;
break;
}
if(conf->checkHeader(s, "libtorrent/lsd.hpp")){
conf->addDefine("V_0_13");
}
if(!found) {
return false;
}
}
conf->addIncludePath(s);
conf->addIncludePath(s+QDir::separator()+"libtorrent");
s = conf->getenv("QC_WITH_LIBTORRENT_STATIC_LIB");
if(!s.isEmpty() && QFile::exists(s) && s.endsWith(".a")){
conf->addLib(s);
return true;
}
s = conf->getenv("QC_WITH_LIBTORRENT_LIB");
if(!s.isEmpty()) {
if(!conf->checkLibrary(s, "torrent")) {
@@ -68,7 +63,16 @@ public:
if(!found) return false;
conf->addLib(QString("-L") + s);
}
//conf->addLib("-ltorrent");
// BUGFIX for Fedora (doesn't support pkg-config?)
QFile issue_file("/etc/issue");
if(issue_file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString content = issue_file.readAll();
issue_file.close();
if(content.indexOf("Fedora") != -1){
qWarning("Fedora detected. WORKAROUND for Fedora pkg-config problem enabled");
conf->addLib("-lssl -lcrypto -lboost_date_time -lboost_filesystem -lboost_thread -lz -ltorrent");
}
}
return true;
}
};

69
qcm/libzzip.qcm Normal file
View File

@@ -0,0 +1,69 @@
/*
-----BEGIN QCMOD-----
name: libzzip
arg: with-libzzip-inc=[path], Path to libzzip++ include files
arg: with-libzzip-lib=[path], Path to libzzip++ library files
-----END QCMOD-----
*/
#include <QProcess>
class qc_libzzip : public ConfObj
{
public:
qc_libzzip(Conf *c) : ConfObj(c) {}
QString name() const { return "Zzip library (libzzip)"; }
QString shortname() const { return "libzzip"; }
QString checkString() const {
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
return "";
return ConfObj::checkString();
}
bool exec(){
if(!conf->getenv("QC_DISABLE_LIBZZIP").isEmpty())
return false;
QString s;
s = conf->getenv("QC_WITH_LIBZZIP_INC");
if(!s.isEmpty()) {
if(!conf->checkHeader(s, "zzip/zzip.h")) {
return false;
}
}else{
QStringList sl;
sl << "/usr/include";
sl << "/usr/local/include";
bool found = false;
foreach(s, sl){
if(conf->checkHeader(s, "zzip/zzip.h")){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addIncludePath(s);
s = conf->getenv("QC_WITH_LIBZZIP_LIB");
if(!s.isEmpty()) {
if(!QFile::exists(s+QString("libzzip.so"))){
return false;
}
}else{
QStringList sl;
sl << "/usr/lib/";
sl << "/usr/local/lib/";
bool found = false;
foreach(s, sl){
if(QFile::exists(s+QString("libzzip.so"))){
found = true;
break;
}
}
if(!found)
return false;
}
conf->addLib(QString("-L") + s);
conf->addLib("-lzzip");
conf->addDefine("HAVE_ZZIP");
return true;
}
};

16
qcm/qt4.qcm Normal file
View File

@@ -0,0 +1,16 @@
/*
-----BEGIN QCMOD-----
name: Qt >= 4.3
-----END QCMOD-----
*/
class qc_qt4 : public ConfObj
{
public:
qc_qt4(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.3"; }
QString shortname() const { return "Qt 4.3"; }
bool exec()
{
return(QT_VERSION >= 0x040300);
}
};

View File

@@ -1,16 +0,0 @@
/*
-----BEGIN QCMOD-----
name: Qt >= 4.2
-----END QCMOD-----
*/
class qc_qt42 : public ConfObj
{
public:
qc_qt42(Conf *c) : ConfObj(c) {}
QString name() const { return "Qt >= 4.2"; }
QString shortname() const { return "qt42"; }
bool exec()
{
return(QT_VERSION >= 0x040200);
}
};

View File

@@ -22,10 +22,11 @@
#ifndef DLLISTDELEGATE_H
#define DLLISTDELEGATE_H
#include <QAbstractItemDelegate>
#include <QItemDelegate>
#include <QModelIndex>
#include <QPainter>
#include <QStyleOptionProgressBarV2>
#include <QStyleOptionViewItemV2>
#include <QProgressBar>
#include <QApplication>
#include "misc.h"
@@ -37,128 +38,66 @@
#define DLSPEED 3
#define UPSPEED 4
#define SEEDSLEECH 5
#define STATUS 6
#define RATIO 6
#define ETA 7
#define HASH 8
class DLListDelegate: public QAbstractItemDelegate {
class DLListDelegate: public QItemDelegate {
Q_OBJECT
public:
DLListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
DLListDelegate(QObject *parent) : QItemDelegate(parent){}
~DLListDelegate(){}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
QStyleOptionViewItem opt = option;
char tmp[MAX_CHAR_TMP];
// set text color
QVariant value = index.data(Qt::TextColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
}else{
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if(index.column() != PROGRESS){
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
}else{
value = index.data(Qt::BackgroundColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
}
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
switch(index.column()){
case SIZE:
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;
case ETA:
painter->drawText(option.rect, Qt::AlignCenter, misc::userFriendlyDuration(index.data().toLongLong()));
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::userFriendlyDuration(index.data().toLongLong()));
break;
case UPSPEED:
case DLSPEED:{
float speed = index.data().toDouble();
snprintf(tmp, MAX_CHAR_TMP, "%.1f", speed/1024.);
painter->drawText(option.rect, Qt::AlignCenter, QString(tmp)+" "+tr("KiB/s"));
QItemDelegate::drawBackground(painter, opt, index);
double speed = index.data().toDouble();
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(speed/1024., 'f', 1))+QString::fromUtf8(" ")+tr("KiB/s"));
break;
}
case RATIO:{
QItemDelegate::drawBackground(painter, opt, index);
double ratio = index.data().toDouble();
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
break;
}
case PROGRESS:{
QStyleOptionProgressBarV2 newopt;
float progress;
progress = index.data().toDouble()*100.;
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
double progress = index.data().toDouble()*100.;
newopt.rect = opt.rect;
newopt.text = QString(tmp)+"%";
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
newopt.progress = (int)progress;
newopt.maximum = 100;
newopt.minimum = 0;
newopt.state |= QStyle::State_Enabled;
newopt.textVisible = false;
newopt.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
painter);
//We prefer to display text manually to control color/font/boldness
if (option.state & QStyle::State_Selected){
opt.palette.setColor(QPalette::Text, QColor("grey"));
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
break;
}
case NAME:{
// decoration
value = index.data(Qt::DecorationRole);
QPixmap pixmap = qvariant_cast<QIcon>(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off);
QRect pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize));
if (pixmapRect.isValid()){
QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft();
painter->drawPixmap(p, pixmap);
}
painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString());
break;
}
default:
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
QItemDelegate::paint(painter, option, index);
}
}
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
QVariant value = index.data(Qt::FontRole);
QFont fnt = value.isValid() ? qvariant_cast<QFont>(value) : option.font;
QFontMetrics fontMetrics(fnt);
const QString text = index.data(Qt::DisplayRole).toString();
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
return textRect.size();
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
// No editor here
return 0;
}
// QWidget* createEditor(QWidget * parent, const QStyleOptionViewItem& /*option*/, const QModelIndex & index) const{
// if(index.column() == PROGRESS){
// QProgressBar *progressBar = new QProgressBar(parent);
// progressBar->setRange(0,100);
// progressBar->installEventFilter(const_cast<DLListDelegate*>(this));
// return progressBar;
// }
// return 0;
// }
// void setEditorData(QWidget *editor, const QModelIndex &index) const{
// QProgressBar *progressBar = static_cast<QProgressBar*>(editor);
// float progress = index.data().toDouble();
// progressBar->setValue((int)(progress*100.));
// }
// void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & index) const{
// if(index.column() == PROGRESS){
// editor->setGeometry(option.rect);
// }
// }
};
#endif

View File

@@ -0,0 +1,96 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef FINISHEDLISTDELEGATE_H
#define FINISHEDLISTDELEGATE_H
#include <QItemDelegate>
#include <QModelIndex>
#include <QPainter>
#include <QStyleOptionProgressBarV2>
#include <QStyleOptionViewItemV2>
#include <QProgressBar>
#include <QApplication>
#include "misc.h"
// Defines for download list list columns
#define F_NAME 0
#define F_SIZE 1
#define F_PROGRESS 2
#define F_UPSPEED 3
#define F_SEEDSLEECH 4
#define F_RATIO 5
#define F_HASH 6
class FinishedListDelegate: public QItemDelegate {
Q_OBJECT
public:
FinishedListDelegate(QObject *parent) : QItemDelegate(parent){}
~FinishedListDelegate(){}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
switch(index.column()){
case F_SIZE:
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;
case F_UPSPEED:{
QItemDelegate::drawBackground(painter, opt, index);
double speed = index.data().toDouble();
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(speed/1024., 'f', 1))+QString::fromUtf8(" ")+tr("KiB/s"));
break;
}
case F_RATIO:{
QItemDelegate::drawBackground(painter, opt, index);
double ratio = index.data().toDouble();
QItemDelegate::drawDisplay(painter, opt, opt.rect, QString(QByteArray::number(ratio, 'f', 1)));
break;
}
case F_PROGRESS:{
QStyleOptionProgressBarV2 newopt;
double progress = index.data().toDouble()*100.;
newopt.rect = opt.rect;
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
newopt.progress = (int)progress;
newopt.maximum = 100;
newopt.minimum = 0;
newopt.state |= QStyle::State_Enabled;
newopt.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
painter);
break;
}
default:
QItemDelegate::paint(painter, option, index);
}
}
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
// No editor here
return 0;
}
};
#endif

425
src/FinishedTorrents.cpp Normal file
View File

@@ -0,0 +1,425 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#include "FinishedTorrents.h"
#include "misc.h"
#include "properties_imp.h"
#include "bittorrent.h"
#include "allocationDlg.h"
#include "FinishedListDelegate.h"
#include "GUI.h"
#include <QFile>
#include <QSettings>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QMenu>
FinishedTorrents::FinishedTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), nbFinished(0){
setupUi(this);
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
finishedListModel = new QStandardItemModel(0,7);
finishedListModel->setHeaderData(F_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
finishedListModel->setHeaderData(F_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
finishedListModel->setHeaderData(F_PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
finishedListModel->setHeaderData(F_UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
finishedListModel->setHeaderData(F_SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources"));
finishedListModel->setHeaderData(F_RATIO, Qt::Horizontal, tr("Ratio"));
finishedList->setModel(finishedListModel);
// Hide ETA & hash column
finishedList->hideColumn(F_HASH);
// Load last columns width for download list
if(!loadColWidthFinishedList()){
finishedList->header()->resizeSection(0, 200);
}
// Make download list header clickable for sorting
finishedList->header()->setClickable(true);
finishedList->header()->setSortIndicatorShown(true);
connect(finishedList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortFinishedList(int)));
finishedListDelegate = new FinishedListDelegate(finishedList);
finishedList->setItemDelegate(finishedListDelegate);
connect(finishedList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFinishedListMenu(const QPoint&)));
connect(finishedList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
}
FinishedTorrents::~FinishedTorrents(){
saveColWidthFinishedList();
delete finishedListDelegate;
delete finishedListModel;
}
void FinishedTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
unsigned int row = index.row();
QString hash = getHashFromRow(row);
emit torrentDoubleClicked(hash);
}
void FinishedTorrents::addTorrent(QString hash){
if(!BTSession->isFinished(hash)){
BTSession->setFinishedTorrent(hash);
}
int row = getRowFromHash(hash);
if(row != -1) return;
row = finishedListModel->rowCount();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
// Adding torrent to download list
finishedListModel->insertRow(row);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(h.name()));
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.));
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant("0/0"));
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(QString::fromUtf8(misc::toString(BTSession->getRealRatio(hash)).c_str())));
finishedListModel->setData(finishedListModel->index(row, F_HASH), QVariant(hash));
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)1.));
if(h.is_paused()) {
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(":/Icons/skin/paused.png"), Qt::DecorationRole);
setRowColor(row, "red");
}else{
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(":/Icons/skin/seeding.png")), Qt::DecorationRole);
setRowColor(row, "orange");
}
// Update the number of finished torrents
++nbFinished;
emit finishedTorrentsNumberChanged(nbFinished);
}
void FinishedTorrents::torrentAdded(QString, QTorrentHandle& h, bool) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
addTorrent(hash);
}
}
// Set the color of a row in data model
void FinishedTorrents::setRowColor(int row, QString color){
unsigned int nbColumns = finishedListModel->columnCount()-1;
for(unsigned int i=0; i<nbColumns; ++i){
finishedListModel->setData(finishedListModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
}
}
QStringList FinishedTorrents::getSelectedTorrents(bool only_one) const{
QStringList res;
QModelIndex index;
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
foreach(index, selectedIndexes) {
if(index.column() == F_NAME) {
// Get the file hash
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
res << hash;
if(only_one) break;
}
}
return res;
}
unsigned int FinishedTorrents::getNbTorrentsInList() const {
return nbFinished;
}
// Load columns width in a file that were saved previously
// (finished list)
bool FinishedTorrents::loadColWidthFinishedList(){
qDebug("Loading columns width for finished list");
QSettings settings("qBittorrent", "qBittorrent");
QString line = settings.value("FinishedListColsWidth", QString()).toString();
if(line.isEmpty())
return false;
QStringList width_list = line.split(' ');
if(width_list.size() != finishedListModel->columnCount()-1)
return false;
unsigned int listSize = width_list.size();
for(unsigned int i=0; i<listSize; ++i){
finishedList->header()->resizeSection(i, width_list.at(i).toInt());
}
qDebug("Finished list columns width loaded");
return true;
}
// Save columns width in a file to remember them
// (finished list)
void FinishedTorrents::saveColWidthFinishedList() const{
qDebug("Saving columns width in finished list");
QSettings settings("qBittorrent", "qBittorrent");
QStringList width_list;
unsigned int nbColumns = finishedListModel->columnCount()-1;
for(unsigned int i=0; i<nbColumns; ++i){
width_list << QString::fromUtf8(misc::toString(finishedList->columnWidth(i)).c_str());
}
settings.setValue("FinishedListColsWidth", width_list.join(" "));
qDebug("Finished list columns width saved");
}
void FinishedTorrents::on_actionSet_upload_limit_triggered(){
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
QModelIndex index;
QStringList hashes;
foreach(index, selectedIndexes){
if(index.column() == F_NAME){
// Get the file hash
hashes << finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
}
}
new BandwidthAllocationDialog(this, true, BTSession, hashes);
}
void FinishedTorrents::updateFinishedList(){
QString hash;
QStringList finishedSHAs = BTSession->getFinishedTorrents();
foreach(hash, finishedSHAs){
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()){
qDebug("Problem: This torrent is not valid in finished list");
continue;
}
int row = getRowFromHash(hash);
if(row == -1){
qDebug("Cannot find torrent in finished list, adding it");
addTorrent(hash);
row = getRowFromHash(hash);
}
Q_ASSERT(row != -1);
if(h.is_paused()) continue;
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)h.progress()));
continue;
}
if(h.state() == torrent_status::downloading || (h.state() != torrent_status::checking_files && h.state() != torrent_status::queued_for_checking && h.progress() < 1.)) {
// What are you doing here? go back to download tab!
qDebug("Info: a torrent was moved from finished to download tab");
deleteTorrent(hash);
BTSession->setFinishedTorrent(hash);
emit torrentMovedFromFinishedList(hash);
continue;
}
if(h.state() == torrent_status::checking_files){
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)h.progress()));
continue;
}
setRowColor(row, QString::fromUtf8("orange"));
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)h.upload_payload_rate()));
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+"/"+misc::toQString(h.num_peers() - h.num_seeds(), true)));
finishedListModel->setData(finishedListModel->index(row, F_RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
finishedListModel->setData(finishedListModel->index(row, F_PROGRESS), QVariant((double)1.));
}
}
int FinishedTorrents::getRowFromHash(QString hash) const{
unsigned int nbRows = finishedListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i){
if(finishedListModel->data(finishedListModel->index(i, F_HASH)) == hash){
return i;
}
}
return -1;
}
// Note: does not actually pause the torrent in BT Session
void FinishedTorrents::pauseTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
finishedListModel->setData(finishedListModel->index(row, F_UPSPEED), QVariant((double)0.0));
finishedListModel->setData(finishedListModel->index(row, F_NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(row, F_SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
setRowColor(row, QString::fromUtf8("red"));
}
void FinishedTorrents::resumeTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
finishedListModel->setData(finishedListModel->index(row, F_NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("orange"));
}
QString FinishedTorrents::getHashFromRow(unsigned int row) const {
Q_ASSERT(row < (unsigned int)finishedListModel->rowCount());
return finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
}
// Will move it to download tab
void FinishedTorrents::deleteTorrent(QString hash){
int row = getRowFromHash(hash);
if(row == -1){
qDebug("Torrent is not in finished list, nothing to delete");
return;
}
finishedListModel->removeRow(row);
--nbFinished;
emit finishedTorrentsNumberChanged(nbFinished);
}
// Show torrent properties dialog
void FinishedTorrents::showProperties(const QModelIndex &index){
int row = index.row();
QString hash = finishedListModel->data(finishedListModel->index(row, F_HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
properties *prop = new properties(this, BTSession, h);
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSize(QString)));
prop->show();
}
void FinishedTorrents::updateFileSize(QString hash){
int row = getRowFromHash(hash);
QTorrentHandle h = BTSession->getTorrentHandle(hash);
finishedListModel->setData(finishedListModel->index(row, F_SIZE), QVariant((qlonglong)h.actual_size()));
}
// display properties of selected items
void FinishedTorrents::propertiesSelection(){
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
QModelIndex index;
foreach(index, selectedIndexes){
if(index.column() == F_NAME){
showProperties(index);
}
}
}
void FinishedTorrents::displayFinishedListMenu(const QPoint& pos){
QMenu myFinishedListMenu(this);
QModelIndex index;
// Enable/disable pause/start action given the DL state
QModelIndexList selectedIndexes = finishedList->selectionModel()->selectedIndexes();
QSettings settings("qBittorrent", "qBittorrent");
QString previewProgram = settings.value("Preferences/general/MediaPlayer", QString()).toString();
bool has_pause = false, has_start = false, has_preview = false;
foreach(index, selectedIndexes) {
if(index.column() == F_NAME) {
// Get the file name
QString hash = finishedListModel->data(finishedListModel->index(index.row(), F_HASH)).toString();
// Get handle and pause the torrent
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()) continue;
if(h.is_paused()) {
if(!has_start) {
myFinishedListMenu.addAction(actionStart);
has_start = true;
}
}else{
if(!has_pause) {
myFinishedListMenu.addAction(actionPause);
has_pause = true;
}
}
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
myFinishedListMenu.addAction(actionPreview_file);
has_preview = true;
}
if(has_pause && has_start && has_preview) break;
}
}
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionDelete);
myFinishedListMenu.addAction(actionDelete_Permanently);
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionSet_upload_limit);
myFinishedListMenu.addSeparator();
myFinishedListMenu.addAction(actionTorrent_Properties);
// Call menu
// XXX: why mapToGlobal() is not enough?
myFinishedListMenu.exec(mapToGlobal(pos)+QPoint(10,55));
}
/*
* Sorting functions
*/
void FinishedTorrents::sortFinishedList(int index){
static Qt::SortOrder sortOrder = Qt::AscendingOrder;
if(finishedList->header()->sortIndicatorSection() == index){
if(sortOrder == Qt::AscendingOrder){
sortOrder = Qt::DescendingOrder;
}else{
sortOrder = Qt::AscendingOrder;
}
}
finishedList->header()->setSortIndicator(index, sortOrder);
switch(index){
case F_SIZE:
case F_UPSPEED:
case F_PROGRESS:
sortFinishedListFloat(index, sortOrder);
break;
default:
sortFinishedListString(index, sortOrder);
}
}
void FinishedTorrents::sortFinishedListFloat(int index, Qt::SortOrder sortOrder){
QList<QPair<int, double> > lines;
// insertion sorting
unsigned int nbRows = finishedListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i){
misc::insertSort(lines, QPair<int,double>(i, finishedListModel->data(finishedListModel->index(i, index)).toDouble()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row){
finishedListModel->insertRow(finishedListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = finishedListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col){
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
finishedListModel->removeRows(0, nbRows_old);
}
void FinishedTorrents::sortFinishedListString(int index, Qt::SortOrder sortOrder){
QList<QPair<int, QString> > lines;
// Insertion sorting
unsigned int nbRows = finishedListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i){
misc::insertSortString(lines, QPair<int, QString>(i, finishedListModel->data(finishedListModel->index(i, index)).toString()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row){
finishedListModel->insertRow(finishedListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = finishedListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col){
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col)));
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
finishedListModel->setData(finishedListModel->index(nbRows_old+row, col), finishedListModel->data(finishedListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
finishedListModel->removeRows(0, nbRows_old);
}

81
src/FinishedTorrents.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef SEEDING_H
#define SEEDING_H
#include "ui_seeding.h"
#include "qtorrenthandle.h"
class QStandardItemModel;
class bittorrent;
class FinishedListDelegate;
using namespace libtorrent;
class FinishedTorrents : public QWidget, public Ui::seeding {
Q_OBJECT
private:
QObject *parent;
bittorrent *BTSession;
FinishedListDelegate *finishedListDelegate;
QStandardItemModel *finishedListModel;
unsigned int nbFinished;
public:
FinishedTorrents(QObject *parent, bittorrent *BTSession);
~FinishedTorrents();
// Methods
bool loadColWidthFinishedList();
int getRowFromHash(QString hash) const;
QStringList getSelectedTorrents(bool only_one=false) const;
unsigned int getNbTorrentsInList() const;
QString getHashFromRow(unsigned int row) const;
protected slots:
void showProperties(const QModelIndex &index);
void displayFinishedListMenu(const QPoint&);
void setRowColor(int row, QString color);
void saveColWidthFinishedList() const;
void sortFinishedList(int index);
void sortFinishedListFloat(int index, Qt::SortOrder sortOrder);
void sortFinishedListString(int index, Qt::SortOrder sortOrder);
void updateFileSize(QString hash);
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void on_actionSet_upload_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
public slots:
void addTorrent(QString hash);
void updateFinishedList();
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void propertiesSelection();
void deleteTorrent(QString hash);
signals:
void torrentMovedFromFinishedList(QString);
void torrentDoubleClicked(QString hash);
void finishedTorrentsNumberChanged(unsigned int);
};
#endif

File diff suppressed because it is too large Load Diff

202
src/GUI.h
View File

@@ -22,169 +22,132 @@
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include <QProcess>
#include <QTcpServer>
#include <QSystemTrayIcon>
#include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/session.hpp>
#include <libtorrent/fingerprint.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/identify_client.hpp>
#include <libtorrent/alert_types.hpp>
#include "ui_MainWindow.h"
#include "options_imp.h"
#include "about_imp.h"
#include "previewSelect.h"
#include "trackerLogin.h"
#include "bittorrent.h"
#define TIME_TRAY_BALLOON 5000
#include "qtorrenthandle.h"
class bittorrent;
class createtorrent;
class QTimer;
class QCompleter;
class DLListDelegate;
class SearchListDelegate;
class downloadThread;
class DownloadingTorrents;
class FinishedTorrents;
class downloadFromURL;
class SearchEngine;
class QTcpServer;
class QTcpSocket;
class QCloseEvent;
using namespace libtorrent;
namespace fs = boost::filesystem;
class RSSImp;
class QShortcut;
class about;
class previewSelect;
class options_imp;
class QTabWidget;
class QLabel;
class QModelIndex;
class GUI : public QMainWindow, private Ui::MainWindow{
Q_OBJECT
private:
// Bittorrent
bittorrent BTSession;
bittorrent *BTSession;
QTimer *checkConnect;
QHash<QString, QStringList> trackerErrors;
QList<QPair<torrent_handle,std::string> > unauthenticated_trackers;
downloadFromURL *downloadFromURLDialog;
QList<QPair<QTorrentHandle,QString> > unauthenticated_trackers;
// GUI related
QTabWidget *tabs;
options_imp *options;
createtorrent *createWindow;
QTimer *refresher;
QSystemTrayIcon *myTrayIcon;
QMenu *myTrayIconMenu;
about *aboutdlg;
QStandardItemModel *DLListModel;
DLListDelegate *DLDelegate;
QStandardItemModel *SearchListModel;
SearchListDelegate *SearchDelegate;
unsigned int nbTorrents;
DownloadingTorrents *downloadingTorrentTab;
FinishedTorrents *finishedTorrentTab;
QLabel *connecStatusLblIcon;
bool systrayIntegration;
bool displaySpeedInTitle;
bool force_exit;
unsigned int refreshInterval;
QTimer *refresher;
// Keyboard shortcuts
QShortcut *switchSearchShortcut;
QShortcut *switchSearchShortcut2;
QShortcut *switchDownShortcut;
QShortcut *switchUpShortcut;
QShortcut *switchRSSShortcut;
// Preview
previewSelect *previewSelection;
QProcess *previewProcess;
// Search related
QHash<QString, QString> searchResultsUrls;
QProcess *searchProcess;
bool search_stopped;
bool no_search_results;
QByteArray search_result_line_truncated;
unsigned long nb_search_results;
QTcpServer tcpServer;
// Search
SearchEngine *searchEngine;
// RSS
RSSImp *rssWidget;
// Misc
QTcpServer *tcpServer;
QTcpSocket *clientConnection;
QCompleter *searchCompleter;
QStringList searchHistory;
protected slots:
// GUI related slots
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void toggleVisibility(QSystemTrayIcon::ActivationReason e);
void showAbout();
void setInfoBar(const QString& info, const QString& color="black");
void updateDlList(bool force=false);
void showCreateWindow();
void clearLog();
void openqBTHomepage();
void openqBTBugTracker();
void on_actionAbout_triggered();
void on_actionCreate_torrent_triggered();
void on_actionWebsite_triggered() const;
void on_actionBugReport_triggered() const;
void readParamsOnSocket();
void acceptConnection();
void saveCheckedSearchEngines(int) const;
void saveColWidthDLList() const;
void saveColWidthSearchList() const;
void loadCheckedSearchEngines();
bool loadColWidthDLList();
bool loadColWidthSearchList();
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
void sortSearchList(int index);
void sortSearchListInt(int index, Qt::SortOrder sortOrder);
void sortSearchListString(int index, Qt::SortOrder sortOrder);
void displayDLListMenu(const QPoint& pos);
void selectGivenRow(const QModelIndex& index);
void togglePausedState(const QModelIndex& index);
void displayInfoBarMenu(const QPoint& pos);
void displayGUIMenu(const QPoint& pos);
void previewFileSelection();
void previewFile(const QString& filePath);
void cleanTempPreviewFile(int, QProcess::ExitStatus);
void togglePausedState(QString hash);
void on_actionPreview_file_triggered();
void previewFile(QString filePath);
void cleanTempPreviewFile(int, QProcess::ExitStatus) const;
void balloonClicked();
void writeSettings();
void readSettings();
void forceExit();
void on_actionExit_triggered();
void createTrayIcon();
void updateUnfinishedTorrentNumber(unsigned int nb);
void updateFinishedTorrentNumber(unsigned int nb);
void fullDiskError(QTorrentHandle& h) const;
void handleDownloadFromUrlFailure(QString, QString) const;
// Keyboard shortcuts
void createKeyboardShortcuts();
void displayDownTab() const;
void displayUpTab() const;
void displaySearchTab() const;
void displayRSSTab() const;
// Torrent actions
size_type torrentEffectiveSize(QString hash) const;
void showProperties(const QModelIndex &index);
void propertiesSelection();
void pauseSelection();
void pauseAll();
void startSelection();
void resumeAll();
void askForTorrents();
void deletePermanently();
void deleteSelection();
void on_actionTorrent_Properties_triggered();
void on_actionPause_triggered();
void on_actionPause_All_triggered();
void on_actionStart_triggered();
void on_actionStart_All_triggered();
void on_actionOpen_triggered();
void on_actionDelete_Permanently_triggered();
void on_actionDelete_triggered();
void on_actionSet_global_upload_limit_triggered();
void on_actionSet_global_download_limit_triggered();
void on_actionDocumentation_triggered() const;
void checkConnectionStatus();
void configureSession(bool deleteOptions);
void processParams(const QStringList& params);
void addUnauthenticatedTracker(QPair<torrent_handle,std::string> tracker);
void addTorrent(QString path);
void addUnauthenticatedTracker(QPair<QTorrentHandle,QString> tracker);
void processScannedFiles(const QStringList& params);
void processDownloadedFiles(const QString& path, const QString& url);
void processDownloadedFiles(QString path, QString url);
void downloadFromURLList(const QStringList& urls);
void displayDownloadingUrlInfos(const QString& url);
// Search slots
void on_search_button_clicked();
void on_stop_search_button_clicked();
void on_clear_button_clicked();
void on_download_button_clicked();
void on_update_nova_button_clicked();
void appendSearchResult(const QString& line);
void searchFinished(int exitcode,QProcess::ExitStatus);
void readSearchOutput();
void searchStarted();
void downloadSelectedItem(const QModelIndex& index);
void startSearchHistory();
void saveSearchHistory();
// Utils slots
void setRowColor(int row, const QString& color, bool inDLList=true);
void deleteTorrent(QString hash, QString fileName, bool finished);
void finishedTorrent(QTorrentHandle& h) const;
void torrentChecked(QString hash) const;
void updateLists();
// Options slots
void showOptions();
void OptionsSaved(const QString& info, bool deleteOptions);
void on_actionOptions_triggered();
void OptionsSaved(QString info, bool deleteOptions);
// HTTP slots
void askForTorrentUrl();
void on_actionDownload_from_URL_triggered();
public slots:
void torrentAdded(const QString& path, torrent_handle& h, bool fastResume);
void torrentDuplicate(const QString& path);
void torrentCorrupted(const QString& path);
void finishedTorrent(torrent_handle& h);
void fullDiskError(torrent_handle& h);
void portListeningFailure();
void trackerError(const QString& hash, const QString& time, const QString& msg);
void trackerAuthenticationRequired(torrent_handle& h);
void updateFileSize(QString hash);
void trackerAuthenticationRequired(QTorrentHandle& h);
void setTabText(int index, QString text) const;
protected:
void closeEvent(QCloseEvent *);
@@ -195,11 +158,8 @@ class GUI : public QMainWindow, private Ui::MainWindow{
GUI(QWidget *parent=0, QStringList torrentCmdLine=QStringList());
~GUI();
// Methods
int getRowFromHash(const QString& hash) const;
float getNovaVersion(const QString& novaPath) const;
QByteArray getNovaChangelog(const QString& novaPath) const;
void updateNova() const;
QPoint screenCenter();
unsigned int getCurrentTabIndex() const;
QPoint screenCenter() const;
};
#endif

BIN
src/Icons/add_file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

BIN
src/Icons/add_folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/Icons/bt_settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/configure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/Icons/connection.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

BIN
src/Icons/description.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

BIN
src/Icons/downarrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

BIN
src/Icons/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 998 B

BIN
src/Icons/flags/brazil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

BIN
src/Icons/flags/hungary.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

BIN
src/Icons/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

BIN
src/Icons/gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/Icons/loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

BIN
src/Icons/mascot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 532 B

BIN
src/Icons/password.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -1,22 +1,23 @@
[Desktop Entry]
Categories=Qt;Application;Network;P2P
Comment=V0.9.2
Comment=V1.0.0
Encoding=UTF-8
Exec=qbittorrent
GenericName=Bittorrent client
GenericName[fr]=Client Bittorrent
GenericName[nl]=Bittorrent client
GenericName[bg]=Торент клиент
GenericName[de]=Bittorren Client
GenericName[el]=Τορεντ πελάτης
GenericName[es]=Cliente Bittorrent
GenericName[fr]=Client Bittorrent
GenericName[ja]=Bittorrent クライアント
GenericName[ko]=비토렌트 클라이언트
GenericName[nl]=Bittorrent client
GenericName[pl]=Klient Bittorrent
GenericName[ru]=клиент Bittorrent
GenericName[sv]=Bittorrent-klient
GenericName[tr]=Bittorrent istemcisi
GenericName[de]=Bittorren Client
GenericName[pl]=Klient Bittorrent
GenericName[zh]=Bittorrent之用户
GenericName[ko]=비토렌트 클라이언트
GenericName[el]=Τορεντ πελάτης
GenericName[bg]=Торент клиент
GenericName[uk]=Bittorrent-клієнт
GenericName[ru]=клиент Bittorrent
GenericName[zh]=Bittorrent之用户
Icon=qbittorrent
MimeType=application/x-bittorrent
Name=qBittorrent

BIN
src/Icons/refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

BIN
src/Icons/rss16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

BIN
src/Icons/rss32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/Icons/sphere.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

BIN
src/Icons/sphere2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

BIN
src/Icons/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
src/Icons/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/subscribe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/Icons/subscribe16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

BIN
src/Icons/time.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

BIN
src/Icons/unavailable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/Icons/unsubscribe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/Icons/unsubscribe16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

BIN
src/Icons/uparrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

BIN
src/Icons/url.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

View File

@@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>849</width>
<height>576</height>
<height>563</height>
</rect>
</property>
<property name="contextMenuPolicy" >
@@ -17,713 +17,12 @@
</property>
<widget class="QWidget" name="centralwidget" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QTabWidget" name="tabs" >
<property name="tabPosition" >
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<string>Transfers</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_DLSpeed" >
<property name="text" >
<string>Total DL Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_DownSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0" >
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitDL" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Session ratio: </string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_Ratio" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="numDigits" >
<number>4</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_ratio_icon" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_UPSpeed" >
<property name="text" >
<string>Total UP Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_UpSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitUP" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="downloadList" >
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll" >
<bool>true</bool>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="info_icon" >
<property name="minimumSize" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_info" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Log:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>661</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTextBrowser" name="infoBar" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>123</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2" >
<attribute name="title" >
<string>Search</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="groupEngines" >
<property name="minimumSize" >
<size>
<width>131</width>
<height>132</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>125</width>
<height>132</height>
</size>
</property>
<property name="title" >
<string>Search Engines</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QCheckBox" name="mininova" >
<property name="text" >
<string/>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="piratebay" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="isohunt" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="meganova" >
<property name="text" >
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="search_lbl" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>35</height>
</size>
</property>
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Search Pattern:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="search_pattern" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="search_button" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>29</height>
</size>
</property>
<property name="text" >
<string>Search</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stop_search_button" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>29</height>
</size>
</property>
<property name="text" >
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="status_lbl" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>35</height>
</size>
</property>
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Status:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="search_status" >
<property name="minimumSize" >
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>35</height>
</size>
</property>
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>true</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Stopped</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="results_lbl" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Results:</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>721</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="resultsBrowser" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll" >
<bool>true</bool>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="download_button" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>Download</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clear_button" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>Clear</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>601</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="update_nova_button" >
<property name="text" >
<string>Update search plugin</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<property name="margin" >
<number>9</number>
</property>
</layout>
</widget>
<widget class="QMenuBar" name="menubar" >
@@ -735,12 +34,6 @@
<height>29</height>
</rect>
</property>
<widget class="QMenu" name="menu_Options" >
<property name="title" >
<string>&amp;Options</string>
</property>
<addaction name="actionOptions" />
</widget>
<widget class="QMenu" name="menu_Edit" >
<property name="title" >
<string>&amp;Edit</string>
@@ -760,9 +53,16 @@
<property name="title" >
<string>&amp;Help</string>
</property>
<addaction name="actionAbout" />
<addaction name="actionBugReport" />
<addaction name="actionWebsite" />
<addaction name="actionDocumentation" />
<addaction name="actionAbout" />
</widget>
<widget class="QMenu" name="menu_Options" >
<property name="title" >
<string>Options</string>
</property>
<addaction name="actionOptions" />
</widget>
<widget class="QMenu" name="menu_File" >
<property name="title" >
@@ -800,6 +100,9 @@
<attribute name="toolBarArea" >
<number>4</number>
</attribute>
<attribute name="toolBarBreak" >
<bool>false</bool>
</attribute>
<addaction name="actionOpen" />
<addaction name="actionDownload_from_URL" />
<addaction name="separator" />
@@ -903,24 +206,32 @@
<string>Report a bug</string>
</property>
</action>
<action name="actionSet_upload_limit" >
<property name="text" >
<string>Set upload limit</string>
</property>
</action>
<action name="actionSet_download_limit" >
<property name="text" >
<string>Set download limit</string>
</property>
</action>
<action name="actionDocumentation" >
<property name="text" >
<string>Documentation</string>
</property>
</action>
<action name="actionSet_global_download_limit" >
<property name="text" >
<string>Set global download limit</string>
</property>
</action>
<action name="actionSet_global_upload_limit" >
<property name="text" >
<string>Set global upload limit</string>
</property>
</action>
</widget>
<resources/>
<connections>
<connection>
<sender>search_pattern</sender>
<signal>returnPressed()</signal>
<receiver>search_button</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel" >
<x>405</x>
<y>125</y>
</hint>
<hint type="destinationlabel" >
<x>543</x>
<y>123</y>
</hint>
</hints>
</connection>
</connections>
<connections/>
</ui>

View File

@@ -24,6 +24,7 @@
#include <QItemDelegate>
#include <QStyleOptionProgressBarV2>
#include <QStyleOptionViewItemV2>
#include <QModelIndex>
#include <QPainter>
#include <QProgressBar>
@@ -35,80 +36,43 @@
#define SIZE 1
#define PROGRESS 2
class PreviewListDelegate: public QAbstractItemDelegate {
class PreviewListDelegate: public QItemDelegate {
Q_OBJECT
public:
PreviewListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
PreviewListDelegate(QObject *parent=0) : QItemDelegate(parent){}
~PreviewListDelegate(){}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
QItemDelegate delegate;
QStyleOptionViewItem opt = option;
QStyleOptionProgressBarV2 newopt;
char tmp[MAX_CHAR_TMP];
float progress;
// set text color
QVariant value = index.data(Qt::TextColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
}else{
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if(index.column() != PROGRESS){
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
}else{
value = index.data(Qt::BackgroundColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
}
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
switch(index.column()){
case SIZE:
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;
case NAME:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
break;
case PROGRESS:
progress = index.data().toDouble()*100.;
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
case PROGRESS:{
float progress = index.data().toDouble()*100.;
QStyleOptionProgressBarV2 newopt;
newopt.rect = opt.rect;
newopt.text = QString(tmp)+"%";
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
newopt.progress = (int)progress;
newopt.maximum = 100;
newopt.minimum = 0;
newopt.state |= QStyle::State_Enabled;
newopt.textVisible = false;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
painter);
//We prefer to display text manually to control color/font/boldness
if (option.state & QStyle::State_Selected){
opt.palette.setColor(QPalette::Text, QColor("grey"));
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
newopt.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
break;
}
default:
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
QItemDelegate::paint(painter, option, index);
}
}
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
QItemDelegate delegate;
return delegate.sizeHint(option, index);
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
// No editor here
return 0;
}
};

View File

@@ -22,8 +22,11 @@
#ifndef PROPLISTDELEGATE_H
#define PROPLISTDELEGATE_H
#include <QAbstractItemDelegate>
#include <QItemDelegate>
#include <QStyleOptionProgressBarV2>
#include <QStyleOptionViewItemV2>
#include <QStyleOptionComboBox>
#include <QComboBox>
#include <QModelIndex>
#include <QPainter>
#include <QProgressBar>
@@ -34,82 +37,112 @@
#define NAME 0
#define SIZE 1
#define PROGRESS 2
#define SELECTED 3
#define PRIORITY 3
#define INDEX 4
class PropListDelegate: public QAbstractItemDelegate {
#define IGNORED 0
#define NORMAL 1
#define HIGH 2
#define MAXIMUM 7
class PropListDelegate: public QItemDelegate {
Q_OBJECT
private:
bool* filteredFilesChanged;
public:
PropListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
PropListDelegate(QObject *parent=0, bool* filteredFilesChanged=0) : QItemDelegate(parent){
this->filteredFilesChanged = filteredFilesChanged;
}
~PropListDelegate(){}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
QStyleOptionViewItem opt = option;
char tmp[MAX_CHAR_TMP];
// set text color
QVariant value = index.data(Qt::TextColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
}else{
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if(index.column() != PROGRESS){
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
}else{
value = index.data(Qt::BackgroundColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
}
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
switch(index.column()){
case SIZE:
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
break;
case NAME:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;
case PROGRESS:{
QStyleOptionProgressBarV2 newopt;
float progress = index.data().toDouble()*100.;
snprintf(tmp, MAX_CHAR_TMP, "%.1f", progress);
newopt.rect = opt.rect;
newopt.text = QString(tmp)+"%";
newopt.text = QString(QByteArray::number(progress, 'f', 1))+QString::fromUtf8("%");
newopt.progress = (int)progress;
newopt.maximum = 100;
newopt.minimum = 0;
newopt.state |= QStyle::State_Enabled;
newopt.textVisible = false;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt,
painter);
//We prefer to display text manually to control color/font/boldness
if (option.state & QStyle::State_Selected){
opt.palette.setColor(QPalette::Text, QColor("grey"));
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
painter->drawText(option.rect, Qt::AlignCenter, newopt.text);
newopt.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter);
break;
}
case SELECTED:
if(index.data().toBool()){
painter->drawText(option.rect, Qt::AlignCenter, tr("True"));
}else{
painter->drawText(option.rect, Qt::AlignCenter, tr("False"));
case PRIORITY:{
QStyleOptionComboBox newopt;
newopt.rect = opt.rect;
switch(index.data().toInt()){
case IGNORED:
newopt.currentText = tr("Ignored");
break;
case NORMAL:
newopt.currentText = tr("Normal", "Normal (priority)");
break;
case HIGH:
newopt.currentText = tr("High", "High (priority)");
break;
case MAXIMUM:
newopt.currentText = tr("Maximum", "Maximum (priority)");
break;
default:
qDebug("Unhandled priority, setting NORMAL");
newopt.currentText = tr("Normal", "Normal (priority)");
}
newopt.state |= QStyle::State_Enabled;
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &newopt,
painter);
opt.palette.setColor(QPalette::Text, QColor("black"));
painter->setPen(opt.palette.color(cg, QPalette::Text));
painter->drawText(option.rect, Qt::AlignLeft, QString::fromUtf8(" ")+newopt.currentText);
break;
}
default:
QItemDelegate::paint(painter, option, index);
}
}
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const {
if(index.column() != PRIORITY) return 0;
QComboBox* editor = new QComboBox(parent);
editor->setFocusPolicy(Qt::StrongFocus);
editor->addItem(tr("Ignored"));
editor->addItem(tr("Normal", "Normal (priority)"));
editor->addItem(tr("High", "High (priority)"));
editor->addItem(tr("Maximum", "Maximum (priority)"));
return editor;
}
void setEditorData(QWidget *editor, const QModelIndex &index) const {
unsigned short val = index.model()->data(index, Qt::DisplayRole).toInt();
QComboBox *combobox = static_cast<QComboBox*>(editor);
qDebug("Set Editor data: Prio is %d", val);
switch(val){
case IGNORED:
combobox->setCurrentIndex(0);
break;
case NORMAL:
combobox->setCurrentIndex(1);
break;
case HIGH:
combobox->setCurrentIndex(2);
break;
case MAXIMUM:
combobox->setCurrentIndex(3);
break;
default:
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
qDebug("Unhandled priority, setting to NORMAL");
combobox->setCurrentIndex(1);
}
}
@@ -121,6 +154,71 @@ class PropListDelegate: public QAbstractItemDelegate {
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
return textRect.size();
}
public slots:
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QComboBox *combobox = static_cast<QComboBox*>(editor);
int value = combobox->currentIndex();
qDebug("Setting combobox value in index: %d", value);
unsigned short old_val = index.model()->data(index, Qt::DisplayRole).toInt();
switch(value){
case 0:
if(old_val != IGNORED){
model->setData(index, QVariant(IGNORED));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
} else {
// XXX: hack to force the model to send the itemChanged() signal
model->setData(index, QVariant(NORMAL));
model->setData(index, QVariant(IGNORED));
}
break;
case 1:
if(old_val != NORMAL){
model->setData(index, QVariant(NORMAL));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
} else {
model->setData(index, QVariant(HIGH));
model->setData(index, QVariant(NORMAL));
}
break;
case 2:
if(old_val != HIGH){
model->setData(index, QVariant(HIGH));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
} else {
model->setData(index, QVariant(NORMAL));
model->setData(index, QVariant(HIGH));
}
break;
case 3:
if(old_val != MAXIMUM){
model->setData(index, QVariant(MAXIMUM));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
} else {
model->setData(index, QVariant(HIGH));
model->setData(index, QVariant(MAXIMUM));
}
break;
default:
if(old_val != NORMAL){
model->setData(index, QVariant(NORMAL));
if(filteredFilesChanged != 0)
*filteredFilesChanged = true;
} else {
model->setData(index, QVariant(HIGH));
model->setData(index, QVariant(NORMAL));
}
}
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const {
editor->setGeometry(option.rect);
}
};
#endif

View File

@@ -22,8 +22,9 @@
#ifndef SEARCHLISTDELEGATE_H
#define SEARCHLISTDELEGATE_H
#include <QAbstractItemDelegate>
#include <QItemDelegate>
#include <QStyleOptionProgressBarV2>
#include <QStyleOptionViewItemV2>
#include <QModelIndex>
#include <QPainter>
#include <QProgressBar>
@@ -36,59 +37,29 @@
#define LEECHERS 3
#define ENGINE 4
class SearchListDelegate: public QAbstractItemDelegate {
class SearchListDelegate: public QItemDelegate {
Q_OBJECT
public:
SearchListDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
SearchListDelegate(QObject *parent=0) : QItemDelegate(parent){}
~SearchListDelegate(){}
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const{
QStyleOptionViewItem opt = option;
// set text color
QVariant value = index.data(Qt::TextColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
}
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (option.state & QStyle::State_Selected){
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
}else{
painter->setPen(opt.palette.color(cg, QPalette::Text));
}
// draw the background color
if (option.showDecorationSelected && (option.state & QStyle::State_Selected)){
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)){
cg = QPalette::Inactive;
}
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
}else{
value = index.data(Qt::BackgroundColorRole);
if (value.isValid() && qvariant_cast<QColor>(value).isValid()){
painter->fillRect(option.rect, qvariant_cast<QColor>(value));
}
}
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
switch(index.column()){
case SIZE:
painter->drawText(option.rect, Qt::AlignCenter, misc::friendlyUnit(index.data().toLongLong()));
break;
case NAME:
painter->drawText(option.rect, Qt::AlignLeft, index.data().toString());
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
break;
default:
painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
QItemDelegate::paint(painter, option, index);
}
}
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const{
QVariant value = index.data(Qt::FontRole);
QFont fnt = value.isValid() ? qvariant_cast<QFont>(value) : option.font;
QFontMetrics fontMetrics(fnt);
const QString text = index.data(Qt::DisplayRole).toString();
QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1));
return textRect.size();
QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const {
// No editor here
return 0;
}
};

View File

@@ -1,7 +1,5 @@
<ui version="4.0" >
<author>Christophe Dumez</author>
<comment></comment>
<exportmacro></exportmacro>
<class>AboutDlg</class>
<widget class="QDialog" name="AboutDlg" >
<property name="geometry" >
@@ -12,26 +10,38 @@
<height>320</height>
</rect>
</property>
<property name="minimumSize" >
<size>
<width>504</width>
<height>320</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>504</width>
<height>320</height>
</size>
</property>
<property name="windowTitle" >
<string>About qBittorrent</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="logo" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<string/>
</property>
@@ -40,9 +50,7 @@
<item>
<widget class="QLabel" name="lb_name" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>5</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -55,6 +63,19 @@
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
@@ -66,289 +87,257 @@
<attribute name="title" >
<string>About</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
<widget class="QLabel" name="mascot_lbl" >
<property name="geometry" >
<rect>
<x>380</x>
<y>50</y>
<width>94</width>
<height>162</height>
</rect>
</property>
<property name="spacing" >
<number>6</number>
<property name="text" >
<string/>
</property>
<item>
<widget class="QWidget" name="widget1" >
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lb_about" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>7</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.&lt;br>
</widget>
<widget class="QLabel" name="lb_about" >
<property name="geometry" >
<rect>
<x>0</x>
<y>40</y>
<width>481</width>
<height>102</height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>A bittorrent client using Qt4 and libtorrent, programmed in C++.&lt;br>
&lt;br>
Copyright © 2006 by Christophe Dumez&lt;br>
&lt;br> &lt;u>Home Page:&lt;/u> &lt;i>http://www.qbittorrent.org&lt;/i>&lt;br></string>
</property>
<property name="textFormat" >
<enum>Qt::RichText</enum>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</property>
<property name="textFormat" >
<enum>Qt::RichText</enum>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab3" >
<attribute name="title" >
<string>Author</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QFrame" name="te_authors" >
<layout class="QHBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QSplitter" name="splitter" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="widget" >
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_3" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="spacing" >
<number>6</number>
<property name="text" >
<string>Name:</string>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_3" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Country:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_birthday" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Birthday:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_occupation" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Occupation:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>E-mail:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Home page:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Christophe Dumez</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7" >
<property name="text" >
<string>France</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11" >
<property name="text" >
<string>03/05/1985</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10" >
<property name="text" >
<string>Student in computer science</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>chris@qbittorrent.org</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9" >
<property name="text" >
<string>http://www.dchris.eu</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Country:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_birthday" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Birthday:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_occupation" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Occupation:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>E-mail:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_8" >
<property name="font" >
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>true</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text" >
<string>Home page:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType" >
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Christophe Dumez</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7" >
<property name="text" >
<string>France</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11" >
<property name="text" >
<string>03/05/1985</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10" >
<property name="text" >
<string>Student in computer science</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>chris@qbittorrent.org</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9" >
<property name="text" >
<string>http://www.dchris.eu</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer>
@@ -370,12 +359,9 @@ Copyright © 2006 by Christophe Dumez&lt;br>
</widget>
<widget class="QWidget" name="tab4" >
<attribute name="title" >
<string>Thanks To</string>
<string>Thanks to</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
@@ -389,9 +375,6 @@ Copyright © 2006 by Christophe Dumez&lt;br>
<string>Translation</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
@@ -409,9 +392,6 @@ Copyright © 2006 by Christophe Dumez&lt;br>
<string>License</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
@@ -425,7 +405,6 @@ Copyright © 2006 by Christophe Dumez&lt;br>
</layout>
</widget>
<layoutdefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>

View File

@@ -23,51 +23,64 @@
#define ABOUT_H
#include "ui_about.h"
#include <QScrollBar>
class about : public QDialog, private Ui::AboutDlg{
Q_OBJECT
public:
about(QWidget *parent = 0): QDialog(parent){
~about() {
qDebug("Deleting about dlg");
}
about(QWidget *parent): QDialog(parent){
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
// Set icons
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent32.png")));
logo->setPixmap(QPixmap(QString::fromUtf8(":/Icons/qbittorrent22.png")));
mascot_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/mascot.png")));
//Title
lb_name->setText("<b><h1>"+tr("qBittorrent")+" "VERSION"</h1></b>");
lb_name->setText(QString::fromUtf8("<b><h1>")+tr("qBittorrent")+QString::fromUtf8(" "VERSION"</h1></b>"));
// Thanks
te_thanks->append("<ul><li>I would like to thank sourceforge.net for hosting qBittorrent project.</li>");
te_thanks->append("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, webdevelopper and RPM packager, for his help.</li>");
te_thanks->append("<li>I am gratefull to Peter Koeleman (peter@qbittorrent.org) and Johnny Mast (rave@qbittorrent.org) who helped me port qBittorrent to Windows.</li>");
te_thanks->append("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul>");
te_thanks->append(QString::fromUtf8("<a name='top'></a>"));
te_thanks->append(QString::fromUtf8("<ul><li>I would like to thank sourceforge.net for hosting qBittorrent project.</li>"));
te_thanks->append(QString::fromUtf8("<li>I am happy that Arnaud Demaizière is contributing to the project as a developer. His help is greatly appreciated</li>"));
te_thanks->append(QString::fromUtf8("<li>I also want to thank Jeffery Fernandez (jeffery@qbittorrent.org), project consultant, RPM packager, for his help and support.</li>"));
te_thanks->append(QString::fromUtf8("<li>I am grateful to Peter Koeleman (peter@qbittorrent.org) who is helping port qBittorrent to Windows.</li>"));
te_thanks->append(QString::fromUtf8("<li>Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.</li></ul><br><br>"));
te_thanks->scrollToAnchor(QString::fromUtf8("top"));
// Translation
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+"<br>");
te_translation->append(QString::fromUtf8("<a name='top'></a>"));
te_translation->append(tr("I would like to thank the following people who volunteered to translate qBittorrent:")+QString::fromUtf8("<br>"));
te_translation->append(QString::fromUtf8(
"<i>- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
"<i>- <u>Brazilian:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
- <u>Bulgarian:</u> Tsvetan & Boiko Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Catalan:</u> Gekko Dam Beer (gekko04@users.sourceforge.net)<br>\
- <u>Chinese (Simplified):</u> Guo Yue (guoyue0418@hotmail.com)<br>\
- <u>Chinese (Traditional):</u> Jeff Chen (jeff.cn.chen@gmail.com)<br>\
- <u>Danish:</u> Mathias Nielsen (comoneo@gmail.com)<br>\
- <u>Dutch:</u> Luke Niesink (luke@lukeniesink.net)<br>\
- <u>Dutch:</u> Joost Schipper (heavyjoost@users.sourceforge.net)<br>\
- <u>Finnish:</u> Niklas Laxström (nikerabbit@users.sourceforge.net)<br>\
- <u>German:</u> Niels Hoffmann (zentralmaschine@users.sourceforge.net)<br>\
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Italian:</u> Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
- <u>Greek:</u> Tsvetan Bankov (emerge_life@users.sourceforge.net)<br>\
- <u>Hungarian:</u> Majoros Péter (majoros.j.p@t-online.hu)<br>\
- <u>Italian:</u> Mirko Ferrari (mirkoferrari@gmail.com) and Ferraro Luciano (luciano.ferraro@gmail.com)<br>\
- <u>Japanese:</u> Nardog (nardog@e2umail.com)<br>\
- <u>Korean:</u> Jin Woo Sin (jin828sin@users.sourceforge.net)<br>\
- <u>Norwegian:</u> Lars-Erik Labori (hamil@users.sourceforge.net)<br>\
- <u>Polish:</u> Adam Babol (a-b@users.sourceforge.net)<br>\
- <u>Polish:</u> Jarek Smieja (ajep9691@wp.pl)<br>\
- <u>Portuguese:</u> Nick Marinho (nickmarinho@gmail.com)<br>\
- <u>Romanian:</u> Obada Denis (obadadenis@users.sourceforge.net)<br>\
- <u>Russian:</u> Nick Khazov (m2k3d0n at users.sourceforge.net)<br>\
- <u>Slovak:</u> helix84<br>\
- <u>Spanish:</u> Vicente Raul Plata Fonseca (silverxnt@users.sourceforge.net)<br>\
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
- <u>Swedish:</u> Daniel Nylander (po@danielnylander.se)<br>\
- <u>Turkish:</u> Erdem Bingöl (erdem84@gmail.com)<br>\
- <u>Ukrainian:</u> Andrey Shpachenko (masterfix@users.sourceforge.net)<br><br>"));
te_translation->append(tr("Please contact me if you would like to translate qBittorrent into your own language."));
te_translation->scrollToAnchor(QString::fromUtf8("top"));
// License
te_license->append("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
te_license->append(QString::fromUtf8("<a name='top'></a>"));
te_license->append(QString::fromUtf8("<center><b>GNU GENERAL PUBLIC LICENSE</b></center><br>\
<center>Version 2, June 1991</center><br>\
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>\
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br>\
@@ -400,7 +413,8 @@ class about : public QDialog, private Ui::AboutDlg{
proprietary programs. If your program is a subroutine library, you may<br>\
consider it more useful to permit linking proprietary applications with the<br>\
library. If this is what you want to do, use the GNU Library General<br>\
Public License instead of this License.<br>");
Public License instead of this License.<br>"));
te_license->scrollToAnchor(QString::fromUtf8("top"));
show();
}
};

View File

@@ -5,20 +5,29 @@
<rect>
<x>0</x>
<y>0</y>
<width>440</width>
<height>389</height>
<width>511</width>
<height>441</height>
</rect>
</property>
<property name="windowTitle" >
<string>Torrent addition dialog</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<widget class="QLabel" name="fileNameLbl" >
<property name="text" >
@@ -48,12 +57,21 @@
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="savePathTxt" />
</item>
@@ -80,31 +98,16 @@
</widget>
</item>
<item>
<widget class="QTreeWidget" name="torrentContentList" >
<widget class="QTreeView" name="torrentContentList" >
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers" >
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>2</number>
</property>
<column>
<property name="text" >
<string>File name</string>
</property>
</column>
<column>
<property name="text" >
<string>File size</string>
</property>
</column>
<column>
<property name="text" >
<string>Selected</string>
</property>
</column>
</widget>
</item>
<item>
@@ -123,12 +126,21 @@
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
@@ -172,20 +184,24 @@
</layout>
</item>
</layout>
<action name="actionSelect" >
<action name="actionIgnored" >
<property name="text" >
<string>Select</string>
</property>
<property name="iconText" >
<string>Select</string>
</property>
<property name="toolTip" >
<string>Select</string>
<string>Ignored</string>
</property>
</action>
<action name="actionUnselect" >
<action name="actionNormal" >
<property name="text" >
<string>Unselect</string>
<string>Normal</string>
</property>
</action>
<action name="actionHigh" >
<property name="text" >
<string>High</string>
</property>
</action>
<action name="actionMaximum" >
<property name="text" >
<string>Maximum</string>
</property>
</action>
</widget>

179
src/allocationDlg.h Normal file
View File

@@ -0,0 +1,179 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef BANDWIDTH_ALLOCATION_H
#define BANDWIDTH_ALLOCATION_H
#include <QDialog>
#include <QList>
#include <QSettings>
#include "ui_bandwidth_limit.h"
#include "misc.h"
#include "bittorrent.h"
using namespace libtorrent;
class BandwidthAllocationDialog : public QDialog, private Ui_bandwidth_dlg {
Q_OBJECT
public:
BandwidthAllocationDialog(QWidget *parent, bool uploadMode, bittorrent *BTSession, QStringList hashes): QDialog(parent), uploadMode(uploadMode), hashes(hashes){
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
qDebug("Bandwidth allocation dialog creation");
this->BTSession = BTSession;
if(hashes.size() == 0)
global = true;
else
global = false;
if(uploadMode)
lblTitle->setText(tr("Upload limit:"));
else
lblTitle->setText(tr("Download limit:"));
connect(bandwidthSlider, SIGNAL(valueChanged(int)), this, SLOT(updateBandwidthLabel(int)));
if(!global){
unsigned int nbTorrents = hashes.size();
if(!nbTorrents) close();
int val = 0;
int max = -1;
if(nbTorrents == 1){
QTorrentHandle h = BTSession->getTorrentHandle(hashes.at(0));
if(uploadMode){
if(h.upload_limit() > 0)
val = (int)(h.upload_limit() / 1024.);
if(BTSession->getSession()->upload_rate_limit() > 0)
max = (int)(BTSession->getSession()->upload_rate_limit() / 1024.);
}else{
if(h.download_limit() > 0)
val = (int)(h.download_limit() / 1024.);
if(BTSession->getSession()->download_rate_limit() > 0){
qDebug("there is a global download rate limit at: %d kb/s", (int)(BTSession->getSession()->download_rate_limit() / 1024.));
max = (int)(BTSession->getSession()->download_rate_limit() / 1024.);
}
}
if(max != -1)
bandwidthSlider->setMaximum(max);
qDebug("Bandwidth limit: %d", val);
if(val > bandwidthSlider->maximum())
val = bandwidthSlider->maximum();
else if(val < bandwidthSlider->minimum())
val = 0;
bandwidthSlider->setValue(val);
if(val == 0) {
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
kb_lbl->setText(QString::fromUtf8(""));
} else {
limit_lbl->setText(misc::toQString(val));
}
}else{
qDebug("More than one torrent selected, no initilization");
bandwidthSlider->setValue(0);
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
kb_lbl->setText(QString::fromUtf8(""));
}
}else{
// Global limit
int val = 0;
session *s = BTSession->getSession();
if(uploadMode){
if(s->upload_rate_limit() > 0)
val = (int)(s->upload_rate_limit()/1024.);
}else{
if(s->download_rate_limit() > 0)
val = (int)(s->download_rate_limit()/1024.);
}
if(val == 0){
bandwidthSlider->setValue(0);
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
kb_lbl->setText(QString::fromUtf8(""));
}else{
bandwidthSlider->setValue(val);
}
}
connect(buttonBox, SIGNAL(accepted()), this, SLOT(setBandwidth()));
show();
}
~BandwidthAllocationDialog(){
qDebug("Deleting bandwidth allocation dialog");
}
protected slots:
void updateBandwidthLabel(int val){
if(val == 0){
limit_lbl->setText(tr("Unlimited", "Unlimited (bandwidth)"));
kb_lbl->setText(QString::fromUtf8(""));
}else{
limit_lbl->setText(misc::toQString(val));
kb_lbl->setText(tr("KiB/s"));
}
}
void setBandwidth(){
qDebug("setBandwidth called");
int val = bandwidthSlider->value();
if(!global){
QString hash;
if(uploadMode) {
foreach(hash, hashes) {
if(!val)
BTSession->setUploadLimit(hash, -1);
else
BTSession->setUploadLimit(hash, val*1024);
qDebug("Setting upload limit");
}
} else {
foreach(hash, hashes) {
if(!val)
BTSession->setDownloadLimit(hash, -1);
else
BTSession->setDownloadLimit(hash, val*1024);
qDebug("Setting download limit");
}
}
}else{
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
session *s = BTSession->getSession();
if(uploadMode){
if(!val)
s->set_upload_rate_limit(-1);
else
s->set_upload_rate_limit(val*1024);
settings.setValue(QString::fromUtf8("Preferences/Connection/GlobalUPLimit"), val);
}else{
if(!val)
s->set_download_rate_limit(-1);
else
s->set_download_rate_limit(val*1024);
settings.setValue(QString::fromUtf8("Preferences/Connection/GlobalDLLimit"), val);
}
}
close();
}
private:
bool uploadMode;
bool global;
bittorrent *BTSession;
QStringList hashes;
};
#endif

256
src/arborescence.h Normal file
View File

@@ -0,0 +1,256 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef ARBORESCENCE_H
#define ARBORESCENCE_H
#include <QFileInfo>
#include <QStringList>
#include <QDir>
#include "misc.h"
class file {
private:
file *parent;
bool is_dir;
QString rel_path;
QList<file*> children;
size_type size;
float progress;
int priority;
int index; // Index in torrent_info
public:
file(file *parent, QString path, bool dir, size_type size=0, int index=-1, float progress=0., int priority=1): parent(parent), is_dir(dir), size(size), progress(progress), priority(priority), index(index){
qDebug("created a file with index %d", index);
rel_path = QDir::cleanPath(path);
if(parent) {
parent->updateProgress();
parent->updatePriority(priority);
}
}
~file() {
qDeleteAll(children);
}
QString path() const {
return rel_path;
}
QString name() const {
return rel_path.split(QDir::separator()).last();
}
void updateProgress() {
Q_ASSERT(is_dir);
float sum = 0;
file *child;
foreach(child, children) {
sum += child->getProgress();
}
progress = sum / (float)children.size();
}
void updatePriority(int prio) {
Q_ASSERT(is_dir);
file *child;
foreach(child, children) {
if(child->getPriority() != prio) return;
}
priority = prio;
}
int getPriority() const {
return priority;
}
size_type getSize() const {
return size;
}
float getProgress() const {
return progress;
}
int getIndex() const {
return index;
}
bool isDir() const {
return is_dir;
}
bool hasChildren() const {
return (!children.isEmpty());
}
QList<file*> getChildren() const {
return children;
}
file* getChild(QString fileName) const {
Q_ASSERT(is_dir);
file* f;
foreach(f, children) {
if(f->name() == fileName) return f;
}
return 0;
}
void addBytes(size_type b) {
size += b;
if(parent)
parent->addBytes(b);
}
file* addChild(QString fileName, bool dir, size_type size=0, int index = -1, float progress=0., int priority=1) {
Q_ASSERT(is_dir);
qDebug("Adding a new child of size: %ld", (long)size);
file *f = new file(this, QDir::cleanPath(rel_path+QDir::separator()+fileName), dir, size, index, progress, priority);
children << f;
if(size) {
addBytes(size);
}
return f;
}
bool removeFromFS(QString saveDir) {
QString full_path = saveDir + QDir::separator() + rel_path;
if(!QFile::exists(full_path)) {
qDebug("%s does not exist, no need to remove it", full_path.toUtf8().data());
return true;
}
bool success = true;
file *f;
qDebug("We have %d children", children.size());
foreach(f, children) {
bool s = f->removeFromFS(saveDir);
success = s && success;
}
if(is_dir) {
qDebug("trying to remove directory: %s", full_path.toUtf8().data());
QDir dir(full_path);
dir.rmdir(full_path);
} else {
qDebug("trying to remove file: %s", full_path.toUtf8().data());
bool s = QFile::remove(full_path);
success = s && success;
}
return success;
}
};
class arborescence {
private:
file *root;
public:
arborescence(torrent_info t) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
root = new file(0, misc::toQString(t.name()), true);
} else {
// XXX: Will crash if there is no file in torrent
root = new file(0, misc::toQString(t.name()), false, fi->size, 0);
return;
}
int i = 0;
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i);
fi++;
++i;
}
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t.total_size());
}
arborescence(torrent_info t, std::vector<float> fp, int *prioritiesTab) {
torrent_info::file_iterator fi = t.begin_files();
if(t.num_files() > 1) {
qDebug("More than one file in the torrent, setting a folder as root");
root = new file(0, misc::toQString(t.name()), true);
} else {
// XXX: Will crash if there is no file in torrent
qDebug("one file in the torrent, setting it as root with index 0");
root = new file(0, misc::toQString(t.name()), false, fi->size, 0, fp[0], prioritiesTab[0]);
return;
}
int i = 0;
while(fi != t.end_files()) {
QString path = QDir::cleanPath(misc::toQString(fi->path.string()));
addFile(path, fi->size, i, fp[i], prioritiesTab[i]);
fi++;
++i;
}
qDebug("real size: %ld, tree size: %ld", (long)t.total_size(), (long)root->getSize());
Q_ASSERT(root->getSize() == t.total_size());
}
~arborescence() {
delete root;
}
file* getRoot() const {
return root;
}
bool removeFromFS(QString saveDir) {
if(!QFile::exists(saveDir+QDir::separator()+root->path())) return true;
bool success = root->removeFromFS(saveDir);
QDir root_dir(root->path());
root_dir.rmdir(saveDir+QDir::separator()+root->path());
return success;
}
protected:
void addFile(QString path, size_type file_size, int index, float progress=0., int priority=1) {
Q_ASSERT(root->isDir());
path = QDir::cleanPath(path);
Q_ASSERT(path.startsWith(root->path()));
QString relative_path = path.remove(0, root->path().size());
if(relative_path.at(0) ==QDir::separator())
relative_path.remove(0, 1);
QStringList fileNames = relative_path.split(QDir::separator());
QString fileName;
file *dad = root;
unsigned int nb_i = 0;
unsigned int size = fileNames.size();
foreach(fileName, fileNames) {
++nb_i;
if(fileName == ".") continue;
file* child = dad->getChild(fileName);
if(!child) {
if(nb_i != size) {
// Folder
child = dad->addChild(fileName, true);
} else {
// File
child = dad->addChild(fileName, false, file_size, index, progress, priority);
}
}
dad = child;
}
}
};
#endif

113
src/bandwidth_limit.ui Normal file
View File

@@ -0,0 +1,113 @@
<ui version="4.0" >
<class>bandwidth_dlg</class>
<widget class="QDialog" name="bandwidth_dlg" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>222</width>
<height>129</height>
</rect>
</property>
<property name="windowTitle" >
<string>Bandwidth allocation</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="lblTitle" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="limit_lbl" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="kb_lbl" >
<property name="text" >
<string>KiB/s</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QSlider" name="bandwidthSlider" >
<property name="minimum" >
<number>0</number>
</property>
<property name="maximum" >
<number>1000</number>
</property>
<property name="sliderPosition" >
<number>0</number>
</property>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>bandwidth_dlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>212</x>
<y>83</y>
</hint>
<hint type="destinationlabel" >
<x>221</x>
<y>98</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because it is too large Load Diff

View File

@@ -21,133 +21,149 @@
#ifndef __BITTORRENT_H__
#define __BITTORRENT_H__
#include <QTimer>
#include <libtorrent/entry.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/session.hpp>
#include <libtorrent/fingerprint.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/identify_client.hpp>
#include <libtorrent/alert_types.hpp>
#include <libtorrent/ip_filter.hpp>
#ifndef NO_PEX
#include <libtorrent/extensions/metadata_transfer.hpp>
#include <libtorrent/extensions/ut_pex.hpp>
#endif
#ifdef NO_PEX
#include <QHash>
#endif
#include <QList>
#include <QPair>
#include <QStringList>
#include <boost/format.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/exception.hpp>
#include "deleteThread.h"
#include <libtorrent/session.hpp>
#include <libtorrent/ip_filter.hpp>
#include "qtorrenthandle.h"
using namespace libtorrent;
namespace fs = boost::filesystem;
class downloadThread;
class QTimer;
class bittorrent : public QObject{
Q_OBJECT
private:
session *s;
bool DHTEnabled;
QString scan_dir;
QTimer *timerScan;
QTimer *timerAlerts;
bool DHTEnabled;
downloadThread *downloader;
QStringList supported_preview_extensions;
QString defaultSavePath;
#ifdef NO_PEX
QHash<QString, torrent_handle> torrent_list;
#endif
QStringList torrentsToPauseAfterChecking;
QHash<QString, bool> reloadingTorrents;
QHash<QString, QList<qlonglong> > ETAstats;
QHash<QString, qlonglong> ETAs;
QHash<QString, QPair<size_type,size_type> > ratioData;
QTimer *ETARefresher;
QHash<QString, QList<QPair<QString, QString> > > trackersErrors;
QStringList waitingForPause;
QStringList finishedTorrents;
QStringList unfinishedTorrents;
bool preAllocateAll;
bool addInPause;
int maxConnecsPerTorrent;
int maxUploadsPerTorrent;
float max_ratio;
protected:
QString getSavePath(const QString& hash);
QString getSavePath(QString hash);
public:
// Constructor / Destructor
bittorrent();
~bittorrent();
torrent_handle getTorrentHandle(const QString& hash) const;
#ifndef NO_PEX
std::vector<torrent_handle> getTorrentHandles() const;
#endif
#ifdef NO_PEX
QList<torrent_handle> getTorrentHandles() const;
#endif
bool isPaused(const QString& hash) const;
bool hasFilteredFiles(const QString& fileHash) const;
bool isFilePreviewPossible(const QString& fileHash) const;
QTorrentHandle getTorrentHandle(QString hash) const;
bool isPaused(QString hash) const;
bool isFilePreviewPossible(QString fileHash) const;
bool isDHTEnabled() const;
float getPayloadDownloadRate() const;
float getPayloadUploadRate() const;
QList<torrent_handle> getFinishedTorrentHandles() const;
session_status getSessionStatus() const;
int getListenPort() const;
QStringList getTorrentsToPauseAfterChecking() const;
long getETA(QString hash) const;
float getRealRatio(QString hash) const;
session* getSession() const;
QList<QPair<QString, QString> > getTrackersErrors(QString hash) const;
QStringList getFinishedTorrents() const;
QStringList getUnfinishedTorrents() const;
bool isFinished(QString hash) const;
bool has_filtered_files(QString hash) const;
public slots:
void addTorrent(const QString& path, bool fromScanDir = false, const QString& from_url = QString());
void downloadFromUrl(const QString& url);
void addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false);
void downloadFromUrl(QString url);
void downloadFromURLList(const QStringList& url_list);
void deleteTorrent(const QString& hash, bool permanent = false);
void pauseTorrent(const QString& hash);
void pauseAllTorrents();
void resumeAllTorrents();
void resumeTorrent(const QString& hash);
void enableDHT();
void disableDHT();
void deleteTorrent(QString hash, bool permanent = false);
bool pauseTorrent(QString hash);
bool resumeTorrent(QString hash);
void saveDHTEntry();
void saveFastResumeData();
void enableDirectoryScanning(const QString& scan_dir);
void preAllocateAllFiles(bool b);
void saveFastResumeAndRatioData();
void enableDirectoryScanning(QString scan_dir);
void disableDirectoryScanning();
#ifndef NO_PEX
void enablePeerExchange();
#endif
void enableIPFilter(ip_filter filter);
void disableIPFilter();
void reloadTorrent(const torrent_handle &h, bool compact_mode = true);
void resumeUnfinishedTorrents();
void updateETAs();
void saveTorrentSpeedLimits(QString hash);
void loadTorrentSpeedLimits(QString hash);
void saveDownloadUploadForTorrent(QString hash);
void loadDownloadUploadForTorrent(QString hash);
void handleDownloadFailure(QString url, QString reason);
void loadWebSeeds(QString fileHash);
// Session configuration - Setters
void setListeningPortsRange(std::pair<unsigned short, unsigned short> ports);
void setMaxConnections(int maxConnec);
void setDownloadRateLimit(int rate);
void setUploadRateLimit(int rate);
void setMaxConnectionsPerTorrent(int max);
void setMaxUploadsPerTorrent(int max);
void setDownloadRateLimit(long rate);
void setUploadRateLimit(long rate);
void setGlobalRatio(float ratio);
void setDeleteRatio(float ratio);
void setDHTPort(int dht_port);
void setProxySettings(proxy_settings proxySettings, bool trackers=true, bool peers=true, bool web_seeds=true, bool dht=true);
void setSessionSettings(session_settings sessionSettings);
#ifdef V_0_13
void setProxySettings(proxy_settings proxySettings);
#endif
void setDefaultSavePath(const QString& savepath);
void startTorrentsInPause(bool b);
void setDefaultSavePath(QString savepath);
void applyEncryptionSettings(pe_settings se);
void loadFilesPriorities(QTorrentHandle& h);
void setDownloadLimit(QString hash, long val);
void setUploadLimit(QString hash, long val);
void setUnfinishedTorrent(QString hash);
void setFinishedTorrent(QString hash);
void enableUPnP(bool b);
void enableNATPMP(bool b);
void enableLSD(bool b);
void enableDHT(bool b);
protected slots:
void cleanDeleter(deleteThread* deleter);
void loadFilteredFiles(torrent_handle& h);
void scanDirectory();
void readAlerts();
void processDownloadedFile(const QString&, const QString&, int, const QString&);
void resumeUnfinished();
void processDownloadedFile(QString, QString);
bool loadTrackerFile(QString hash);
void saveTrackerFile(QString hash);
void pauseAndReloadTorrent(QTorrentHandle h, bool full_alloc);
void reloadTorrent(const QTorrentHandle &h, bool full_alloc); // This is protected now, call pauseAndReloadTorrent() instead
void deleteBigRatios();
signals:
void invalidTorrent(const QString& path);
void duplicateTorrent(const QString& path);
void addedTorrent(const QString& path, torrent_handle& h, bool fastResume);
void finishedTorrent(torrent_handle& h);
void fullDiskError(torrent_handle& h);
void trackerError(const QString& hash, const QString& time, const QString& msg);
void invalidTorrent(QString path);
void duplicateTorrent(QString path);
void addedTorrent(QString path, QTorrentHandle& h, bool fastResume);
void finishedTorrent(QTorrentHandle& h);
void fullDiskError(QTorrentHandle& h);
void trackerError(QString hash, QString time, QString msg);
void portListeningFailure();
void trackerAuthenticationRequired(torrent_handle& h);
void downloadFromUrlFailure(const QString& url, const QString& error);
void trackerAuthenticationRequired(QTorrentHandle& h);
void scanDirFoundTorrents(const QStringList& pathList);
void newDownloadedTorrent(const QString& path, const QString& url);
void aboutToDownloadFromUrl(const QString& url);
void newDownloadedTorrent(QString path, QString url);
void aboutToDownloadFromUrl(QString url);
void updateFileSize(QString hash);
void peerBlocked(QString);
void downloadFromUrlFailure(QString url, QString reason);
void fastResumeDataRejected(QString name);
void urlSeedProblem(QString url, QString msg);
void torrentFinishedChecking(QString hash);
void torrent_deleted(QString hash, QString fileName, bool finished);
};
#endif

19
src/convertPOtoTS.py Normal file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/python
import os
LANG_FOLDER = "lang/"
PO_FOLDER = 'po_files'
if __name__ == '__main__':
po_files = os.listdir(os.path.join(LANG_FOLDER, PO_FOLDER))
po_files = [x for x in po_files if os.path.splitext(x)[-1] == ".po"]
for file in po_files:
# First clean up the ts file
ts_file = os.path.join(LANG_FOLDER, os.path.splitext(file)[0]+'.ts')
po_file = os.path.join(LANG_FOLDER, PO_FOLDER, file)
if os.path.exists(ts_file):
os.remove(ts_file)
# Convert to PO
print "Converting %s..." % (po_file,)
os.system("po2ts %s -o %s" % (po_file, ts_file))

24
src/convertTStoPO.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/python
import os
LANG_FOLDER = 'lang/'
PO_FOLDER = 'po_files'
if __name__ == '__main__':
ts_files = os.listdir(LANG_FOLDER)
ts_files = [x for x in ts_files if os.path.splitext(x)[-1] == ".ts"]
for file in ts_files:
# First clean up the po file
po_file = os.path.join(LANG_FOLDER, PO_FOLDER, os.path.splitext(file)[0]+'.po')
ts_file = os.path.join(LANG_FOLDER, file)
if os.path.exists(po_file):
os.remove(po_file)
# create po folder if it doesn't exist
if not os.path.exists(os.path.join(LANG_FOLDER, PO_FOLDER)):
os.mkdir(os.path.join(LANG_FOLDER, PO_FOLDER))
# Convert to PO
print "Converting %s..." % (ts_file,)
os.system("ts2po %s -o %s" % (ts_file, po_file))
# Making an archive
os.system("tar czf %s %s" % (os.path.join(LANG_FOLDER, PO_FOLDER)+'.tar.gz', os.path.join(LANG_FOLDER, PO_FOLDER)))

View File

@@ -1,27 +1,18 @@
<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<class>createTorrentDialog</class>
<widget class="QDialog" name="createTorrentDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>307</height>
<width>592</width>
<height>590</height>
</rect>
</property>
<property name="windowTitle" >
<string>Torrent Creation Tool</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="createTorrent_title" >
<property name="minimumSize" >
@@ -48,63 +39,59 @@
</font>
</property>
<property name="text" >
<string>Create Torrent file</string>
<string>Torrent file creation</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_input" >
<property name="text" >
<string>File or folder to add to the torrent:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textInputPath" />
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QPushButton" name="addFile_button" >
<property name="text" >
<string>Add a file</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/add_file.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addFolder_button" >
<property name="text" >
<string>Add a folder</string>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/add_folder.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="lbl_destination" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>26</height>
</size>
</property>
<property name="text" >
<string>&lt;center>Destination torrent file:&lt;/center></string>
</property>
<property name="buddy" >
<cstring>txt_destination</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_input" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>26</height>
</size>
</property>
<property name="text" >
<string>&lt;center>Input file or directory:&lt;/center></string>
</property>
<property name="buddy" >
<cstring>txt_input</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_announce_url" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>102</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
@@ -112,7 +99,7 @@
</size>
</property>
<property name="text" >
<string>&lt;center>Announce url:&lt;br>(One per line)&lt;/center></string>
<string>Announce urls (trackers):</string>
</property>
<property name="buddy" >
<cstring></cstring>
@@ -120,9 +107,34 @@
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_comment" >
<widget class="QLabel" name="urlSeeds_lbl" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>101</height>
</size>
</property>
<property name="text" >
<string>&lt;center>Comment:&lt;/center></string>
<string>Web seeds urls (optional):</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_comment" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>102</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>102</height>
</size>
</property>
<property name="text" >
<string>Comment (optional):</string>
</property>
<property name="buddy" >
<cstring>txt_comment</cstring>
@@ -133,64 +145,244 @@
</item>
<item>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="txt_destination" />
</item>
<item>
<widget class="QToolButton" name="browse_destination" >
<property name="text" >
<string>...</string>
<widget class="QListWidget" name="trackers_list" >
<property name="selectionMode" >
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="addTracker_button" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeTracker_button" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="txt_input" />
</item>
<item>
<widget class="QCheckBox" name="checkDirectory" >
<property name="text" >
<string>Directory</string>
<widget class="QListWidget" name="URLSeeds_list" >
<property name="selectionMode" >
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="browse_input" >
<property name="text" >
<string>...</string>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
</widget>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="addURLSeed_button" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeURLSeed_button" >
<property name="minimumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text" >
<string/>
</property>
<property name="icon" >
<iconset resource="icons.qrc" >:/Icons/skin/remove.png</iconset>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QTextEdit" name="txt_announce" />
</item>
<item>
<widget class="QTextEdit" name="txt_comment" >
<property name="maximumSize" >
<size>
<width>421</width>
<height>102</height>
</size>
</property>
<property name="acceptRichText" >
<bool>false</bool>
</property>
@@ -202,12 +394,106 @@
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
<item>
<widget class="QLabel" name="txtPieceSize" >
<property name="text" >
<string>Piece size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboPieceSize" >
<property name="currentIndex" >
<number>3</number>
</property>
<item>
<property name="text" >
<string>32 KiB</string>
</property>
</item>
<item>
<property name="text" >
<string>64 KiB</string>
</property>
</item>
<item>
<property name="text" >
<string>128 KiB</string>
</property>
</item>
<item>
<property name="text" >
<string>256 KiB</string>
</property>
</item>
<item>
<property name="text" >
<string>512 KiB</string>
</property>
</item>
<item>
<property name="text" >
<string>1 MiB</string>
</property>
</item>
<item>
<property name="text" >
<string>2 MiB</string>
</property>
</item>
<item>
<property name="text" >
<string>4 MiB</string>
</property>
</item>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="check_private" >
<property name="text" >
<string>Private (won't be distributed on DHT network if enabled)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkStartSeeding" >
<property name="text" >
<string>Start seeding after creation</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
@@ -224,7 +510,7 @@
<item>
<widget class="QPushButton" name="createButton" >
<property name="text" >
<string>Create</string>
<string>Create and save...</string>
</property>
</widget>
</item>
@@ -252,8 +538,9 @@
</item>
</layout>
</widget>
<pixmapfunction></pixmapfunction>
<resources/>
<resources>
<include location="icons.qrc" />
</resources>
<connections>
<connection>
<sender>cancelButton</sender>

View File

@@ -21,6 +21,7 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
@@ -32,10 +33,7 @@
#include <libtorrent/file.hpp>
#include <libtorrent/storage.hpp>
#include <libtorrent/hasher.hpp>
#ifndef NO_PEX
#include <libtorrent/file_pool.hpp>
#endif
#include "createtorrent_imp.h"
@@ -48,26 +46,74 @@ createtorrent::createtorrent(QWidget *parent): QDialog(parent){
show();
}
void createtorrent::on_browse_destination_clicked(){
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+" (*.torrent)");
if(!destination.isEmpty()){
txt_destination->setText(destination);
void createtorrent::on_addFolder_button_clicked(){
QString dir = QFileDialog::getExistingDirectory(this, tr("Select a folder to add to the torrent"), QDir::homePath(), QFileDialog::ShowDirsOnly);
if(!dir.isEmpty())
textInputPath->setText(dir);
}
void createtorrent::on_addFile_button_clicked(){
QString file = QFileDialog::getOpenFileName(this, tr("Select a file to add to the torrent"), QDir::homePath(), QString(), 0, QFileDialog::ShowDirsOnly);
if(!file.isEmpty())
textInputPath->setText(file);
}
void createtorrent::on_removeTracker_button_clicked() {
QModelIndexList selectedIndexes = trackers_list->selectionModel()->selectedIndexes();
for(int i=selectedIndexes.size()-1; i>=0; --i){
QListWidgetItem *item = trackers_list->takeItem(selectedIndexes.at(i).row());
delete item;
}
}
void createtorrent::on_browse_input_clicked(){
// Can't use QFileDialog static functions for this because
// user can select a file or a directory
QFileDialog *fd = new QFileDialog(this, tr("Select input directory or file"), QDir::homePath());
if(checkDirectory->isChecked()){
fd->setFileMode(QFileDialog::DirectoryOnly);
}else{
fd->setFileMode(QFileDialog::ExistingFile);
int createtorrent::getPieceSize() const {
switch(comboPieceSize->currentIndex()) {
case 0:
return 32*1024;
case 1:
return 64*1024;
case 2:
return 128*1024;
case 3:
return 256*1024;
case 4:
return 512*1024;
case 5:
return 1024*1024;
case 6:
return 2048*1024;
default:
return 256*1024;
}
QStringList fileNames;
if (fd->exec()){
fileNames = fd->selectedFiles();
txt_input->setText(fileNames.first());
}
void createtorrent::on_addTracker_button_clicked() {
bool ok;
QString URL = QInputDialog::getText(this, tr("Please type an announce URL"),
tr("Announce URL:", "Tracker URL"), QLineEdit::Normal,
"http://", &ok);
if(ok){
if(trackers_list->findItems(URL, Qt::MatchFixedString).size() == 0)
trackers_list->addItem(URL);
}
}
void createtorrent::on_removeURLSeed_button_clicked(){
QModelIndexList selectedIndexes = URLSeeds_list->selectionModel()->selectedIndexes();
for(int i=selectedIndexes.size()-1; i>=0; --i){
QListWidgetItem *item = URLSeeds_list->takeItem(selectedIndexes.at(i).row());
delete item;
}
}
void createtorrent::on_addURLSeed_button_clicked(){
bool ok;
QString URL = QInputDialog::getText(this, tr("Please type a web seed url"),
tr("Web seed URL:"), QLineEdit::Normal,
"http://", &ok);
if(ok){
if(URLSeeds_list->findItems(URL, Qt::MatchFixedString).size() == 0)
URLSeeds_list->addItem(URL);
}
}
@@ -83,72 +129,85 @@ void add_files(torrent_info& t, path const& p, path const& l){
}
}
QStringList createtorrent::allItems(QListWidget *list){
QStringList res;
unsigned int nbItems = list->count();
for(unsigned int i=0; i< nbItems; ++i){
res << list->item(i)->text();
}
return res;
}
// Main function that create a .torrent file
void createtorrent::on_createButton_clicked(){
QString destination = txt_destination->text();
if(destination.isEmpty()){
QMessageBox::critical(0, tr("No destination path set"), tr("Please type a destination path first"));
return;
}
QString input = txt_input->text();
QString input = textInputPath->text().trimmed();
if(input.isEmpty()){
QMessageBox::critical(0, tr("No input path set"), tr("Please type an input path first"));
return;
}
if(!QFile::exists(input)){
QMessageBox::critical(0, tr("Input path does not exist"), tr("Please type a valid input path first"));
QStringList trackers = allItems(trackers_list);
if(!trackers.size()){
QMessageBox::critical(0, tr("No tracker path set"), tr("Please set at least one tracker"));
return;
}
char const* creator_str = "qBittorrent";
int piece_size = 256 * 1024;
QString destination = QFileDialog::getSaveFileName(this, tr("Select destination torrent file"), QDir::homePath(), tr("Torrent Files")+QString::fromUtf8(" (*.torrent)"));
if(!destination.isEmpty()) {
if(!destination.endsWith(QString::fromUtf8(".torrent")))
destination += QString::fromUtf8(".torrent");
} else {
return;
}
char const* creator_str = "qBittorrent "VERSION;
try {
torrent_info t;
path full_path = complete(path((const char*)input.toUtf8()));
boost::intrusive_ptr<torrent_info> t(new torrent_info);
ofstream out(complete(path((const char*)destination.toUtf8())), std::ios_base::binary);
add_files(t, full_path.branch_path(), full_path.leaf());
t.set_piece_size(piece_size);
#ifndef NO_PEX
file_pool fp;
#ifndef V_0_13
storage st(t, full_path.branch_path(), fp);
#endif
#ifdef V_0_13
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
#endif
#endif
#ifdef NO_PEX
storage st(t, full_path.branch_path());
#endif
QStringList trackers = txt_announce->toPlainText().split('\n');
path full_path;
// Adding files to the torrent
full_path = complete(path(input.toUtf8().data()));
add_files(*t, full_path.branch_path(), full_path.leaf());
// Set piece size
int piece_size = getPieceSize();
t->set_piece_size(piece_size);
// Add url seeds
QStringList urlSeeds = allItems(URLSeeds_list);
QString seed;
foreach(seed, urlSeeds){
t->add_url_seed(seed.toUtf8().data());
}
for(int i=0; i<trackers.size(); ++i){
t.add_tracker((const char*)trackers.at(i).toUtf8());
t->add_tracker(trackers.at(i).toUtf8().data());
}
// calculate the hash for all pieces
int num = t.num_pieces();
file_pool fp;
boost::scoped_ptr<storage_interface> st(default_storage_constructor(t, full_path.branch_path(), fp));
int num = t->num_pieces();
std::vector<char> buf(piece_size);
for (int i = 0; i < num; ++i)
{
#ifndef V_0_13
st.read(&buf[0], i, 0, t.piece_size(i));
#endif
#ifdef V_0_13
st->read(&buf[0], i, 0, t.piece_size(i));
#endif
hasher h(&buf[0], t.piece_size(i));
t.set_hash(i, h.final());
for (int i = 0; i < num; ++i) {
st->read(&buf[0], i, 0, t->piece_size(i));
hasher h(&buf[0], t->piece_size(i));
t->set_hash(i, h.final());
}
// Set qBittorrent as creator and add user comment to
// torrent_info structure
t.set_creator(creator_str);
t.set_comment((const char*)txt_comment->toPlainText().toUtf8());
t->set_creator(creator_str);
t->set_comment((const char*)txt_comment->toPlainText().toUtf8());
// Is private ?
if(check_private->isChecked()){
t->set_priv(true);
}
// create the torrent and print it to out
entry e = t.create_torrent();
entry e = t->create_torrent();
libtorrent::bencode(std::ostream_iterator<char>(out), e);
out.flush();
if(checkStartSeeding->isChecked())
emit torrent_to_seed(destination);
}
catch (std::exception& e){
std::cerr << e.what() << "\n";
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent creation was unsuccessful, reason: %1").arg(QString::fromUtf8(e.what())));
hide();
return;
}
hide();
QMessageBox::information(0, tr("Torrent creation"), tr("Torrent was created successfully:")+" "+destination);

View File

@@ -22,7 +22,6 @@
#ifndef CREATE_TORRENT_IMP_H
#define CREATE_TORRENT_IMP_H
#include <QDialog>
#include "ui_createtorrent.h"
class createtorrent : public QDialog, private Ui::createTorrentDialog{
@@ -30,11 +29,20 @@ class createtorrent : public QDialog, private Ui::createTorrentDialog{
public:
createtorrent(QWidget *parent = 0);
QStringList allItems(QListWidget *list);
int getPieceSize() const;
signals:
void torrent_to_seed(QString path);
protected slots:
void on_browse_destination_clicked();
void on_browse_input_clicked();
void on_createButton_clicked();
void on_addFile_button_clicked();
void on_addFolder_button_clicked();
void on_addTracker_button_clicked();
void on_removeTracker_button_clicked();
void on_addURLSeed_button_clicked();
void on_removeURLSeed_button_clicked();
};
#endif

View File

@@ -23,31 +23,102 @@
#define DELETETHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QMutexLocker>
#include <QPair>
#include "misc.h"
#include "arborescence.h"
class subDeleteThread : public QThread {
Q_OBJECT
private:
QString save_path;
arborescence *arb;
bool abort;
public:
subDeleteThread(QObject *parent, QString saveDir, arborescence *arb) : QThread(parent), save_path(saveDir), arb(arb), abort(false){}
~subDeleteThread(){
abort = true;
wait();
}
signals:
// For subthreads
void deletionSuccessST(subDeleteThread* st);
void deletionFailureST(subDeleteThread* st);
protected:
void run(){
if(arb->removeFromFS(save_path))
emit deletionSuccessST(this);
else
emit deletionFailureST(this);
delete arb;
}
};
class deleteThread : public QThread {
Q_OBJECT
private:
QString path;
QList<QPair<QString, arborescence*> > torrents_list;
QMutex mutex;
QWaitCondition condition;
bool abort;
QList<subDeleteThread*> subThreads;
public :
deleteThread(QString _path): path(_path){
start();
}
public:
deleteThread(QObject* parent) : QThread(parent), abort(false){}
~deleteThread(){
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
qDeleteAll(subThreads);
wait();
}
signals:
void deletionFinished(deleteThread*) const;
void deleteTorrent(QString saveDir, arborescence *arb){
qDebug("deleteThread called");
QMutexLocker locker(&mutex);
torrents_list << QPair<QString, arborescence*>(saveDir, arb);
if(!isRunning()){
start();
}else{
condition.wakeOne();
}
}
private:
protected:
void run(){
misc::removePath(path);
emit deletionFinished(this);
forever{
if(abort)
return;
mutex.lock();
if(torrents_list.size() != 0){
QPair<QString, arborescence *> torrent = torrents_list.takeFirst();
mutex.unlock();
subDeleteThread *st = new subDeleteThread(0, torrent.first, torrent.second);
subThreads << st;
connect(st, SIGNAL(deletionSuccessST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
connect(st, SIGNAL(deletionFailureST(subDeleteThread*)), this, SLOT(deleteSubThread(subDeleteThread*)));
st->start();
}else{
condition.wait(&mutex);
mutex.unlock();
}
}
}
protected slots:
void deleteSubThread(subDeleteThread* st){
int index = subThreads.indexOf(st);
Q_ASSERT(index != -1);
subThreads.removeAt(index);
delete st;
}
};

352
src/download.ui Normal file
View File

@@ -0,0 +1,352 @@
<ui version="4.0" >
<class>downloading</class>
<widget class="QWidget" name="downloading" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>811</width>
<height>453</height>
</rect>
</property>
<property name="windowTitle" >
<string>Search</string>
</property>
<layout class="QVBoxLayout" >
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="margin" >
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="margin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_DLSpeed" >
<property name="text" >
<string>Total DL Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_DownSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0" >
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitDL" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>Session ratio: </string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_Ratio" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="numDigits" >
<number>4</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_ratio_icon" >
<property name="text" >
<string/>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbl_UPSpeed" >
<property name="text" >
<string>Total UP Speed:</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="LCD_UpSpeed" >
<property name="autoFillBackground" >
<bool>true</bool>
</property>
<property name="smallDecimalPoint" >
<bool>false</bool>
</property>
<property name="numDigits" >
<number>6</number>
</property>
<property name="segmentStyle" >
<enum>QLCDNumber::Flat</enum>
</property>
<property name="value" stdset="0" >
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="unitUP" >
<property name="text" >
<string>KiB/s</string>
</property>
<property name="alignment" >
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="downloadList" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="autoScroll" >
<bool>true</bool>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation" >
<number>1</number>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabBottom" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>142</height>
</size>
</property>
<property name="tabPosition" >
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="log_tab" >
<attribute name="title" >
<string>Log</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="margin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="infoBar" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>7</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="filter_tab" >
<attribute name="title" >
<string>IP filter</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="margin" >
<number>9</number>
</property>
<item>
<widget class="QTextBrowser" name="textBlockedUsers" >
<property name="maximumSize" >
<size>
<width>16777215</width>
<height>123</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
<action name="actionStart" >
<property name="text" >
<string>Start</string>
</property>
</action>
<action name="actionPause" >
<property name="text" >
<string>Pause</string>
</property>
</action>
<action name="actionDelete" >
<property name="text" >
<string>Delete</string>
</property>
</action>
<action name="actionClearLog" >
<property name="text" >
<string>Clear</string>
</property>
</action>
<action name="actionPreview_file" >
<property name="text" >
<string>Preview file</string>
</property>
</action>
<action name="actionSet_upload_limit" >
<property name="text" >
<string>Set upload limit</string>
</property>
</action>
<action name="actionSet_download_limit" >
<property name="text" >
<string>Set download limit</string>
</property>
</action>
<action name="actionDelete_Permanently" >
<property name="text" >
<string>Delete Permanently</string>
</property>
</action>
<action name="actionTorrent_Properties" >
<property name="text" >
<string>Torrent Properties</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -37,7 +37,6 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
icon_lbl->setPixmap(QPixmap(QString::fromUtf8(":/Icons/skin/url.png")));
connect(this, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), parent, SLOT(downloadFromURLList(const QStringList&)));
show();
}
@@ -49,7 +48,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
public slots:
void on_downloadButton_clicked(){
QString urls = textUrls->toPlainText();
QStringList url_list = urls.split("\n");
QStringList url_list = urls.split(QString::fromUtf8("\n"));
QString url;
QStringList url_list_cleaned;
foreach(url, url_list){
@@ -65,6 +64,7 @@ class downloadFromURL : public QDialog, private Ui::downloadFromURL{
return;
}
emit urlsReadyToBeDownloaded(url_list_cleaned);
qDebug("Emitted urlsReadytobedownloaded signal");
close();
}

174
src/downloadThread.cpp Normal file
View File

@@ -0,0 +1,174 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#include "downloadThread.h"
#include <iostream>
#include <cc++/common.h>
QString subDownloadThread::errorCodeToString(int status) {
switch(status){
case 1://ost::URLStream::errUnreachable:
return tr("Host is unreachable");
case 2://ost::URLStream::errMissing:
return tr("File was not found (404)");
case 3://ost::URLStream::errDenied:
return tr("Connection was denied");
case 4://ost::URLStream::errInvalid:
return tr("Url is invalid");
case 5://ost::URLStream::errForbidden:
return tr("Connection forbidden (403)");
case 6://ost::URLStream::errUnauthorized:
return tr("Connection was not authorized (401)");
case 7://ost::URLStream::errRelocated:
return tr("Content has moved (301)");
case 8://ost::URLStream::errFailure:
return tr("Connection failure");
case 9://ost::URLStream::errTimeout:
return tr("Connection was timed out");
case 10://ost::URLStream::errInterface:
return tr("Incorrect network interface");
default:
return tr("Unknown error");
}
}
subDownloadThread::subDownloadThread(QObject *parent, QString url) : QThread(parent), url(url), abort(false){
url_stream = new ost::URLStream();
}
subDownloadThread::~subDownloadThread(){
abort = true;
wait();
delete url_stream;
}
void subDownloadThread::run(){
// XXX: Trick to get a unique filename
QString filePath;
QTemporaryFile *tmpfile = new QTemporaryFile();
if (tmpfile->open()) {
filePath = tmpfile->fileName();
}
delete tmpfile;
QFile dest_file(filePath);
if(!dest_file.open(QIODevice::WriteOnly | QIODevice::Text)){
std::cerr << "Error: could't create temporary file: " << (const char*)filePath.toUtf8() << '\n';
return;
}
ost::URLStream::Error status = url_stream->get((const char*)url.toUtf8());
if(status){
// Failure
QString error_msg = errorCodeToString((int)status);
qDebug("Download failed for %s, reason: %s", (const char*)url.toUtf8(), (const char*)error_msg.toUtf8());
url_stream->close();
emit downloadFailureST(this, url, error_msg);
return;
}
qDebug("Downloading %s...", (const char*)url.toUtf8());
char cbuf[1024];
int len;
while(!url_stream->eof()) {
url_stream->read(cbuf, sizeof(cbuf));
len = url_stream->gcount();
if(len > 0)
dest_file.write(cbuf, len);
if(abort){
dest_file.close();
url_stream->close();
return;
}
}
dest_file.close();
url_stream->close();
emit downloadFinishedST(this, url, filePath);
qDebug("download completed here: %s", (const char*)filePath.toUtf8());
}
/** Download Thread **/
downloadThread::downloadThread(QObject* parent) : QThread(parent), abort(false){}
downloadThread::~downloadThread(){
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
qDeleteAll(subThreads);
wait();
}
void downloadThread::downloadUrl(QString url){
QMutexLocker locker(&mutex);
if(downloading_list.contains(url)) return;
url_list << url;
downloading_list << url;
if(!isRunning()){
start();
}else{
condition.wakeOne();
}
}
void downloadThread::run(){
forever{
if(abort)
return;
mutex.lock();
if(url_list.size() != 0){
QString url = url_list.takeFirst();
mutex.unlock();
subDownloadThread *st = new subDownloadThread(0, url);
subThreads << st;
connect(st, SIGNAL(downloadFinishedST(subDownloadThread*, QString, QString)), this, SLOT(propagateDownloadedFile(subDownloadThread*, QString, QString)));
connect(st, SIGNAL(downloadFailureST(subDownloadThread*, QString, QString)), this, SLOT(propagateDownloadFailure(subDownloadThread*, QString, QString)));
st->start();
}else{
condition.wait(&mutex);
mutex.unlock();
}
}
}
void downloadThread::propagateDownloadedFile(subDownloadThread* st, QString url, QString path){
int index = subThreads.indexOf(st);
Q_ASSERT(index != -1);
subThreads.removeAt(index);
delete st;
emit downloadFinished(url, path);
mutex.lock();
index = downloading_list.indexOf(url);
Q_ASSERT(index != -1);
downloading_list.removeAt(index);
mutex.unlock();
}
void downloadThread::propagateDownloadFailure(subDownloadThread* st, QString url, QString reason){
int index = subThreads.indexOf(st);
Q_ASSERT(index != -1);
subThreads.removeAt(index);
delete st;
emit downloadFailure(url, reason);
mutex.lock();
index = downloading_list.indexOf(url);
Q_ASSERT(index != -1);
downloading_list.removeAt(index);
mutex.unlock();
}

View File

@@ -28,144 +28,62 @@
#include <QMutex>
#include <QMutexLocker>
#include <QWaitCondition>
#include <curl/curl.h>
#include <iostream>
#include <QStringList>
#include "misc.h"
namespace ost {
class URLStream;
}
class subDownloadThread : public QThread {
Q_OBJECT
private:
QString url;
ost::URLStream *url_stream;
bool abort;
public:
subDownloadThread(QObject *parent, QString url);
~subDownloadThread();
QString errorCodeToString(int status);
signals:
// For subthreads
void downloadFinishedST(subDownloadThread* st, QString url, QString file_path);
void downloadFailureST(subDownloadThread* st, QString url, QString reason);
protected:
void run();
};
class downloadThread : public QThread {
Q_OBJECT
private:
QStringList url_list;
QStringList downloading_list;
QMutex mutex;
QWaitCondition condition;
bool abort;
QList<subDownloadThread*> subThreads;
signals:
void downloadFinished(const QString& url, const QString& file_path, int return_code, const QString& errorBuffer);
void downloadFinished(QString url, QString file_path);
void downloadFailure(QString url, QString reason);
public:
downloadThread(QObject* parent) : QThread(parent){
mutex.lock();
abort = false;
mutex.unlock();
}
downloadThread(QObject* parent);
~downloadThread(){
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
wait();
}
~downloadThread();
void downloadUrl(const QString& url){
QMutexLocker locker(&mutex);
qDebug("In Download thread function, mutex locked");
url_list << url;
qDebug("In Download thread function, mutex unlocked (url added)");
if(!isRunning()){
qDebug("In Download thread function, Launching thread (was stopped)");
start();
}else{
condition.wakeOne();
}
}
void downloadUrl(QString url);
protected:
void run(){
forever{
if(abort)
return;
mutex.lock();
qDebug("In Download thread RUN, mutex locked");
if(url_list.size() != 0){
QString url = url_list.takeFirst();
mutex.unlock();
qDebug("In Download thread RUN, mutex unlocked (got url)");
CURL *curl;
QString filePath;
int return_code, response;
// XXX: Trick to get a unique filename
QTemporaryFile *tmpfile = new QTemporaryFile;
if (tmpfile->open()) {
filePath = tmpfile->fileName();
}
delete tmpfile;
if(abort)
return;
FILE *file = fopen((const char*)filePath.toUtf8(), "w");
if(!file){
std::cerr << "Error: could not open temporary file...\n";
return;
}
// Initilization required by libcurl
curl = curl_easy_init();
if(!curl){
std::cerr << "Error: Failed to init curl...\n";
fclose(file);
return;
}
// Set url to download
curl_easy_setopt(curl, CURLOPT_URL, url.toLocal8Bit().constData());
qDebug("Url: %s", url.toLocal8Bit().constData());
// Define our callback to get called when there's data to be written
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, misc::my_fwrite);
// Set destination file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
// Some SSL mambo jambo
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
// Disable progress meter
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
// Any kind of authentication
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
// Auto referrer
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
// Follow redirections
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
// Enable cookies
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
// We want error message:
char errorBuffer[CURL_ERROR_SIZE];
errorBuffer[0]=0; /* prevent junk from being output */
return_code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
if(return_code){
std::cerr << "Error: failed to set error buffer in curl\n";
fclose(file);
QFile::remove(filePath);
return;
}
unsigned short retries = 0;
bool to_many_users = false;
do{
// Perform Download
return_code = curl_easy_perform(curl);
// We want HTTP response code
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
qDebug("HTTP response code: %d", response);
if(response/100 == 5){
to_many_users = true;
++retries;
SleeperThread::msleep(1000);
}
}while(to_many_users && retries < 10);
// Cleanup
curl_easy_cleanup(curl);
// Close tmp file
fclose(file);
emit downloadFinished(url, filePath, return_code, QString(errorBuffer));
qDebug("In Download thread RUN, signal emitted, ErrorBuffer: %s", errorBuffer);
}else{
qDebug("In Download thread RUN, mutex still locked (no urls) -> sleeping");
condition.wait(&mutex);
mutex.unlock();
qDebug("In Download thread RUN, woke up, mutex unlocked");
}
}
}
void run();
protected slots:
void propagateDownloadedFile(subDownloadThread* st, QString url, QString path);
void propagateDownloadFailure(subDownloadThread* st, QString url, QString reason);
};
#endif

688
src/downloadingTorrents.cpp Normal file
View File

@@ -0,0 +1,688 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#include "downloadingTorrents.h"
#include "misc.h"
#include "properties_imp.h"
#include "bittorrent.h"
#include "allocationDlg.h"
#include "DLListDelegate.h"
#include "GUI.h"
#include <QFile>
#include <QSettings>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QTime>
#include <QMenu>
DownloadingTorrents::DownloadingTorrents(QObject *parent, bittorrent *BTSession) : parent(parent), BTSession(BTSession), delayedSorting(false), nbTorrents(0) {
setupUi(this);
// Setting icons
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png")));
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png")));
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionClearLog->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png")));
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png")));
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png")));
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png")));
actionDelete_Permanently->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete_perm.png")));
actionTorrent_Properties->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/properties.png")));
// tabBottom->setTabIcon(0, QIcon(QString::fromUtf8(":/Icons/log.png")));
// tabBottom->setTabIcon(1, QIcon(QString::fromUtf8(":/Icons/filter.png")));
// Set default ratio
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
// Set Download list model
DLListModel = new QStandardItemModel(0,9);
DLListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
DLListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
DLListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
DLListModel->setHeaderData(DLSPEED, Qt::Horizontal, tr("DL Speed", "i.e: Download speed"));
DLListModel->setHeaderData(UPSPEED, Qt::Horizontal, tr("UP Speed", "i.e: Upload speed"));
DLListModel->setHeaderData(SEEDSLEECH, Qt::Horizontal, tr("Seeds/Leechs", "i.e: full/partial sources"));
DLListModel->setHeaderData(RATIO, Qt::Horizontal, tr("Ratio"));
DLListModel->setHeaderData(ETA, Qt::Horizontal, tr("ETA", "i.e: Estimated Time of Arrival / Time left"));
downloadList->setModel(DLListModel);
DLDelegate = new DLListDelegate(downloadList);
downloadList->setItemDelegate(DLDelegate);
// Hide hash column
downloadList->hideColumn(HASH);
connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), this, SLOT(torrentAdded(QString, QTorrentHandle&, bool)));
connect(BTSession, SIGNAL(duplicateTorrent(QString)), this, SLOT(torrentDuplicate(QString)));
connect(BTSession, SIGNAL(invalidTorrent(QString)), this, SLOT(torrentCorrupted(QString)));
connect(BTSession, SIGNAL(portListeningFailure()), this, SLOT(portListeningFailure()));
connect(BTSession, SIGNAL(peerBlocked(QString)), this, SLOT(addLogPeerBlocked(const QString)));
connect(BTSession, SIGNAL(fastResumeDataRejected(QString)), this, SLOT(addFastResumeRejectedAlert(QString)));
connect(BTSession, SIGNAL(aboutToDownloadFromUrl(QString)), this, SLOT(displayDownloadingUrlInfos(QString)));
connect(BTSession, SIGNAL(urlSeedProblem(QString, QString)), this, SLOT(addUrlSeedError(QString, QString)));
// Load last columns width for download list
if(!loadColWidthDLList()) {
downloadList->header()->resizeSection(0, 200);
}
// Make download list header clickable for sorting
downloadList->header()->setClickable(true);
downloadList->header()->setSortIndicatorShown(true);
// Connecting Actions to slots
connect(downloadList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(notifyTorrentDoubleClicked(const QModelIndex&)));
connect(downloadList->header(), SIGNAL(sectionPressed(int)), this, SLOT(sortDownloadList(int)));
connect(downloadList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayDLListMenu(const QPoint&)));
connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&)));
// Actions
connect(actionPause, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPause_triggered()));
connect(actionStart, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionStart_triggered()));
connect(actionDelete, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_triggered()));
connect(actionPreview_file, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionPreview_file_triggered()));
connect(actionDelete_Permanently, SIGNAL(triggered()), (GUI*)parent, SLOT(on_actionDelete_Permanently_triggered()));
connect(actionTorrent_Properties, SIGNAL(triggered()), this, SLOT(propertiesSelection()));
// Set info Bar infos
setInfoBar(tr("qBittorrent %1 started.", "e.g: qBittorrent v0.x started.").arg(QString::fromUtf8(""VERSION)));
setInfoBar(tr("Be careful, sharing copyrighted material without permission is against the law."), QString::fromUtf8("red"));
qDebug("Download tab built");
}
DownloadingTorrents::~DownloadingTorrents() {
saveColWidthDLList();
delete DLDelegate;
delete DLListModel;
}
void DownloadingTorrents::notifyTorrentDoubleClicked(const QModelIndex& index) {
unsigned int row = index.row();
QString hash = getHashFromRow(row);
emit torrentDoubleClicked(hash);
}
void DownloadingTorrents::addLogPeerBlocked(QString ip) {
static unsigned int nbLines = 0;
++nbLines;
if(nbLines > 200) {
textBlockedUsers->clear();
nbLines = 1;
}
textBlockedUsers->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - ")+tr("<font color='red'>%1</font> <i>was blocked</i>", "x.y.z.w was blocked").arg(ip));
}
unsigned int DownloadingTorrents::getNbTorrentsInList() const {
return nbTorrents;
}
// Note: do not actually pause the torrent in BT session
void DownloadingTorrents::pauseTorrent(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.0));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.0));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, NAME), QIcon(QString::fromUtf8(":/Icons/skin/paused.png")), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
QTorrentHandle h = BTSession->getTorrentHandle(hash);
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
setRowColor(row, QString::fromUtf8("red"));
}
QString DownloadingTorrents::getHashFromRow(unsigned int row) const {
Q_ASSERT(row < (unsigned int)DLListModel->rowCount());
return DLListModel->data(DLListModel->index(row, HASH)).toString();
}
void DownloadingTorrents::setBottomTabEnabled(unsigned int index, bool b){
if(index and !b)
tabBottom->setCurrentIndex(0);
tabBottom->setTabEnabled(index, b);
}
// Show torrent properties dialog
void DownloadingTorrents::showProperties(const QModelIndex &index) {
int row = index.row();
QString hash = DLListModel->data(DLListModel->index(row, HASH)).toString();
QTorrentHandle h = BTSession->getTorrentHandle(hash);
properties *prop = new properties(this, BTSession, h);
connect(prop, SIGNAL(filteredFilesChanged(QString)), this, SLOT(updateFileSizeAndProgress(QString)));
prop->show();
}
void DownloadingTorrents::resumeTorrent(QString hash){
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
// Remove a torrent from the download list but NOT from the BT Session
void DownloadingTorrents::deleteTorrent(QString hash) {
int row = getRowFromHash(hash);
if(row == -1){
qDebug("torrent is not in download list, nothing to delete");
return;
}
DLListModel->removeRow(row);
--nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
// Update Info Bar information
void DownloadingTorrents::setInfoBar(QString info, QColor color) {
static unsigned int nbLines = 0;
++nbLines;
// Check log size, clear it if too big
if(nbLines > 200) {
infoBar->clear();
nbLines = 1;
}
qDebug("Color is %s", color.name().toUtf8().data());
infoBar->append(QString::fromUtf8("<font color='grey'>")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8("</font> - <font color='") + color.name() +QString::fromUtf8("'><i>") + info + QString::fromUtf8("</i></font>"));
}
void DownloadingTorrents::addFastResumeRejectedAlert(QString name) {
setInfoBar(tr("Fast resume data was rejected for torrent %1, checking again...").arg(name), QString::fromUtf8("red"));
}
void DownloadingTorrents::addUrlSeedError(QString url, QString msg) {
setInfoBar(tr("Url seed lookup failed for url: %1, message: %2").arg(url).arg(msg), QString::fromUtf8("red"));
}
void DownloadingTorrents::on_actionSet_download_limit_triggered() {
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
QStringList hashes;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
}
}
Q_ASSERT(hashes.size() > 0);
new BandwidthAllocationDialog(this, false, BTSession, hashes);
}
void DownloadingTorrents::on_actionSet_upload_limit_triggered() {
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
QStringList hashes;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
hashes << DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
}
}
Q_ASSERT(hashes.size() > 0);
new BandwidthAllocationDialog(this, true, BTSession, hashes);
}
// display properties of selected items
void DownloadingTorrents::propertiesSelection(){
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QModelIndex index;
foreach(index, selectedIndexes){
if(index.column() == NAME){
showProperties(index);
}
}
}
void DownloadingTorrents::displayDLListMenu(const QPoint& pos) {
QMenu myDLLlistMenu(this);
QModelIndex index;
// Enable/disable pause/start action given the DL state
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString previewProgram = settings.value(QString::fromUtf8("Preferences/general/MediaPlayer"), QString()).toString();
bool has_pause = false, has_start = false, has_preview = false;
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file name
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
// Get handle and pause the torrent
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()) continue;
if(h.is_paused()) {
if(!has_start) {
myDLLlistMenu.addAction(actionStart);
has_start = true;
}
}else{
if(!has_pause) {
myDLLlistMenu.addAction(actionPause);
has_pause = true;
}
}
if(!previewProgram.isEmpty() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
myDLLlistMenu.addAction(actionPreview_file);
has_preview = true;
}
if(has_pause && has_start && has_preview) break;
}
}
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionDelete);
myDLLlistMenu.addAction(actionDelete_Permanently);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionSet_download_limit);
myDLLlistMenu.addAction(actionSet_upload_limit);
myDLLlistMenu.addSeparator();
myDLLlistMenu.addAction(actionTorrent_Properties);
// Call menu
// XXX: why mapToGlobal() is not enough?
myDLLlistMenu.exec(mapToGlobal(pos)+QPoint(10,60));
}
void DownloadingTorrents::on_actionClearLog_triggered() {
infoBar->clear();
}
QStringList DownloadingTorrents::getSelectedTorrents(bool only_one) const{
QStringList res;
QModelIndex index;
QModelIndexList selectedIndexes = downloadList->selectionModel()->selectedIndexes();
foreach(index, selectedIndexes) {
if(index.column() == NAME) {
// Get the file hash
QString hash = DLListModel->data(DLListModel->index(index.row(), HASH)).toString();
res << hash;
if(only_one) break;
}
}
return res;
}
void DownloadingTorrents::updateRatio() {
// Update ratio info
float ratio = 1.;
session_status sessionStatus = BTSession->getSessionStatus();
if(sessionStatus.total_payload_download == 0) {
if(sessionStatus.total_payload_upload == 0)
ratio = 1.;
else
ratio = 10.;
}else{
ratio = (double)sessionStatus.total_payload_upload / (double)sessionStatus.total_payload_download;
if(ratio > 10.)
ratio = 10.;
}
LCD_Ratio->display(QString(QByteArray::number(ratio, 'f', 1)));
if(ratio < 0.5) {
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/unhappy.png")));
}else{
if(ratio > 1.0) {
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/smile.png")));
}else{
lbl_ratio_icon->setPixmap(QPixmap(QString::fromUtf8(":/Icons/stare.png")));
}
}
}
void DownloadingTorrents::displayInfoBarMenu(const QPoint& pos) {
// Log Menu
QMenu myLogMenu(this);
myLogMenu.addAction(actionClearLog);
// XXX: Why mapToGlobal() is not enough?
myLogMenu.exec(mapToGlobal(pos)+QPoint(44,305));
}
void DownloadingTorrents::sortProgressColumnDelayed() {
if(delayedSorting) {
sortDownloadListFloat(PROGRESS, delayedSortingOrder);
qDebug("Delayed sorting of progress column");
}
}
// get information from torrent handles and
// update download list accordingly
void DownloadingTorrents::updateDlList() {
// update global informations
LCD_UpSpeed->display(QString(QByteArray::number(BTSession->getPayloadUploadRate()/1024., 'f', 1))); // UP LCD
LCD_DownSpeed->display(QString(QByteArray::number(BTSession->getPayloadDownloadRate()/1024., 'f', 1))); // DL LCD
// browse handles
QStringList unfinishedTorrents = BTSession->getUnfinishedTorrents();
QString hash;
foreach(hash, unfinishedTorrents) {
QTorrentHandle h = BTSession->getTorrentHandle(hash);
if(!h.is_valid()){
qDebug("We have an invalid handle for: %s", qPrintable(hash));
continue;
}
try{
QString hash = h.hash();
int row = getRowFromHash(hash);
if(row == -1) {
qDebug("Info: Could not find filename in download list, adding it...");
addTorrent(hash);
row = getRowFromHash(hash);
}
Q_ASSERT(row != -1);
// No need to update a paused torrent
if(h.is_paused()) continue;
if(BTSession->getTorrentsToPauseAfterChecking().indexOf(hash) != -1) {
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
continue;
}
// Parse download state
// Setting download state
switch(h.state()) {
case torrent_status::finished:
case torrent_status::seeding:
qDebug("A torrent that was in download tab just finished, moving it to finished tab");
BTSession->setUnfinishedTorrent(hash);
emit torrentFinished(hash);
deleteTorrent(hash);
continue;
case torrent_status::checking_files:
case torrent_status::queued_for_checking:
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/time.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
break;
case torrent_status::connecting_to_tracker:
if(h.download_payload_rate() > 0) {
// Display "Downloading" status when connecting if download speed > 0
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("green"));
}else{
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
break;
case torrent_status::downloading:
case torrent_status::downloading_metadata:
if(h.download_payload_rate() > 0) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/downloading.png"))), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)BTSession->getETA(hash)));
setRowColor(row, QString::fromUtf8("green"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/stalled.png"))), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
setRowColor(row, QPalette::WindowText);
}
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)h.download_payload_rate()));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)h.upload_payload_rate()));
break;
default:
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
}
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(misc::toQString(h.num_seeds(), true)+QString::fromUtf8("/")+misc::toQString(h.num_peers() - h.num_seeds(), true)));
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
}catch(invalid_handle e) {
continue;
}
}
}
void DownloadingTorrents::addTorrent(QString hash) {
if(BTSession->isFinished(hash)){
BTSession->setUnfinishedTorrent(hash);
}
QTorrentHandle h = BTSession->getTorrentHandle(hash);
int row = getRowFromHash(hash);
if(row != -1) return;
row = DLListModel->rowCount();
// Adding torrent to download list
DLListModel->insertRow(row);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it was paused last time
if(BTSession->isPaused(hash)) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
void DownloadingTorrents::sortDownloadListFloat(int index, Qt::SortOrder sortOrder) {
QList<QPair<int, double> > lines;
// insertion sorting
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
misc::insertSort(lines, QPair<int,double>(i, DLListModel->data(DLListModel->index(i, index)).toDouble()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row) {
DLListModel->insertRow(DLListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = DLListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col) {
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
DLListModel->removeRows(0, nbRows_old);
}
void DownloadingTorrents::sortDownloadListString(int index, Qt::SortOrder sortOrder) {
QList<QPair<int, QString> > lines;
// Insertion sorting
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
misc::insertSortString(lines, QPair<int, QString>(i, DLListModel->data(DLListModel->index(i, index)).toString()), sortOrder);
}
// Insert items in new model, in correct order
unsigned int nbRows_old = lines.size();
for(unsigned int row=0; row<nbRows_old; ++row) {
DLListModel->insertRow(DLListModel->rowCount());
unsigned int sourceRow = lines[row].first;
unsigned int nbColumns = DLListModel->columnCount();
for(unsigned int col=0; col<nbColumns; ++col) {
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col)));
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::DecorationRole), Qt::DecorationRole);
DLListModel->setData(DLListModel->index(nbRows_old+row, col), DLListModel->data(DLListModel->index(sourceRow, col), Qt::ForegroundRole), Qt::ForegroundRole);
}
}
// Remove old rows
DLListModel->removeRows(0, nbRows_old);
}
void DownloadingTorrents::sortDownloadList(int index, Qt::SortOrder startSortOrder, bool fromLoadColWidth) {
qDebug("Called sort download list");
static Qt::SortOrder sortOrder = startSortOrder;
if(!fromLoadColWidth && downloadList->header()->sortIndicatorSection() == index) {
if(sortOrder == Qt::AscendingOrder) {
sortOrder = Qt::DescendingOrder;
}else{
sortOrder = Qt::AscendingOrder;
}
}
QString sortOrderLetter;
if(sortOrder == Qt::AscendingOrder)
sortOrderLetter = QString::fromUtf8("a");
else
sortOrderLetter = QString::fromUtf8("d");
if(fromLoadColWidth) {
// XXX: Why is this needed?
if(sortOrder == Qt::DescendingOrder)
downloadList->header()->setSortIndicator(index, Qt::AscendingOrder);
else
downloadList->header()->setSortIndicator(index, Qt::DescendingOrder);
} else {
downloadList->header()->setSortIndicator(index, sortOrder);
}
switch(index) {
case SIZE:
case ETA:
case UPSPEED:
case DLSPEED:
sortDownloadListFloat(index, sortOrder);
break;
case PROGRESS:
if(fromLoadColWidth) {
// Progress sorting must be delayed until files are checked (on startup)
delayedSorting = true;
qDebug("Delayed sorting of the progress column");
delayedSortingOrder = sortOrder;
}else{
sortDownloadListFloat(index, sortOrder);
}
break;
default:
sortDownloadListString(index, sortOrder);
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("DownloadListSortedCol"), misc::toQString(index)+sortOrderLetter);
}
// Save columns width in a file to remember them
// (download list)
void DownloadingTorrents::saveColWidthDLList() const{
qDebug("Saving columns width in download list");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QStringList width_list;
unsigned int nbColumns = DLListModel->columnCount()-1;
for(unsigned int i=0; i<nbColumns; ++i) {
width_list << misc::toQString(downloadList->columnWidth(i));
}
settings.setValue(QString::fromUtf8("DownloadListColsWidth"), width_list.join(QString::fromUtf8(" ")));
qDebug("Download list columns width saved");
}
// Load columns width in a file that were saved previously
// (download list)
bool DownloadingTorrents::loadColWidthDLList() {
qDebug("Loading columns width for download list");
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QString line = settings.value(QString::fromUtf8("DownloadListColsWidth"), QString()).toString();
if(line.isEmpty())
return false;
QStringList width_list = line.split(QString::fromUtf8(" "));
if(width_list.size() != DLListModel->columnCount()-1) {
qDebug("Corrupted values for download list columns sizes");
return false;
}
unsigned int listSize = width_list.size();
for(unsigned int i=0; i<listSize; ++i) {
downloadList->header()->resizeSection(i, width_list.at(i).toInt());
}
// Loading last sorted column
QString sortedCol = settings.value(QString::fromUtf8("DownloadListSortedCol"), QString()).toString();
if(!sortedCol.isEmpty()) {
Qt::SortOrder sortOrder;
if(sortedCol.endsWith(QString::fromUtf8("d")))
sortOrder = Qt::DescendingOrder;
else
sortOrder = Qt::AscendingOrder;
sortedCol = sortedCol.left(sortedCol.size()-1);
int index = sortedCol.toInt();
sortDownloadList(index, sortOrder, true);
}
qDebug("Download list columns width loaded");
return true;
}
// Called when a torrent is added
void DownloadingTorrents::torrentAdded(QString path, QTorrentHandle& h, bool fastResume) {
QString hash = h.hash();
if(BTSession->isFinished(hash)) {
return;
}
int row = DLListModel->rowCount();
// Adding torrent to download list
DLListModel->insertRow(row);
DLListModel->setData(DLListModel->index(row, NAME), QVariant(h.name()));
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, UPSPEED), QVariant((double)0.));
DLListModel->setData(DLListModel->index(row, SEEDSLEECH), QVariant(QString::fromUtf8("0/0")));
DLListModel->setData(DLListModel->index(row, RATIO), QVariant(misc::toQString(BTSession->getRealRatio(hash))));
DLListModel->setData(DLListModel->index(row, ETA), QVariant((qlonglong)-1));
DLListModel->setData(DLListModel->index(row, HASH), QVariant(hash));
// Pause torrent if it was paused last time
// Not using isPaused function because torrents are paused after checking now
if(QFile::exists(misc::qBittorrentPath()+QString::fromUtf8("BT_backup")+QDir::separator()+hash+QString::fromUtf8(".paused"))) {
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/paused.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("red"));
}else{
DLListModel->setData(DLListModel->index(row, NAME), QVariant(QIcon(QString::fromUtf8(":/Icons/skin/connecting.png"))), Qt::DecorationRole);
setRowColor(row, QString::fromUtf8("grey"));
}
if(!fastResume) {
setInfoBar(tr("'%1' added to download list.", "'/home/y/xxx.torrent' was added to download list.").arg(path));
}else{
setInfoBar(tr("'%1' resumed. (fast resume)", "'/home/y/xxx.torrent' was resumed. (fast resume)").arg(path));
}
++nbTorrents;
emit unfinishedTorrentsNumberChanged(nbTorrents);
}
// Called when trying to add a duplicate torrent
void DownloadingTorrents::torrentDuplicate(QString path) {
setInfoBar(tr("'%1' is already in download list.", "e.g: 'xxx.avi' is already in download list.").arg(path));
}
void DownloadingTorrents::torrentCorrupted(QString path) {
setInfoBar(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(path), QString::fromUtf8("red"));
setInfoBar(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red"));
}
void DownloadingTorrents::updateFileSizeAndProgress(QString hash) {
int row = getRowFromHash(hash);
Q_ASSERT(row != -1);
QTorrentHandle h = BTSession->getTorrentHandle(hash);
DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)h.actual_size()));
DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant((double)h.progress()));
}
// Called when we couldn't listen on any port
// in the given range.
void DownloadingTorrents::portListeningFailure() {
setInfoBar(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
}
// Set the color of a row in data model
void DownloadingTorrents::setRowColor(int row, QColor color) {
unsigned int nbColumns = DLListModel->columnCount()-1;
for(unsigned int i=0; i<nbColumns; ++i) {
DLListModel->setData(DLListModel->index(row, i), QVariant(color), Qt::ForegroundRole);
}
}
// return the row of in data model
// corresponding to the given the hash
int DownloadingTorrents::getRowFromHash(QString hash) const{
unsigned int nbRows = DLListModel->rowCount();
for(unsigned int i=0; i<nbRows; ++i) {
if(DLListModel->data(DLListModel->index(i, HASH)) == hash) {
return i;
}
}
return -1;
}
void DownloadingTorrents::displayDownloadingUrlInfos(QString url) {
setInfoBar(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(url), QPalette::WindowText);
}

97
src/downloadingTorrents.h Normal file
View File

@@ -0,0 +1,97 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef DOWNLOADINGTORRENTS_H
#define DOWNLOADINGTORRENTS_H
#include "ui_download.h"
#include "qtorrenthandle.h"
class QStandardItemModel;
class bittorrent;
class DLListDelegate;
using namespace libtorrent;
class DownloadingTorrents : public QWidget, public Ui::downloading{
Q_OBJECT
private:
QObject *parent;
bittorrent *BTSession;
DLListDelegate *DLDelegate;
QStandardItemModel *DLListModel;
bool delayedSorting;
unsigned int nbTorrents;
Qt::SortOrder delayedSortingOrder;
public:
DownloadingTorrents(QObject *parent, bittorrent *BTSession);
~DownloadingTorrents();
// Methods
bool loadColWidthDLList();
int getRowFromHash(QString hash) const;
QString getHashFromRow(unsigned int row) const;
QStringList getSelectedTorrents(bool only_one=false) const;
unsigned int getNbTorrentsInList() const;
signals:
void unfinishedTorrentsNumberChanged(unsigned int);
void torrentDoubleClicked(QString hash);
void torrentFinished(QString hash);
protected slots:
void addLogPeerBlocked(QString);
void addFastResumeRejectedAlert(QString);
void addUrlSeedError(QString url, QString msg);
void on_actionSet_download_limit_triggered();
void notifyTorrentDoubleClicked(const QModelIndex& index);
void on_actionSet_upload_limit_triggered();
void displayDLListMenu(const QPoint& pos);
void on_actionClearLog_triggered();
void displayInfoBarMenu(const QPoint& pos);
void addTorrent(QString hash);
void sortDownloadList(int index, Qt::SortOrder startSortOrder=Qt::AscendingOrder, bool fromLoadColWidth=false);
void sortDownloadListFloat(int index, Qt::SortOrder sortOrder);
void sortDownloadListString(int index, Qt::SortOrder sortOrder);
void saveColWidthDLList() const;
void torrentAdded(QString path, QTorrentHandle& h, bool fastResume);
void torrentDuplicate(QString path);
void torrentCorrupted(QString path);
void portListeningFailure();
void setRowColor(int row, QColor color);
void displayDownloadingUrlInfos(QString url);
void showProperties(const QModelIndex &index);
public slots:
void updateDlList();
void setInfoBar(QString info, QColor color=QPalette::WindowText);
void pauseTorrent(QString hash);
void resumeTorrent(QString hash);
void updateRatio();
void deleteTorrent(QString hash);
void setBottomTabEnabled(unsigned int index, bool b);
void propertiesSelection();
void sortProgressColumnDelayed();
void updateFileSizeAndProgress(QString hash);
};
#endif

125
src/engineSelect.ui Normal file
View File

@@ -0,0 +1,125 @@
<ui version="4.0" >
<class>engineSelect</class>
<widget class="QDialog" name="engineSelect" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>541</width>
<height>254</height>
</rect>
</property>
<property name="acceptDrops" >
<bool>true</bool>
</property>
<property name="windowTitle" >
<string>Search plugins</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="lbl_engines" >
<property name="font" >
<font>
<weight>75</weight>
<bold>true</bold>
<underline>true</underline>
</font>
</property>
<property name="text" >
<string>Installed search engines:</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="pluginsTree" >
<property name="contextMenuPolicy" >
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="uniformRowHeights" >
<bool>true</bool>
</property>
<property name="itemsExpandable" >
<bool>false</bool>
</property>
<column>
<property name="text" >
<string>Name</string>
</property>
</column>
<column>
<property name="text" >
<string>Url</string>
</property>
</column>
<column>
<property name="text" >
<string>Enabled</string>
</property>
</column>
<column>
<property name="text" >
<string/>
</property>
</column>
</widget>
</item>
<item>
<widget class="QLabel" name="getNewEngine_lbl" >
<property name="font" >
<font>
<italic>true</italic>
</font>
</property>
<property name="text" >
<string>You can get new search engine plugins here: &lt;a href="http:plugins.qbittorrent.org">http://plugins.qbittorrent.org&lt;/a></string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QPushButton" name="installButton" >
<property name="text" >
<string>Install a new one</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="updateButton" >
<property name="text" >
<string>Check for updates</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton" >
<property name="text" >
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<action name="actionEnable" >
<property name="text" >
<string>Enable</string>
</property>
</action>
<action name="actionDisable" >
<property name="text" >
<string>Disable</string>
</property>
</action>
<action name="actionUninstall" >
<property name="text" >
<string>Uninstall</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

697
src/engineSelectDlg.cpp Normal file
View File

@@ -0,0 +1,697 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#include "engineSelectDlg.h"
#include "downloadThread.h"
#include "misc.h"
#include "pluginSource.h"
#include <QProcess>
#include <QHeaderView>
#include <QSettings>
#include <QMenu>
#include <QMessageBox>
#include <QFileDialog>
#include <QDropEvent>
#include <QInputDialog>
#ifdef HAVE_MAGICK
#include <Magick++.h>
using namespace Magick;
#endif
#ifdef HAVE_ZZIP
#include <zzip/zzip.h>
#endif
#define ENGINE_NAME 0
#define ENGINE_URL 1
#define ENGINE_STATE 2
#define ENGINE_ID 3
engineSelectDlg::engineSelectDlg(QWidget *parent) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
pluginsTree->header()->resizeSection(0, 170);
pluginsTree->header()->resizeSection(1, 220);
pluginsTree->hideColumn(ENGINE_ID);
actionEnable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_ok.png")));
actionDisable->setIcon(QIcon(QString::fromUtf8(":/Icons/button_cancel.png")));
actionUninstall->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/remove.png")));
connect(actionEnable, SIGNAL(triggered()), this, SLOT(enableSelection()));
connect(actionDisable, SIGNAL(triggered()), this, SLOT(disableSelection()));
connect(pluginsTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContextMenu(const QPoint&)));
downloader = new downloadThread(this);
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
loadSupportedSearchEngines(true);
connect(pluginsTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(toggleEngineState(QTreeWidgetItem*, int)));
show();
}
engineSelectDlg::~engineSelectDlg() {
qDebug("Destroying engineSelectDlg");
saveSettings();
emit enginesChanged();
qDebug("Before deleting downloader");
delete downloader;
qDebug("Engine plugins dialog destroyed");
}
void engineSelectDlg::dropEvent(QDropEvent *event) {
event->acceptProposedAction();
QStringList files=event->mimeData()->text().split(QString::fromUtf8("\n"));
QString file;
foreach(file, files) {
qDebug("dropped %s", file.toUtf8().data());
file = file.replace("file://", "");
if(file.startsWith("http://", Qt::CaseInsensitive) || file.startsWith("https://", Qt::CaseInsensitive) || file.startsWith("ftp://", Qt::CaseInsensitive)) {
downloader->downloadUrl(file);
continue;
}
if(file.endsWith(".py", Qt::CaseInsensitive)) {
QString plugin_name = file.split(QDir::separator()).last();
plugin_name.replace(".py", "");
installPlugin(file, plugin_name);
}
#ifdef HAVE_ZZIP
if(file.endsWith(".zip", Qt::CaseInsensitive)) {
installZipPlugin(file);
}
#endif
}
}
// Decode if we accept drag 'n drop or not
void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
QString mime;
foreach(mime, event->mimeData()->formats()){
qDebug("mimeData: %s", mime.toUtf8().data());
}
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) {
event->acceptProposedAction();
}
}
void engineSelectDlg::saveSettings() {
qDebug("Saving engines settings");
QStringList known_engines;
QVariantList known_enginesEnabled;
QString engine;
foreach(engine, installed_engines.keys()) {
known_engines << engine;
known_enginesEnabled << QVariant(installed_engines.value(engine, true));
qDebug("Engine %s has state: %d", engine.toUtf8().data(), installed_engines.value(engine, true));
}
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
settings.setValue(QString::fromUtf8("SearchEngines/knownEngines"), known_engines);
settings.setValue(QString::fromUtf8("SearchEngines/knownEnginesEnabled"), known_enginesEnabled);
}
void engineSelectDlg::on_updateButton_clicked() {
// Download version file from primary server
downloader->downloadUrl("http://www.dchris.eu/search_engine/versions.txt");
}
void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
int index = pluginsTree->indexOfTopLevelItem(item);
QString id = item->text(ENGINE_ID);
bool new_val = !installed_engines.value(id, true);
installed_engines[id] = new_val;
QString enabledTxt;
if(new_val){
enabledTxt = tr("True");
setRowColor(index, "green");
}else{
enabledTxt = tr("False");
setRowColor(index, "red");
}
item->setText(ENGINE_STATE, enabledTxt);
}
void engineSelectDlg::displayContextMenu(const QPoint& pos) {
QMenu myContextMenu(this);
QModelIndex index;
// Enable/disable pause/start action given the DL state
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
bool has_enable = false, has_disable = false;
QTreeWidgetItem *item;
foreach(item, items) {
QString id = item->text(ENGINE_ID);
if(installed_engines.value(id, true) and !has_disable) {
myContextMenu.addAction(actionDisable);
has_disable = true;
}
if(!installed_engines.value(id, true) and !has_enable) {
myContextMenu.addAction(actionEnable);
has_enable = true;
}
if(has_enable && has_disable) break;
}
myContextMenu.addSeparator();
myContextMenu.addAction(actionUninstall);
myContextMenu.exec(mapToGlobal(pos)+QPoint(12, 58));
}
void engineSelectDlg::on_closeButton_clicked() {
close();
}
void engineSelectDlg::on_actionUninstall_triggered() {
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
QTreeWidgetItem *item;
bool change = false;
bool error = false;
foreach(item, items) {
int index = pluginsTree->indexOfTopLevelItem(item);
Q_ASSERT(index != -1);
QString id = item->text(ENGINE_ID);
if(QFile::exists(":/search_engine/engines/"+id+".py")) {
error = true;
// Disable it instead
installed_engines.insert(id, false);
item->setText(ENGINE_STATE, tr("False"));
setRowColor(index, "red");
continue;
}else {
// Proceed with uninstall
// remove it from hard drive
QDir enginesFolder(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines");
QStringList filters;
filters << id+".*";
QStringList files = enginesFolder.entryList(filters, QDir::Files, QDir::Unsorted);
QString file;
foreach(file, files) {
enginesFolder.remove(file);
}
// Remove it from lists
installed_engines.remove(id);
delete item;
change = true;
}
}
if(error)
QMessageBox::warning(0, tr("Uninstall warning"), tr("Some plugins could not be uninstalled because they are included in qBittorrent.\n Only the ones you added yourself can be uninstalled.\nHowever, those plugins were disabled."));
else
QMessageBox::information(0, tr("Uninstall success"), tr("All selected plugins were uninstalled successfully"));
}
void engineSelectDlg::enableSelection() {
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
QTreeWidgetItem *item;
foreach(item, items) {
int index = pluginsTree->indexOfTopLevelItem(item);
Q_ASSERT(index != -1);
QString id = item->text(ENGINE_ID);
installed_engines.insert(id, true);
item->setText(ENGINE_STATE, tr("True"));
setRowColor(index, "green");
}
}
void engineSelectDlg::disableSelection() {
QList<QTreeWidgetItem *> items = pluginsTree->selectedItems();
QTreeWidgetItem *item;
foreach(item, items) {
int index = pluginsTree->indexOfTopLevelItem(item);
Q_ASSERT(index != -1);
QString id = item->text(ENGINE_ID);
installed_engines.insert(id, false);
item->setText(ENGINE_STATE, tr("False"));
setRowColor(index, "red");
}
}
// Set the color of a row in data model
void engineSelectDlg::setRowColor(int row, QString color){
QTreeWidgetItem *item = pluginsTree->topLevelItem(row);
for(int i=0; i<pluginsTree->columnCount()-1; ++i){
item->setData(i, Qt::ForegroundRole, QVariant(QColor(color)));
}
}
bool engineSelectDlg::checkInstalled(QString plugin_name) const {
QProcess nova;
QStringList params;
params << "--supported_engines";
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
QByteArray result = nova.readAll();
result = result.replace("\n", "");
QList<QByteArray> plugins_list = result.split(',');
return plugins_list.contains(plugin_name.toUtf8());
}
void engineSelectDlg::loadSupportedSearchEngines(bool first) {
// Some clean up first
pluginsTree->clear();
QHash<QString, bool> old_engines;
if(first) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent"));
QStringList known_engines = settings.value(QString::fromUtf8("SearchEngines/knownEngines"), QStringList()).toStringList();
QVariantList enabled = settings.value(QString::fromUtf8("SearchEngines/knownEnginesEnabled"), QList<QVariant>()).toList();
Q_ASSERT(known_engines.size() == enabled.size());
unsigned int nbKnownEngines = known_engines.size();
for(unsigned int i=0; i<nbKnownEngines; ++i) {
old_engines[known_engines.at(i)] = enabled.at(i).toBool();
}
} else {
old_engines = installed_engines;
}
installed_engines.clear();
QStringList params;
// Ask nova core for the supported search engines
QProcess nova;
params << "--supported_engines";
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
QByteArray result = nova.readAll();
result = result.replace("\n", "");
qDebug("read: %s", result.data());
QByteArray e;
QStringList supported_engines_ids;
foreach(e, result.split(',')) {
QString en = QString(e);
supported_engines_ids << en;
installed_engines[en] = old_engines.value(en, true);
}
params.clear();
params << "--supported_engines_infos";
nova.start(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"nova2.py", params, QIODevice::ReadOnly);
nova.waitForStarted();
nova.waitForFinished();
result = nova.readAll();
result = result.replace("\n", "");
qDebug("read: %s", result.data());
unsigned int i = 0;
foreach(e, result.split(',')) {
QString id = supported_engines_ids.at(i);
QString nameUrlCouple(e);
QStringList line = nameUrlCouple.split('|');
if(line.size() != 2) continue;
QString enabledTxt;
if(installed_engines.value(id, true)) {
enabledTxt = tr("True");
} else {
enabledTxt = tr("False");
}
line << enabledTxt;
line << id;
QTreeWidgetItem *item = new QTreeWidgetItem(pluginsTree, line);
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
if(QFile::exists(iconPath)) {
// Good, we already have the icon
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
} else {
// Icon is missing, we must download it
downloader->downloadUrl(line.at(1)+"/favicon.ico");
}
if(installed_engines.value(id, true))
setRowColor(i, "green");
else
setRowColor(i, "red");
++i;
}
}
QList<QTreeWidgetItem*> engineSelectDlg::findItemsWithUrl(QString url){
QList<QTreeWidgetItem*> res;
for(int i=0; i<pluginsTree->topLevelItemCount(); ++i) {
QTreeWidgetItem *item = pluginsTree->topLevelItem(i);
if(url.startsWith(item->text(ENGINE_URL), Qt::CaseInsensitive))
res << item;
}
return res;
}
QTreeWidgetItem* engineSelectDlg::findItemWithID(QString id){
QList<QTreeWidgetItem*> res;
for(int i=0; i<pluginsTree->topLevelItemCount(); ++i) {
QTreeWidgetItem *item = pluginsTree->topLevelItem(i);
if(id == item->text(ENGINE_ID))
return item;
}
return 0;
}
bool engineSelectDlg::isUpdateNeeded(QString plugin_name, float new_version) const {
float old_version = misc::getPluginVersion(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py");
qDebug("IsUpdate needed? tobeinstalled: %.2f, alreadyinstalled: %.2f", new_version, old_version);
return (new_version > old_version);
}
#ifdef HAVE_ZZIP
void engineSelectDlg::installZipPlugin(QString path) {
QStringList plugins;
QStringList favicons;
ZZIP_DIR* dir = zzip_dir_open(path.toUtf8().data(), 0);
if(!dir) {
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("Search engine plugin archive could not be read."));
return;
}
ZZIP_DIRENT dirent;
while(zzip_dir_read(dir, &dirent)) {
/* show info for first file */
QString name(dirent.d_name);
if(name.endsWith(".py", Qt::CaseInsensitive)) {
plugins << name;
} else {
if(name.endsWith(".png", Qt::CaseInsensitive)) {
favicons << name;
}
}
}
QString plugin;
std::cout << dirent.d_name << std::endl;
ZZIP_FILE* fp = zzip_file_open(dir, dirent.d_name, 0);
if (fp) {
char buf[10];
zzip_ssize_t len = zzip_file_read(fp, buf, 10);
if (len) {
/* show head of README */
std::cout << buf;
}
zzip_file_close(fp);
std::cout << std::endl;
}
foreach(plugin, plugins) {
QString plugin_name = plugin.split(QDir::separator()).last();
plugin_name.chop(3); // Remove .py extension
qDebug("Detected plugin %s in archive", plugin_name.toUtf8().data());
ZZIP_FILE* fp = zzip_file_open(dir, plugin.toUtf8().data(), 0);
if(fp) {
QTemporaryFile *tmpfile = new QTemporaryFile();
QString tmpPath;
// Write file
if(tmpfile->open()) {
tmpPath = tmpfile->fileName();
char buf[255];
zzip_ssize_t len = zzip_file_read(fp, buf, 255);
while(len) {
tmpfile->write(buf, len);
len = zzip_file_read(fp, buf, 255);
}
zzip_file_close(fp);
tmpfile->close();
} else {
qDebug("Could not open tmp file");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
delete tmpfile;
continue;
}
// Install plugin
installPlugin(tmpPath, plugin_name);
qDebug("installPlugin() finished");
delete tmpfile;
qDebug("Deleted tmpfile");
} else {
qDebug("Cannot read file in archive");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
}
QString favicon;
foreach(favicon, favicons) {
qDebug("Detected favicon %s in archive", favicon.toUtf8().data());
// Ok we have a favicon here
QString plugin_name = favicon.split(QDir::separator()).last();
plugin_name.chop(4); // Remove .png extension
if(!QFile::exists(misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py"))
continue;
// Check if we already have a favicon for this plugin
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".png";
if(QFile::exists(iconPath)) continue;
ZZIP_FILE* fp = zzip_file_open(dir, favicon.toUtf8().data(), 0);
if(fp) {
QFile dest_icon(iconPath);
// Write icon
if(dest_icon.open(QIODevice::WriteOnly | QIODevice::Text)) {
char buf[255];
zzip_ssize_t len = zzip_file_read(fp, buf, 255);
while(len) {
dest_icon.write(buf, len);
len = zzip_file_read(fp, buf, 255);
}
zzip_file_close(fp);
dest_icon.close();
// Update icon in list
QTreeWidgetItem *item = findItemWithID(plugin_name);
Q_ASSERT(item);
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
}
}
}
zzip_dir_close(dir);
}
#endif
void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
qDebug("Asked to install plugin at %s", path.toUtf8().data());
float new_version = misc::getPluginVersion(path);
qDebug("Version to be installed: %.2f", new_version);
if(!isUpdateNeeded(plugin_name, new_version)) {
qDebug("Apparently update it not needed, we have a more recent version");
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("A more recent version of %1 search engine plugin is already installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
// Process with install
QString dest_path = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+plugin_name+".py";
bool update = false;
if(QFile::exists(dest_path)) {
// Backup in case install fails
QFile::copy(dest_path, dest_path+".bak");
QFile::remove(dest_path);
update = true;
}
// Copy the plugin
QFile::copy(path, dest_path);
// Check if this was correctly installed
if(!checkInstalled(plugin_name)) {
if(update) {
// Remove broken file
QFile::remove(dest_path);
// restore backup
QFile::copy(dest_path+".bak", dest_path);
QFile::remove(dest_path+".bak");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
} else {
// Remove broken file
QFile::remove(dest_path);
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
}
// Install was successful, remove backup
if(update) {
QFile::remove(dest_path+".bak");
}
// Refresh plugin list
loadSupportedSearchEngines();
if(update) {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
} else {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully installed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
return;
}
}
void engineSelectDlg::on_installButton_clicked() {
pluginSourceDlg *dlg = new pluginSourceDlg(this);
connect(dlg, SIGNAL(askForLocalFile()), this, SLOT(askForLocalPlugin()));
connect(dlg, SIGNAL(askForUrl()), this, SLOT(askForPluginUrl()));
}
void engineSelectDlg::askForPluginUrl() {
bool ok;
QString url = QInputDialog::getText(this, tr("New search engine plugin URL"),
tr("URL:"), QLineEdit::Normal,
"http://", &ok);
if (ok && !url.isEmpty())
downloader->downloadUrl(url);
}
void engineSelectDlg::askForLocalPlugin() {
QStringList pathsList = QFileDialog::getOpenFileNames(0,
tr("Select search plugins"), QDir::homePath(),
#ifdef HAVE_ZZIP
tr("qBittorrent search plugins")+QString::fromUtf8(" (*.py *.zip)"));
#else
tr("qBittorrent search plugins")+QString::fromUtf8(" (*.py)"));
#endif
QString path;
foreach(path, pathsList) {
if(path.endsWith(".py", Qt::CaseInsensitive)) {
QString plugin_name = path.split(QDir::separator()).last();
plugin_name.replace(".py", "", Qt::CaseInsensitive);
installPlugin(path, plugin_name);
}
#ifdef HAVE_ZZIP
else {
if(path.endsWith(".zip", Qt::CaseInsensitive)) {
installZipPlugin(path);
}
}
#endif
}
}
bool engineSelectDlg::parseVersionsFile(QString versions_file, QString updateServer) {
qDebug("Checking if update is needed");
bool file_correct = false;
QFile versions(versions_file);
if(!versions.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug("* Error: Could not read versions.txt file");
return false;
}
bool updated = false;
while(!versions.atEnd()) {
QByteArray line = versions.readLine();
line.replace("\n", "");
line = line.trimmed();
if(line.isEmpty()) continue;
if(line.startsWith("#")) continue;
QList<QByteArray> list = line.split(' ');
if(list.size() != 2) continue;
QString plugin_name = QString(list.first());
if(!plugin_name.endsWith(":")) continue;
plugin_name.chop(1); // remove trailing ':'
bool ok;
float version = list.last().toFloat(&ok);
qDebug("read line %s: %.2f", plugin_name.toUtf8().data(), version);
if(!ok) continue;
file_correct = true;
if(isUpdateNeeded(plugin_name, version)) {
qDebug("Plugin: %s is outdated", plugin_name.toUtf8().data());
// Downloading update
downloader->downloadUrl(updateServer+plugin_name+".pyqBT"); // Actually this is really a .py
downloader->downloadUrl(updateServer+plugin_name+".png");
updated = true;
}else {
qDebug("Plugin: %s is up to date", plugin_name.toUtf8().data());
}
}
// Close file
versions.close();
// Clean up tmp file
QFile::remove(versions_file);
if(file_correct && !updated) {
QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date."));
}
return file_correct;
}
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
qDebug("engineSelectDlg received %s", url.toUtf8().data());
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
// Icon downloaded
QImage fileIcon;
#ifdef HAVE_MAGICK
try{
QFile::copy(filePath, filePath+".ico");
Image image(QDir::cleanPath(filePath+".ico").toUtf8().data());
// Convert to PNG since we can't read ICO format
image.magick("PNG");
// Resize to 16x16px
image.sample(Geometry(16, 16));
image.write(filePath.toUtf8().data());
QFile::remove(filePath+".ico");
}catch(Magick::Exception &error_){
qDebug("favicon conversion to PNG failure: %s", error_.what());
}
#endif
if(fileIcon.load(filePath)) {
QList<QTreeWidgetItem*> items = findItemsWithUrl(url);
QTreeWidgetItem *item;
foreach(item, items){
QString id = item->text(ENGINE_ID);
QString iconPath = misc::qBittorrentPath()+"search_engine"+QDir::separator()+"engines"+QDir::separator()+id+".png";
QFile::copy(filePath, iconPath);
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
}
}
// Delete tmp file
QFile::remove(filePath);
return;
}
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
if(!parseVersionsFile(filePath, "http://www.dchris.eu/search_engine/")) {
qDebug("Primary update server failed, try secondary");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
}
QFile::remove(filePath);
return;
}
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
if(!parseVersionsFile(filePath, "http://hydr0g3n.free.fr/search_engine/")) {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
}
QFile::remove(filePath);
return;
}
if(url.endsWith(".pyqBT", Qt::CaseInsensitive) || url.endsWith(".py", Qt::CaseInsensitive)) {
QString plugin_name = url.split('/').last();
plugin_name.replace(".pyqBT", "");
plugin_name.replace(".py", "");
installPlugin(filePath, plugin_name);
QFile::remove(filePath);
return;
}
#ifdef HAVE_ZZIP
if(url.endsWith(".zip", Qt::CaseInsensitive)) {
installZipPlugin(filePath);
QFile::remove(filePath);
return;
}
#endif
}
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
if(url.endsWith("favicon.ico", Qt::CaseInsensitive)){
qDebug("Could not download favicon: %s, reason: %s", url.toUtf8().data(), reason.toUtf8().data());
return;
}
if(url == "http://www.dchris.eu/search_engine/versions.txt") {
// Primary update server failed, try secondary
qDebug("Primary update server failed, try secondary");
downloader->downloadUrl("http://hydr0g3n.free.fr/search_engine/versions.txt");
return;
}
if(url == "http://hydr0g3n.free.fr/search_engine/versions.txt") {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
return;
}
if(url.endsWith(".pyqBT", Qt::CaseInsensitive) || url.endsWith(".py", Qt::CaseInsensitive)) {
// a plugin update download has been failed
QString plugin_name = url.split('/').last();
plugin_name.replace(".pyqBT", "", Qt::CaseInsensitive);
plugin_name.replace(".py", "", Qt::CaseInsensitive);
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
#ifdef HAVE_ZZIP
if(url.endsWith(".zip", Qt::CaseInsensitive)) {
QString plugin_name = url.split('/').last();
plugin_name.replace(".zip", "", Qt::CaseInsensitive);
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, %1 search plugin install failed.", "%1 is the name of the search engine").arg(plugin_name.toUtf8().data()));
}
#endif
}

76
src/engineSelectDlg.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2006 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact : chris@qbittorrent.org
*/
#ifndef ENGINE_SELECT_DLG_H
#define ENGINE_SELECT_DLG_H
#include "ui_engineSelect.h"
class downloadThread;
class QDropEvent;
class engineSelectDlg : public QDialog, public Ui::engineSelect{
Q_OBJECT
private:
// Search related
QHash<QString, bool> installed_engines;
downloadThread *downloader;
public:
engineSelectDlg(QWidget *parent);
~engineSelectDlg();
QList<QTreeWidgetItem*> findItemsWithUrl(QString url);
QTreeWidgetItem* findItemWithID(QString id);
protected:
bool parseVersionsFile(QString versions_file, QString updateServer);
bool isUpdateNeeded(QString plugin_name, float new_version) const;
bool checkInstalled(QString plugin_name) const;
signals:
void enginesChanged();
protected slots:
void saveSettings();
void on_closeButton_clicked();
void loadSupportedSearchEngines(bool first=false);
void toggleEngineState(QTreeWidgetItem*, int);
void setRowColor(int row, QString color);
void processDownloadedFile(QString url, QString filePath);
void handleDownloadFailure(QString url, QString reason);
void displayContextMenu(const QPoint& pos);
void enableSelection();
void disableSelection();
void on_actionUninstall_triggered();
void on_updateButton_clicked();
void on_installButton_clicked();
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void installPlugin(QString plugin_path, QString plugin_name);
void askForLocalPlugin();
void askForPluginUrl();
#ifdef HAVE_ZZIP
void installZipPlugin(QString path);
#endif
};
#endif

View File

@@ -1,48 +1,77 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>Icons/encrypted.png</file>
<file>Icons/time.png</file>
<file>Icons/connection.png</file>
<file>Icons/locale.png</file>
<file>Icons/newmsg.png</file>
<file>Icons/style.png</file>
<file>Icons/wizard.png</file>
<file>Icons/button_cancel.png</file>
<file>Icons/url.png</file>
<file>Icons/button_ok.png</file>
<file>Icons/smile.png</file>
<file>Icons/stare.png</file>
<file>Icons/qbittorrent22.png</file>
<file>Icons/proxy.png</file>
<file>Icons/log.png</file>
<file>Icons/qbittorrent32.png</file>
<file>Icons/downarrow.png</file>
<file>Icons/description.png</file>
<file>Icons/qbittorrent16.png</file>
<file>Icons/file.png</file>
<file>Icons/systemtray.png</file>
<file>Icons/unhappy.png</file>
<file>Icons/filter.png</file>
<file>Icons/splash.jpg</file>
<file>Icons/sphere.png</file>
<file>Icons/mascot.png</file>
<file>Icons/encrypted.png</file>
<file>Icons/refresh.png</file>
<file>Icons/uparrow.png</file>
<file>Icons/style.png</file>
<file>Icons/wizard.png</file>
<file>Icons/password.png</file>
<file>Icons/gear.png</file>
<file>Icons/sphere2.png</file>
<file>Icons/smile.png</file>
<file>Icons/loading.png</file>
<file>Icons/button_cancel.png</file>
<file>Icons/qbittorrent22.png</file>
<file>Icons/proxy.png</file>
<file>Icons/add_folder.png</file>
<file>Icons/unavailable.png</file>
<file>Icons/add_file.png</file>
<file>Icons/home.png</file>
<file>Icons/flags/netherlands.png</file>
<file>Icons/splash.png</file>
<file>Icons/rss32.png</file>
<file>Icons/rss16.png</file>
<file>Icons/unsubscribe.png</file>
<file>Icons/subscribe.png</file>
<file>Icons/unsubscribe16.png</file>
<file>Icons/subscribe16.png</file>
<file>Icons/bt_settings.png</file>
<file>Icons/star.png</file>
<file>Icons/configure.png</file>
<file>Icons/download.png</file>
<file>Icons/folder.png</file>
<file>Icons/flags/portugal.png</file>
<file>Icons/flags/france.png</file>
<file>Icons/flags/ukraine.png</file>
<file>Icons/flags/germany.png</file>
<file>Icons/flags/united_kingdom.png</file>
<file>Icons/flags/germany.png</file>
<file>Icons/flags/russia.png</file>
<file>Icons/flags/south_korea.png</file>
<file>Icons/flags/netherlands.png</file>
<file>Icons/flags/slovakia.png</file>
<file>Icons/flags/spain.png</file>
<file>Icons/flags/finland.png</file>
<file>Icons/flags/poland.png</file>
<file>Icons/flags/china_hong_kong.png</file>
<file>Icons/flags/spain_catalunya.png</file>
<file>Icons/flags/poland.png</file>
<file>Icons/flags/hungary.png</file>
<file>Icons/flags/norway.png</file>
<file>Icons/flags/denmark.png</file>
<file>Icons/flags/italy.png</file>
<file>Icons/flags/china.png</file>
<file>Icons/flags/denmark.png</file>
<file>Icons/flags/brazil.png</file>
<file>Icons/flags/south_korea.png</file>
<file>Icons/flags/turkey.png</file>
<file>Icons/flags/sweden.png</file>
<file>Icons/flags/romania.png</file>
<file>Icons/flags/bulgaria.png</file>
<file>Icons/flags/greece.png</file>
<file>Icons/flags/romania.png</file>
<file>Icons/flags/japan.png</file>
<file>Icons/flags/greece.png</file>
<file>Icons/skin/properties.png</file>
<file>Icons/skin/play_all.png</file>
<file>Icons/skin/remove.png</file>
@@ -67,6 +96,7 @@
<file>Icons/skin/add.png</file>
<file>Icons/skin/stalled.png</file>
<file>Icons/skin/new.png</file>
<file>Icons/skin/qb_question.png</file>
<file>Icons/skin/delete_all.png</file>
<file>Icons/skin/info.png</file>
</qresource>

View File

@@ -2,6 +2,7 @@
<qresource>
<file>lang/qbittorrent_es.qm</file>
<file>lang/qbittorrent_ko.qm</file>
<file>lang/qbittorrent_hu.qm</file>
<file>lang/qbittorrent_sk.qm</file>
<file>lang/qbittorrent_uk.qm</file>
<file>lang/qbittorrent_ro.qm</file>
@@ -9,20 +10,20 @@
<file>lang/qbittorrent_nb.qm</file>
<file>lang/qbittorrent_el.qm</file>
<file>lang/qbittorrent_en.qm</file>
<file>lang/qbittorrent_pt_BR.qm</file>
<file>lang/qbittorrent_fr.qm</file>
<file>lang/qbittorrent_nl.qm</file>
<file>lang/qbittorrent_pl.qm</file>
<file>lang/qbittorrent_it.qm</file>
<file>lang/qbittorrent_zh.qm</file>
<file>lang/qbittorrent_pt.qm</file>
<file>lang/qbittorrent_ca.qm</file>
<file>lang/qbittorrent_pt.qm</file>
<file>lang/qbittorrent_da.qm</file>
<file>lang/qbittorrent_tr.qm</file>
<file>lang/qbittorrent_bg.qm</file>
<file>lang/qbittorrent_de.qm</file>
<file>lang/qbittorrent_sv.qm</file>
<file>lang/qbittorrent_fi.qm</file>
<file>lang/qbittorrent_zh_HK.qm</file>
<file>lang/qbittorrent_da.qm</file>
<file>lang/qbittorrent_ja.qm</file>
<file>lang/qbittorrent_fi.qm</file>
</qresource>
</RCC>

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.

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