Compare commits

...

231 Commits

Author SHA1 Message Date
Andrew Resch
c81fbf788d Update version numbers 2011-05-24 15:16:56 -07:00
Andrew Resch
a35b2497f3 Update javascript release files 2011-05-24 15:13:50 -07:00
Andrew Resch
8fe299dc21 Update translations 2011-05-24 11:49:35 -07:00
Calum Lind
e66f0cb503 Small text updates 2011-05-24 01:58:40 +01:00
Andrew Resch
5e129b3c64 Fix up displaying versions in the about dialog 2011-05-24 01:42:35 +01:00
Pedro Algarvio
2d40d2b224 PEP-8 2011-05-24 01:41:15 +01:00
Calum Lind
ce0234f0ef Change Connection Manager Key Shortcut to Ctrl-M 2011-05-23 22:20:10 +01:00
Andrew Resch
c225eae189 1862: Fix typo in move storage 2011-05-23 13:41:37 -07:00
Calum Lind
afa941df2e Update Changelog 2011-05-23 01:22:18 +01:00
Calum Lind
49cbcf1f9c Update certain torrentview columns to default to not visible 2011-05-23 01:00:23 +01:00
Andrew Resch
3c3b68e2cc Add ability to set columns as not visible by default by setting the kwarg default to False when adding the column 2011-05-22 15:18:17 -07:00
tecknicaltom
b93477c41e Feature #1308: Add Seeds/Peers ratio to torrent list view 2011-05-22 21:04:59 +01:00
runeks
766c48e3ca Feature #1646: Add columns for per torrent upload and download speed limits 2011-05-22 21:04:59 +01:00
Calum Lind
1f73476dc3 Fix Up/Down buttons in Edit Trackers Dialog
This fix properly reflects the movement of the tracker in the dialog table rather than by the tracker index.
2011-05-22 21:04:41 +01:00
Calum Lind
5bfb98f9a9 Change default value of close_to_tray to False
Prevents default install of Deluge disappearing if tray icon is missing.
2011-05-22 21:04:41 +01:00
Calum Lind
d07b53f665 Add key shortcuts for menu items 2011-05-21 18:53:22 +01:00
Calum Lind
449be00e33 Supress gobject warning in filtertreeview and torrentview
In console the warning "g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed" will appear. Quick investigation could find no solution with suggestions a python issue.
2011-05-21 18:53:03 +01:00
Calum Lind
655af15695 Modify setup scripts to be executable 2011-05-21 18:46:10 +01:00
Eirik Byrkjeflot Anonsen
a549eac063 Add --sort option to deluge-console's "info" command. 2011-05-21 18:46:10 +01:00
Eirik Byrkjeflot Anonsen
6fa2728ddc Add seeding_time, active_time and tracker_status to deluge-console's "info" command. 2011-05-20 19:51:33 +01:00
Eirik Byrkjeflot Anonsen
9060de9b70 Fix spelling error in deluge-console output. 2011-05-20 19:49:22 +01:00
Calum Lind
57ac902d50 Updates to desktop file
Add magnet mimetype and tryexec key
Fix exec key to handle files and urls to conform with new desktop-entry spec
Update name, comment and category keys
2011-05-16 22:14:43 +01:00
Calum Lind
05578e0c75 Fix LP Bug #779074 - TypeError in on_key_press_event(): cannot concatenate 'str' and 'NoneType' 2011-05-12 18:14:10 +01:00
Damien Churchill
a0d4141afd fix unrequired requests 2011-05-07 13:19:41 +01:00
Damien Churchill
493d0ac690 fix a bug when the host_id doesn't exist 2011-05-07 11:51:47 +01:00
Damien Churchill
fe9fe7977c update changelog 2011-05-07 00:03:27 +01:00
Damien Churchill
e579a78d26 apply patch from #1742 2011-05-07 00:02:20 +01:00
Damien Churchill
bf96475840 update changelog 2011-05-07 00:00:18 +01:00
Damien Churchill
93c49495b2 apply patch from #1548 2011-05-06 23:59:31 +01:00
Damien Churchill
54ae8a4482 update changelog 2011-05-06 23:44:19 +01:00
Damien Churchill
d658c8fe47 fix #1537 editing trackers list, trackers have to be reselected 2011-05-06 23:43:40 +01:00
Damien Churchill
58134925a2 update changelog 2011-05-06 23:25:05 +01:00
Damien Churchill
244583ef97 Fix #1333 Peer list doesn't update automatically 2011-05-06 23:24:00 +01:00
Damien Churchill
0b821640bb fix #1481 file uploads from behind a reverse proxy 2011-05-06 22:38:55 +01:00
Damien Churchill
612ed4123f fix #1323 filter panels not scrollable 2011-05-06 22:32:46 +01:00
Damien Churchill
91b9eac075 update changelog 2011-05-06 22:23:12 +01:00
Damien Churchill
5be93cd5d8 Fix #1268, Torrent errors not displayed in webui 2011-05-06 22:22:29 +01:00
Damien Churchill
816f3ff6d2 update changelog 2011-05-06 22:09:05 +01:00
Damien Churchill
2e62140d2c fix issue #1567, js from plugins not working with different base setting 2011-05-06 22:08:59 +01:00
Damien Churchill
2381b1ae28 update changelog 2011-05-06 22:03:18 +01:00
Damien Churchill
6a131f021e fix issue #1799 2011-05-06 22:00:47 +01:00
Damien Churchill
871d9ac4b0 apply patch from #1562 2011-05-06 19:14:26 +01:00
Damien Churchill
0d665d772d fix the widths on the input boxes, whitespace changes too 2011-05-06 19:02:54 +01:00
Damien Churchill
aef2a83f25 fix the path given by the set-cookie header 2011-05-03 19:05:04 +01:00
Pedro Algarvio
e6cd4d17ee Fix #1278 by keeping references.
Conflicts:

	deluge/ui/gtkui/menubar.py
2011-04-28 10:44:18 +01:00
John Garland
b9c49f27fa Include gif pixmaps in the package data 2011-04-09 22:34:23 +10:00
Damien Churchill
e2118b6bb2 Merge branch '1.3-stable' of git.deluge-torrent.org:deluge into 1.3-stable 2011-03-28 16:51:34 +01:00
Damien Churchill
d7ba74f01d split the auto_add_trackers textfield otherwise it breaks the label plugin 2011-03-28 16:50:47 +01:00
John Garland
bc9abc8bc9 Fix libtorrent not compiling with boost libs 1.46 2011-03-26 17:34:56 +11:00
John Garland
00ad550a52 Improve autoadd filename matching (fixes #1614) 2011-03-26 17:34:44 +11:00
Andrew Resch
884bfd777e Apply patch from #1581 to add an option to enable the app indicator
interface
2011-03-22 17:16:03 -07:00
John Garland
e7db1b285f Fix indentation on Changelog 2011-03-09 00:56:04 +11:00
John Garland
ee3a17bf37 Update ChangeLog for previous commits 2011-03-09 00:51:33 +11:00
John Garland
292ffb35ac Handle redirection when adding a torrent by url 2011-03-09 00:37:35 +11:00
John Garland
fd458fbe64 Handle partial downloads due to incorrect headers (fixes #1517) 2011-03-09 00:05:07 +11:00
Andrew Resch
b9fdb5a65f Update translation template files 2011-02-19 11:25:00 -08:00
Calum Lind
36f92231a6 Updated Changelog 2011-02-15 17:37:50 +00:00
Damien Churchill
6cb584d53d update changelog 2011-02-15 12:57:09 +00:00
Damien Churchill
2eb1a51f6b make the edit trackers window resizable 2011-02-15 12:54:25 +00:00
Damien Churchill
84804d37cc fix scrolling on the edit trackers window 2011-02-15 12:50:38 +00:00
Calum Lind
1da7a518b5 Fixes for gtk-ui translations 2011-02-14 23:39:16 +00:00
Calum Lind
808d9bfba8 Fix translate issue for Trackers tree in sidebar 2011-02-14 23:39:02 +00:00
Calum Lind
53b4a06fd1 Fix: os.join created root path in Remove_Empty_Folder if variable 'folder' had a leading slash 2011-02-14 23:37:33 +00:00
Calum Lind
4490cd371a Sidebar: Enabled strings for translation and added icons to Trackers filter 2011-02-11 21:48:49 +00:00
Calum Lind
7d36a4fa51 Fix #1527 - Converting unicode to unicode error in move_storage 2011-02-11 21:48:41 +00:00
Calum Lind
6f844a86d2 Fix Create Torrent Dialog Box - Some buttons raise Type Error if no row selected 2011-02-11 21:48:35 +00:00
Calum Lind
03689a805b Fix #1510 - Cannot create a torrent with only non-zero tier trackers 2011-02-11 21:48:28 +00:00
Calum Lind
1d0857964e Fix #1513: Unhandled Twisted Error in test_listen_port 2011-02-11 21:48:20 +00:00
Calum Lind
fd3a33af03 #1514 - Indicator Applet Patch 2011-02-09 19:14:33 +00:00
Calum Lind
2354eeca7b Fix #690 - Renaming folders does not remove old empty folders 2011-02-08 19:34:16 +00:00
Calum Lind
ca0003a7af Catch a possible DivByZero error when moving folders around in fileview tab 2011-02-08 17:38:03 +00:00
Calum Lind
2c615e468b Fix #1336 - Uneeded Horizontal Scrollbar shows in Files&Peers Tab 2011-02-08 17:37:53 +00:00
Calum Lind
3794773e95 Fix #1248 - Deluge-console unicode support on redirected stdout 2011-02-08 17:01:37 +00:00
wyrm
1731fd641b Fix #1506 - max speed not restored on a yellow->green transition 2011-02-08 05:00:25 +00:00
Calum Lind
c379b6c3b2 Fix #755 - Can't set listen_ports through console UI 2011-02-05 01:08:37 +00:00
Calum Lind
e1896d2ace Fix #1450 Trailing white space in paths 2011-02-05 01:08:36 +00:00
Calum Lind
5f168f3a25 Fix #1500 - Console crashes on command longer than terminal width. This error is raised if the cursor is off screen and is supressed with try-except 2011-02-05 01:08:33 +00:00
Calum Lind
8346b4bb77 Fix #1282 - Text for AutoManaged changed to 'On/Off' and localized 2011-02-05 01:08:31 +00:00
Calum Lind
39bbe76436 Updated help text for deluge-console on Windows 2011-02-05 01:08:27 +00:00
Calum Lind
3bd28208d1 Fix for deluge-console adding torrent files in Windows 2011-02-05 01:08:26 +00:00
Chad Miller
ffebfb9cdf Fix #1508 - TypeError in cell_data_queue() could not convert argument to correct param type 2011-02-05 01:08:24 +00:00
Calum Lind
93091fbe23 Fix #1373, #1386 - Creating and moving non-ascii folder names in MS Windows 2011-02-05 01:08:11 +00:00
geoffk
efd2762255 Fix #1507 - Temporary file race condition in core/core.py:add_torrent_url 2011-02-05 01:08:04 +00:00
alderz
4870d34a52 #1494 - Add Downloaded and Uploaded columns to torrent view 2011-02-05 01:06:26 +00:00
Motiejus Jakštys
26410ca9c1 Apply patch from #1194 2011-02-04 19:49:54 +00:00
Andrew Resch
c1477e45cb Fix typo 2011-01-27 11:18:40 -08:00
Andrew Resch
25e58bc8a2 Fix #1498: Use os.path.normpath on new_folder to remove any double slashes or other problems that could be in the string 2011-01-27 11:11:28 -08:00
Andrew Resch
4d2a0b1856 Fix #1484: trying to access the screen object when not using interactive mode 2011-01-16 15:58:50 -08:00
Damien Churchill
82fbbad385 fix bug #1355 2010-12-12 00:02:41 +00:00
Damien Churchill
29a306e378 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-12-01 10:21:56 +00:00
Damien Churchill
5cfe3b5601 fix a bug that can occur when upgrading 1.1 config files 2010-12-01 10:21:26 +00:00
Calum
3f458e46dd Fix #1283 Consistent icons and add localization to file priorities
Signed-off-by: John Garland <johnnybg+deluge@gmail.com>
2010-11-11 14:02:21 +11:00
Damien Churchill
1067eb7f98 rebuild the compressed javascript 2010-11-01 09:15:19 +00:00
Damien Churchill
dca27a4cf9 update the build file to include the spinnerfieldfix file 2010-11-01 09:15:14 +00:00
Andrew Resch
b0ceae8d28 Fix copying scripts 2010-10-31 10:50:51 -07:00
Andrew Resch
dc0bf3bc88 Update versions and changelog 2010-10-31 10:15:02 -07:00
Damien Churchill
3b9d7ff9c3 remove the convert conf script that won't actually work anymore 2010-10-31 14:35:12 +00:00
Damien Churchill
a165d5d746 fix a silly bug 2010-10-31 10:13:22 +00:00
Damien Churchill
cc02ebea6a Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-10-31 09:18:36 +00:00
Damien Churchill
41ffee5d8a change entry_points to a dictionary and split it up into console and gui scripts 2010-10-31 09:16:18 +00:00
Damien Churchill
14a89b3f8a don't depend on being executed from a specific directory 2010-10-29 10:09:15 +01:00
John Garland
6f0c2af58a Fix up Changelog (entry was in wrong section) 2010-10-25 09:59:06 +11:00
Damien Churchill
84cccabf19 update changelog 2010-10-24 23:44:40 +01:00
Damien Churchill
7fb483adde fix a bug in the MultiOptionsManager that didn't fire the right arguments in the initial event fire 2010-10-24 23:42:29 +01:00
Damien Churchill
28ce7a70a0 apply patch from #1377 2010-10-24 13:30:39 +01:00
Damien Churchill
14565977fa include a file that fixes the SpinnerField onBlur method (no idea why it is set to emptyFn) 2010-10-23 22:22:00 +01:00
Damien Churchill
e4420ef354 fix the path to the loading gif (not that its actually used) 2010-10-23 21:24:05 +01:00
John Garland
02ad0b93ab Fix hang on quit 2010-10-23 01:14:48 +11:00
Andrew Resch
6d2a001635 Fix #1373 use of cyrllic paths 2010-10-16 12:56:29 -07:00
Andrew Resch
2a3eb0578c Fix #1349 force a theme style with expander-size = 15 to show entries in the sidebar properly. 2010-10-15 19:31:36 -07:00
Andrew Resch
60fac28217 Keep a torrent paused after a forced recheck if it was paused to start. 2010-10-10 12:34:13 -07:00
Damien Churchill
59e01e7ecf add a check to ensure that the events loop doesn't continue indefinitely 2010-10-10 19:51:50 +01:00
John Garland
4c52ee4229 Update ChangeLog for previous commit 2010-10-07 22:46:49 +11:00
Damien Churchill
8428524793 wrap client.disconnect() call with a check to see if its classic mode 2010-10-07 00:14:55 +01:00
John Garland
21c8d02d9a Update ChangeLog for previous commit 2010-10-03 19:52:33 +11:00
John Garland
0c687c7684 Make sure config value strings are utf8 encoded (fixes #1369) 2010-10-03 19:24:29 +11:00
John Garland
78f9efefd9 Move decode_string/utf8_encoded to common 2010-10-03 19:24:27 +11:00
John Garland
6b228ce31f Fix sidebar not updating (#1365) 2010-10-03 00:01:29 +10:00
John Garland
40ce4ec731 Use better attribute / method names in blocklist 2010-09-26 11:39:47 +10:00
John Garland
c029c312e4 Fix attribute error in blocklist plugin 2010-09-26 11:37:29 +10:00
John Garland
16c38cd027 Set locale to the user's default settings in the gtkui 2010-09-20 02:44:18 +10:00
John Garland
e23a6b852a Organise latest changes into appropriate sections 2010-09-19 20:59:27 +10:00
Andrew Resch
90e4de54e9 Do not include unnecessary dlls in windows build 2010-09-18 16:03:21 -07:00
Andrew Resch
c1505bea3a Update versions 2010-09-18 11:31:31 -07:00
John Garland
6235e832fe include missing theme images 2010-09-18 00:48:22 +10:00
Damien Churchill
a71f14c47e include the .order files 2010-09-16 09:23:35 -07:00
Damien Churchill
ed3b23b0fc add all the other scripts to package_data 2010-09-16 09:23:19 -07:00
Andrew Resch
6402634ec1 Update win32 build files 2010-09-14 11:48:05 -07:00
Andrew Resch
3e68733cfd More clean-up of setup.py 2010-09-14 11:40:41 -07:00
Andrew Resch
f847a7dc4e Remove the custom 'install' class and include_package_data 2010-09-14 11:40:34 -07:00
Andrew Resch
c7954c20eb Fix preference page index when removing a preference page 2010-09-13 18:22:08 -07:00
Andrew Resch
dc7ed11601 Update ChangeLog 2010-09-13 16:11:57 -07:00
Chase Sterling
d898def9ec Fix bugs with unicode torrents in AutoAdd plugin. 2010-09-13 02:22:18 -04:00
Chase Sterling
3e2f6c4060 Fix bug in AutoAdd plugin where watchdirs would not display in gtkui when first enabled. 2010-09-13 02:22:17 -04:00
John Garland
321a22a6f0 Increase max piece size to 8 MiB in create torrent dialog (closes #1358) 2010-09-13 08:53:19 +10:00
Chase Sterling
b4774af2f3 Fix VersionSplit behavior when comparing to a dev version. 2010-09-11 05:39:40 -04:00
Chase Sterling
d0fd709c74 AutoAdd plugin can now recover when one of the watchfolders has an unhandled exception. 2010-09-03 22:30:24 -04:00
Chase Sterling
e24212b3f8 Fix "adjustment with non-zero page size" deprication warning in autoadd plugin. 2010-09-03 22:28:41 -04:00
Andrew Resch
f8f72af6dc Add TorrentFileCompleted event. 2010-09-03 17:11:57 -07:00
Andrew Resch
b9caa4eeeb Fix issue when adding torrents without a 'session'. This can happen
when a plugin adds a torrent, like how the AutoAdd plugin works.  The
user that adds this torrent will be an empty string.
2010-09-03 14:29:36 -07:00
John Garland
6c3b216b40 Use a temp filename with add_torrent_url 2010-08-31 00:11:58 +10:00
John Garland
eaad867885 Update get_free_space test 2010-08-31 00:11:54 +10:00
Chase Sterling
f6b9f67df8 Fix error in last commit. 2010-08-26 02:33:24 -04:00
Chase Sterling
24fe3f7fd5 Ensure preferencesmanager only changes intended libtorrent session settings. 2010-08-26 02:23:40 -04:00
Chase Sterling
da2fb41a3a Fix scheduler so that it keeps current state, even after global settings change. 2010-08-26 01:39:40 -04:00
Chase Sterling
f8d7f22167 Ignore global stop ratio related settings in logic, so per torrent ones are used. 2010-08-24 22:47:24 -04:00
Chase Sterling
b75abc70e5 Add max active downloading and seeding options to scheduler. 2010-08-24 00:58:28 -04:00
Andrew Resch
2d821bd79a Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-08-23 17:35:31 -07:00
Andrew Resch
12d9a7a5bd Fix key error after enabling a plugin that introduces a new status key 2010-08-23 17:35:19 -07:00
Chase Sterling
c118fa36a9 Moved xdg import so it is not called on Windows, where it is unused. fixes #1343 2010-08-22 15:38:22 -04:00
Chase Sterling
82c91cdc51 AutoAdd plugin changes
adds queue to top option
adds ability to append extension instead of deleting torrent once added
2010-08-22 00:01:58 -04:00
Andrew Resch
5501094214 Fix unhandled exception when adding a torrent to the session 2010-08-21 12:54:19 -07:00
Andrew Resch
b41aa808be Fix issue where the save_timer is cancelled when it's not active 2010-08-21 12:54:13 -07:00
Andrew Resch
b9336889f5 Update version 2010-08-20 14:20:51 -07:00
Andrew Resch
995f5387eb Update windows files 2010-08-20 14:19:42 -07:00
Andrew Resch
38958d3c4f Update ChangeLog 2010-08-20 14:15:21 -07:00
John Garland
b45e019f08 Fix man deluged not showing '-u' on its own line 2010-08-20 01:16:09 +10:00
Andrew Resch
d93fcf6eea Fix #1341 issue where Config would try to cancel the save_timer when it is None. 2010-08-18 12:32:11 -07:00
Andrew Resch
a2d75a5274 Add cache expiry check by key update times to fix issue where some status updates would not return
correctly if they were done < cache_time from the previous status request
2010-08-18 12:17:31 -07:00
Andrew Resch
8797c3ce1b Add additional test for get_torrents_status and fix the other one to properly invalidate the cache
time from startup before proceeding
2010-08-18 12:17:23 -07:00
Andrew Resch
79749cca03 Add test to demonstrate flaw in SessionProxy design. Need to keep track of update times for each
status key individually to fix this.
2010-08-18 11:05:21 -07:00
Damien Churchill
5fd8628761 fix the script resource on windows 2010-08-14 17:38:31 +01:00
Damien Churchill
0e80b3ea0a add the apple iOS bookmark icons from #1339 2010-08-14 16:15:18 +01:00
Damien Churchill
aa61d33ee2 Merge branch '1.3-stable' of deluge-torrent.org:deluge into 1.3-stable 2010-08-14 16:06:00 +01:00
Damien Churchill
13f29a77dd fix the system.listMethods json call when running in classic mode 2010-08-14 16:05:41 +01:00
Andrew Resch
97453d1411 Add test suite for SessionProxy 2010-08-10 09:58:28 -07:00
Andrew Resch
62d02091b3 Fix getting a torrent's status with an empty key list to return all the
torrent's status keys instead of an empty dict
2010-08-06 17:26:23 -07:00
Damien Churchill
161ad0ff0d use the get_libtorrent.sh script to get libtorrent if it is missing 2010-07-22 21:13:27 +01:00
Damien Churchill
7f323ec0fc add libtorrent fetch script 2010-07-22 18:17:51 +01:00
Damien Churchill
05aebbb575 remove the libtorrent submodule 2010-07-22 18:04:49 +01:00
Damien Churchill
de85e1dcdc a couple of fixes to stop the webui crashing when running within the gtkui 2010-07-18 23:11:02 +01:00
John Garland
1ce480ff23 Only use an icon if it passes some sanity checks 2010-07-17 17:13:15 +10:00
Andrew Resch
007a9912d2 Use a blank icon when the tracker icon downloaded isn't a proper image 2010-07-15 19:17:48 -07:00
Andrew Resch
d793b9e6b8 Attempt to create a move_storage destination path if it doesn't exist 2010-07-15 10:50:15 -07:00
Andrew Resch
72ec926c1a Do not attempt to move a torrents storage if the destination path does
not exist
2010-07-12 14:45:51 -07:00
Andrew Resch
0d431ae7db Try to import system rencode before deluge.rencode to allow the use of the new rencode library at: http://code.google.com/p/rencode/ 2010-07-08 16:39:53 -07:00
Andrew Resch
f1e0e3be15 Add logging the user when a torrent is added or removed 2010-07-05 21:10:16 -07:00
John Garland
e8bf5eb592 Fix ChangeLog 2010-07-04 02:13:31 +10:00
John Garland
d9a2c4db72 Fix uncaught exception when closing deluge in classic mode 2010-07-02 02:43:07 +10:00
John Garland
8fb7277a82 Fix typo 2010-07-02 02:41:30 +10:00
Damien Churchill
35128cf18f more improvements to the shift select 2010-07-01 14:21:37 +01:00
Damien Churchill
6ff1da2391 fix select 'upwards' 2010-07-01 14:08:20 +01:00
Damien Churchill
4614188c62 update changelog 2010-07-01 13:46:27 +01:00
Damien Churchill
80297b8e45 allow for shift selecting in tree grids 2010-07-01 13:45:22 +01:00
Andrew Resch
9173a9cfdd Update Changelog 2010-06-22 18:26:43 -07:00
Andrew Resch
571d1079f6 Fix #1302 an uncaught exception in an state_changed event handler in SessionProxy was preventing the
TorrentManager's stop method from properly saving all the resume data.
2010-06-22 18:25:50 -07:00
Andrew Resch
0497c407e1 Always look for -mt boost libraries first 2010-06-18 09:51:50 -07:00
Damien Churchill
8b58c960f3 fix typo 2010-06-12 22:48:00 +01:00
Damien Churchill
b615ebe1b8 change bits to bytes, thanks to charles 2010-06-11 15:59:33 +01:00
John Garland
3ed8279219 Fix typo in label plugin - thanks konti 2010-06-11 00:51:46 +10:00
John Garland
f2944bdeef Handle os.remove failing on windows 2010-06-08 03:20:48 +10:00
John Garland
0fcd90ee2c Python independent version of previous commit 2010-06-08 01:57:13 +10:00
John Garland
26460808e7 Fix console ui not liking paths with backslashes on windows (#1293) 2010-06-08 01:30:10 +10:00
John Garland
7aba1af0b2 Print a more informative error message if the torrent file doesn't exist 2010-06-08 01:26:49 +10:00
John Garland
4d2b7df49d Fix execute plugin only executing last event (#1306) 2010-06-08 00:20:07 +10:00
John Garland
bd775d0d40 Only encode if necessary 2010-06-07 20:18:37 +10:00
John Garland
7fb3c3c04c Fix unicode support in console ui (#1307) 2010-06-07 20:18:35 +10:00
Damien Churchill
19c27ee8c5 Add some debug logging statements 2010-06-04 18:05:27 +01:00
Damien Churchill
d69b8e1099 Fix an error in the key 2010-06-04 17:37:45 +01:00
Damien Churchill
88daf82cb0 Fix saving the correct event name 2010-06-04 16:37:50 +01:00
Damien Churchill
99c1a61383 Save the execute config after adding/removing/saving commands 2010-06-04 16:30:51 +01:00
John Garland
2e55769c18 Fix typo in execute plugin 2010-05-20 00:06:18 +10:00
John Garland
259d2633e7 Fix man deluged not showing '-d' on its own line 2010-05-16 22:32:59 +10:00
John Garland
8e5aab660c Fix remote save path dialog not disappearing after creating a torrent 2010-05-16 18:13:34 +10:00
John Garland
fc96e9d02c Fix only being able to click "remote path" once when creating a torrent 2010-05-16 18:13:31 +10:00
John Garland
821d403a6c Fix deluged crashing on windows when logfile's directory doesn't exist 2010-05-16 13:12:51 +10:00
John Garland
5e0d988ef0 Revert "Fix trac wiki turning CamelCase words into broken links"
This reverts commit 925ac42f7c67a0b4b0c68bab3f402aeb62cbda6a.
2010-05-11 23:46:48 +10:00
John Garland
925ac42f7c Fix trac wiki turning CamelCase words into broken links 2010-05-11 23:29:02 +10:00
John Garland
1ac72b81b6 Update email address and copyright 2010-05-11 03:52:17 +10:00
John Garland
3417caf1d2 Fix label plugin not remembering newly created labels 2010-05-09 17:52:29 +10:00
John Garland
1bcfc91c35 Remove unused code from label plugin 2010-05-09 17:52:25 +10:00
John Garland
6ee0e5b6be Update docstrings to use names from previous commit 2010-05-09 17:07:11 +10:00
John Garland
58a74202e1 Use better names for TrackerIcons' args 2010-05-09 17:01:47 +10:00
John Garland
a4c6f4e8c9 Return the noIcon for empty strings as well 2010-05-09 16:44:12 +10:00
John Garland
60f3d32de7 Raise IconsError instead of IndexError (fixes infinite looping) 2010-05-09 16:36:54 +10:00
Andrew Resch
b3eed8a1f0 Add test for tracker_icons for when requesting an icon for host that is "". This test results in an infinite loop. 2010-05-08 20:10:12 -07:00
Andrew Resch
37137d9b54 Return 0 in get_free_space if the download_location is invalid 2010-05-08 20:09:57 -07:00
Andrew Resch
4fb14b581d Use previously defined host variable instead of getting the tracker host from the TreeModel 2010-05-08 20:09:49 -07:00
Andrew Resch
98da4d0291 Do not request a tracker icon if the host is "" 2010-05-08 20:09:37 -07:00
Andrew Resch
f0c06f4bc5 Update Changelog 2010-05-08 11:50:19 -07:00
Damien Churchill
63d701305c rebuild deluge-all and ext-extensions 2010-05-08 16:19:40 +01:00
Damien Churchill
99396afa0c update the build files for deluge-all and ext-extensions 2010-05-08 16:19:40 +01:00
Damien Churchill
6231dbd1ca fix the null comparison 2010-05-08 16:19:40 +01:00
Damien Churchill
8f021c7f06 set the baseCls for the add label form panel to x-plain 2010-05-08 16:19:40 +01:00
John Garland
6bb4559d18 Make host_to_url support redirection and add another test 2010-05-08 16:26:08 +10:00
John Garland
7c9eea0361 Try favicon.ico if there's a HTMLParseError 2010-05-08 15:50:57 +10:00
John Garland
15247507d4 Fix relative redirecting in blocklist plugin 2010-05-06 23:31:25 +10:00
Andrew Resch
10de8d5475 Remove plugins that aren't release ready 2010-05-05 17:48:04 -07:00
Damien Churchill
e304c1f719 update the ChangeLog 2010-05-05 23:03:19 +01:00
Andrew Resch
48d3e89d84 Update windows build files 2010-05-05 15:01:52 -07:00
Andrew Resch
44f9e17a09 Update version
Update ChangeLog
2010-05-05 14:52:18 -07:00
234 changed files with 254551 additions and 158154 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "libtorrent"]
path = libtorrent
url = git://deluge-torrent.org/libtorrent

138
ChangeLog
View File

@ -1,4 +1,120 @@
=== Deluge 1.3.0 (In Development) ===
=== Deluge 1.3.2 (24 May 2011) ===
==== Core ====
* #1527: Fix Converting unicode to unicode error in move_storage
* #1373: Fix creating and moving non-ascii folder names in MS Windows
* #1507: Fix temporary file race condition in core/core.py:add_torrent_url
* Fix a bug that can occur when upgrading 1.1 config files
* #1517: Fix isohunt urls not loading
* Handle redirection when adding a torrent by url
* #1614: Fix autoadd matching a directory called "torrent"
* #1742: Fix failure in Event handler prevents further emissions
==== GtkUI ====
* #1514: Added Indicator Applet
* #1494: Add torrent columns Downloaded and Uploaded
* #1308: Add torrent column Seeds/Peers ratio
* #1646: Add torrent columns for per torrent upload and download speed limits
* Add missing icons for Trackers filter
* Fix inconsistancies in the text for translation
* #1510: Fix cannot create a torrent with only non-zero tier trackers
* #1513: Fix unhandled Twisted Error in test_listen_port
* #690: Fix renaming folders does not remove old empty folders
* #1336: Fix uneeded horizontal scrollbar showing in Files & Peers Tab
* #1508: Fix TypeError in cell_data_queue() could not convert argument to correct param type
* #1498: Fix double slashes appearing when renaming
* #1283: Fix consistent icons for Files tab
* #1282: Text for AutoManaged changed to 'On/Off' and localized
* Fix Up/Down buttons in Edit Trackers Dialog
* Add Key Shortcuts for main menu functions
==== WebUI ====
* #1194: Fix infinite login prompt in web ui through reverse proxy
* #1355: Fix slow changing states in webUI
* #1536: Fix Edit Trackers window not scrolling and not being resizable
* #1799: Fix Missing textbox for "Move completed" in torrent options
* #1562: Fix Javascript error in Web UI when re-opening preferences
* #1567: Fix js from plugins does not work with different 'base' setting
* #1268: Fix torrent errors not displayed in webui
* #1323: Fix filter panels not scrollable
* Fix file uploads from behind a reverse proxy.
* #1333: Fix peer list doesn't update automatically
* #1537: Fix editing trackers list, trackers have to be reselected
==== ConsoleUI ====
* #755: Fix can't set listen_ports through console UI
* #1500: Fix Console crashes on command longer than terminal width
* #1248: Fix deluge-console unicode support on redirected stdout
* Fix for deluge-console not adding torrent files on MS Windows
* #1450: Fix trailing white space in paths
* Misc: Updated help text for deluge-console on MS Windows
* #1484: Fix trying to access the screen object when not using interactive mode
* #1548: Fix cli argument processing
* #1856: Add --sort option to info command
* #1857: Add seeding_time, active_time and tracker_status to info command
==== Scheduler ====
* #1506: Fix max speed not restored on a yellow->green transition
=== Deluge 1.3.1 (31 October 2010) ===
==== Core ====
* #1369: Fix non-ascii config folders not working in windows
==== GtkUI ====
* #1365: Fix sidebar not updating show/hide trackers
* #1247: Fix hang on quit
==== WebUI ====
* #1364: Fix preferences not saving when the web ui plugin is enabled in classic mode
* #1377: Fix bug when enabling plugins
* #1370: Fix issues with preferences
* #1312: Fix deluge-web using 100% CPU
=== Deluge 1.3.0 (18 September 2010) ===
==== Core ====
* Fix issue where the save_timer is cancelled when it's not active
* Fix unhandled exception when adding a torrent to the session
* Moved xdg import so it is not called on Windows, where it is unused. fixes #1343
* Fix key error after enabling a plugin that introduces a new status key
* Ignore global stop ratio related settings in logic, so per torrent ones are used.
* Ensure preferencesmanager only changes intended libtorrent session settings.
* Fix issue when adding torrents without a 'session'. This can happen when a plugin adds a torrent, like how the AutoAdd plugin works. The user that adds this torrent will be an empty string.
* Add TorrentFileCompleted event
==== GtkUI ====
* Increase max piece size to 8 MiB in create torrent dialog (closes #1358)
==== Scheduler ====
* Add max active downloading and seeding options to scheduler.
* Fix scheduler so that it keeps current state, even after global settings change.
==== AutoAdd ====
* AutoAdd plugin can now recover when one of the watchfolders has an unhandled exception.
* Fix bug in AutoAdd plugin where watchdirs would not display in gtkui when first enabled.
* Fix bugs with unicode torrents in AutoAdd plugin.
=== Deluge 1.3.0-rc2 (20 August 2010) ===
==== Core ====
* Fix tracker_icons failing on windows
* Fix #1302 an uncaught exception in an state_changed event handler in SessionProxy was preventing the TorrentManager's stop method from properly saving all the resume data
* Fix issue with SessionProxy not updating the torrent status correctly when get_torrent_status calls take place within the cache_expiry time
==== ConsoleUI ====
* #1307: Fix not being able to add torrents
* #1293: Fix not being able to add paths that contain backslashes
==== GtkUI ====
* Fix uncaught exception when closing deluge in classic mode
==== Execute ====
* #1306: Fix always executing last event
==== Label ====
* Fix being able to remove labels in web ui
==== WebUI ====
* #1319: Fix shift selecting in file trees
=== Deluge 1.3.0-rc1 (08 May 2010) ===
==== Core ====
* Implement #1063 option to delete torrent file copy on torrent removal - patch from Ghent
* Implement #457 progress bars for folders
@ -7,15 +123,33 @@
* #1112: Fix renaming files in add torrent dialog
* #1247: Fix deluge-gtk from hanging on shutdown
* #995: Rewrote tracker_icons
* Add AutoAdd plugin
* Add Notifications plugin
==== GtkUI ====
* Use new SessionProxy class for caching torrent status client-side
* Use torrent status diffs to reduce RPC traffic
==== Blocklist ====
* Implement local blocklist support
* #861: Pause transfers until blocklist is imported
* Fix redirection not working with relative paths
==== Execute ====
* Fix running commands with the TorrentAdded event
* Fix the web interface
==== Label ====
* Fix the web interface (#733)
==== Web ====
* Migrate to ExtJS 3.1
* Add gzip compression of HTTP data to the server
* Improve the efficiency of the TorrentGrid
* Improve the efficiency of the TorrentGrid with lots of torrents (#1026)
* Add a base parameter to allow reverse proxying (#1076)
* Fix showing all the peers in the details tab (#1054)
* Fix uploading torrent files in Opera or IE (#1087)
* Complete IE support
=== Deluge 1.2.0 - "Bursting like an infected kidney" (10 January 2010) ===
==== Core ====

View File

@ -7,6 +7,7 @@
* setuptools
* gettext
* pyxdg
* chardet
* geoip-database (optional)
* libtorrent >= 0.14, or build the included version
@ -16,9 +17,6 @@
* openssl
* zlib
=== UIs ===
* chardet
=== Gtk ===
* python-notify (libnotify python wrapper)
* pygame

1
create_potfiles_in.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
import os
# Paths to exclude

View File

@ -41,6 +41,7 @@ import time
import subprocess
import platform
import sys
import chardet
try:
import json
@ -63,7 +64,6 @@ if not hasattr(json, "dumps"):
json.load = load
import pkg_resources
import xdg, xdg.BaseDirectory
import gettext
import locale
@ -150,6 +150,7 @@ def get_default_config_dir(filename=None):
else:
return os.path.join(os.environ.get("APPDATA"), "deluge")
else:
import xdg.BaseDirectory
if filename:
return os.path.join(xdg.BaseDirectory.save_config_path("deluge"), filename)
else:
@ -474,7 +475,7 @@ def free_space(path):
sectors, bytes, free, total = map(long, win32file.GetDiskFreeSpace(path))
return (free * sectors * bytes)
else:
disk_data = os.statvfs(path)
disk_data = os.statvfs(path.encode("utf8"))
block_size = disk_data.f_bsize
return disk_data.f_bavail * block_size
@ -560,6 +561,41 @@ def xml_encode(string):
string = string.replace(char, escape)
return string
def decode_string(s, encoding="utf8"):
"""
Decodes a string and re-encodes it in utf8. If it cannot decode using
`:param:encoding` then it will try to detect the string encoding and
decode it.
:param s: string to decode
:type s: string
:keyword encoding: the encoding to use in the decoding
:type encoding: string
"""
try:
s = s.decode(encoding).encode("utf8", "ignore")
except UnicodeDecodeError:
s = s.decode(chardet.detect(s)["encoding"], "ignore").encode("utf8", "ignore")
return s
def utf8_encoded(s):
"""
Returns a utf8 encoded string of s
:param s: (unicode) string to (re-)encode
:type s: basestring
:returns: a utf8 encoded string of s
:rtype: str
"""
if isinstance(s, str):
s = decode_string(s)
elif isinstance(s, unicode):
s = s.encode("utf8", "ignore")
return s
class VersionSplit(object):
"""
Used for comparing version numbers.
@ -570,13 +606,15 @@ class VersionSplit(object):
"""
def __init__(self, ver):
ver = ver.lower()
vs = ver.split("_") if "_" in ver else ver.split("-")
vs = ver.replace("_", "-").split("-")
self.version = [int(x) for x in vs[0].split(".")]
self.suffix = None
self.dev = False
if len(vs) > 1:
for s in ("rc", "alpha", "beta", "dev"):
if s in vs[1][:len(s)]:
self.suffix = vs[1]
if vs[1].startswith(("rc", "alpha", "beta")):
self.suffix = vs[1]
if vs[-1] == 'dev':
self.dev = True
def __cmp__(self, ver):
"""
@ -587,19 +625,8 @@ class VersionSplit(object):
"""
if self.version > ver.version or (self.suffix and self.suffix[:3] == "dev"):
return 1
if self.version < ver.version:
return -1
if self.version == ver.version:
if self.suffix == ver.suffix:
return 0
if self.suffix is None:
return 1
if ver.suffix is None:
return -1
if self.suffix < ver.suffix:
return -1
if self.suffix > ver.suffix:
return 1
# If there is no suffix we use z because we want final
# to appear after alpha, beta, and rc alphabetically.
v1 = [self.version, self.suffix or 'z', self.dev]
v2 = [ver.version, ver.suffix or 'z', ver.dev]
return cmp(v1, v2)

View File

@ -45,9 +45,9 @@ The format of the config file is two json encoded dicts:
<version dict>
<content dict>
The version dict contains two keys: file and format. The format version is
controlled by the Config class. It should only be changed when anything below
it is changed directly by the Config class. An example of this would be if we
The version dict contains two keys: file and format. The format version is
controlled by the Config class. It should only be changed when anything below
it is changed directly by the Config class. An example of this would be if we
changed the serializer for the content to something different.
The config file version is changed by the 'owner' of the config file. This is
@ -93,13 +93,13 @@ def prop(func):
def find_json_objects(s):
"""
Find json objects in a string.
:param s: the string to find json objects in
:type s: string
:returns: a list of tuples containing start and end locations of json objects in the string `s`
:rtype: [(start, end), ...]
"""
objects = []
opens = 0
@ -119,8 +119,8 @@ def find_json_objects(s):
start = index + offset + 1
return objects
class Config(object):
"""
This class is used to access/create/modify config files
@ -146,7 +146,8 @@ class Config(object):
self._save_timer = None
if defaults:
self.__config = dict(defaults)
for key, value in defaults.iteritems():
self.set_item(key, value)
# Load the config from file in the config_dir
if config_dir:
@ -187,6 +188,10 @@ what is currently in the config and it could not convert the value
5
"""
if isinstance(value, basestring):
value = deluge.common.utf8_encoded(value)
if not self.__config.has_key(key):
self.__config[key] = value
log.debug("Setting '%s' to %s of %s", key, value, type(value))
@ -200,7 +205,10 @@ what is currently in the config and it could not convert the value
if value is not None and oldtype != type(None) and oldtype != newtype:
try:
value = oldtype(value)
if oldtype == unicode:
value = oldtype(value, "utf8")
else:
value = oldtype(value)
except ValueError:
log.warning("Type '%s' invalid for '%s'", newtype, key)
raise
@ -250,7 +258,13 @@ what is currently in the config and it could not convert the value
5
"""
return self.__config[key]
if isinstance(self.__config[key], str):
try:
return self.__config[key].decode("utf8")
except UnicodeDecodeError:
return self.__config[key]
else:
return self.__config[key]
def register_change_callback(self, callback):
"""
@ -348,21 +362,21 @@ what is currently in the config and it could not convert the value
return
objects = find_json_objects(data)
if not len(objects):
# No json objects found, try depickling it
try:
self.__config.update(pickle.loads(data))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
elif len(objects) == 1:
start, end = objects[0]
try:
self.__config.update(json.loads(data[start:end]))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
elif len(objects) == 2:
try:
start, end = objects[0]
@ -371,8 +385,8 @@ what is currently in the config and it could not convert the value
self.__config.update(json.loads(data[start:end]))
except Exception, e:
log.exception(e)
log.warning("Unable to load config file: %s", filename)
log.warning("Unable to load config file: %s", filename)
log.debug("Config %s version: %s.%s loaded: %s", filename,
self.__version["format"], self.__version["file"], self.__config)
@ -396,26 +410,24 @@ what is currently in the config and it could not convert the value
version = json.loads(data[start:end])
start, end = objects[1]
loaded_data = json.loads(data[start:end])
if self.__config == loaded_data and self.__version == version:
# The config has not changed so lets just return
self._save_timer.cancel()
return
except Exception, e:
log.warning("Unable to open config file: %s", filename)
if self._save_timer and self._save_timer.active():
self._save_timer.cancel()
return True
except IOError, e:
log.warning("Unable to open config file: %s because: %s", filename, e)
# Save the new config and make sure it's written to disk
try:
log.debug("Saving new config file %s", filename + ".new")
f = open(filename + ".new", "wb")
json.dump(self.__version, f, indent=2)
json.dump(self.__version, f, indent=2)
json.dump(self.__config, f, indent=2)
f.flush()
os.fsync(f.fileno())
f.close()
except Exception, e:
except IOError, e:
log.error("Error writing new config file: %s", e)
return False

View File

@ -74,12 +74,12 @@ class AutoAdd(component.Component):
return
for filename in os.listdir(self.config["autoadd_location"]):
if filename.split(".")[-1] == "torrent":
try:
filepath = os.path.join(self.config["autoadd_location"], filename)
except UnicodeDecodeError, e:
log.error("Unable to auto add torrent due to inproper filename encoding: %s", e)
continue
try:
filepath = os.path.join(self.config["autoadd_location"], filename)
except UnicodeDecodeError, e:
log.error("Unable to auto add torrent due to improper filename encoding: %s", e)
continue
if os.path.isfile(filepath) and filename.endswith(".torrent"):
try:
filedump = self.load_torrent(filepath)
except (RuntimeError, Exception), e:

View File

@ -42,11 +42,14 @@ import shutil
import threading
import pkg_resources
import warnings
import tempfile
from urlparse import urljoin
from twisted.internet import reactor, defer
from twisted.internet.task import LoopingCall
import twisted.web.client
import twisted.web.error
from deluge.httpdownloader import download_file
from deluge.log import LOG as log
@ -236,20 +239,35 @@ class Core(component.Component):
:returns: a Deferred which returns the torrent_id as a str or None
"""
log.info("Attempting to add url %s", url)
def on_get_file(filename):
def on_download_success(filename):
# We got the file, so add it to the session
data = open(filename, "rb").read()
f = open(filename, "rb")
data = f.read()
f.close()
try:
os.remove(filename)
except Exception, e:
log.warning("Couldn't remove temp file: %s", e)
return self.add_torrent_file(filename, base64.encodestring(data), options)
def on_get_file_error(failure):
# Log the error and pass the failure onto the client
log.error("Error occured downloading torrent from %s", url)
log.error("Reason: %s", failure.getErrorMessage())
return failure
def on_download_fail(failure):
if failure.check(twisted.web.error.PageRedirect):
new_url = urljoin(url, failure.getErrorMessage().split(" to ")[1])
result = download_file(new_url, tempfile.mkstemp()[1], headers=headers, force_filename=True)
result.addCallbacks(on_download_success, on_download_fail)
elif failure.check(twisted.web.client.PartialDownloadError):
result = download_file(url, tempfile.mkstemp()[1], headers=headers, force_filename=True,
allow_compression=False)
result.addCallbacks(on_download_success, on_download_fail)
else:
# Log the error and pass the failure onto the client
log.error("Error occured downloading torrent from %s", url)
log.error("Reason: %s", failure.getErrorMessage())
result = failure
return result
d = download_file(url, url.split("/")[-1], headers=headers)
d.addCallback(on_get_file)
d.addErrback(on_get_file_error)
d = download_file(url, tempfile.mkstemp()[1], headers=headers, force_filename=True)
d.addCallbacks(on_download_success, on_download_fail)
return d
@export
@ -747,7 +765,11 @@ class Core(component.Component):
def on_get_page(result):
return bool(int(result))
def logError(failure):
log.warning("Error testing listen port: %s", failure)
d.addCallback(on_get_page)
d.addErrback(logError)
return d
@ -768,7 +790,10 @@ class Core(component.Component):
"""
if not path:
path = self.config["download_location"]
return deluge.common.free_space(path)
try:
return deluge.common.free_space(path)
except InvalidPathError:
return 0
@export
def get_libtorrent_version(self):

View File

@ -53,7 +53,10 @@ class EventManager(component.Component):
if event.name in self.handlers:
for handler in self.handlers[event.name]:
#log.debug("Running handler %s for event %s with args: %s", event.name, handler, event.args)
handler(*event.args)
try:
handler(*event.args)
except:
log.error("Event handler %s failed in %s", event.name, handler)
def register_event_handler(self, event, handler):
"""

View File

@ -196,9 +196,8 @@ class FilterManager(component.Component):
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
items["tracker_host"]["All"] = len(torrent_ids)
if "tracker_host" in items:
items["tracker_host"]["All"] = len(torrent_ids)
items["tracker_host"]["Error"] = len(tracker_error_filter(torrent_ids, ("Error",)))
if "state" in tree_keys and not show_zero_hits:

View File

@ -152,7 +152,6 @@ class PreferencesManager(component.Component):
def start(self):
self.core = component.get("Core")
self.session = component.get("Core").session
self.settings = component.get("Core").settings
# Register set functions in the Config
self.config.register_set_function("torrentfiles_location",
@ -233,6 +232,11 @@ class PreferencesManager(component.Component):
self.new_release_timer.stop()
# Config set functions
def session_set_setting(self, key, value):
settings = self.session.settings()
setattr(settings, key, value)
self.session.set_settings(settings)
def _on_config_value_change(self, key, value):
component.get("EventManager").emit(ConfigValueChangedEvent(key, value))
@ -274,8 +278,7 @@ class PreferencesManager(component.Component):
def _on_set_outgoing_ports(self, key, value):
if not self.config["random_outgoing_ports"]:
log.debug("outgoing port range set to %s-%s", value[0], value[1])
self.settings.outgoing_ports = value[0], value[1]
self.session.set_settings(self.settings)
self.session_set_setting("outgoing_ports", (value[0], value[1]))
def _on_set_random_outgoing_ports(self, key, value):
if value:
@ -284,13 +287,11 @@ class PreferencesManager(component.Component):
def _on_set_peer_tos(self, key, value):
log.debug("setting peer_tos to: %s", value)
try:
self.settings.peer_tos = chr(int(value, 16))
self.session_set_setting("peer_tos", chr(int(value, 16)))
except ValueError, e:
log.debug("Invalid tos byte: %s", e)
return
self.session.set_settings(self.settings)
def _on_set_dht(self, key, value):
log.debug("dht value set to %s", value)
state_file = deluge.configmanager.get_config_dir("dht.state")
@ -387,51 +388,39 @@ class PreferencesManager(component.Component):
self.session.set_max_half_open_connections(value)
def _on_set_max_connections_per_second(self, key, value):
self.settings.connection_speed = value
self.session.set_settings(self.settings)
self.session_set_setting("connection_speed", value)
def _on_ignore_limits_on_local_network(self, key, value):
self.settings.ignore_limits_on_local_network = value
self.session.set_settings(self.settings)
self.session_set_setting("ignore_limits_on_local_network", value)
def _on_set_share_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.share_ratio_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("share_ratio_limit", value)
def _on_set_seed_time_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.seed_time_ratio_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("seed_time_ratio_limit", value)
def _on_set_seed_time_limit(self, key, value):
log.debug("%s set to %s..", key, value)
# This value is stored in minutes in deluge, but libtorrent wants seconds
self.settings.seed_time_limit = int(value * 60)
self.session.set_settings(self.settings)
self.session_set_setting("seed_time_limit", int(value * 60))
def _on_set_max_active_downloading(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_downloads: %s", self.settings.active_downloads)
self.settings.active_downloads = value
self.session.set_settings(self.settings)
self.session_set_setting("active_downloads", value)
def _on_set_max_active_seeding(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_seeds: %s", self.settings.active_seeds)
self.settings.active_seeds = value
self.session.set_settings(self.settings)
self.session_set_setting("active_seeds", value)
def _on_set_max_active_limit(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_limit: %s", self.settings.active_limit)
self.settings.active_limit = value
self.session.set_settings(self.settings)
self.session_set_setting("active_limit", value)
def _on_set_dont_count_slow_torrents(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.dont_count_slow_torrents = value
self.session.set_settings(self.settings)
self.session_set_setting("dont_count_slow_torrents", value)
def _on_send_info(self, key, value):
log.debug("Sending anonymous stats..")
@ -491,8 +480,7 @@ class PreferencesManager(component.Component):
def _on_rate_limit_ip_overhead(self, key, value):
log.debug("%s: %s", key, value)
self.settings.rate_limit_ip_overhead = value
self.session.set_settings(self.settings)
self.session_set_setting("rate_limit_ip_overhead", value)
def _on_geoip_db_location(self, key, value):
log.debug("%s: %s", key, value)
@ -514,10 +502,8 @@ class PreferencesManager(component.Component):
def _on_cache_size(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_size = value
self.session.set_settings(self.settings)
self.session_set_setting("cache_size", value)
def _on_cache_expiry(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_expiry = value
self.session.set_settings(self.settings)
self.session_set_setting("cache_expiry", value)

View File

@ -47,7 +47,11 @@ from twisted.internet import ssl, reactor, defer
from OpenSSL import crypto, SSL
from types import FunctionType
import deluge.rencode as rencode
try:
import rencode
except ImportError:
import deluge.rencode as rencode
from deluge.log import LOG as log
import deluge.component as component
@ -90,13 +94,13 @@ def export(auth_level=AUTH_LEVEL_DEFAULT):
def format_request(call):
"""
Format the RPCRequest message for debug printing
:param call: the request
:type call: a RPCRequest
:returns: a formatted string for printing
:rtype: str
"""
try:
s = call[1] + "("
@ -111,7 +115,7 @@ def format_request(call):
return "UnicodeEncodeError, call: %s" % call
else:
return s
class DelugeError(Exception):
pass
@ -139,7 +143,7 @@ class DelugeRPCProtocol(Protocol):
"""
This method is called whenever data is received from a client. The
only message that a client sends to the server is a RPC Request message.
If the RPC Request message is valid, then the method is called in
If the RPC Request message is valid, then the method is called in
:meth:`dispatch`.
:param data: the data from the client. It should be a zlib compressed
@ -187,7 +191,7 @@ class DelugeRPCProtocol(Protocol):
:param data: the object that is to be sent to the client. This should
be one of the RPC message types.
:type data: object
"""
self.transport.write(zlib.compress(rencode.dumps(data)))
@ -254,7 +258,7 @@ class DelugeRPCProtocol(Protocol):
try:
ret = component.get("AuthManager").authorize(*args, **kwargs)
if ret:
self.factory.authorized_sessions[self.transport.sessionno] = ret
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
self.factory.session_protocols[self.transport.sessionno] = self
except Exception, e:
sendError()
@ -283,7 +287,7 @@ class DelugeRPCProtocol(Protocol):
if method in self.factory.methods and self.transport.sessionno in self.factory.authorized_sessions:
try:
method_auth_requirement = self.factory.methods[method]._rpcserver_auth_level
auth_level = self.factory.authorized_sessions[self.transport.sessionno]
auth_level = self.factory.authorized_sessions[self.transport.sessionno][0]
if auth_level < method_auth_requirement:
# This session is not allowed to call this method
log.debug("Session %s is trying to call a method it is not authorized to call!", self.transport.sessionno)
@ -338,7 +342,7 @@ class RPCServer(component.Component):
self.factory = Factory()
self.factory.protocol = DelugeRPCProtocol
self.factory.session_id = -1
# Holds the registered methods
self.factory.methods = {}
# Holds the session_ids and auth levels
@ -417,26 +421,41 @@ class RPCServer(component.Component):
def get_session_id(self):
"""
Returns the session id of the current RPC.
:returns: the session id, this will be -1 if no connections have been made
:rtype: int
"""
return self.factory.session_id
def get_session_user(self):
"""
Returns the username calling the current RPC.
:returns: the username of the user calling the current RPC
:rtype: string
"""
session_id = self.get_session_id()
if session_id > -1 and session_id in self.factory.authorized_sessions:
return self.factory.authorized_sessions[session_id][1]
else:
# No connections made yet
return ""
def is_session_valid(self, session_id):
"""
Checks if the session is still valid, eg, if the client is still connected.
:param session_id: the session id
:type session_id: int
:returns: True if the session is valid
:rtype: bool
"""
return session_id in self.factory.authorized_sessions
def emit_event(self, event):
"""
Emits the event to interested clients.

View File

@ -82,7 +82,7 @@ class Torrent(object):
self.config = ConfigManager("core.conf")
self.rpcserver = component.get("RPCServer")
# This dict holds previous status dicts returned for this torrent
# We use this to return dicts that only contain changes from the previous
# {session_id: status_dict, ...}
@ -90,7 +90,7 @@ class Torrent(object):
from twisted.internet.task import LoopingCall
self.prev_status_cleanup_loop = LoopingCall(self.cleanup_prev_status)
self.prev_status_cleanup_loop.start(10)
# Set the libtorrent handle
self.handle = handle
# Set the torrent_id for this torrent
@ -179,6 +179,11 @@ class Torrent(object):
else:
self.time_added = time.time()
# Keep track if we're forcing a recheck of the torrent so that we can
# repause it after its done if necessary
self.forcing_recheck = False
self.forcing_recheck_paused = False
log.debug("Torrent object created.")
## Options methods ##
@ -393,12 +398,11 @@ class Torrent(object):
else:
status = self.status
if self.is_finished and (self.options["stop_at_ratio"] or self.config["stop_seed_at_ratio"]):
if self.is_finished and self.options["stop_at_ratio"]:
# We're a seed, so calculate the time to the 'stop_share_ratio'
if not status.upload_payload_rate:
return 0
stop_ratio = self.config["stop_seed_ratio"] if self.config["stop_seed_at_ratio"] else self.options["stop_ratio"]
stop_ratio = self.options["stop_ratio"]
return ((status.all_time_download * stop_ratio) - status.all_time_upload) / status.upload_payload_rate
left = status.total_wanted - status.total_done
@ -543,18 +547,18 @@ class Torrent(object):
def get_status(self, keys, diff=False):
"""
Returns the status of the torrent based on the keys provided
:param keys: the keys to get the status on
:type keys: list of str
:param diff: if True, will return a diff of the changes since the last
call to get_status based on the session_id
:type diff: bool
:returns: a dictionary of the status keys and their values
:rtype: dict
"""
# Create the full dictionary
self.status = self.handle.status()
if self.handle.has_metadata():
@ -568,6 +572,13 @@ class Torrent(object):
if distributed_copies < 0:
distributed_copies = 0.0
# Calculate the seeds:peers ratio
if self.status.num_incomplete == 0:
# Use -1.0 to signify infinity
seeds_peers_ratio = -1.0
else:
seeds_peers_ratio = self.status.num_complete / float(self.status.num_incomplete)
#if you add a key here->add it to core.py STATUS_KEYS too.
full_status = {
"active_time": self.status.active_time,
@ -586,6 +597,8 @@ class Torrent(object):
"message": self.statusmsg,
"move_on_completed_path": self.options["move_completed_path"],
"move_on_completed": self.options["move_completed"],
"move_completed_path": self.options["move_completed_path"],
"move_completed": self.options["move_completed"],
"next_announce": self.status.next_announce.seconds,
"num_peers": self.status.num_peers - self.status.num_seeds,
"num_seeds": self.status.num_seeds,
@ -595,6 +608,7 @@ class Torrent(object):
"remove_at_ratio": self.options["remove_at_ratio"],
"save_path": self.options["download_location"],
"seeding_time": self.status.seeding_time,
"seeds_peers_ratio": seeds_peers_ratio,
"seed_rank": self.status.seed_rank,
"state": self.state,
"stop_at_ratio": self.options["stop_at_ratio"],
@ -699,7 +713,7 @@ class Torrent(object):
status_dict[key] = full_status[key]
elif key in fns:
status_dict[key] = fns[key]()
session_id = self.rpcserver.get_session_id()
if diff:
if session_id in self.prev_status:
@ -711,7 +725,7 @@ class Torrent(object):
status_diff[key] = value
else:
status_diff[key] = value
self.prev_status[session_id] = status_dict
return status_diff
@ -761,13 +775,8 @@ class Torrent(object):
if self.handle.is_finished():
# If the torrent has already reached it's 'stop_seed_ratio' then do not do anything
if self.config["stop_seed_at_ratio"] or self.options["stop_at_ratio"]:
if self.options["stop_at_ratio"]:
ratio = self.options["stop_ratio"]
else:
ratio = self.config["stop_seed_ratio"]
if self.get_ratio() >= ratio:
if self.options["stop_at_ratio"]:
if self.get_ratio() >= self.options["stop_ratio"]:
#XXX: This should just be returned in the RPC Response, no event
#self.signals.emit_event("torrent_resume_at_stop_ratio")
return
@ -794,8 +803,25 @@ class Torrent(object):
def move_storage(self, dest):
"""Move a torrent's storage location"""
# Attempt to convert utf8 path to unicode
# Note: Inconsistent encoding for 'dest', needs future investigation
try:
self.handle.move_storage(dest.encode("utf8"))
dest_u = unicode(dest, "utf-8")
except TypeError:
# String is already unicode
dest_u = dest
if not os.path.exists(dest_u):
try:
# Try to make the destination path if it doesn't exist
os.makedirs(dest_u)
except IOError, e:
log.exception(e)
log.error("Could not move storage for torrent %s since %s does not exist and could not create the directory.", self.torrent_id, dest_u)
return False
try:
self.handle.move_storage(dest_u)
except:
return False
@ -857,12 +883,15 @@ class Torrent(object):
def force_recheck(self):
"""Forces a recheck of the torrents pieces"""
paused = self.handle.is_paused()
try:
self.handle.force_recheck()
self.handle.resume()
except Exception, e:
log.debug("Unable to force recheck: %s", e)
return False
self.forcing_recheck = True
self.forcing_recheck_paused = paused
return True
def rename_files(self, filenames):
@ -879,8 +908,8 @@ class Torrent(object):
log.error("Attempting to rename a folder with an invalid folder name: %s", new_folder)
return
if new_folder[-1:] != "/":
new_folder += "/"
# Make sure the new folder path is nice and has a trailing slash
new_folder = os.path.normpath(new_folder) + "/"
wait_on_folder = (folder, new_folder, [])
for f in self.get_files():
@ -889,12 +918,12 @@ class Torrent(object):
wait_on_folder[2].append(f["index"])
self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1).encode("utf-8"))
self.waiting_on_folder_rename.append(wait_on_folder)
def cleanup_prev_status(self):
"""
This method gets called to check the validity of the keys in the prev_status
dict. If the key is no longer valid, the dict will be deleted.
"""
for key in self.prev_status.keys():
if not self.rpcserver.is_session_valid(key):

View File

@ -41,22 +41,21 @@ import os
import time
import shutil
import operator
import re
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from deluge._libtorrent import lt
from deluge.event import *
from deluge.error import *
import deluge.common
import deluge.component as component
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.torrent import Torrent
from deluge.core.torrent import TorrentOptions
import deluge.core.oldstateupgrader
from deluge.ui.common import utf8_encoded
from deluge.common import utf8_encoded
from deluge.log import LOG as log
@ -192,6 +191,8 @@ class TorrentManager(component.Component):
self.on_alert_metadata_received)
self.alerts.register_handler("file_error_alert",
self.on_alert_file_error)
self.alerts.register_handler("file_completed_alert",
self.on_alert_file_completed)
def start(self):
# Get the pluginmanager reference
@ -256,16 +257,13 @@ class TorrentManager(component.Component):
def update(self):
for torrent_id, torrent in self.torrents.items():
if self.config["stop_seed_at_ratio"] or torrent.options["stop_at_ratio"] and torrent.state not in ("Checking", "Allocating", "Paused", "Queued"):
if torrent.options["stop_at_ratio"] and torrent.state not in ("Checking", "Allocating", "Paused", "Queued"):
# If the global setting is set, but the per-torrent isn't.. Just skip to the next torrent
# This is so that a user can turn-off the stop at ratio option on a per-torrent basis
if self.config["stop_seed_at_ratio"] and not torrent.options["stop_at_ratio"]:
if not torrent.options["stop_at_ratio"]:
continue
stop_ratio = self.config["stop_seed_ratio"]
if torrent.options["stop_at_ratio"]:
stop_ratio = torrent.options["stop_ratio"]
if torrent.get_ratio() >= stop_ratio and torrent.is_finished:
if self.config["remove_seed_at_ratio"] or torrent.options["remove_at_ratio"]:
if torrent.get_ratio() >= torrent.options["stop_ratio"] and torrent.is_finished:
if torrent.options["remove_at_ratio"]:
self.remove(torrent_id)
break
if not torrent.handle.is_paused():
@ -476,6 +474,7 @@ class TorrentManager(component.Component):
# Emit the torrent_added signal
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id))
log.info("Torrent %s added by user: %s", torrent.get_status(["name"])["name"], component.get("RPCServer").get_session_user())
return torrent.torrent_id
def load_torrent(self, torrent_id):
@ -515,6 +514,8 @@ class TorrentManager(component.Component):
if torrent_id not in self.torrents:
raise InvalidTorrentError("torrent_id not in session")
torrent_name = self.torrents[torrent_id].get_status(["name"])["name"]
# Emit the signal to the clients
component.get("EventManager").emit(PreTorrentRemovedEvent(torrent_id))
@ -562,7 +563,7 @@ class TorrentManager(component.Component):
# Emit the signal to the clients
component.get("EventManager").emit(TorrentRemovedEvent(torrent_id))
log.info("Torrent %s removed by user: %s", torrent_name, component.get("RPCServer").get_session_user())
return True
def load_state(self):
@ -731,6 +732,38 @@ class TorrentManager(component.Component):
except IOError:
log.warning("Error trying to save fastresume file")
def remove_empty_folders(self, torrent_id, folder):
"""
Recursively removes folders but only if they are empty.
Cleans up after libtorrent folder renames.
"""
if torrent_id not in self.torrents:
raise InvalidTorrentError("torrent_id is not in session")
info = self.torrents[torrent_id].get_status(['save_path'])
# Regex removes leading slashes that causes join function to ignore save_path
folder_full_path = os.path.join(info['save_path'], re.sub("^/*", "", folder))
folder_full_path = os.path.normpath(folder_full_path)
try:
if not os.listdir(folder_full_path):
os.removedirs(folder_full_path)
log.debug("Removed Empty Folder %s", folder_full_path)
else:
for root, dirs, files in os.walk(folder_full_path, topdown=False):
for name in dirs:
try:
os.removedirs(os.path.join(root, name))
log.debug("Removed Empty Folder %s", os.path.join(root, name))
except OSError as (errno, strerror):
if errno == 39:
# Error raised if folder is not empty
log.debug("%s", strerror)
except OSError as (errno, strerror):
log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno)
def queue_top(self, torrent_id):
"""Queue torrent to top"""
if self.torrents[torrent_id].get_queue_position() == 0:
@ -850,6 +883,13 @@ class TorrentManager(component.Component):
except:
return
# Check to see if we're forcing a recheck and set it back to paused
# if necessary
if torrent.forcing_recheck:
torrent.forcing_recheck = False
if torrent.forcing_recheck_paused:
torrent.handle.pause()
# Set the torrent state
torrent.update_state()
@ -985,6 +1025,8 @@ class TorrentManager(component.Component):
if len(wait_on_folder[2]) == 1:
# This is the last alert we were waiting for, time to send signal
component.get("EventManager").emit(TorrentFolderRenamedEvent(torrent_id, wait_on_folder[0], wait_on_folder[1]))
# Empty folders are removed after libtorrent folder renames
self.remove_empty_folders(torrent_id, wait_on_folder[0])
del torrent.waiting_on_folder_rename[i]
self.save_resume_data((torrent_id,))
break
@ -1012,3 +1054,9 @@ class TorrentManager(component.Component):
except:
return
torrent.update_state()
def on_alert_file_completed(self, alert):
log.debug("file_completed_alert: %s", alert.message())
torrent_id = str(alert.handle.info_hash())
component.get("EventManager").emit(
TorrentFileCompletedEvent(torrent_id, alert.index))

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

View File

@ -1,12 +1,14 @@
[Desktop Entry]
Version=1.0
Name=Deluge BitTorrent Client
GenericName=Bittorrent Client
Comment=Transfer files using the Bittorrent protocol
Exec=deluge-gtk
Name=Deluge
GenericName=BitTorrent Client
X-GNOME-FullName=Deluge BitTorrent Client
Comment=Download and share files over BitTorrent
TryExec=deluge-gtk
Exec=deluge-gtk %U
Icon=deluge
Terminal=false
Type=Application
Categories=Network;
Categories=Network;FileTransfer;P2P;GTK
StartupNotify=true
MimeType=application/x-bittorrent;
MimeType=application/x-bittorrent;x-scheme-handler/magnet;

View File

@ -164,6 +164,22 @@ class TorrentResumedEvent(DelugeEvent):
"""
self._args = [torrent_id]
class TorrentFileCompletedEvent(DelugeEvent):
"""
Emitted when a file completes.
This will only work with libtorrent 0.15 or greater.
"""
def __init__(self, torrent_id, index):
"""
:param torrent_id: the torrent_id
:type torrent_id: string
:param index: the file index
:type index: int
"""
self._args = [torrent_id, index]
class NewVersionAvailableEvent(DelugeEvent):
"""
Emitted when a more recent version of Deluge is available.

View File

@ -1,290 +1,190 @@
deluge/configmanager.py
deluge/httpdownloader.py
deluge/error.py
deluge/bencode.py
deluge/component.py
deluge/log.py
deluge/metafile.py
deluge/config.py
deluge/main.py
deluge/__init__.py
deluge/common.py
deluge/bencode.py
deluge/pluginmanagerbase.py
deluge/event.py
deluge/rencode.py
deluge/decorators.py
deluge/_libtorrent.py
deluge/__rpcapi.py
deluge/__init__.py
deluge/pluginmanagerbase.py
deluge/config.py
deluge/common.py
deluge/maketorrent.py
deluge/rencode.py
deluge/metafile.py
deluge/_libtorrent.py
deluge/preferencesmanager.py
deluge/httpdownloader.py
deluge/__rpcapi.py
deluge/event.py
deluge/configmanager.py
deluge/core/daemon.py
deluge/core/pluginmanager.py
deluge/core/rpcserver.py
deluge/core/authmanager.py
deluge/core/autoadd.py
deluge/core/eventmanager.py
deluge/core/__init__.py
deluge/core/oldstateupgrader.py
deluge/core/alertmanager.py
deluge/core/preferencesmanager.py
deluge/core/torrent.py
deluge/core/filtermanager.py
deluge/core/core.py
deluge/core/torrentmanager.py
deluge/ui/countries.py
deluge/ui/client.py
deluge/ui/Win32IconImagePlugin.py
deluge/ui/ui.py
deluge/ui/sessionproxy.py
deluge/ui/__init__.py
deluge/ui/common.py
deluge/ui/tracker_icons.py
deluge/ui/session.py
deluge/ui/coreconfig.py
deluge/ui/gtkui/pluginmanager.py
deluge/ui/gtkui/systemtray.py
deluge/ui/gtkui/queuedtorrents.py
deluge/ui/gtkui/aboutdialog.py
deluge/ui/gtkui/files_tab.py
deluge/ui/gtkui/torrentdetails.py
deluge/ui/gtkui/dialogs.py
deluge/ui/gtkui/gtkui.py
deluge/ui/gtkui/toolbar.py
deluge/ui/gtkui/options_tab.py
deluge/ui/gtkui/notification.py
deluge/ui/gtkui/status_tab.py
deluge/ui/gtkui/details_tab.py
deluge/ui/gtkui/listview.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/__init__.py
deluge/ui/gtkui/filtertreeview.py
deluge/ui/gtkui/edittrackersdialog.py
deluge/ui/gtkui/sidebar.py
deluge/ui/gtkui/statusbar.py
deluge/ui/gtkui/removetorrentdialog.py
deluge/ui/gtkui/peers_tab.py
deluge/ui/gtkui/ipcinterface.py
deluge/ui/gtkui/new_release_dialog.py
deluge/ui/gtkui/common.py
deluge/ui/gtkui/menubar.py
deluge/ui/gtkui/connectionmanager.py
deluge/ui/gtkui/createtorrentdialog.py
deluge/ui/gtkui/preferences.py
deluge/ui/gtkui/mainwindow.py
deluge/ui/gtkui/preferences_old.py
deluge/ui/gtkui/torrentview.py
deluge/ui/gtkui/glade/create_torrent_dialog.glade
deluge/ui/gtkui/glade/filtertree_menu.glade
deluge/ui/gtkui/glade/dgtkpopups.glade
deluge/ui/gtkui/glade/torrent_menu.glade
deluge/ui/gtkui/glade/main_window.glade
deluge/ui/gtkui/glade/remove_torrent_dialog.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/preferences_dialog.glade
deluge/ui/gtkui/glade/edit_trackers.glade
deluge/ui/gtkui/glade/move_storage_dialog.glade
deluge/ui/gtkui/glade/connection_manager.glade
deluge/ui/gtkui/glade/add_torrent_dialog.glade
deluge/ui/gtkui/glade/queuedtorrents.glade
deluge/ui/console/colors.py
deluge/ui/console/statusbars.py
deluge/ui/console/main.py
deluge/ui/console/eventlog.py
deluge/ui/console/__init__.py
deluge/ui/console/screen.py
deluge/ui/console/commands/add.py
deluge/ui/console/commands/info.py
deluge/ui/console/commands/halt.py
deluge/ui/console/commands/__init__.py
deluge/ui/console/commands/connect.py
deluge/ui/console/commands/resume.py
deluge/ui/console/commands/config.py
deluge/ui/console/commands/quit.py
deluge/ui/console/commands/rm.py
deluge/ui/console/commands/help.py
deluge/ui/console/commands/pause.py
deluge/ui/console/commands/recheck.py
deluge/ui/console/commands/cache.py
deluge/ui/console/commands/plugin.py
deluge/ui/console/commands/debug.py
deluge/ui/web/pluginmanager.py
deluge/ui/web/web.py
deluge/ui/web/gen_gettext.py
deluge/ui/web/__init__.py
deluge/ui/web/server.py
deluge/ui/web/common.py
deluge/ui/web/auth.py
deluge/ui/web/json_api.py
deluge/plugins/__init__.py
deluge/plugins/pluginbase.py
deluge/plugins/init.py
deluge/plugins/feeder/setup.py
deluge/plugins/feeder/feeder/__init__.py
deluge/plugins/feeder/feeder/core.py
deluge/plugins/feeder/feeder/webui.py
deluge/plugins/feeder/build/lib/feeder/__init__.py
deluge/plugins/feeder/build/lib/feeder/core.py
deluge/plugins/feeder/build/lib/feeder/webui.py
deluge/plugins/label/setup.py
deluge/plugins/label/label/test.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/core.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/gtkui/__init__.py
deluge/plugins/label/label/gtkui/label_config.py
deluge/plugins/label/label/gtkui/submenu.py
deluge/plugins/label/label/gtkui/sidebar_menu.py
deluge/plugins/label/label/data/label_pref.glade
deluge/plugins/label/label/data/label_options.glade
deluge/plugins/label/build/lib/label/test.py
deluge/plugins/label/build/lib/label/__init__.py
deluge/plugins/label/build/lib/label/core.py
deluge/plugins/label/build/lib/label/webui.py
deluge/plugins/label/build/lib/label/gtkui/__init__.py
deluge/plugins/label/build/lib/label/gtkui/label_config.py
deluge/plugins/label/build/lib/label/gtkui/submenu.py
deluge/plugins/label/build/lib/label/gtkui/sidebar_menu.py
deluge/plugins/label/build/lib/label/data/label_pref.glade
deluge/plugins/label/build/lib/label/data/label_options.glade
deluge/plugins/autoadd/setup.py
deluge/plugins/autoadd/autoadd/__init__.py
deluge/plugins/autoadd/autoadd/common.py
deluge/plugins/autoadd/autoadd/core.py
deluge/plugins/autoadd/autoadd/webui.py
deluge/plugins/autoadd/autoadd/gtkui.py
deluge/plugins/autoadd/autoadd/data/config.glade
deluge/plugins/autoadd/autoadd/data/autoadd_options.glade
deluge/plugins/autoadd/build/lib/autoadd/__init__.py
deluge/plugins/autoadd/build/lib/autoadd/common.py
deluge/plugins/autoadd/build/lib/autoadd/core.py
deluge/plugins/autoadd/build/lib/autoadd/webui.py
deluge/plugins/autoadd/build/lib/autoadd/gtkui.py
deluge/plugins/autoadd/build/lib/autoadd/data/config.glade
deluge/plugins/autoadd/build/lib/autoadd/data/autoadd_options.glade
deluge/plugins/scheduler/setup.py
deluge/plugins/scheduler/scheduler/__init__.py
deluge/plugins/scheduler/scheduler/common.py
deluge/plugins/scheduler/scheduler/core.py
deluge/plugins/scheduler/scheduler/webui.py
deluge/plugins/scheduler/scheduler/gtkui.py
deluge/plugins/scheduler/build/lib/scheduler/__init__.py
deluge/plugins/scheduler/build/lib/scheduler/common.py
deluge/plugins/scheduler/build/lib/scheduler/core.py
deluge/plugins/scheduler/build/lib/scheduler/webui.py
deluge/plugins/scheduler/build/lib/scheduler/gtkui.py
deluge/plugins/notifications/setup.py
deluge/plugins/notifications/notifications/test.py
deluge/plugins/notifications/notifications/gtkui.py
deluge/plugins/notifications/notifications/__init__.py
deluge/plugins/notifications/notifications/common.py
deluge/plugins/notifications/notifications/core.py
deluge/plugins/notifications/notifications/webui.py
deluge/plugins/notifications/notifications/gtkui.py
deluge/plugins/notifications/notifications/core.py
deluge/plugins/notifications/notifications/test.py
deluge/plugins/notifications/notifications/data/config.glade
deluge/plugins/notifications/build/lib/notifications/test.py
deluge/plugins/notifications/build/lib/notifications/__init__.py
deluge/plugins/notifications/build/lib/notifications/common.py
deluge/plugins/notifications/build/lib/notifications/core.py
deluge/plugins/notifications/build/lib/notifications/webui.py
deluge/plugins/notifications/build/lib/notifications/gtkui.py
deluge/plugins/notifications/build/lib/notifications/data/config.glade
deluge/plugins/stats/setup.py
deluge/plugins/stats/stats/test_total.py
deluge/plugins/stats/stats/test.py
deluge/plugins/stats/stats/__init__.py
deluge/plugins/stats/stats/graph.py
deluge/plugins/stats/stats/common.py
deluge/plugins/stats/stats/core.py
deluge/plugins/stats/stats/webui.py
deluge/plugins/stats/stats/gtkui.py
deluge/plugins/stats/stats/data/tabs.glade
deluge/plugins/stats/stats/data/config.glade
deluge/plugins/stats/build/lib/stats/test_total.py
deluge/plugins/stats/build/lib/stats/test.py
deluge/plugins/stats/build/lib/stats/__init__.py
deluge/plugins/stats/build/lib/stats/graph.py
deluge/plugins/stats/build/lib/stats/common.py
deluge/plugins/stats/build/lib/stats/core.py
deluge/plugins/stats/build/lib/stats/webui.py
deluge/plugins/stats/build/lib/stats/gtkui.py
deluge/plugins/stats/build/lib/stats/data/tabs.glade
deluge/plugins/stats/build/lib/stats/data/config.glade
deluge/plugins/freespace/build/lib/freespace/gtkui.py
deluge/plugins/freespace/build/lib/freespace/__init__.py
deluge/plugins/freespace/build/lib/freespace/common.py
deluge/plugins/freespace/build/lib/freespace/webui.py
deluge/plugins/freespace/build/lib/freespace/core.py
deluge/plugins/freespace/build/lib/freespace/data/config.glade
deluge/plugins/webui/setup.py
deluge/plugins/webui/webui/gtkui.py
deluge/plugins/webui/webui/__init__.py
deluge/plugins/webui/webui/common.py
deluge/plugins/webui/webui/core.py
deluge/plugins/webui/webui/gtkui.py
deluge/plugins/webui/webui/data/config.glade
deluge/plugins/webui/build/lib/webui/__init__.py
deluge/plugins/webui/build/lib/webui/common.py
deluge/plugins/webui/build/lib/webui/core.py
deluge/plugins/webui/build/lib/webui/gtkui.py
deluge/plugins/webui/build/lib/webui/data/config.glade
deluge/plugins/extractor/setup.py
deluge/plugins/extractor/build/lib/extractor/__init__.py
deluge/plugins/extractor/build/lib/extractor/common.py
deluge/plugins/extractor/build/lib/extractor/core.py
deluge/plugins/extractor/build/lib/extractor/webui.py
deluge/plugins/extractor/build/lib/extractor/gtkui.py
deluge/plugins/extractor/build/lib/extractor/data/extractor_prefs.glade
deluge/plugins/extractor/extractor/__init__.py
deluge/plugins/extractor/extractor/common.py
deluge/plugins/extractor/extractor/core.py
deluge/plugins/extractor/extractor/webui.py
deluge/plugins/extractor/extractor/gtkui.py
deluge/plugins/extractor/extractor/data/extractor_prefs.glade
deluge/plugins/execute/setup.py
deluge/plugins/execute/build/lib/execute/__init__.py
deluge/plugins/execute/build/lib/execute/common.py
deluge/plugins/execute/build/lib/execute/core.py
deluge/plugins/execute/build/lib/execute/webui.py
deluge/plugins/execute/build/lib/execute/gtkui.py
deluge/plugins/execute/build/lib/execute/data/execute_prefs.glade
deluge/plugins/execute/execute/__init__.py
deluge/plugins/execute/execute/common.py
deluge/plugins/execute/execute/core.py
deluge/plugins/execute/execute/webui.py
deluge/plugins/execute/execute/gtkui.py
deluge/plugins/execute/execute/data/execute_prefs.glade
deluge/plugins/example/setup.py
deluge/plugins/example/build/lib/example/__init__.py
deluge/plugins/example/build/lib/example/common.py
deluge/plugins/example/build/lib/example/core.py
deluge/plugins/example/build/lib/example/webui.py
deluge/plugins/example/build/lib/example/gtkui.py
deluge/plugins/example/example/__init__.py
deluge/plugins/example/example/common.py
deluge/plugins/example/example/core.py
deluge/plugins/example/example/webui.py
deluge/plugins/example/example/gtkui.py
deluge/plugins/freespace/setup.py
deluge/plugins/freespace/build/lib/freespace/__init__.py
deluge/plugins/freespace/build/lib/freespace/common.py
deluge/plugins/freespace/build/lib/freespace/core.py
deluge/plugins/freespace/build/lib/freespace/webui.py
deluge/plugins/freespace/build/lib/freespace/gtkui.py
deluge/plugins/freespace/build/lib/freespace/data/config.glade
deluge/plugins/freespace/freespace/__init__.py
deluge/plugins/freespace/freespace/common.py
deluge/plugins/freespace/freespace/core.py
deluge/plugins/freespace/freespace/webui.py
deluge/plugins/freespace/freespace/gtkui.py
deluge/plugins/freespace/freespace/data/config.glade
deluge/plugins/autoadd/setup.py
deluge/plugins/autoadd/autoadd/gtkui.py
deluge/plugins/autoadd/autoadd/__init__.py
deluge/plugins/autoadd/autoadd/common.py
deluge/plugins/autoadd/autoadd/webui.py
deluge/plugins/autoadd/autoadd/core.py
deluge/plugins/autoadd/autoadd/data/autoadd_options.glade
deluge/plugins/autoadd/autoadd/data/config.glade
deluge/plugins/label/setup.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/core.py
deluge/plugins/label/label/test.py
deluge/plugins/label/label/gtkui/sidebar_menu.py
deluge/plugins/label/label/gtkui/submenu.py
deluge/plugins/label/label/gtkui/__init__.py
deluge/plugins/label/label/gtkui/label_config.py
deluge/plugins/label/label/data/label_options.glade
deluge/plugins/label/label/data/label_pref.glade
deluge/plugins/blocklist/setup.py
deluge/plugins/blocklist/build/lib/blocklist/peerguardian.py
deluge/plugins/blocklist/build/lib/blocklist/decompressers.py
deluge/plugins/blocklist/build/lib/blocklist/detect.py
deluge/plugins/blocklist/build/lib/blocklist/readers.py
deluge/plugins/blocklist/build/lib/blocklist/__init__.py
deluge/plugins/blocklist/build/lib/blocklist/common.py
deluge/plugins/blocklist/build/lib/blocklist/core.py
deluge/plugins/blocklist/build/lib/blocklist/webui.py
deluge/plugins/blocklist/build/lib/blocklist/gtkui.py
deluge/plugins/blocklist/build/lib/blocklist/data/blocklist_pref.glade
deluge/plugins/blocklist/blocklist/peerguardian.py
deluge/plugins/blocklist/blocklist/decompressers.py
deluge/plugins/blocklist/blocklist/detect.py
deluge/plugins/blocklist/blocklist/readers.py
deluge/plugins/blocklist/blocklist/gtkui.py
deluge/plugins/blocklist/blocklist/__init__.py
deluge/plugins/blocklist/blocklist/common.py
deluge/plugins/blocklist/blocklist/core.py
deluge/plugins/blocklist/blocklist/peerguardian.py
deluge/plugins/blocklist/blocklist/decompressers.py
deluge/plugins/blocklist/blocklist/webui.py
deluge/plugins/blocklist/blocklist/gtkui.py
deluge/plugins/blocklist/blocklist/detect.py
deluge/plugins/blocklist/blocklist/core.py
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
deluge/core/eventmanager.py
deluge/core/autoadd.py
deluge/core/authmanager.py
deluge/core/rpcserver.py
deluge/core/torrentmanager.py
deluge/core/oldstateupgrader.py
deluge/core/__init__.py
deluge/core/torrent.py
deluge/core/pluginmanager.py
deluge/core/core.py
deluge/core/daemon.py
deluge/core/alertmanager.py
deluge/core/preferencesmanager.py
deluge/core/filtermanager.py
deluge/ui/sessionproxy.py
deluge/ui/ui.py
deluge/ui/session.py
deluge/ui/tracker_icons.py
deluge/ui/__init__.py
deluge/ui/common.py
deluge/ui/Win32IconImagePlugin.py
deluge/ui/client.py
deluge/ui/countries.py
deluge/ui/coreconfig.py
deluge/ui/web/server.py
deluge/ui/web/web.py
deluge/ui/web/__init__.py
deluge/ui/web/common.py
deluge/ui/web/pluginmanager.py
deluge/ui/web/gen_gettext.py
deluge/ui/web/auth.py
deluge/ui/web/json_api.py
deluge/ui/gtkui/connectionmanager.py
deluge/ui/gtkui/torrentdetails.py
deluge/ui/gtkui/queuedtorrents.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/__init__.py
deluge/ui/gtkui/status_tab.py
deluge/ui/gtkui/preferences.py
deluge/ui/gtkui/mainwindow.py
deluge/ui/gtkui/notification.py
deluge/ui/gtkui/ipcinterface.py
deluge/ui/gtkui/createtorrentdialog.py
deluge/ui/gtkui/torrentview.py
deluge/ui/gtkui/listview.py
deluge/ui/gtkui/systemtray.py
deluge/ui/gtkui/common.py
deluge/ui/gtkui/pluginmanager.py
deluge/ui/gtkui/menubar.py
deluge/ui/gtkui/sidebar.py
deluge/ui/gtkui/statusbar.py
deluge/ui/gtkui/filtertreeview.py
deluge/ui/gtkui/new_release_dialog.py
deluge/ui/gtkui/options_tab.py
deluge/ui/gtkui/peers_tab.py
deluge/ui/gtkui/details_tab.py
deluge/ui/gtkui/files_tab.py
deluge/ui/gtkui/gtkui.py
deluge/ui/gtkui/edittrackersdialog.py
deluge/ui/gtkui/removetorrentdialog.py
deluge/ui/gtkui/toolbar.py
deluge/ui/gtkui/dialogs.py
deluge/ui/gtkui/aboutdialog.py
deluge/ui/gtkui/glade/filtertree_menu.glade
deluge/ui/gtkui/glade/main_window.glade
deluge/ui/gtkui/glade/remove_torrent_dialog.glade
deluge/ui/gtkui/glade/create_torrent_dialog.glade
deluge/ui/gtkui/glade/connection_manager.glade
deluge/ui/gtkui/glade/preferences_dialog.glade
deluge/ui/gtkui/glade/torrent_menu.glade
deluge/ui/gtkui/glade/queuedtorrents.glade
deluge/ui/gtkui/glade/move_storage_dialog.glade
deluge/ui/gtkui/glade/add_torrent_dialog.glade
deluge/ui/gtkui/glade/dgtkpopups.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/edit_trackers.glade
deluge/ui/console/colors.py
deluge/ui/console/eventlog.py
deluge/ui/console/main.py
deluge/ui/console/__init__.py
deluge/ui/console/statusbars.py
deluge/ui/console/screen.py
deluge/ui/console/commands/plugin.py
deluge/ui/console/commands/info.py
deluge/ui/console/commands/recheck.py
deluge/ui/console/commands/quit.py
deluge/ui/console/commands/connect.py
deluge/ui/console/commands/help.py
deluge/ui/console/commands/add.py
deluge/ui/console/commands/config.py
deluge/ui/console/commands/__init__.py
deluge/ui/console/commands/cache.py
deluge/ui/console/commands/debug.py
deluge/ui/console/commands/pause.py
deluge/ui/console/commands/rm.py
deluge/ui/console/commands/halt.py
deluge/ui/console/commands/resume.py
deluge/plugins/extractor/setup.py
deluge/plugins/extractor/extractor/gtkui.py
deluge/plugins/extractor/extractor/__init__.py
deluge/plugins/extractor/extractor/common.py
deluge/plugins/extractor/extractor/webui.py
deluge/plugins/extractor/extractor/core.py
deluge/plugins/extractor/extractor/data/extractor_prefs.glade
deluge/plugins/execute/setup.py
deluge/plugins/execute/execute/gtkui.py
deluge/plugins/execute/execute/__init__.py
deluge/plugins/execute/execute/common.py
deluge/plugins/execute/execute/webui.py
deluge/plugins/execute/execute/core.py
deluge/plugins/execute/execute/data/execute_prefs.glade
deluge/plugins/scheduler/setup.py
deluge/plugins/scheduler/scheduler/gtkui.py
deluge/plugins/scheduler/scheduler/__init__.py
deluge/plugins/scheduler/scheduler/common.py
deluge/plugins/scheduler/scheduler/webui.py
deluge/plugins/scheduler/scheduler/core.py

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3754
deluge/i18n/fo.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3754
deluge/i18n/lb.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3754
deluge/i18n/ml.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3763
deluge/i18n/nn.po Normal file

File diff suppressed because it is too large Load Diff

3783
deluge/i18n/oc.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3754
deluge/i18n/te.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3754
deluge/i18n/ur.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -197,6 +197,11 @@ this should be an IP address", metavar="IFACE",
write_pidfile()
# Setup the logger
try:
# Try to make the logfile's directory if it doesn't exist
os.makedirs(os.path.abspath(os.path.dirname(options.logfile)))
except:
pass
deluge.log.setupLogger(level=options.loglevel, filename=options.logfile)
from deluge.log import LOG as log

View File

@ -56,6 +56,7 @@ DEFAULT_PREFS = {
OPTIONS_AVAILABLE = { #option: builtin
"enabled":False,
"path":False,
"append_extension":False,
"abspath":False,
"download_location":True,
"max_download_speed":True,
@ -70,15 +71,14 @@ OPTIONS_AVAILABLE = { #option: builtin
"move_completed":True,
"move_completed_path":True,
"label":False,
"add_paused":True
"add_paused":True,
"queue_to_top":False
}
MAX_NUM_ATTEMPTS = 10
class AutoaddOptionsChangedEvent(DelugeEvent):
"""
Emitted when a new command is added.
"""
"""Emitted when the options for the plugin are changed."""
def __init__(self):
pass
@ -93,21 +93,20 @@ class Core(CorePluginBase):
self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS)
self.watchdirs = self.config["watchdirs"]
self.core_cfg = deluge.configmanager.ConfigManager("core.conf")
# A list of filenames
self.invalid_torrents = []
# Filename:Attempts
self.attempts = {}
# Dict of Filename:Attempts
self.invalid_torrents = {}
# Loopingcall timers for each enabled watchdir
self.update_timers = {}
# If core autoadd folder is enabled, move it to the plugin
if self.core_cfg.config.get('autoadd_enable'):
# Disable core autoadd
self.core_cfg['autoadd_enable'] = False
self.core_cfg.save()
# Check if core autoadd folder is already added in plugin
for watchdir in self.watchdirs:
if os.path.abspath(self.core_cfg['autoadd_location']) == watchdir['abspath']:
watchdir['enabled'] = True
break
else:
# didn't find core watchdir, add it
@ -125,18 +124,15 @@ class Core(CorePluginBase):
for loopingcall in self.update_timers.itervalues():
loopingcall.stop()
self.config.save()
pass
def update(self):
pass
@export()
def set_options(self, watchdir_id, options):
"""
update the options for a watch folder
"""
"""Update the options for a watch folder."""
watchdir_id = str(watchdir_id)
options = self._clean_unicode(options)
options = self._make_unicode(options)
CheckInput(watchdir_id in self.watchdirs , _("Watch folder does not exist."))
if options.has_key('path'):
options['abspath'] = os.path.abspath(options['path'])
@ -146,7 +142,7 @@ class Core(CorePluginBase):
raise Exception("Path is already being watched.")
for key in options.keys():
if not key in OPTIONS_AVAILABLE:
if not key in [key+'_toggle' for key in OPTIONS_AVAILABLE.iterkeys()]:
if not key in [key2+'_toggle' for key2 in OPTIONS_AVAILABLE.iterkeys()]:
raise Exception("autoadd: Invalid options key:%s" % key)
#disable the watch loop if it was active
if watchdir_id in self.update_timers:
@ -177,33 +173,29 @@ class Core(CorePluginBase):
return filedump
def update_watchdir(self, watchdir_id):
"""Check the watch folder for new torrents to add."""
watchdir_id = str(watchdir_id)
watchdir = self.watchdirs[watchdir_id]
if not watchdir['enabled']:
# We shouldn't be updating because this watchdir is not enabled
#disable the looping call
self.update_timers[watchdir_id].stop()
del self.update_timers[watchdir_id]
self.disable_watchdir(watchdir_id)
return
# Check the auto add folder for new torrents to add
if not os.path.isdir(watchdir["abspath"]):
log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"])
#disable the looping call
watchdir['enabled'] = False
self.update_timers[watchdir_id].stop()
del self.update_timers[watchdir_id]
self.disable_watchdir(watchdir_id)
return
#Generate options dict for watchdir
opts={}
if watchdir.get('stop_at_ratio_toggle'):
watchdir['stop_ratio_toggle'] = True
# Generate options dict for watchdir
opts = {}
if 'stop_at_ratio_toggle' in watchdir:
watchdir['stop_ratio_toggle'] = watchdir['stop_at_ratio_toggle']
# We default to True wher reading _toggle values, so a config
# without them is valid, and applies all its settings.
for option, value in watchdir.iteritems():
if OPTIONS_AVAILABLE.get(option):
if watchdir.get(option+'_toggle', True):
opts[option] = value
opts = self._clean_unicode(opts)
for filename in os.listdir(watchdir["abspath"]):
if filename.split(".")[-1] == "torrent":
try:
@ -219,49 +211,73 @@ class Core(CorePluginBase):
# torrents may not be fully saved during the pass.
log.debug("Torrent is invalid: %s", e)
if filename in self.invalid_torrents:
self.attempts[filename] += 1
if self.attempts[filename] >= MAX_NUM_ATTEMPTS:
self.invalid_torrents[filename] += 1
if self.invalid_torrents[filename] >= MAX_NUM_ATTEMPTS:
os.rename(filepath, filepath + ".invalid")
del self.attempts[filename]
self.invalid_torrents.remove(filename)
del self.invalid_torrents[filename]
else:
self.invalid_torrents.append(filename)
self.attempts[filename] = 1
self.invalid_torrents[filename] = 1
continue
# The torrent looks good, so lets add it to the session
# The torrent looks good, so lets add it to the session.
torrent_id = component.get("TorrentManager").add(filedump=filedump, filename=filename, options=opts)
if ('Label' in component.get("CorePluginManager").get_enabled_plugins()) and torrent_id:
if watchdir.get('label_toggle', True) and watchdir.get('label'):
label = component.get("CorePlugin.Label")
if not watchdir['label'] in label.get_labels():
label.add(watchdir['label'])
label.set_torrent(torrent_id, watchdir['label'])
os.remove(filepath)
# If the torrent added successfully, set the extra options.
if torrent_id:
if 'Label' in component.get("CorePluginManager").get_enabled_plugins():
if watchdir.get('label_toggle', True) and watchdir.get('label'):
label = component.get("CorePlugin.Label")
if not watchdir['label'] in label.get_labels():
label.add(watchdir['label'])
label.set_torrent(torrent_id, watchdir['label'])
if watchdir.get('queue_to_top_toggle', True) and 'queue_to_top' in watchdir:
if watchdir['queue_to_top']:
component.get("TorrentManager").queue_top(torrent_id)
else:
component.get("TorrentManager").queue_bottom(torrent_id)
# Rename or delete the torrent once added to deluge.
if watchdir.get('append_extension_toggle'):
if not watchdir.get('append_extension'):
watchdir['append_extension'] = ".added"
os.rename(filepath, filepath + watchdir['append_extension'])
else:
os.remove(filepath)
def on_update_watchdir_error(self, failure, watchdir_id):
"""Disables any watch folders with unhandled exceptions."""
self.disable_watchdir(watchdir_id)
log.error("Disabling '%s', error during update: %s" % (self.watchdirs[watchdir_id]["path"], failure))
@export
def enable_watchdir(self, watchdir_id):
watchdir_id = str(watchdir_id)
self.watchdirs[watchdir_id]['enabled'] = True
#Enable the looping call
self.update_timers[watchdir_id] = LoopingCall(self.update_watchdir, watchdir_id)
self.update_timers[watchdir_id].start(5)
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
# Enable the looping call
if watchdir_id not in self.update_timers or not self.update_timers[watchdir_id].running:
self.update_timers[watchdir_id] = LoopingCall(self.update_watchdir, watchdir_id)
self.update_timers[watchdir_id].start(5).addErrback(self.on_update_watchdir_error, watchdir_id)
# Update the config
if not self.watchdirs[watchdir_id]['enabled']:
self.watchdirs[watchdir_id]['enabled'] = True
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
@export
def disable_watchdir(self, watchdir_id):
watchdir_id = str(watchdir_id)
self.watchdirs[watchdir_id]['enabled'] = False
#disable the looping call here
self.update_timers[watchdir_id].stop()
del self.update_timers[watchdir_id]
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
# Disable the looping call
if watchdir_id in self.update_timers:
if self.update_timers[watchdir_id].running:
self.update_timers[watchdir_id].stop()
del self.update_timers[watchdir_id]
# Update the config
if self.watchdirs[watchdir_id]['enabled']:
self.watchdirs[watchdir_id]['enabled'] = False
self.config.save()
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
@export
def set_config(self, config):
"""sets the config dictionary"""
"""Sets the config dictionary."""
config = self._make_unicode(config)
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@ -269,35 +285,30 @@ class Core(CorePluginBase):
@export
def get_config(self):
"""returns the config dictionary"""
"""Returns the config dictionary."""
return self.config.config
@export()
def get_watchdirs(self):
return self.watchdirs.keys()
def _clean_unicode(self, options):
def _make_unicode(self, options):
opts = {}
for key, value in options.iteritems():
if isinstance(key, unicode):
key = str(key)
if isinstance(value, unicode):
value = str(value)
opts[key] = value
for key in options:
if isinstance(options[key], str):
options[key] = unicode(options[key], "utf8")
opts[key] = options[key]
return opts
#Labels:
@export()
def add(self, options={}):
"""add a watchdir
"""
options = self._clean_unicode(options)
"""Add a watch folder."""
options = self._make_unicode(options)
abswatchdir = os.path.abspath(options['path'])
CheckInput(os.path.isdir(abswatchdir) , _("Path does not exist."))
CheckInput(os.access(abswatchdir, os.R_OK|os.W_OK), "You must have read and write access to watch folder.")
for watchdir_id, watchdir in self.watchdirs.iteritems():
if watchdir['abspath'] == abswatchdir:
raise Exception("Path is already being watched.")
if abswatchdir in [wd['abspath'] for wd in self.watchdirs.itervalues()]:
raise Exception("Path is already being watched.")
options.setdefault('enabled', False)
options['abspath'] = abswatchdir
watchdir_id = self.config['next_id']
@ -311,7 +322,7 @@ class Core(CorePluginBase):
@export
def remove(self, watchdir_id):
"""remove a label"""
"""Remove a watch folder."""
watchdir_id = str(watchdir_id)
CheckInput(watchdir_id in self.watchdirs, "Unknown Watchdir: %s" % self.watchdirs)
if self.watchdirs[watchdir_id]['enabled']:

View File

@ -83,9 +83,11 @@
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
@ -94,6 +96,7 @@
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkFrame" id="frame2">
<property name="visible">True</property>
@ -106,6 +109,7 @@
<child>
<widget class="GtkVBox" id="vbox6">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="visible">True</property>
@ -170,6 +174,89 @@
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkRadioButton" id="isnt_append_extension">
<property name="label" translatable="yes">Delete .torrent after adding</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<widget class="GtkRadioButton" id="append_extension_toggle">
<property name="label" translatable="yes">Append extension after adding:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">isnt_append_extension</property>
<signal name="toggled" handler="on_toggle_toggled"/>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="append_extension">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x2022;</property>
<property name="text" translatable="yes">.added</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Torrent File Action&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame3">
<property name="visible">True</property>
@ -182,6 +269,7 @@
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkCheckButton" id="download_location_toggle">
<property name="label" translatable="yes">Set download location</property>
@ -244,7 +332,7 @@
</widget>
<packing>
<property name="fill">False</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -259,6 +347,7 @@
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkCheckButton" id="move_completed_toggle">
<property name="label" translatable="yes">Set move completed location</property>
@ -336,7 +425,7 @@
</widget>
<packing>
<property name="fill">False</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
@ -392,7 +481,7 @@
</child>
</widget>
<packing>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
</widget>
@ -411,6 +500,7 @@
<widget class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
@ -484,7 +574,7 @@
<widget class="GtkSpinButton" id="max_download_speed">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">-1 -1 10000 1 10 10</property>
<property name="adjustment">-1 -1 10000 1 10 0</property>
<property name="climb_rate">1</property>
<property name="digits">1</property>
</widget>
@ -498,7 +588,7 @@
<widget class="GtkSpinButton" id="max_upload_speed">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">-1 -1 10000 1 10 10</property>
<property name="adjustment">-1 -1 10000 1 10 0</property>
<property name="climb_rate">1</property>
<property name="digits">1</property>
</widget>
@ -514,7 +604,7 @@
<widget class="GtkSpinButton" id="max_connections">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">-1 -1 10000 1 10 10</property>
<property name="adjustment">-1 -1 10000 1 10 0</property>
<property name="climb_rate">1</property>
</widget>
<packing>
@ -529,7 +619,7 @@
<widget class="GtkSpinButton" id="max_upload_slots">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">-1 -1 10000 1 10 10</property>
<property name="adjustment">-1 -1 10000 1 10 0</property>
<property name="climb_rate">1</property>
</widget>
<packing>
@ -640,14 +730,16 @@
</child>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment14">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkCheckButton" id="remove_at_ratio">
@ -661,8 +753,8 @@
</child>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
@ -676,8 +768,8 @@
<signal name="toggled" handler="on_toggle_toggled"/>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
@ -694,8 +786,8 @@
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
@ -712,8 +804,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
@ -723,21 +815,22 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">2 0 100 0.10000000149 10 10</property>
<property name="adjustment">2 0 100 0.10000000149 10 0</property>
<property name="climb_rate">1</property>
<property name="digits">1</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="auto_managed_box">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkRadioButton" id="auto_managed">
<property name="label" translatable="yes">Yes</property>
@ -768,8 +861,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -786,8 +879,8 @@
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
@ -805,6 +898,7 @@
<child>
<widget class="GtkHBox" id="add_paused_box">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkRadioButton" id="add_paused">
<property name="label" translatable="yes">Yes</property>
@ -824,7 +918,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">add_paused</property>
</widget>
@ -839,10 +932,56 @@
</packing>
</child>
<child>
<placeholder/>
<widget class="GtkCheckButton" id="queue_to_top_toggle">
<property name="label" translatable="yes">Queue to:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_toggle_toggled"/>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<child>
<widget class="GtkRadioButton" id="queue_to_top">
<property name="label" translatable="yes">Top</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="isnt_queue_to_top">
<property name="label" translatable="yes">Bottom</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">queue_to_top</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
@ -911,6 +1050,7 @@
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="orientation">vertical</property>
</widget>
<packing>
<property name="position">1</property>
@ -943,7 +1083,7 @@
</child>
<child>
<widget class="GtkButton" id="opts_add_button">
<property name="label" translatable="no">gtk-add</property>
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
@ -959,7 +1099,7 @@
</child>
<child>
<widget class="GtkButton" id="opts_apply_button">
<property name="label" translatable="no">gtk-apply</property>
<property name="label">gtk-apply</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>

View File

@ -51,11 +51,10 @@ from common import get_resource
class OptionsDialog():
spin_ids = ["max_download_speed", "max_upload_speed", "stop_ratio"]
spin_int_ids = ["max_upload_slots", "max_connections"]
chk_ids = ["stop_at_ratio", "remove_at_ratio", "move_completed", "add_paused", "auto_managed"]
chk_ids = ["stop_at_ratio", "remove_at_ratio", "move_completed", "add_paused", "auto_managed", "queue_to_top"]
def __init__(self):
pass
def show(self, options={}, watchdir_id=None):
self.glade = gtk.glade.XML(get_resource("autoadd_options.glade"))
self.glade.signal_autoconnect({
@ -87,6 +86,8 @@ class OptionsDialog():
def load_options(self, options):
self.glade.get_widget('enabled').set_active(options.get('enabled', False))
self.glade.get_widget('append_extension_toggle').set_active(options.get('append_extension_toggle', False))
self.glade.get_widget('append_extension').set_text(options.get('append_extension', '.added'))
self.glade.get_widget('download_location_toggle').set_active(options.get('download_location_toggle', False))
self.glade.get_widget('label').set_text(options.get('label', ''))
self.glade.get_widget('label_toggle').set_active(options.get('label_toggle', False))
@ -97,7 +98,9 @@ class OptionsDialog():
self.glade.get_widget(id).set_active(bool(options.get(id, True)))
self.glade.get_widget(id+'_toggle').set_active(options.get(id+'_toggle', False))
if not options.get('add_paused', True):
self.glade.get_widget('isnt_add_paused').set_active(True)
self.glade.get_widget('isnt_add_paused').set_active(True)
if not options.get('queue_to_top', True):
self.glade.get_widget('isnt_queue_to_top').set_active(True)
if not options.get('auto_managed', True):
self.glade.get_widget('isnt_auto_managed').set_active(True)
for field in ['move_completed_path', 'path', 'download_location']:
@ -121,9 +124,9 @@ class OptionsDialog():
client.core.get_enabled_plugins().addCallback(on_get_enabled_plugins)
def set_sensitive(self):
maintoggles = ['download_location', 'move_completed', 'label', \
maintoggles = ['download_location', 'append_extension', 'move_completed', 'label', \
'max_download_speed', 'max_upload_speed', 'max_connections', \
'max_upload_slots', 'add_paused', 'auto_managed', 'stop_at_ratio']
'max_upload_slots', 'add_paused', 'auto_managed', 'stop_at_ratio', 'queue_to_top']
[self.on_toggle_toggled(self.glade.get_widget(x+'_toggle')) for x in maintoggles]
def on_toggle_toggled(self, tb):
@ -132,6 +135,8 @@ class OptionsDialog():
if toggle == 'download_location':
self.glade.get_widget('download_location_chooser').set_sensitive(isactive)
self.glade.get_widget('download_location_entry').set_sensitive(isactive)
elif toggle == 'append_extension':
self.glade.get_widget('append_extension').set_sensitive(isactive)
elif toggle == 'move_completed':
self.glade.get_widget('move_completed_path_chooser').set_sensitive(isactive)
self.glade.get_widget('move_completed_path_entry').set_sensitive(isactive)
@ -149,6 +154,9 @@ class OptionsDialog():
elif toggle == 'add_paused':
self.glade.get_widget('add_paused').set_sensitive(isactive)
self.glade.get_widget('isnt_add_paused').set_sensitive(isactive)
elif toggle == 'queue_to_top':
self.glade.get_widget('queue_to_top').set_sensitive(isactive)
self.glade.get_widget('isnt_queue_to_top').set_sensitive(isactive)
elif toggle == 'auto_managed':
self.glade.get_widget('auto_managed').set_sensitive(isactive)
self.glade.get_widget('isnt_auto_managed').set_sensitive(isactive)
@ -193,10 +201,11 @@ class OptionsDialog():
options['path'] = self.glade.get_widget('path_entry').get_text()
options['download_location'] = self.glade.get_widget('download_location_entry').get_text()
options['move_completed_path'] = self.glade.get_widget('move_completed_path_entry').get_text()
options['append_extension_toggle'] = self.glade.get_widget('append_extension_toggle').get_active()
options['append_extension'] = self.glade.get_widget('append_extension').get_text()
options['download_location_toggle'] = self.glade.get_widget('download_location_toggle').get_active()
options['label'] = self.glade.get_widget('label').get_text().lower()
options['label_toggle'] = self.glade.get_widget('label_toggle').get_active()
for id in self.spin_ids:
options[id] = self.glade.get_widget(id).get_value()
@ -245,6 +254,7 @@ class GtkUI(GtkPluginBase):
sw.add(self.treeView)
sw.show_all()
component.get("Preferences").add_page("AutoAdd", self.glade.get_widget("prefs_box"))
self.on_show_prefs()
def disable(self):
@ -320,7 +330,6 @@ class GtkUI(GtkPluginBase):
client.autoadd.set_options(watchdir_id, watchdir)
def on_show_prefs(self):
client.autoadd.get_config().addCallback(self.cb_get_config)
def on_options_changed_event(self):

View File

@ -42,8 +42,8 @@ from setuptools import setup
__plugin_name__ = "AutoAdd"
__author__ = "Chase Sterling"
__author_email__ = "chase.sterling@gmail.com"
__version__ = "0.28"
__url__ = "http://forum.deluge-torrent.org/viewtopic.php?f=9&t=26775"
__version__ = "1.02"
__url__ = "http://dev.deluge-torrent.org/wiki/Plugins/AutoAdd"
__license__ = "GPLv3"
__description__ = "Monitors folders for .torrent files."
__long_description__ = """"""

View File

@ -2,7 +2,7 @@
# core.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2009 John Garland <johnnybg@gmail.com>
# Copyright (C) 2009-2010 John Garland <johnnybg+deluge@gmail.com>
#
# Deluge is free software.
#
@ -38,6 +38,7 @@ import os
import time
from datetime import datetime, timedelta
from wsgiref.handlers import format_date_time
from urlparse import urljoin
import shutil
from twisted.internet.task import LoopingCall
@ -81,6 +82,7 @@ class Core(CorePluginBase):
self.is_importing = False
self.has_imported = False
self.up_to_date = False
self.need_to_resume_session = False
self.num_blocked = 0
self.file_progress = 0.0
@ -94,7 +96,7 @@ class Core(CorePluginBase):
update_now = False
if self.config["load_on_start"]:
self.pause_transfers()
self.pause_session()
if self.config["last_update"]:
last_update = datetime.fromtimestamp(self.config["last_update"])
check_period = timedelta(days=self.config["check_after_days"])
@ -103,7 +105,8 @@ class Core(CorePluginBase):
else:
d = self.import_list(deluge.configmanager.get_config_dir("blocklist.cache"))
d.addCallbacks(self.on_import_complete, self.on_import_error)
d.addBoth(self.resume_transfers)
if self.need_to_resume_session:
d.addBoth(self.resume_session)
# This function is called every 'check_after_days' days, to download
# and import a new list if needed.
@ -149,7 +152,8 @@ class Core(CorePluginBase):
else:
d = self.import_list(self.config["url"])
d.addCallbacks(self.on_import_complete, self.on_import_error)
d.addBoth(self.resume_transfers)
if self.need_to_resume_session:
d.addBoth(self.resume_session)
return d
@ -281,7 +285,7 @@ class Core(CorePluginBase):
d = f
if f.check(error.PageRedirect):
# Handle redirect errors
location = error_msg.split(" to ")[1]
location = urljoin(self.config["url"], error_msg.split(" to ")[1])
if "Moved Permanently" in error_msg:
log.debug("Setting blocklist url to %s", location)
self.config["url"] = location
@ -417,13 +421,14 @@ class Core(CorePluginBase):
else:
self.reader = create_reader(self.config["list_type"], self.config["list_compression"])
def pause_transfers(self):
self.session_was_paused = self.core.session.is_paused()
if not self.session_was_paused:
def pause_session(self):
if not self.core.session.is_paused():
self.core.session.pause()
self.need_to_resume_session = True
else:
self.need_to_resume_session = False
def resume_transfers(self, result):
if not self.session_was_paused:
self.session_was_paused = True
self.core.session.resume()
def resume_session(self, result):
self.core.session.resume()
self.need_to_resume_session = False
return result

View File

@ -1,7 +1,7 @@
#
# decompressers.py
#
# Copyright (C) 2009 John Garland <johnnybg@gmail.com>
# Copyright (C) 2009-2010 John Garland <johnnybg+deluge@gmail.com>
#
# Deluge is free software.
#

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