Compare commits

...

1510 Commits

Author SHA1 Message Date
cc086917c1 Add export-ignore attribute to .gitignore 2010-03-27 13:20:46 -07:00
3e0a35c802 Prep for release 2010-03-27 12:37:04 -07:00
4a2316411d Add .gitignore file to 1.2 branch 2010-03-27 19:15:04 +11:00
1b54d5b93b Merge branch '1.2-stable' of deluge-torrent.org:deluge into 1.2-stable 2010-03-22 13:58:51 -07:00
64d927b499 Fix libtorrent 0.15 compat 2010-03-22 13:58:32 -07:00
3e639c3445 Merged test_versionsplit.py into test_common.py 2010-03-22 18:19:10 +11:00
ec39a8d501 Add test case for deluge/common.py 2010-03-22 18:19:10 +11:00
90103358f3 Fix VersionSplit comparison to do a proper compare and not simply
against the version strings
2010-03-21 15:58:55 -07:00
32a00d7919 Update attributes 2010-03-19 13:56:40 -07:00
3932e632c1 Add export-ignore attributes 2010-03-19 13:51:17 -07:00
3f37b3bb01 Update ChangeLog 2010-03-19 13:37:48 -07:00
03b9b940af Update Windows installer 2010-03-19 13:36:36 -07:00
eeda4a5ecd Update translations 2010-03-19 13:05:58 -07:00
fd5460b403 Update Windows installer files 2010-03-19 12:23:51 -07:00
35b72ba8d7 Fix issue where the gtkui sometimes won't start if there is a stale lock file or socket in the ipc/
directory
2010-03-13 12:13:59 -08:00
fc109479bf Update ChangeLog 2010-03-13 10:10:13 -08:00
f0226decff Fix #1172 notify startup complete when adding torrents externally 2010-03-13 10:09:31 -08:00
5bd22ee6d5 change the libtorrent submodule to point to 0.14-stable 2010-03-12 10:16:00 +00:00
c0b3d4745a update the libtorrent submodule to use the public git repository. 2010-03-07 19:13:53 +00:00
f9414105df Update Changelog 2010-02-28 17:34:27 -08:00
a227617bac Fix #1162 problem with the queued torrents dialog from not properly adding to the add torrent dialog
if set to auto add
2010-02-28 17:27:04 -08:00
58ef466d9c Update changelog 2010-02-28 16:24:21 -08:00
9250bbfb89 Fix #1109 auto add halting when a torrent with invalid filename encoding is in the directory 2010-02-28 16:21:47 -08:00
dfdcf117b4 Fix silly error from last commit 2010-02-26 14:49:20 +00:00
52b5e9d4e3 include the ability to profile the web server, code lifted straight from the daemon 2010-02-26 14:25:17 +00:00
479d84857f Test commit 2010-02-22 18:11:43 -08:00
b9abe8ea10 Test commit 2010-02-22 18:03:18 -08:00
9e51e39629 Test commit 2010-02-22 18:00:29 -08:00
e999d34e5c Test commit 2010-02-22 17:54:33 -08:00
abc66b5b5e Update version numbers 2010-02-22 17:34:53 -08:00
5b23993960 Update version 2010-02-22 17:28:56 -08:00
eadfa323ca Update Changelog 2010-02-22 17:26:15 -08:00
f666c28e14 Fix #1143 deluge-console crashes when tab-completing not-existent
directory
2010-02-22 17:01:40 -08:00
1da79ceb75 change the way that the minimum LT version is specified 2010-02-22 11:56:05 +00:00
8e5f8bb249 Multi-platform fix for #1147. 2010-02-21 18:46:53 +11:00
3791fe2d2f Fix typo 2010-02-20 09:36:54 -08:00
27c0f339ce Prep for release 2010-02-20 09:20:36 -08:00
c605616cb9 Update Changelog 2010-02-20 09:17:40 -08:00
443d4d7a3a Merge branch '1.2-stable' of deluge-torrent.org:deluge into 1.2-stable 2010-02-20 09:12:40 -08:00
34fb2def75 Update translations 2010-02-20 09:11:35 -08:00
95b26efbb4 Make Deluge dependent on libtorrent 0.14.9 or greater. This is due to an over-downloading bug in
libtorrent.
2010-02-20 08:56:20 -08:00
dc35732896 Fixed typo. 2010-02-21 02:31:55 +11:00
292428280d update the changelog to include #1148 fixed 2010-02-20 00:07:20 +00:00
5438a39af2 backport the fix for #1148 from master 2010-02-19 23:49:52 +00:00
ec15c3aadb update the ChangeLog 2010-02-19 19:52:19 +00:00
41ef49a27e fix #1147 by appending -username to the delugeweb folder 2010-02-19 19:41:15 +00:00
e3fcaf0c1a update the copyright headers to include 2010 2010-02-19 19:17:02 +00:00
10262cea81 remove the old libtorrent stuff and add it as a git submodule
change setup.py to check if libtorrent has files
2010-02-19 00:57:13 +00:00
545e64e3c3 Fix weird gtk bug that breaks create dialog box's pieces size selection. 2010-02-04 11:17:26 +00:00
85493750fb Increased GTK UI limit for download / upload to 60000. 2010-01-25 09:46:08 +00:00
124ec3e9c7 Remove debug print 2010-01-23 22:05:49 +00:00
b3975bd4c2 add a __contains__ method to the config class
fix upgrading old configs when the key doesn't exist in the old config
2010-01-20 21:04:40 +00:00
445096378c update the gettext.js generation script and gettext.js 2010-01-20 20:37:14 +00:00
3686130ea5 Fix hanging when using commands from the command-line
Fix displaying plugin command output on the command-line
2010-01-19 23:00:48 +00:00
4af387f774 Fix #1128 Show an error dialog when unable to start a 'deluged' process 2010-01-18 02:36:03 +00:00
a62fdac0a6 Fix date in 1.2_RC changelog. Add release date to trunk changelog. 2010-01-16 04:21:25 +00:00
1941c5976c Fix typo. Remove obselete function. 2010-01-14 12:32:04 +00:00
4f28ab9a39 bump version number so its now 1.2.1-dev 2010-01-12 17:21:00 +00:00
79c78fa7ef Fix displaying new release dialog in Windows 2010-01-10 19:47:31 +00:00
89c9228cec Prep for release 2010-01-09 21:16:08 +00:00
0df79b03c5 Update translations 2010-01-09 20:41:51 +00:00
c54a50af34 Do not save_state right away, but rather wait for the timer loop 2010-01-08 23:36:44 +00:00
e81d2ea0bd Fix displaying root folder when using the 'path.utf-8' keys in torrents 2010-01-08 21:26:33 +00:00
5e19f91613 Add twisted.internet.utils to the freezer includes 2010-01-08 17:28:08 +00:00
5a35d60178 Use cStringIO to open zip files in python 2.5 2010-01-07 15:27:05 +00:00
34b2ada0db Rewrote call to use maybeDeferred (this handles methods that return deferreds).
Fixes #1114.
2010-01-07 00:45:47 +00:00
547cfa6339 put the default password in the manpage for those too lazy to type "deluge default web password" in google 2010-01-05 14:07:16 +00:00
3870c25c9d Fix #1117 can't use the '3' key 2010-01-04 00:18:53 +00:00
4cde35a067 Fix blocklist ignoring try_times.
Make blocklist print error messages on failures.
2010-01-03 16:27:05 +00:00
d5a11d0e95 Fix #1116 not being able to use command aliases when not connected to a daemon 2010-01-03 01:37:57 +00:00
1f8919b47f Fix #1115 not showing usage for the 'debug' command 2010-01-02 23:25:45 +00:00
59f05a890f Don't apply 'stop/remove on completed' rules to torrents in a Queued or Paused state 2009-12-28 21:50:13 +00:00
afbeaa6b7d Fix torrent info name not being utf-8 decoded when root file/folder name is blank 2009-12-26 17:09:05 +00:00
f5409e0d0c Have the .desktop file run 'deluge-gtk' 2009-12-23 23:54:00 +00:00
ac857eaef7 Change share ratio calculation to use the total done instead of the all time downloaded value. This change will make the share ratio calculation not use data downloaded in failed hash checks. 2009-12-23 18:44:00 +00:00
886f2d8682 Add in a '_' builtin method if unable to initialize gettext 2009-12-23 01:34:58 +00:00
fa79c37aa2 Fix possible TorrentFinishedEvents being emitted on startup for already completed torrents 2009-12-23 01:28:33 +00:00
6a8e023ffd Fix exceptions when gettext/locale cannot be initialized properly 2009-12-21 19:41:31 +00:00
6b396f1f77 More relaxed definition of what a commented line is in a blocklist.
Decorate readranges with raiseError rather than parse to increase performance.
2009-12-21 13:58:24 +00:00
b2990e89cb fix filtering on the tracker host, use == rather than in so tracker urls that contain another trackers url within them aren't picked up as well 2009-12-21 10:26:50 +00:00
7ebe07db15 Fix blocklist status icon not opening proper preferences page.
Show blocklist's file date using the locale's date / time representation.
2009-12-20 09:01:07 +00:00
14eb3b8b33 Fix some packing due to the last commit 2009-12-20 04:23:50 +00:00
cffc25aac8 Plugin preference pages will now expand to fill 2009-12-20 04:18:21 +00:00
ed2568c8b0 Fix displaying folders in the add torrent dialog 2009-12-20 04:02:41 +00:00
700fe2ec17 Fix file renaming 2009-12-20 03:45:14 +00:00
571b8a84af Update bbfreeze script to include wsgiref.handlers so that blocklist plugin will work 2009-12-18 04:59:04 +00:00
3d821fb80b Fix #1104, #735 use path.utf-8 if available 2009-12-18 04:36:42 +00:00
00c4b53b67 Remove MANIFEST.in file 2009-12-18 00:46:26 +00:00
9a9ae71564 Update translations 2009-12-18 00:01:36 +00:00
c9c57e0e32 Update pot file 2009-12-17 23:58:21 +00:00
c70a9875c5 Prep for release 2009-12-17 23:49:25 +00:00
c932de8470 Remove redundant variable. 2009-12-17 23:08:55 +00:00
0663da4424 Partial fix for #1103 if the per-torrent option for stopping at a ratio has been unchecked, then do
not stop it at the global setting.
2009-12-17 21:40:21 +00:00
8c265bb308 Fix #1095 incorrect piece size used when using some non-English languages 2009-12-17 21:27:04 +00:00
fe6c89a2e1 Upgrade older confs instead of just dying.
Fix major logic error when checking if an update is needed.
2009-12-16 13:46:39 +00:00
3c5d5aa16e Fix import on startup which got broken in previous commit. 2009-12-16 12:46:57 +00:00
389e9cdbb0 Fix blocklist not working for all locales (#1059). 2009-12-16 11:55:34 +00:00
193f1b85ca Apply #1100 sort plugins list by name 2009-12-15 17:37:05 +00:00
4daa2a098b Fix #1099 use triple quotes on docstrings 2009-12-15 06:36:02 +00:00
52817498cf Fix showing the remove torrent dialog twice if using the delete key and pressing cancel in the dialog 2009-12-14 23:25:03 +00:00
cc3f3495b6 Fix #768 save tracker list for create torrent dialog 2009-12-14 18:46:08 +00:00
4bd00aa331 Fix #1086 deprecated gtk.Tooltips usage 2009-12-14 18:20:51 +00:00
e27c38ca67 Fix #594 tray password dialog freeze in Windows
Made the password dialog prettier
2009-12-14 02:15:08 +00:00
eeac8efcf2 Fix issue where stoping a daemon that you aren't connected to causes the gtkui to shutdown the
currently connected daemon.
2009-12-14 00:48:18 +00:00
f59901c1be Fix #823 setting config values to -1.0 2009-12-13 22:47:15 +00:00
ee76075fa4 Add #891 remove torrents by pressing the Delete key 2009-12-13 22:16:05 +00:00
3f69b05ded disconnect the client if getting information fails 2009-12-13 21:50:16 +00:00
ecca68772e use metavar to change the output of --help by optparse 2009-12-13 21:49:10 +00:00
9878fced37 Fix issue where hosts will show up erroneously as Offline 2009-12-13 21:46:55 +00:00
c312cf4b91 Disconnect from daemon if getting the info fails 2009-12-13 21:34:26 +00:00
de262bf7db Fix autoconnecting to a host other than the first one in the list 2009-12-13 21:29:46 +00:00
8edd91a3d5 Add an error dialog when trying to add a duplicate host
Center the add host dialog over the connection manager
2009-12-13 21:25:22 +00:00
f6fdae727d Fix #1036 autoconnecting to localhost daemon on start-up 2009-12-13 20:49:23 +00:00
139d6538a2 Fix #782 do not ask for tray password when window is not minimized to tray 2009-12-12 22:38:26 +00:00
b88319b4be Fix #692 no longer require tray password when quitting from the tray icon while the window is
visible.
2009-12-12 21:22:51 +00:00
dd129f8544 reset the add torrent window on hide 2009-12-12 15:56:49 +00:00
af18bdb72a Fix typo 2009-12-11 23:29:21 +00:00
85b3546c47 Fix printing 'rm' command usage when called with no arguments 2009-12-11 21:19:48 +00:00
07cd4ba83d fix #1075 (changing priority on a whole folder) 2009-12-11 20:45:59 +00:00
361f2b2390 Fix possible exception when upgrading from a 0.5 state file 2009-12-10 21:28:51 +00:00
97a69b8c0c update some of the icons in the webui 2009-12-10 18:24:31 +00:00
29f2ed84dd disable the files and options tabs until a torrent has been selected 2009-12-10 17:45:40 +00:00
9e9fbd6242 fix uploading plugins when the daemon is not localhost 2009-12-10 17:35:35 +00:00
2840d43ccb fix the onResize method for the togglefield so it resizes the textfield to the correct size 2009-12-10 17:26:45 +00:00
14454791c4 implement installing plugins via the webui 2009-12-10 15:40:37 +00:00
fcbaa1f4f2 fix the upload_plugin method as it wasn't upgraded to deluge-rpc spec 2009-12-10 15:31:27 +00:00
c716f55dda fix incorrect class name 2009-12-10 14:39:14 +00:00
a1e950d6e5 remove the margin and padding from the bottom of the options fieldset 2009-12-10 14:35:10 +00:00
e646a5ef87 fix enabling plugins on the fly 2009-12-10 14:32:55 +00:00
3c703d2ef7 Fix using the console in Windows, but only in command-line mode 2009-12-10 01:26:26 +00:00
429f7064fa tweak the download prefs page so no scrollbars appear 2009-12-10 00:38:48 +00:00
47b5274f34 improve the ToggleField widget, having the checkbox to the left of the
field rather than above it
2009-12-10 00:32:24 +00:00
a6c6d5b2b4 add tooltips to the statusbar items
add disk free space to the statusbar
2009-12-10 00:06:34 +00:00
3d3edccdac Apply cookie date fix from adios 2009-12-09 13:13:04 +00:00
36b2a82561 fix a bug in the execute plugin when move_completed is used the incorrect path was passed in 2009-12-08 11:24:56 +00:00
f5096c6e7c tweak the sizes of some form elements to improve the layout 2009-12-08 02:09:03 +00:00
76bc32d72a begin the makings of the togglefield widget that allows enabling of move completed/copy torrent files/auto add torrent files fields 2009-12-08 01:56:15 +00:00
581517c8e9 Change the compressed js script to deluge-all.js to avoid naming conflicts on case sensitive filesystems 2009-12-01 17:11:07 +00:00
b41a025217 Add button to Other preferences to associate magnet links with Deluge 2009-11-30 03:50:28 +00:00
7a91b96183 Fix #1085 only use ints for specific options to prevent unhandled exception 2009-11-29 21:32:56 +00:00
a317fdec48 Fix crash in Windows when creating a torrent 2009-11-29 07:38:29 +00:00
20b6791670 Properly show 100.00% and reduce number of progress bar updates during a torrent creation 2009-11-29 07:37:29 +00:00
411ee123f1 Register just 'deluge' not '/usr/bin/deluge' in the magnet uri handler 2009-11-29 01:45:46 +00:00
2bc13a3fb7 Attempt to register as the default magnet uri handler in GNOME on startup 2009-11-29 01:40:30 +00:00
dda893e2b7 Add some checks for OSX since it doesn't support SVG icons 2009-11-29 00:52:00 +00:00
00de8311fd swap the order of the buttons in the remove window 2009-11-26 14:59:04 +00:00
6d7572c444 update the build script and rebuild deluge.js and ext-extensions.js 2009-11-25 18:52:00 +00:00
3e1a6a1fb8 exclude some more things from the sdist 2009-11-25 18:37:40 +00:00
dbbc1124f4 prevent undefineds ending up as a key in the option manager 2009-11-25 18:37:06 +00:00
13d949381a Set batch_write to False in __init__ 2009-11-25 18:24:29 +00:00
bfea47c8bd add the updated manifest to 1.2 2009-11-25 18:00:15 +00:00
f858e271ad Add magnet link association to the installer 2009-11-25 03:09:42 +00:00
708f052153 Prep for release 2009-11-25 02:41:15 +00:00
8d6bc283d0 Fix loading the saved metadata when loading state with magnet uris 2009-11-25 01:55:51 +00:00
313c73c40c Fix files list when using magnet uris 2009-11-25 01:41:50 +00:00
012dd1919c Update translations 2009-11-23 18:16:51 +00:00
d7e83d922c Re-commit. This change got lost on the mess of merging HG and SVN branches. 2009-11-22 06:17:55 +00:00
860ceccd52 Fix adding torrents with different metadata by storing the bencoded dict too. If we bencode the stored metadata dict, there is a chance the order of the dict will be different and change the info-hash. 2009-11-20 19:13:12 +00:00
907f618607 add the beginnings of a MANIFEST.in file for specifying which files to include in the sdist command
tweak setup.py
2009-11-19 21:20:17 +00:00
abcb76e959 rename deluge-yc.js to deluge.js 2009-11-19 20:27:36 +00:00
825edb1fd8 Update changelog 2009-11-19 04:51:28 +00:00
4cdf919076 Fix issues adding magnet uris 2009-11-19 04:51:19 +00:00
90a143a4ef Fix issue where some torrents with special characters could not be added 2009-11-19 02:39:07 +00:00
04f8f80b9b Fix exception on startup when the system tray icon is not enabled 2009-11-19 02:29:37 +00:00
266693a6f9 Remove maketorrent.py in 1.2 since we're not using it 2009-11-18 19:02:05 +00:00
2b9e1e5ff4 Change the event_list to be a dictionary of known_events and their docstrings 2009-11-16 00:39:15 +00:00
68fe9512df Add way to get a list of DelugeEvent classes 2009-11-14 23:42:04 +00:00
b10ea808fd Fix endless loop when trying to autoconnect to an offline daemon 2009-11-13 05:26:54 +00:00
234863b664 Fix autoconnecting to the next host in the list if the selected one isn't available 2009-11-13 05:22:38 +00:00
940bc4a3dc Add bug number to changelog 2009-11-13 01:08:41 +00:00
aa5f69b203 Fix #1071 issue where Deluge will fail to start if there is a stale ipc lockfile 2009-11-13 01:07:36 +00:00
5f4b39aeb8 Comment out a debug log 2009-11-10 18:28:27 +00:00
0e07cdf8b1 Reduce height of Add Torrent Dialog by ~80 pixels 2009-11-10 02:45:36 +00:00
64eb296c9d remove alpha from the title 2009-11-09 23:48:32 +00:00
fa40f38c1b Allow for colons in PeerGuardian/SafePeer lists' descriptions.
Check that the start & end range resembles an ip when checking a list's validity.
2009-11-09 08:54:13 +00:00
1b46d99620 Force blocklist to re-detect the format when a download is forced.
Move remove_zeros to common.py and simplify / speed up.
Change debug logging lines to be more uniform.
2009-11-09 01:52:58 +00:00
441c20491c Fix printing info, help, etc.. on the command line 2009-11-08 17:22:57 +00:00
8c7bbbf398 Fix disabling/enabling plugins after switching daemons 2009-11-08 04:04:40 +00:00
267905295c Fix #1067 import os 2009-11-06 19:22:13 +00:00
fb4495fc33 Only try to stop LoopingCalls if they are running 2009-11-05 04:35:17 +00:00
447da3b1b4 Fix deleting old .fastresume files with fresh configs 2009-11-05 03:44:46 +00:00
9af41fd457 allow commands that are .pyc files to be used 2009-11-04 23:49:07 +00:00
7e19a11521 run the path from the add command through os.path.expanduser 2009-11-04 23:36:27 +00:00
4da33c72cc add a basic move storage window that fixes #1057 2009-11-04 20:45:21 +00:00
d411f90a67 remove the connected call upon an update to reduce the number of ajax calls 2009-11-04 19:54:59 +00:00
3179ff2060 Allow the 'help' command to be called when not connected to a daemon 2009-11-03 22:08:18 +00:00
b6dc72218d remove accidentally left in debug line 2009-11-03 14:48:24 +00:00
e884d2cbfa make the delete key work in the console ui 2009-11-03 12:47:23 +00:00
fc3ae8229f Fix adding torrents from the Queued Torrents dialog 2009-11-03 03:25:57 +00:00
48e3df5ff3 Fix showing the 'Other' speed dialogs in Windows 2009-11-03 03:19:30 +00:00
464e11abe6 Remove debian/ folder 2009-11-02 17:50:32 +00:00
0fbaecbc00 escape the hyphens in the console and web manpages 2009-11-02 17:33:06 +00:00
4c86ed7535 forward port the setup.py fix to trunk and update the 1.2 branch ChangeLog 2009-11-02 15:35:56 +00:00
6f333cefc9 include the deluge-web manpage 2009-11-02 15:28:08 +00:00
750f8fb794 Update translations 2009-11-02 01:35:13 +00:00
be529c1518 Prep rc3 release 2009-11-02 01:23:15 +00:00
e32bd8f4d8 Add the clear() back 2009-11-01 17:49:32 +00:00
87723a3354 Use batch writing mode in the help command 2009-10-31 22:05:35 +00:00
0cb52cca23 Do not include an 'announce-list' key in torrents when there is only one tracker 2009-10-31 19:49:14 +00:00
09ae4fbb72 Improve 'info' command draw speed 2009-10-31 18:52:52 +00:00
6e063e7c85 Don't bother clearing the screen during a refresh 2009-10-31 18:44:27 +00:00
41db357084 Fix crash when string length makes line longer than terminal width 2009-10-31 18:43:48 +00:00
3611584b0b Fix crash when removing multiple torrents 2009-10-31 05:50:01 +00:00
6e695d8410 Fix adding torrents when not showing the add torrent dialog in Windows 2009-10-31 00:08:53 +00:00
60fdcb3bd8 Fix #1052 crash when issuing commands while not connected to a daemon 2009-10-30 20:06:07 +00:00
d110b23a9f Fix improper dos line endings 2009-10-30 19:08:23 +00:00
2457fd0aea Fix displaying non-ascii strings in the console ui -- patch from Ian Martin 2009-10-30 18:00:13 +00:00
92afb8ab80 Fix torrent name being blank when root folder is renamed to /
Update changelog (for previous commit as well)
2009-10-30 00:15:22 +00:00
eba82457bd Make sure renamed files are utf-8 encoded. 2009-10-30 00:02:25 +00:00
099415776d Consider 0 unlimited when displaying limits in the statusbar 2009-10-28 17:43:29 +00:00
145f402aa2 fix #990, showing 0 as a limit when it means unlimited in the statusbar 2009-10-28 17:38:35 +00:00
d44efe8a66 use tag_build in setup.cfg and change version to rc3 in setup.py 2009-10-28 15:55:19 +00:00
1a9f715353 need to actually continue from the loop otherwise another error still occurs 2009-10-28 13:33:27 +00:00
2308961a04 create a method to escape all possible forms of newlines in a translation as well as the quotes 2009-10-28 13:24:37 +00:00
0cdd779396 remove new lines from any translations and replace them with \n characters so javascript can interupt it 2009-10-27 22:32:31 +00:00
db54dada9d fix displaying the protocol speed in the webui
also update the update_ui method in json_api so it gets the status more like how the gtkui does
2009-10-27 11:39:53 +00:00
7c5582a21e fix the eta sort order in the webui 2009-10-27 11:16:55 +00:00
7055a96930 update the ChangeLog so andar doesn't beat me up
fix displaying tracker urls with & in the url in the gtkui
2009-10-27 11:07:30 +00:00
e7a45f6dd1 add < and > escaping to the html escape method 2009-10-27 10:57:47 +00:00
ea4dcfbb5e fix actually escaping (foolish me had left it commented out) and also only update if there has been a change 2009-10-27 10:34:07 +00:00
5c506121a4 create a simple html escape method and escape the fields in the details tab 2009-10-27 10:26:59 +00:00
cc7aaa1ae0 fix a couple of bugs in the M.O.M and fix the options tab and file priorities in the torrent add window (success!) 2009-10-27 10:25:16 +00:00
cca2a4ab60 fixes #1046, changing the option name in the ui rather than the core which would break the other uis 2009-10-27 09:12:22 +00:00
197027510e Fix #1047 move completed does not work if saving to non default path 2009-10-27 03:08:47 +00:00
b12b5a8403 Fix typo in changelog. 2009-10-26 03:10:29 +00:00
0b5a0ac9a0 Update translations 2009-10-26 01:54:19 +00:00
65e50d1992 Prep 1.2_rc2 release 2009-10-25 23:32:13 +00:00
ecd75ba424 modify the M.O.M so the API is practically the same as the O.M, so the only method that accepts an id is changeId 2009-10-25 17:48:28 +00:00
694051e876 Fix typo, update plugin info. 2009-10-25 13:42:11 +00:00
350c523e7d Fix exception when using the 'halt' command 2009-10-24 19:49:20 +00:00
dbece6a6f6 Fix create_plugin.py script 2009-10-24 05:51:26 +00:00
5c26a4b1cf Fix #215 ETA sort order 2009-10-24 04:56:10 +00:00
475a880dd9 Fix previous commit [5864] 2009-10-24 03:47:35 +00:00
b0702e6a6d Fix #799 translate connection status 2009-10-24 02:04:19 +00:00
e506147289 Fix starting plugins when the pluginmanager is started 2009-10-23 23:23:38 +00:00
3c4144e01a Remove '-dev' tag 2009-10-23 22:08:14 +00:00
d4f2c2eda8 Fix possible exception when trying to load pre-1.2 plugins 2009-10-23 01:15:30 +00:00
4a996a1b41 Fix 'autostart localhost if needed' option 2009-10-23 01:07:46 +00:00
e39d1ab679 fix removing torrents that fail to download when added via url 2009-10-21 20:30:07 +00:00
c49ab0c6b1 fix switching the options when a different torrent is selected
fix showing the private flag
2009-10-21 20:15:16 +00:00
9c412e8aff fixes to the M.O.M and the options details tab, still not 100% though 2009-10-21 19:48:44 +00:00
83f42f5bf8 show the infinity symbol if ratio is less than 0 2009-10-20 22:45:32 +00:00
039a41def3 just a slight tweak adding some trac wiki formatting 2009-10-20 22:35:02 +00:00
b94060c60d fix setting bandwidth limits via the statusbar 2009-10-20 22:33:18 +00:00
33301b3433 fix setting the add options in the mom 2009-10-20 21:53:54 +00:00
b9ae412d06 add support for returning all options for an id in the get() method 2009-10-20 21:32:32 +00:00
f55bc6c9d8 Add option to create torrent name sub-folders in extract folder
Fix issue where the plugin would not stop extracting files after being disabled
2009-10-19 02:10:43 +00:00
511bfd5d84 use os._exit() rather than exit() when forking 2009-10-14 15:53:31 +00:00
89f88f3beb big bunch of fixes to the M.O.M along with a couple to the O.M 2009-10-13 16:21:28 +00:00
b1b09fbe89 move the parameter type converting into a seperate method 2009-10-13 15:22:24 +00:00
07b50730a2 improve the forking code 2009-10-13 15:20:45 +00:00
5607e0f6fa change all the 2 space gaps to tabs so vim hightlighting doesn't look irritating 2009-10-13 12:01:20 +00:00
9ab638377b add the option to fork the webui 2009-10-13 11:32:40 +00:00
4b79ae8280 fix a bug in the connection manager where the host list wasn't refreshed after a host was added 2009-10-13 09:56:49 +00:00
f1a1fdb630 update the changelog 2009-10-12 16:46:14 +00:00
d1f52a7051 allow setting of the value without firing an event 2009-10-12 16:45:28 +00:00
000297dc95 give names to both the radio buttons so they end up in a group (duh) 2009-10-12 16:44:30 +00:00
81eeb6edf7 fix a bug in converting non-boolean values back to boolean in the options manager 2009-10-12 09:53:13 +00:00
7d67da4371 Fix saving torrent state on fresh configs
Do not try to call doIteration() on the reactor if it has already stopped
2009-10-11 18:46:35 +00:00
ef5739a6a8 change the value of torrent.queue from -1 to 99999 so the grid sorting works the same as the gtk ui 2009-10-10 14:06:08 +00:00
4f968b9887 add a man page for deluge-web 2009-10-10 13:45:31 +00:00
22447993fa Add man pages for deluge-console and deluge-gtk
Update the other man pages
2009-10-09 16:26:10 +00:00
58be1f08fc Fix localclient authentication by stripping the lines read from the auth file 2009-10-09 00:39:57 +00:00
41d26bbbce Fix path errors when adding torrents externally in Windows 2009-10-09 00:19:07 +00:00
f1383f9655 Update ChangeLog 2009-10-08 02:59:24 +00:00
644f0ecb38 Modify setup.py to allow building without libtorrent/ 2009-10-08 02:51:49 +00:00
42a57b1f41 Fix quitting in Windows 2009-10-08 02:42:22 +00:00
8f50687034 Make sure libtorrent.pyd is included in bbfreeze 2009-10-08 02:42:00 +00:00
9f661caee8 Update win32 folder 2009-10-08 02:18:48 +00:00
044306cb3d Update gettextize.sh script to use proper encoding
Regenerate deluge.pot
2009-10-05 00:00:37 +00:00
ebd0290e44 Add script to regenerate the POTFILES.in file
Update the POTFILES.in file
2009-10-04 23:48:18 +00:00
4f1713734f Remove feeder, example and stats plugin from 1.2 2009-10-04 23:24:45 +00:00
f86e319d49 Update setup.py 2009-10-04 23:19:34 +00:00
95bb8fb4c3 Branch 1.2 2009-10-04 23:13:40 +00:00
718a12b492 Update ChangeLog and README 2009-10-04 23:07:24 +00:00
34b25d77f1 Fix blocklist plugin 2009-10-04 22:47:27 +00:00
b680ff48e5 Use new method to add plugin tab
Stop graph tearing
Patches from Ian Martin
2009-10-04 19:25:10 +00:00
9a0b6030e6 Allow plugins to properly add tabs and have them restored upon restart - patch from Ian Martin 2009-10-04 19:24:15 +00:00
0e532c7f4e Commit #1019 allow up to 4 MiB piece sizes 2009-10-04 19:15:35 +00:00
384a828795 Commit #850 make urls clickable in the comments field 2009-10-04 19:11:37 +00:00
5c481c3b13 A few fixes for the blocklist plugin 2009-10-04 19:09:06 +00:00
c3193f3c70 Add support for forward slashes in config setting 2009-10-03 22:53:21 +00:00
cb36beded4 Fix #1018 issue with 2nd level folder rename in the gtkui and save resume data on file/folder renamed 2009-10-03 22:10:38 +00:00
fbd6db859f fix bug in the tracker icons resource 2009-10-03 20:44:19 +00:00
d28e5998b9 Commit Ideal's one fastresume file patch with some tweaks 2009-10-03 00:15:43 +00:00
0a9cccb5e8 Fix up the sizing of the downloads preference page 2009-10-01 10:51:27 +00:00
5be72551f0 add copyright header 2009-10-01 10:46:35 +00:00
e1f68fb8fa fix the package name in common
change the script name in webui
add copyright headers to the js file and change indentation
2009-10-01 10:45:59 +00:00
365d21ed04 rename deluge-execute.js to execute.js 2009-10-01 10:43:03 +00:00
2d10f88714 add the missing s to %(filename)s 2009-10-01 10:40:48 +00:00
3d83dab4a1 add a GPL copyright header to the javascript plugin template 2009-10-01 10:39:09 +00:00
c17eb14dd2 remove the paranthesis from the export deco since they aren't needed anymore 2009-10-01 10:36:10 +00:00
95af21eca9 fix up the webui side of the plugin, even if it is skeletal 2009-10-01 10:35:46 +00:00
8fd03cb9ac remove the template folder, since the webui no longer uses templates 2009-10-01 10:33:50 +00:00
9d6aeaecdb add the common module that now exists in most plugins 2009-10-01 10:33:02 +00:00
02e7a7d361 fix web plugin entry point 2009-10-01 10:32:20 +00:00
a0a8c598da move the code that updates the buttons in the CM depending on the host status into a single method 2009-10-01 10:25:11 +00:00
eae452dbe4 change indentation to 4 spaces 2009-10-01 10:12:56 +00:00
3baa1a18d4 disable the connect button if the host is offline 2009-10-01 10:09:21 +00:00
6b13eeeb38 change the _libtorrent module so that the included libtorrent is checked for the correct version also (incase people have been following svn and the version requirement changes) 2009-09-29 09:24:16 +00:00
9fafa31afe fix silly bug in the setup script. bad damoxc. 2009-09-29 09:20:25 +00:00
fd9bf112c4 just some whitespace changes 2009-09-28 16:53:52 +00:00
3f8abf1e34 move the stateful stuff to Deluge.js before any other js has executed 2009-09-28 16:48:02 +00:00
d075ac888e use the version check within deluge so the correct version is checked for 2009-09-28 15:18:51 +00:00
a4d1fbd0bd Fix unbound local error when adding a torrent fails. 2009-09-26 16:25:16 +00:00
66402b7526 Remove some unnecessary dependencies 2009-09-26 03:15:09 +00:00
0be6d83d92 Remove 'state_location' and 'config_location' preferences and all references from the code. We should use configmanager.get_config_dir() instead. 2009-09-25 00:57:22 +00:00
7749f99828 change the labelAlign to top and icnrease the width of the fields 2009-09-24 16:42:36 +00:00
51b15c78a8 add a comment and remove one of the OLD_CONFIG_KEYS 2009-09-24 15:56:42 +00:00
5c5a0712b0 only try and load the old config if the file exists 2009-09-24 15:55:21 +00:00
fb154eaba9 Set the maxValue of the port spinner to 65535 2009-09-24 14:26:05 +00:00
9df5269fee give a bit more love to the connection manager, updating buttons when the host status is updated as well 2009-09-24 08:41:00 +00:00
8270c397da fix bug in the start_daemon method 2009-09-24 08:37:20 +00:00
e0671a0daa fix bug in the stop_daemon method 2009-09-24 08:35:40 +00:00
1b6d92c778 add a start_daemon method 2009-09-24 08:33:35 +00:00
401aa28ba8 update deluge-yc and ext-extensions 2009-09-24 08:11:11 +00:00
9bdcb04cb3 change the spinner strategy so it's an integer 2009-09-24 08:08:43 +00:00
68b4af839f disable the remove button and the stop daemon button when no host is selected 2009-09-23 19:10:44 +00:00
ce449e7b3b fix bug when upgrading old passwords on new logins 2009-09-23 18:16:08 +00:00
a23812f880 Fix #1014 autoadd should verify that the autoadd location is a directory 2009-09-21 05:39:43 +00:00
0d2c73063c Fix previous commit to recursively copy the args 2009-09-19 05:41:36 +00:00
9c40b777f3 Make a copy of the args and kwargs when making a daemon call in classic mode.. This makes it's
behaviour to the same as when making a RPC
2009-09-19 05:16:33 +00:00
3f8441af6a Update the about dialog and have it show the core version and libtorrent version 2009-09-19 00:18:14 +00:00
3901f3e6b2 update the create_plugin script allowing for the new webui plugin stuff 2009-09-17 07:36:13 +00:00
5645d6644d update the example plugin with the new webui plugin stuff 2009-09-17 07:27:33 +00:00
2f49c5cfa7 rewrite the plugins page using the new get_plugins method in the web json api
update the grid when a Plugin{Dis|En}abledEvent occurs
2009-09-16 09:53:49 +00:00
037fbcaaa7 store remote events and register them when the events are started 2009-09-16 09:39:30 +00:00
f831cdce9a add a method that returns both the available and enabled plugins to reduce the number of AJAX calls required 2009-09-16 09:38:46 +00:00
443b4854b4 remove the test children accidentally left in 2009-09-16 09:38:17 +00:00
13109f8a1f just a couple of small tweaks 2009-09-16 09:03:30 +00:00
e4fb98bd02 add a working javascript loader
implement the core code for disabling/enabling plugins on the fly
2009-09-16 09:02:26 +00:00
b2390b8ff4 have the plugin manager remove the scripts and directories from the server when a plugin is disabled 2009-09-16 08:42:39 +00:00
92ecb3fe87 don't enable plugins until connected to a daemonm 2009-09-16 08:32:33 +00:00
63aa818c47 remove the seeds status key from the Peers key list 2009-09-15 11:51:03 +00:00
dcfa83bf09 remove the js loader, doesn't work correctly 2009-09-15 07:29:08 +00:00
cd0f4f69fb have the help button open the user guide on the wiki 2009-09-15 07:28:09 +00:00
dd519f936c tie up the find more button so it opens the plugins page on the wiki 2009-09-14 21:28:02 +00:00
45840727e9 add a js loader class, taken from http://www.extjs.com/forum/showthread.php?p=272104 2009-09-14 16:32:23 +00:00
137be4c8f1 add a method to gather the plugins resources for when they need to be loaded after the ui 2009-09-14 16:31:59 +00:00
6fc1e23fce indicate whether the UI is in debug mode via an additional script tag in the index page 2009-09-14 16:24:47 +00:00
3c02a499a5 stop a session from subscribing to the same event more than once server side 2009-09-14 16:04:52 +00:00
fc1b1a6aa8 improve the plugin manager so that it handles the adding and removing of scripts 2009-09-14 15:56:09 +00:00
b164fef0c5 extend the Deluge.Events class to include support for subscribing to the remote events 2009-09-14 15:55:36 +00:00
daab4aade6 fix a KeyError in the JSON component
implement the EventQueue for the server side handling of events
2009-09-14 15:41:12 +00:00
aa4202b9ed add enable/disable methods to the JSON component
remove the empty enable/disable plugin methods from the web api
2009-09-14 10:36:40 +00:00
da5697490d change the scheduler plugin to use the new plugin architecture 2009-09-14 10:26:59 +00:00
63b02f28d1 change WebPluginBase so it has empty enable/disable methods (web plugins don't need to enable/disable themselves, it's optional) 2009-09-14 10:26:29 +00:00
e7095195f7 fix enabling plugins when the UI is created
change Deluge.Plugin so it implements the enable/disable methods that merely fire events that the plugins can use
2009-09-14 10:19:15 +00:00
4df98df1f2 change Deluge.Plugins to an object rather than array 2009-09-14 10:07:56 +00:00
3d33696c94 add copyright headers to all the preference pages 2009-09-14 10:05:53 +00:00
fef34b3f6f fix the plugin base class scope in the constructor
enable plugins when the UI is initialised
add an array for plugins to put in
2009-09-14 10:02:35 +00:00
7d495e2a16 add a javascript base class for plugins 2009-09-14 09:44:35 +00:00
77253f835c return a 404 if no resource is found, also enable the JSON component when the server starts 2009-09-14 09:25:27 +00:00
3367d0af48 improve the LookupResource class so plugin resources can be put in a sub directory 2009-09-14 09:23:46 +00:00
5e829ca160 tidy up the config dictionary and add default_daemon option 2009-09-14 08:18:29 +00:00
0bc97733bf Do not fail to start if deluged.pid contains no data 2009-09-13 17:17:37 +00:00
7343c5bb39 Fix typo and logic error. 2009-09-13 15:33:45 +00:00
2b46224ef1 Readers raise ReaderParseError when parsing b0rks.
on_import_failure, now handles parse errors.
2009-09-13 14:45:23 +00:00
0952f84d6c Detect now handles creating a reader.
Finished writing detect_format and hence auto_detect (could it really be?)
is_valid() doesn't need to take in a filename (already has it).
2009-09-13 13:51:00 +00:00
d6597bdc22 Added is_valid method to readers.
detect_format now takes in optional compression type.
2009-09-12 14:25:38 +00:00
5573d7ef7d fix indentation 2009-09-10 14:26:14 +00:00
1ebb490e4e fix an AlreadyCalledError when getting a hosts status 2009-09-10 14:19:05 +00:00
a78ab9529f Fix up the Execute plugin's gtk code 2009-09-09 20:47:12 +00:00
3d4e05b5e0 Run the plugin's show_prefs callbacks before the preferences dialog's show() 2009-09-09 20:04:04 +00:00
9c641bb6d0 Fix more indentations 2009-09-09 17:08:00 +00:00
9c6ff72a83 Fix indentation 2009-09-09 17:05:13 +00:00
c0276a541c improve the WebPluginBase class, registering it with the json rpc-api and adding space for scripts/stylesheets 2009-09-09 16:51:44 +00:00
c333ad4f6a remove obselete plugin base file 2009-09-09 16:39:35 +00:00
0ddb1526a1 Add 'plain' as a possible ico type 2009-09-09 05:12:41 +00:00
aca9e853d7 change UTC to GMT and add a method for generating the expires int and string 2009-09-08 09:55:19 +00:00
2caee15f7f Pretty up the Proxy preference page by dynamically showing/hiding fields as needed 2009-09-07 20:47:51 +00:00
b849a4b451 Fix #1009 enabling a plugin twice in the gtkui
Prevent plugins from being enabled more than once in pluginmanagerbase
2009-09-05 19:32:01 +00:00
d1c6e551a9 another patch from David Mohr adding basic cookies support in core 2009-09-04 16:30:56 +00:00
82682dbb2d applying patch from David Mohr replacing the Timer object with LoopingCall 2009-09-04 15:58:41 +00:00
4e3f4128fa Apply patch from David Mohr to make core.py more 1.2 compatible 2009-09-02 22:36:34 +00:00
a6ab62f7ce re-set the _session_id cookie updating the expires time 2009-09-01 22:39:34 +00:00
5d85af9adf Add SSL exception to license in the about dialog 2009-08-31 22:16:39 +00:00
9712d1c16f Updated the feeder __init__.py for 1.2 2009-08-31 19:07:11 +00:00
753e17d612 importing the feeder-plugin for porting to 1.2 2009-08-31 18:55:51 +00:00
7a09ef5356 add the beginnings of the plugins preferences page 2009-08-27 19:13:45 +00:00
f10bf6961b Add PluginEnabledEvent
Add PluginDisabledEvent
Add event handlers to enable/disable plugins on events
2009-08-26 16:59:29 +00:00
6ca835314e add a method for grabbing plugin info 2009-08-26 08:53:58 +00:00
32ed499b2a connect up the key-press-event and have the context menus pop up when the menu key is pressed 2009-08-24 22:13:54 +00:00
bcbe3108c9 ensure the port is a Number 2009-08-24 20:08:03 +00:00
00882ac867 Hide the 'Open File' menu option when connected to a remote daemon 2009-08-23 20:46:31 +00:00
df72c38f22 ensure that the value is a number 2009-08-21 01:06:22 +00:00
24db5bd72a make sure the value is a float 2009-08-21 00:57:08 +00:00
a75405feb0 working version of the proxy preferences page with field hiding, config saving, the whole shebang 2009-08-21 00:50:56 +00:00
aa97b5a273 allow the preferences config panel to overflow and tweak the pages so only the ones required to overflow do so 2009-08-20 23:50:59 +00:00
80634db44c Fix num_pieces calculation 2009-08-20 22:27:40 +00:00
1b3448ad91 add spinner strategies to all the spinners on the bandwidth page 2009-08-20 01:23:04 +00:00
f127d1c451 decrease the margin-top on the server fieldset 2009-08-20 01:19:18 +00:00
e2fb2ddd03 tweak the layout slightly 2009-08-20 01:12:43 +00:00
e05e0b4e35 add support for binding an option to multiple fields 2009-08-20 01:08:09 +00:00
9962206907 include yet more preferences (ssl, port, certificate locations) 2009-08-20 00:55:58 +00:00
937f8715a4 only output config keys that the ui needs in /config.js 2009-08-20 00:54:57 +00:00
54083e0a7e remove some unused configuration values 2009-08-20 00:47:27 +00:00
88471024d9 have the option manager return the field from a bind 2009-08-20 00:47:02 +00:00
e676bcf576 add the session timeout to one of the options on the interface preferences 2009-08-20 00:32:32 +00:00
1a635e8860 only return deferreds for those methods that require it 2009-08-20 00:31:31 +00:00
7d0ccb8847 fix returning the call when the method doesn't return a deferred 2009-08-20 00:27:34 +00:00
ea3f8b7d34 fix the message boxes on the return of the password change call 2009-08-20 00:12:41 +00:00
56aca8f2f9 rewrite the interfaces preferences page as a class
implement password changing
2009-08-20 00:05:35 +00:00
c94c9c36e4 have the change_password method accept an old_password parameter for extra checking
move the password checking logic into a seperate check_password method
2009-08-20 00:04:55 +00:00
865027b3ec increase the expires time each time a session is checked for authentication 2009-08-19 23:30:36 +00:00
9f3ef6556a add an isObjectEmpty method to Ext to test to see if an object == {}
fix a couple of bugs in the options manager
only call core.set_config if there are changed options
call all the pages onApply method if they have one
2009-08-19 23:17:50 +00:00
b4547c0bf0 add a show_session_speed option
add a get_config() method to the web api
2009-08-19 23:16:19 +00:00
219a509bee Fix terminal resizing support 2009-08-19 22:13:58 +00:00
39a09f2704 Fix piece size calculation 2009-08-19 02:14:29 +00:00
4ca5f9a371 Use piece_sizes in KiBs
Fix bug with webseeds
Fix bug with multi-level directories
2009-08-19 01:45:55 +00:00
4014b3fba9 remove an extra creation of the options manager 2009-08-18 22:19:09 +00:00
97163b7cb0 change the session timeout to be configurable 2009-08-18 22:04:58 +00:00
199a307cd9 Add 'cache' command to the console ui to display the cache status 2009-08-17 20:21:02 +00:00
3d3f7e53f9 Fix docstring 2009-08-17 20:20:45 +00:00
fed7392a5d Add a 'plugin' command to the console ui to enable, disable and list available/enabled plugins 2009-08-17 20:09:22 +00:00
fb4e4856d1 Show an error instead of crashing when trying to use a command option without a required argument 2009-08-17 19:13:09 +00:00
2b31544754 Fix console ui from crashing when the terminal size is shrunk 2009-08-17 18:02:56 +00:00
06ecfceb74 Fix print torrent info to the console 2009-08-16 17:13:34 +00:00
66eaa4071d Add the auth level to the RPC Export docstring
Fix up docstrings in the rpcserver module
2009-08-14 23:11:22 +00:00
2681acbc8d Add 'RPC Exported Function' to the beginning of every docstring on rpc exported functions 2009-08-14 22:47:28 +00:00
567a42b0ec Fix some docstrings 2009-08-13 05:02:39 +00:00
74ed19b5f2 Do not use property decorators as 2.5 does not support .setter et al 2009-08-12 21:18:39 +00:00
f562e8aff3 remove log messages as they don't work 2009-08-12 08:20:19 +00:00
8ef55c380e add a log message stating which json encoder is being using 2009-08-12 07:24:10 +00:00
c35535edc3 Print libtorrent version in the log 2009-08-12 07:22:13 +00:00
bd5998ec05 Remove gtkui.rst for the time being 2009-08-12 07:17:21 +00:00
c33cf71b62 stop using get_stats and fix the protocol overheads in the statusbar 2009-08-12 00:59:19 +00:00
b431368b67 remove cruft in the preferences folder 2009-08-12 00:43:40 +00:00
58c3b60ca7 add a new preferences page for encryption 2009-08-12 00:42:48 +00:00
a207e1010b increase the width of the spinners on the bandwidth page 2009-08-12 00:19:33 +00:00
5376ae307a Add maketorrent.rst 2009-08-12 00:11:08 +00:00
b74fdcf558 fix calling core methods 2009-08-12 00:10:07 +00:00
1cfc057b05 Add new maketorrent module 2009-08-12 00:09:22 +00:00
c9b8428106 change onLogout to logout 2009-08-11 23:58:19 +00:00
2c65d21b0b remove rogue print statement 2009-08-11 23:57:54 +00:00
3ed6e28adc fix the scope of the each loop 2009-08-11 23:56:35 +00:00
7f597aff70 fix for when the login window hasn't been rendered 2009-08-11 23:55:01 +00:00
6b8ff92fe2 improve the connection manager 2009-08-11 23:43:56 +00:00
3e8c17b071 complete the new auth system using cookies & sessions 2009-08-11 23:39:58 +00:00
1b17d66576 add a missing method 2009-08-11 23:15:42 +00:00
444272344e change it so the event is only subscribed to for a single fire 2009-08-11 23:15:20 +00:00
7c0590f399 fix a bug when firing the error event 2009-08-11 23:14:38 +00:00
c0d0498f36 Add rst files for all the modules 2009-08-11 23:05:13 +00:00
ba909ebcc9 add an error event to the rpc client 2009-08-11 22:53:53 +00:00
074c2f85a5 return if stats is null or false 2009-08-11 22:51:37 +00:00
6334820a5d stop the update_ui method from calling core methods when the client isn't connected
make the current http request available to exported methods via a __request__ global that gets set before each call
2009-08-11 15:22:59 +00:00
2de8069c9f add an onOk event handler that saves and closes the preferences window 2009-08-10 10:24:45 +00:00
78df3d10ce fix update calls in a few places 2009-08-10 09:58:51 +00:00
01ec3f5b5a change runCheck to update 2009-08-10 09:56:43 +00:00
33d889aaf8 add dump and load methods to the json module if it isn't simplejson 2009-08-10 09:46:57 +00:00
2bece0e03d add everything aside from encryption to the network preferences 2009-08-07 07:33:35 +00:00
38aaea29a0 increase the icon size to 64 so it doesn't look crummy in application switchers that use large icons 2009-08-07 07:31:27 +00:00
c2361f5865 update javascript to ext 2.3 2009-08-07 07:10:55 +00:00
bf0218d785 update the doc string for export 2009-08-07 07:09:53 +00:00
c154301dbd Add a force recheck command to the console 2009-08-06 20:16:23 +00:00
299add850c Have the console command 'info' display all torrents info when no argument is given 2009-08-06 20:15:52 +00:00
7b9fe6ea94 working implementation of the port configuration 2009-08-06 19:03:08 +00:00
5af8fec10a add a spinnergroup widget to make the port sections in the network preferences easier 2009-08-06 18:58:37 +00:00
9bf89455e6 Get the number of rows/columns on refresh() 2009-08-06 18:21:18 +00:00
8425e9915d Move the add_torrent_url_with_cookie url to our server 2009-08-04 01:01:26 +00:00
fa2dedda73 add an override to setValue within the ext spinner extension so setValue amounts are run through the strategy 2009-08-03 22:26:18 +00:00
f216ffe54e Add a comment 2009-08-03 21:45:03 +00:00
ea57cad95b call check_ssl_keys prior to listenSSL 2009-08-03 21:41:53 +00:00
ee573b4816 Add a check_ssl_keys() function that will check for the keys and generate them if needed 2009-08-03 21:39:06 +00:00
352ec837d5 add a webui plugin to core and gtk for integrating the web interface with the core 2009-08-03 21:37:35 +00:00
706c52dd1b Move generate_ssl_keys() out of RPCServer 2009-08-03 21:34:07 +00:00
ac9be780cf Revert 5619
Fix find_json_objects when there is a newline at the end of the string
Add test for find_json_objects
2009-08-03 20:27:03 +00:00
5f561dabda fix a bug in the Config class relating to the config directory 2009-08-03 19:49:47 +00:00
c0ce36b216 only stop the port/socket if one exists
add a start_reactor=True param to the start method
2009-08-03 19:23:27 +00:00
76587be1a7 change the pluginmanager component name to Web.PluginManager 2009-08-03 19:21:53 +00:00
e496fda499 fix for when there isn't a save timer yet 2009-08-03 19:04:54 +00:00
704435f721 Config copies the defaults dict now since it is mutable
Fix saving with the save_timer after setting an item
Add test for testing the save timer
2009-08-03 18:43:05 +00:00
e8b04c1542 Add a test for saving the config 2009-08-03 17:39:12 +00:00
abc3964f73 Reset the config_files when the config directory changes 2009-08-03 16:56:01 +00:00
c2299b793c add .gif images from the images folder also 2009-08-03 16:27:45 +00:00
1f817b3d56 change it so starting in ssl mode is left up to the server
add a stop method that doesn't stop the reactor
2009-08-03 15:40:58 +00:00
a14f4f6869 Fix get_deluge_icon 2009-08-03 14:40:24 +00:00
4cfa6485d7 remove the paranthesis from the decorators in core.py 2009-08-03 11:46:49 +00:00
92a37b7d81 Make sure url, filename and headers are strings before downloading. 2009-08-01 03:00:04 +00:00
9b0d4f6118 Add support for cookies when adding a torrent by url.
Don't set torrent if torrentId is null.
Fix typo.
2009-08-01 02:38:30 +00:00
ded6bb9566 Change the config format
Add test_config
2009-08-01 02:26:26 +00:00
838cef1c36 Fix shutdown handler with GNOME session manager 2009-08-01 00:15:05 +00:00
eef9345e8b Add test file for httpdownloader. 2009-07-31 23:53:23 +00:00
d5f7df8a96 Fix issue where the column state wouldn't save if not using English 2009-07-31 18:47:42 +00:00
aeb087eb3d add the cache preferences page 2009-07-31 08:35:28 +00:00
bdaf0062af Don't clobber the label config 2009-07-31 07:52:01 +00:00
a528f78529 Properly unload Execute plugin when disabling it 2009-07-31 07:40:50 +00:00
2334fff388 Add support for the deluge-gtk start script 2009-07-31 00:57:04 +00:00
983e37d4ab Make sure the 'quit and shutdown daemon' menuitem is shown when switching daemons 2009-07-31 00:46:42 +00:00
ee442536a8 Fix properly disconnecting from the currently connected daemon when connecting to a different daemon 2009-07-31 00:39:09 +00:00
2089fd1823 Add gtkui.common.get_deluge_icon() and use it 2009-07-31 00:18:35 +00:00
26af4214fa add the other preferences page 2009-07-30 23:49:34 +00:00
1429b87da7 disable all the textfields that should have accompanying checkboxes 2009-07-30 23:49:05 +00:00
b8b292c7fb convert the other icons that i could see to the icon theme 2009-07-30 23:46:03 +00:00
91c5028701 use the icon theme's icon where available 2009-07-30 23:41:27 +00:00
974b9a5f3c Fix showing some menuitems when disabling classic mode due to an already running daemon 2009-07-30 23:38:14 +00:00
e6cf3a2fd9 Fix saving column widths when quitting from the tray with the window hidden 2009-07-30 23:23:16 +00:00
2447ed4425 add the indent class and also apply it in the options tab 2009-07-30 23:14:12 +00:00
48ba81b61b add a strategy to the daemon port spinner 2009-07-30 23:13:49 +00:00
63af59ab46 finish the queue preferences page 2009-07-30 23:11:28 +00:00
ccaf4e65f7 Increase the seed time limit spinner max value to 10000 2009-07-30 22:51:44 +00:00
5998eea0bd hide all the preferences page upon the first page change and don't set the width/height 2009-07-30 22:32:58 +00:00
0c4cc4d0e2 fix the dodgy splitter positions on the spinners 2009-07-30 22:26:23 +00:00
8ad774cd3c build the config panel in the initComponent method 2009-07-30 22:14:37 +00:00
c383345cd9 Use the proper download_location when adding a newly created torrent to the session 2009-07-30 22:04:23 +00:00
9c4b6afc05 listen to the 'check' event on the field also incase it is a checkbox 2009-07-30 21:50:16 +00:00
c76e67b109 convert the daemon preferences page into a class 2009-07-30 21:42:04 +00:00
525ffee93e Fix up some docstrings 2009-07-30 21:41:51 +00:00
15dd22812d Fix a bug in the sidebar states when show zero is checked 2009-07-30 21:37:01 +00:00
f07c0d9894 Implement better version check when importing libtorrent -- account for minor version numbers 2009-07-30 21:27:36 +00:00
d685b2ddd6 Move the VersionSplit class to deluge.common 2009-07-30 21:14:50 +00:00
90789982f7 fix the config names of some of the fields 2009-07-29 16:35:52 +00:00
abb05829dc disable setting bandwidth limits via the statusbar for the time being
make the uxpsinner fire the change event when they spin
2009-07-29 16:16:03 +00:00
ee16bffbbd add a cookies field to the url window 2009-07-29 16:05:27 +00:00
97a7890a28 fix a bug in the add torrent via file in browsers other than FF 2009-07-29 10:17:10 +00:00
9b56fab8a1 fix the build script to include the multioptionsmanager and rebuild 2009-07-29 09:59:10 +00:00
999803fce5 set the server to always run in debug mode if 'dev' is in the version 2009-07-29 09:11:19 +00:00
0ac8e39dda build and commit the compressed copies 2009-07-29 09:01:11 +00:00
f031ec5628 increase the widths of the textfields and pass in inputValue rather than value to the radiogroup 2009-07-29 08:58:28 +00:00
5ec004b2ff use item.el.getValue() to compare the value when picking the radio in the radiogroup 2009-07-29 08:55:24 +00:00
a62c545d4a fix a bug in setValue for the RadioGroup 2009-07-29 08:22:19 +00:00
82a4367aa9 use boolean values rather than string values for the radiobuttons 2009-07-29 08:19:45 +00:00
f4b34637dd add the new bandwidth pane in the compressed file 2009-07-28 23:37:11 +00:00
21f09a636a an initial attempt at the bandwidth pane 2009-07-28 23:33:37 +00:00
58b5c1a68f the first iteration of the preferences window that loads AND SAVES preferences (at least the paths in the downloads section) 2009-07-28 22:39:32 +00:00
be07281207 allow set to take an object of options and also update bound fields after the set 2009-07-28 22:31:57 +00:00
deac8e0128 add a property to the field object since we can't use a bi directional lookup in javascript :( 2009-07-28 22:04:00 +00:00
174d974da8 tweak the doc strings (although jsdoc-toolkit still seems to be failing) 2009-07-28 21:51:58 +00:00
eb889c1e33 change the way bound fields work within the optionsmanager 2009-07-28 20:58:24 +00:00
34b0289f24 change Deluge.OptionsManager to only handle a single set of options, and add Deluge.MultiOptionsManager to manage multiple sets 2009-07-28 18:01:58 +00:00
ed4a741e4d make the config constructor parameter optional 2009-07-28 16:53:40 +00:00
9e10012004 make the deprecation warning on get_stats say that its coming from get_stats 2009-07-28 07:39:30 +00:00
ba6f30dad1 Add a deluge._libtorrent module to handle importing libtorrent
Use the new module
2009-07-26 03:26:18 +00:00
100dd1e2a7 Fix test_client 2009-07-25 04:05:00 +00:00
ac36c6b3ee Blocklist now uses get_ip_filter.
Added docstrings.
2009-07-25 03:57:45 +00:00
ac28a01e0b download_file now returns the filename of the downloaded file
when the deferred is successfully fired.
Updated the docstrings in HTTPDownloader.
2009-07-25 03:56:33 +00:00
2731d5be17 Fix get_free_space test 2009-07-25 01:49:05 +00:00
a8c79d1954 Use the deferred returned by getPage in test_listen_port. 2009-07-25 00:54:56 +00:00
22a982430c Remove _update method 2009-07-25 00:41:20 +00:00
25f96f57bb Remove some unnecessary code
Clean up docstrings
2009-07-25 00:39:25 +00:00
e24ba6a025 Change core.test_listen_port to use twisted instead of urllib
Add test for test_listen_port
Remove some unncessary code
2009-07-25 00:30:45 +00:00
321e042a06 Move the InvalidTorrentError check to torrentmanager.remove 2009-07-24 23:40:03 +00:00
5977647528 Add get_free_space() to core 2009-07-24 23:36:43 +00:00
f6d3c108f7 Add InvalidTorrentError. 2009-07-24 10:32:14 +00:00
034606b203 fix the remove torrent dialog 2009-07-23 22:30:08 +00:00
037871e1b3 Fix up some docstrings
Add some deprecation warnings
Add more tests for core
2009-07-23 21:19:01 +00:00
fbaa8db003 Update some docstrings 2009-07-23 04:23:41 +00:00
1b7be24bdf Change core.remove_torrent to only accept one torrent_id, not a list
Added test for core.remove_torrent
2009-07-23 04:14:08 +00:00
0ca5a10d5e Couple more tweaks to the docstrings 2009-07-23 00:46:23 +00:00
0fa403929a update the docs for the ui common module 2009-07-23 00:42:38 +00:00
996d8fd2cc Test commit 2009-07-23 00:27:43 +00:00
5f89f5239e add autodoc for ui.common
fix some docstrings in the json_api module
2009-07-23 00:24:07 +00:00
94891cb1f6 Test commit 2009-07-23 00:23:48 +00:00
d7168f5f49 Test commit 2009-07-23 00:20:57 +00:00
129f3bb7c7 Test commit 2009-07-23 00:19:43 +00:00
1291fd52d1 Test commit 2009-07-23 00:13:54 +00:00
41b3d555c3 Test commit 2009-07-23 00:09:13 +00:00
3af616adb1 Test commit 2009-07-23 00:07:27 +00:00
d972a0c951 Test commit 2009-07-23 00:06:44 +00:00
a29cd7bf1e Test commit 2009-07-23 00:01:21 +00:00
5ca119827b update documentation about the webui 2009-07-22 23:53:30 +00:00
aef0a4616f Don't depend on sphinx to build 2009-07-22 23:52:18 +00:00
5278c82580 Add a version for twisted-web too 2009-07-22 23:40:58 +00:00
a1e41d1fe6 Add required version for twisted. 2009-07-22 23:35:54 +00:00
50ba89659c Remove some unncessary code 2009-07-22 23:06:24 +00:00
ead063e279 Add a 'build_docs' command to build the documentation 2009-07-22 23:04:48 +00:00
85c49595ee update the doc string for add_torrent_url 2009-07-22 20:56:08 +00:00
e5021cdbc8 remove the docs/build folder
revert the removal of the __rpcapi file for auto-generating the rpc api docs
2009-07-22 20:50:06 +00:00
46b5e9b406 exclude docs and tests from find_packages also 2009-07-22 20:31:16 +00:00
f1c192b996 just autodoc the Core and Daemon classes rather than use the RpcApi class 2009-07-22 20:23:16 +00:00
063c8b3980 add the deluge remove js script to the debug list
add a css class for the windows icon
2009-07-22 20:11:18 +00:00
fafe2d3bea add a new window for removing torrents that allows the torrent data to be also removed 2009-07-22 18:57:24 +00:00
88c77f063d Update to the latest ez_setup.py 2009-07-21 18:02:49 +00:00
c9228c99a7 Updated docstring in add_torrent_url.
Wrote test for add_torrent_url which tests sending headers.
2009-07-21 02:45:16 +00:00
698d37f535 setup automatically generating the core's rpc api 2009-07-20 10:51:33 +00:00
8a25bd4adc add a page on deluge-rpc 2009-07-20 10:25:21 +00:00
891bc9df89 use configmanagers get_config_dir rather than get_default_config_dir 2009-07-20 10:08:29 +00:00
6bb4d857c2 add some logging showing pkey/cert locations when starting the webserver 2009-07-20 09:57:17 +00:00
2591845512 Fix error when trying to install. 2009-07-20 09:41:44 +00:00
3c74a8e4bf update the docs, creating a simple structure for user orientated documentation 2009-07-20 09:36:16 +00:00
8bb70f1671 rebuild the docs 2009-07-20 09:09:53 +00:00
c62258fa48 move docs out of the deluge package 2009-07-20 09:02:09 +00:00
cd7b202d9d moves tests out of the deluge package 2009-07-20 09:01:43 +00:00
ae5011ec92 setup the build_spinx command 2009-07-20 09:00:47 +00:00
dcccc3f4de add_torrent_url now uses httpdownloader's download_file.
This also allows it to send request headers.
As a result it can download torrents from sites that require cookies.
2009-07-20 08:47:32 +00:00
3a94a33b56 just return the deferred created by httpdownloader 2009-07-20 08:39:46 +00:00
a2893cc1b7 change download_torrent_from_url to use the httpdownloader module 2009-07-20 08:20:17 +00:00
e1ee5c3436 Blocklist reader's read() now calls callback with two arguments: start and end.
This will allow us to better detect when a blocklist reader fails to parse an entry.
Renamed is_valid to is_ignored to make the purpose of the function less ambigious.
2009-07-20 04:49:55 +00:00
8fbe456410 change BLANK_IMAGE_URL to /images/s.gif rather than http://extjs.com/s.gif
begin converting D.P.D to a class
2009-07-16 13:25:00 +00:00
9aec641965 set the mimetype for the documentation 2009-07-16 09:43:36 +00:00
45eb817301 make the locations of the pkey/cert configurable 2009-07-16 09:24:55 +00:00
aa05a27d28 use the same ssl key and certificate as the daemon (will add the option to specify a different one later) 2009-07-16 08:58:05 +00:00
0490df5a42 clear the options panel when the add window is closed 2009-07-15 18:56:41 +00:00
2450599789 trim the trim variable so there is no decimal point 2009-07-15 18:54:58 +00:00
929a501453 remove the borders on the GridPanels 2009-07-15 16:43:42 +00:00
ba91b6e587 Updated imports.
Added decompresser and reader dicts.
Make import_list actually import list into libtorrent session.
Begin auto-detection of blocklists.
2009-07-15 14:00:57 +00:00
4df5fe20ce Use wiki formatting in DEPENDS 2009-07-15 03:06:58 +00:00
35136b652d Update README and add a DEPENDS file that lists the dependencies 2009-07-15 02:50:26 +00:00
e9d7b71fe8 Changed decompressers names.
No longer use new module, decompressers will decorate an un-instantiated class.
2009-07-14 04:59:35 +00:00
c9a622b846 Prevent exception when clicking 'Rescan Plugins' button when not connected to a daemon 2009-07-13 21:55:34 +00:00
f42e8c4316 Show an Error dialog if starting the core in classic mode is unsuccessful 2009-07-13 21:44:21 +00:00
d0fb657ada Fix exception when quitting in classic mode 2009-07-13 20:23:17 +00:00
fbba1795ad Make the test port button insensitive when not connected to a daemon 2009-07-13 19:45:30 +00:00
0f453eb8f1 Fix some deprecation warnings regarding spinbuttons page adjustment size 2009-07-13 18:27:08 +00:00
bdcc0047a8 Fix opening the preferences window when not connected to a daemon 2009-07-13 18:26:40 +00:00
c4c6d1d511 Fix syntax error 2009-07-13 18:04:26 +00:00
f1350da011 Removed old code from get status. 2009-07-13 05:15:03 +00:00
4c9d01efe8 Removed type combo box from gtkui (will be auto-detecting type).
Removed old format readers.
Added new format readers and decompressers.
2009-07-13 05:12:26 +00:00
c7db93e954 rebuild docs 2009-07-12 23:33:54 +00:00
26b4f4020b disable the options tab in the add window (will complete post release) 2009-07-12 23:33:34 +00:00
2156d1f6f6 large changes within the optionsmanager
fix the details panel to reflect this
add setting of file priorities in the add window
2009-07-12 23:27:41 +00:00
324679de1f build the compressed version 2009-07-12 23:26:52 +00:00
3b810f5ce3 fix a bug in the radio group setValue when the buttons haven't been rendered yet 2009-07-12 23:23:05 +00:00
9762853d32 add a try/except block testing for openssl support before adding it as an option to the commandline 2009-07-08 18:07:12 +00:00
e9541ab7c6 Fix setting cache options 2009-07-08 07:10:15 +00:00
6a78e51475 Fix race condition when blocklist is up to date.
Make import_list return a deferred to prevent error (still doesn't do anything).
Fix typos.
2009-07-07 06:51:47 +00:00
2b789b501b Better fix for last commit.. AuthManager will now raise a BadLoginError if the username or password
does not match
2009-07-06 21:09:22 +00:00
b6793f7268 Fix client.connect() not firing the errback when a login attempt result is 0 (meaning no
authorization)
Fix console connect command
2009-07-06 20:00:41 +00:00
66243d1859 allow for the scope to be specified when calling the walkFileTree method 2009-07-06 11:51:06 +00:00
4cefabe2db add a generic method for walking the file tree in the add window 2009-07-06 11:36:12 +00:00
c2e3f3d228 Store removed columns' state so that plugin's columns are restored properly 2009-07-06 07:05:39 +00:00
9238fab360 Likewise for Windows close/shutdown events 2009-07-06 06:51:54 +00:00
594bc7cb9f Have the gnome "die" signal call gtk.main_quit instead of shutdown 2009-07-06 06:50:40 +00:00
c53af6af33 Fix status reporting. 2009-07-06 06:49:34 +00:00
b3a3b9e4f1 Fix loading old configs with version numbers 2009-07-06 06:38:06 +00:00
2909e285fc Fix restoring vpaned position when window is maximized
Fix stopping gtkui with ctrl+c
Fix showing the connection manager window in the certain of the window if maximized on start-up
2009-07-06 06:29:45 +00:00
efa125ac83 Fix starting plugins when enabled 2009-07-06 05:18:18 +00:00
cdddc38780 Put string conversion from last commit in correct place. 2009-07-06 04:54:45 +00:00
1f2072f8c2 Make sure last_update is an ascii encoded string. 2009-07-06 04:40:57 +00:00
d8e265011a Several blocklist fixes. 2009-07-05 18:38:51 +00:00
1b997b2349 The default format version and file version should be 1 2009-07-05 17:42:36 +00:00
e9f62ea08c Fix typos in blocklist core.
Remove reset_ip_filter and block_ip_range from deluge core.
2009-07-05 16:27:22 +00:00
75338d8a9e Make sure child folders of renamed folders are properly renamed in the torrent options 2009-07-05 16:25:05 +00:00
1b29d267cc Add / to the end of folder names when renaming 2009-07-05 16:19:47 +00:00
f221a39bcf Updated config values names in gtkui. 2009-07-05 06:20:19 +00:00
76bc45a3bf Add some tests for core 2009-07-05 01:17:38 +00:00
2ced8ad189 Change add_torrent_magnets to add_torrent_magnet
Have add_torrent_magnet return a torrent_id on successful add
2009-07-05 00:09:49 +00:00
054ab20402 Use deluge.configmanager.get_config_dir() to find the state folder location since the 'state_location' key in the config may be wrong if the config folder has changed 2009-07-04 23:59:38 +00:00
8c23baa4e2 Modify add_torrent_url to return a deferred that returns the torrent_id as a result if successful 2009-07-04 23:06:14 +00:00
7815f22a73 Stop some LoopingCalls when stopping components 2009-07-04 22:53:10 +00:00
061cd96096 Have add_torrent_file return a torrent_id on successful add 2009-07-04 22:52:41 +00:00
191d83c4be Added check to see if blocklist should be downloaded when load on start is enabled.
Updated function names in gtkui.
2009-07-04 17:05:50 +00:00
5b4d138baf Fix renaming files with / in them 2009-07-04 16:49:18 +00:00
016e99b728 Add a dep to the apt-get list 2009-07-02 18:51:26 +00:00
34def2524f Fix typo 2009-07-02 18:13:37 +00:00
a8b83281ab If a exported method returns a deferred, the rpcserver will now wait for it to fire before sending either the RPC_RESPONSE or RPC_ERROR message back to the client 2009-07-02 18:10:13 +00:00
85c32f0403 Use stored last_update for conditional get. 2009-07-02 15:40:13 +00:00
8e69a82881 Begin rewrite of blocklist (core) using twisted. 2009-07-02 15:29:57 +00:00
d317d5c857 update the sudo apt-get install line 2009-07-02 08:23:24 +00:00
0c0cfaf597 Clean-up the tests and add some new ones 2009-07-02 04:16:37 +00:00
883e61909f Fix deregister_handler 2009-07-02 04:10:20 +00:00
b9a2bf786c Write out the new auth file right away and do not re-read the file if doing so 2009-07-02 03:48:03 +00:00
bbb087c04a suppress only deprecation warnings 2009-07-01 13:56:36 +00:00
74627f682a use only "twisted" in the module arg as that suppresses all warnings from twisted 2009-07-01 13:51:56 +00:00
958c6334b0 suppress depreciation warnings generated by twisted 2009-07-01 13:49:39 +00:00
65697faca5 remove unnecessary import 2009-07-01 13:45:56 +00:00
d3d991d8aa Added support for sending headers when using download_file.
Allows HTTP conditional GET for servers which support it.
2009-07-01 10:02:45 +00:00
d592c0370c HTTPDownloader now "raises" a PageRedirect error when it encounters a temporary redirect or permanent move.
This allows the callee to download the file from the new location.
2009-07-01 08:45:09 +00:00
a66910e50b Move reparent_iter to common
Add support for 'spliting' folders in the add torrent dialog
2009-06-28 00:56:36 +00:00
2ccebaca3b Move 'add_peer_dialog' to peers_tab.py where it should belong.. 2009-06-27 22:49:01 +00:00
23944abc4c Optimize walk_tree() by only getting the base_path once for all siblings 2009-06-27 22:30:01 +00:00
2d379b3c67 Make the cache refresh button actually work 2009-06-27 22:13:50 +00:00
cdf2f79c66 fix some indentation issues 2009-06-27 11:36:34 +00:00
3194f0f994 Add ability to rename files prior to adding them in the gtkui 2009-06-27 02:24:21 +00:00
0a9a6b4816 Add ability to rename files prior to adding with the option "mapped_files" which is a dictionary of {index: filename, ...} 2009-06-26 23:31:47 +00:00
6fb180ed23 add checkboxes to folders and change all the child checkboxes on a change 2009-06-26 18:43:38 +00:00
1edafe2b6c sort out some whitespace 2009-06-26 18:40:48 +00:00
790a10e317 Fix #535 fix saving column widths 2009-06-26 05:29:48 +00:00
abf6de8462 Add a Cache preferences page to adjust cache settings and examine cache status 2009-06-25 23:58:54 +00:00
88e494c197 Fixed stats url encoding. 2009-06-24 05:41:30 +00:00
182845ce3e Fixed #916.
Removed unused code.
2009-06-24 03:22:06 +00:00
a7c2e596d9 Use a more efficient sort to put the torrent state list in queue order 2009-06-24 02:54:39 +00:00
139519d7d1 Fix error when sending stats (quote_plus expects string not list). 2009-06-24 02:35:24 +00:00
33ac5beba5 update the stored option in the onFieldChange event handler 2009-06-23 23:20:11 +00:00
2debe69e34 proxy the check event from the child radio boxes to the radiogroup 2009-06-23 23:18:25 +00:00
c5a21e2be9 add in a radiogroup to facilitate in hiding compact/full allocation as one field and extend Ext.form.RadioGroup so it provides the setValue and getValue methods 2009-06-23 23:10:13 +00:00
e94129135b add the options form layout to the options tab of the add window 2009-06-23 18:46:25 +00:00
b75e17069f change the command options help string a little 2009-06-23 18:22:11 +00:00
b13efa08ff add ssl support to the webui webserver 2009-06-23 18:21:25 +00:00
148afede5b Check to see if the files_list for the torrent_id is available when receiving file_renamed or
folder_renamed events
2009-06-23 17:36:01 +00:00
a29904fefd fix bug in get_hosts if host[x:y] is not a list 2009-06-23 10:02:22 +00:00
76d3c2567e fix the files tree for when there is only 1 file in the torrent and also fix the file size in the add torrent window 2009-06-23 09:37:28 +00:00
2e0bd1bd3c fix an error in the doc string for add_torrents 2009-06-23 09:36:30 +00:00
46163b992f split out getting host status from getting the host list to greatly improve performance of the connection manager 2009-06-22 18:28:51 +00:00
4b934a07ba dummy function now accepts arbitrary number of variables.
metafile uses hashlib instead of sha library.
2009-06-22 14:11:02 +00:00
206718de08 fix adding hosts to the connection manager 2009-06-22 07:58:59 +00:00
7bdc595dd0 fix the error callbacks in the client 2009-06-22 07:56:45 +00:00
f6b90c0097 improve the docstring for the add_torrents method 2009-06-18 08:25:14 +00:00
9a55987ecb fix removing connections from the connection manager 2009-06-17 19:07:30 +00:00
dd85ca3c3e add another escaping slash 2009-06-17 14:51:07 +00:00
12757ef7e8 fix the gettext generation script so that resulting apostrophes from a translation are escaped 2009-06-17 13:57:11 +00:00
9370911ee1 use changeId in the clear method of the options tab 2009-06-17 06:42:37 +00:00
7bc81fbaf9 add a changeId method to the OptionManager 2009-06-17 06:36:55 +00:00
7dfce33065 rebuild the docs 2009-06-16 18:15:28 +00:00
d5f92b506a change the arg from doc to docs 2009-06-16 18:15:09 +00:00
4edb79bcd7 add in support to the optionsmanager for binding form fields 2009-06-16 18:14:23 +00:00
3458b238d8 Add option in Preferences to change the listen interface 2009-06-12 16:12:00 +00:00
ca7f33db1f Get the Stats plugin working again.. sort of.. It still needs a lot of work. 2009-06-11 01:06:08 +00:00
520be10e4d Fix turning off Classic mode dialog
Fix showing the connection manager icon on the toolbar depending on classic mode setting
2009-06-10 22:50:57 +00:00
e36ca0e5ba Fix calling set functions 2009-06-10 22:43:43 +00:00
9495fffeac Show a progress window when downloading torrents from URL
Add ErrorDialogs when trying to add bad torrents and when downloading of torrent fails
2009-06-10 22:35:47 +00:00
e7158c499f Fix dialogs so that they do not run another gtk main loop, but rather run within the current
twisted mainloop
2009-06-10 22:23:49 +00:00
a82a5277a5 Add a httpdownloader module to download files using twisted 2009-06-10 20:18:22 +00:00
4c43980d66 Fix #518 remove header in add torrent dialog to save vertical space 2009-06-10 18:39:14 +00:00
c274da9245 Move the 'Find More Plugins' button down to reduce horizontal usage 2009-06-10 18:34:27 +00:00
7ddb5db6ed Fix the set functions so that you are able to register more than one per config key
Likewise for the config change callbacks
2009-06-10 18:15:52 +00:00
853138e4ee If a 'localclient' entry is not in the auth file, then have the daemon add one. 2009-06-10 18:11:14 +00:00
aa4c783601 tweak the setup script so the web plugin has the correct entry point
implement the webui server side plugin
add a page to the preferences window in the javascript
2009-06-10 16:37:21 +00:00
227e464b63 Fixed typo in seeking. 2009-06-10 14:28:37 +00:00
06b19538fd provide 2 helper methods for adding and removing scripts from the webserver 2009-06-10 13:27:55 +00:00
110af0c2fc fix indentation 2009-06-10 13:27:22 +00:00
29f72a244f Remove statusbar icon when disconnected from daemon 2009-06-10 05:38:59 +00:00
5cdb5f41e4 Make the default schedule all Green 2009-06-10 05:37:28 +00:00
f2002f9077 Fix division by 0 2009-06-10 05:34:06 +00:00
79746c5bc6 Fix svn:externals 2009-06-10 04:44:51 +00:00
267c7408d7 Get the blocklist plugin kind of working.. Still needs some lovin'. 2009-06-10 03:42:33 +00:00
581dcb8202 Force str when calling session.load_country_db() 2009-06-10 03:08:41 +00:00
72d3b0a549 Fix exception when tracker column is not enabled 2009-06-09 21:44:24 +00:00
b430899862 Only move a torrent due to 'move on complete' when some data has been downloaded 2009-06-09 00:35:43 +00:00
ff25a7e969 Torrent creation fixes in regards to web seeds
Fix adding torrent to session after creation by setting the proper download location
2009-06-08 21:57:02 +00:00
95cd5e4932 Remove some more externals 2009-06-08 20:07:47 +00:00
edd3b5d847 fix a bug in the spinner to force the decimal precision to be displayed 2009-06-05 07:39:45 +00:00
db36e9dbfa disable the move storage menu item, this won't be active until the remote file browser has been added
add decimal precision to the spinner strategy (although it doesn't seem to be working?)
2009-06-05 07:19:47 +00:00
ef3b22691b Apply the global bandwidth settings on plugin disable to prevent slow limits from staying in effect. 2009-06-05 02:10:41 +00:00
d4c7134746 Only require 2.12 in preferences dialog 2009-06-04 17:46:15 +00:00
0eee49891a Update Changelog and README 2009-06-04 17:42:57 +00:00
86fca4b43b Remove GeoIP.dat from tree
Add configuration option to set the GeoIP db location, default is /usr/share/GeoIP/GeoIP.dat
2009-06-04 17:25:06 +00:00
a24c07a9bd Fix some issues with creating torrent files, was putting the announce list in the wrong key
Add support for using a system installed GeoIP db file.  It will look for /usr/share/GeoIP/GeoIP.dat first and try to load that
2009-06-04 16:57:53 +00:00
49e27a33bf Update the GeoIP db 2009-06-04 16:20:28 +00:00
b28f75d92d Add support for lt 0.15 2009-06-04 02:26:56 +00:00
b8ab51dc0f Revert trunk to use lt RC_0_14 branch.. 2009-06-03 21:34:14 +00:00
77adcc4b37 Change the svn:externals to point to libtorrent trunk 2009-06-03 21:15:41 +00:00
5c75d3664c remove no longer needed alert 2009-06-02 22:34:02 +00:00
1b9e3c00c8 rebuild docs
improve the options manager, adding events
sort disabling of fields in the options tab
2009-06-02 22:13:16 +00:00
616561ca6d disable all tabs on startup
tweak the options tab layout
2009-06-02 16:51:26 +00:00
b56bb9e2be stop an error in the peers tab if no data is returned
add the code to enforce the sidebar_show_zero option
2009-06-02 12:34:54 +00:00
b54c73d466 Fix the disabling and clearing of the torrent details tabs 2009-06-02 12:19:22 +00:00
f26870ad19 Update ChangeLog 2009-06-02 04:01:46 +00:00
54af19f249 Add Scheduler plugin 2009-06-02 00:57:52 +00:00
c4782e91f0 Update create_plugin script a bit 2009-06-02 00:57:04 +00:00
1091054b38 Add ability to run individual set functions 2009-06-02 00:56:05 +00:00
502fa6983e fix setting prioritize first/last from the options tab 2009-06-01 23:46:35 +00:00
bf3b0bf5c6 remove the # from the copyright comments 2009-06-01 22:51:36 +00:00
ed36526a24 fix the progress bar in the files tab 2009-06-01 22:23:47 +00:00
ff262acbdf change the progress bar to auto width again 2009-06-01 21:36:12 +00:00
3f525293ca tweak the widths so the ui can be used more easily on a resolution of 1024x768 2009-06-01 21:27:23 +00:00
c9ba8b1583 fix the class name for time_added 2009-06-01 21:26:17 +00:00
87355e0490 use inline if/else to set the value of auto managed and also run through gettext 2009-06-01 20:13:05 +00:00
e71c562612 Fix #950 renaming a parent folder into multiple folders 2009-06-01 19:29:15 +00:00
30efe143fe Catch exception when trying to open config file 2009-05-30 01:32:25 +00:00
019c78db47 Add some command line options to the daemon to set the listen
interfaces, -i and -u
2009-05-30 00:22:14 +00:00
d29934a534 Add a "Find More Plugins" button the Plugins pref page that links the user to the Plugins page on the wiki 2009-05-29 00:31:59 +00:00
ea829d0826 Show libtorrent performance warnings in the debug log 2009-05-28 23:55:34 +00:00
63f1874ae8 Modify the Config class to version the config files now.
Add ability to register converter functions for config files to convert them to newer versions.
2009-05-28 23:43:45 +00:00
d1c47982a8 Optimize get_tracker_host by storing the tracker_host value 2009-05-28 19:16:58 +00:00
fa728510dd This should have been in the last commit.. 2009-05-28 19:16:28 +00:00
4dc2f7d9d0 Fix up docstrings in AlertManager and do some minor optimizations 2009-05-28 19:15:32 +00:00
8c587f7330 Add support to profile the daemon using the --profile option 2009-05-28 18:28:33 +00:00
bf2f4ee860 remove debug alert 2009-05-28 10:37:09 +00:00
aa866d5187 improve the optionsmanager
implement setting torrent options via the options tab
rebuild the docs and js file
2009-05-28 10:36:06 +00:00
c8de0b897d Show hosts as Offline when they are initially added to the listview
Select the first host in the list on show
2009-05-28 01:15:38 +00:00
bbdcf7534c Make chardet a non-optional dependency in 1.2.x 2009-05-27 19:18:13 +00:00
629b239739 add a couple of extra methods to the option manager
updateOptions in onRequestComplete in the options tab
2009-05-27 16:31:36 +00:00
ea2a79a903 improve some of the docs in Deluge.UI 2009-05-27 15:51:24 +00:00
9b860c9b3c add a build_docs method to build.sh and rebuild the docs 2009-05-27 15:24:37 +00:00
5b6ecc2b4e rebuild the deluge js 2009-05-27 11:50:50 +00:00
91a471e781 fix setting the download priority for files in the files tab 2009-05-27 11:49:27 +00:00
668683f369 add a new class for managing a options throughout the ui 2009-05-27 11:35:52 +00:00
b5e0222689 Make the global move torrent on completed option a template for newly added torrents to allow
turning off the movement - patch from Plisk
2009-05-27 02:59:44 +00:00
6c023c111f Fix the extracting command call
Touch up the gtkui config a bit
2009-05-27 02:32:00 +00:00
b883ffc474 Fix exception when trackers are disabled from the sidebar 2009-05-25 22:55:42 +00:00
9324134d8f Prevent some uncaught exceptions when systemtray is not enabled 2009-05-25 06:07:26 +00:00
360790876b Fix not using the encoding used in the torrent file to decode some strings 2009-05-25 02:27:33 +00:00
fa9d39c5fb Fix typo 2009-05-21 19:33:12 +00:00
d45e2de1c9 Add InformationDialog
Use InformationDialog instead of ErrorDialog in AddTorrentDialog
Make dialog in GtkUI translatable
2009-05-21 00:18:53 +00:00
2374d44c70 Add error dialog popup when trying to de-select files in the add torrent
dialog while using compact allocation
2009-05-20 23:46:27 +00:00
d2b5e69a5e Add an ErrorDialog 2009-05-20 23:42:03 +00:00
b4a329474a Fix #943 exception when options is None 2009-05-20 21:39:02 +00:00
f78cf72544 Create a BaseDialog class 2009-05-20 21:09:50 +00:00
1d006e1368 Handle shutdown() better 2009-05-20 20:11:57 +00:00
447620f89f Add some extra include dirs for when building on OS X using Fink 2009-05-20 18:51:37 +00:00
2741623e91 Add some more information to the error message when trying to run
multiple daemons
2009-05-20 16:53:32 +00:00
5f8a1ed971 Fix up daemon start-up code a bit.. 2009-05-20 16:11:54 +00:00
0a33931c6b Detect when a daemon is already running in the same config folder.
When the gtkui is run in classic mode with an already running daemon 
process, prompt the user to turn off classic mode or exit.
2009-05-20 01:07:58 +00:00
5afeabd56d attempt to set the icon via the icon theme before falling back to the logo (as in the statusbar) 2009-05-19 23:49:31 +00:00
11351e1544 remove the disable in the options tab
disable all tabs when there is no torrent selected and enable them when there is
2009-05-19 22:47:51 +00:00
323d8133b0 set the mime-type propety on all the html files 2009-05-19 22:33:45 +00:00
1b0ffe748c update the options tab and set the torrent values
improve the docstrings in a few of the javascript modules, and include the
generated documentation.
2009-05-19 22:30:59 +00:00
038c92376a build up the layout for the options tab in initComponent, allowing for easy storage of the fields. 2009-05-18 22:51:06 +00:00
716c0ee564 Update man page to refer to console instead of null 2009-05-18 22:07:51 +00:00
d67477f6e2 Add OpenSSL exception to all GPL headers 2009-05-18 21:51:49 +00:00
c4a247018b Fix up the console ui so that command-line options work again.. Also,
use the new UI class for the 'deluge-console' script.
2009-05-18 21:35:16 +00:00
56735452a8 Clean-up CoreConfig a bit 2009-05-18 21:34:24 +00:00
df21107e3f Improvements to the new UI class and improve how ConfigManager handles
setting the config directory
2009-05-18 21:34:03 +00:00
62bc9d1844 make use of the DeferredList rather than chaining one request after another 2009-05-18 17:43:29 +00:00
1a3e38b1f5 Set some sane defaults for peers/file tabs column widths 2009-05-18 16:26:26 +00:00
bb12f74ae6 Remove unnecessary file 2009-05-17 17:05:28 +00:00
100227f4e1 Added filemode support to setupLogger.
This allows log files to be appended to if desired.
2009-05-17 12:28:03 +00:00
ac418d5935 Potential patch for libtorrent @ 3507 2009-05-17 12:19:14 +00:00
982aaff2a1 Remove icon_size property from toolbar to prevent gtk warnings 2009-05-16 05:47:35 +00:00
8da20c042f Fix some config file locations when using a non-default config directory 2009-05-15 18:09:59 +00:00
be5e12e1e4 Have authmanager return ints instead of strings for the auth level 2009-05-15 17:48:03 +00:00
a7e70509b0 Remove needless del 2009-05-14 23:14:09 +00:00
78d0439d6f Move countries.py to ui/ since it's only used by the UIs 2009-05-14 18:16:16 +00:00
19e21606cd Fix exception when timing out trying to send notification email 2009-05-13 20:52:51 +00:00
5606925aa0 Fix #934 use 'name.utf-8' if available and decode the file path before
joining it with the prefix
2009-05-12 20:22:21 +00:00
397434f7ca Update deluge.pot and a couple i18n tweaks 2009-05-12 18:10:52 +00:00
090e1a035e Implement #259 show tooltip with country name in the peers tab 2009-05-12 17:52:01 +00:00
90e05827dd Remove 5 minute config save timer as it's not really needed and it's
preventing gtkui from starting
2009-05-12 17:48:47 +00:00
65583cfe12 Add some more stuff to the new ui class 2009-05-12 17:07:17 +00:00
c754fc7c74 Remove dep on gobject and replace with twisted.reactor.callLater 2009-05-12 16:57:35 +00:00
54bfbb888b Update deps to include pyxdg 2009-05-12 16:27:41 +00:00
0ab8fa4871 Remove gobject timer and replace with a twisted LoopingCall 2009-05-12 16:15:06 +00:00
901038b3c2 improvements to the doc strings 2009-05-11 19:31:29 +00:00
2b4ca765fa move the config_directory attribute to a property that gets lazily set 2009-05-11 10:28:59 +00:00
7aea3a290e Fix up error message when not specifying a directory with the --config option and add this to 1.1.x 2009-05-11 04:10:05 +00:00
128b40641f Apply #932 minor ti_name optimization 2009-05-10 19:28:23 +00:00
2d2f8f7700 Remove some useless code 2009-05-10 19:11:06 +00:00
384eee2744 Fix showing non-utf8 encoded torrents in add torrent dialog -- this adds an additional dependency on chardet. 2009-05-09 17:46:13 +00:00
96c399f7f5 Optimize ti_name a touch 2009-05-09 03:42:39 +00:00
f12f02fff8 Fix #921 detect if user has json-py installed and add dumps and loads attributes to it 2009-05-09 03:18:54 +00:00
5b3528c9d1 Torrent name is now changed when the root folder or file is renamed 2009-05-09 03:05:43 +00:00
876a01ff84 Fix some debug output when not using utf8 2009-05-09 03:02:11 +00:00
f7bb2f330b Fix #927 add support for more boost versions 2009-05-09 02:59:42 +00:00
00ca3e158b Prevent page headers from moving when adjusting window size 2009-05-08 00:10:03 +00:00
3276de91c3 document the methods 2009-05-07 19:14:02 +00:00
7e291268bb improve the password convertion methods 2009-05-07 18:02:08 +00:00
aeb5e8311b don't delete the salt 2009-05-07 17:51:01 +00:00
107daa57b5 commit the record after updating it 2009-05-07 17:50:16 +00:00
af4c73a594 big change to the webui auth system
added converting of old 1.1 config files
added converting of old md5 passwords to sha1
2009-05-07 16:27:22 +00:00
2766c103e2 change the config class to return true or false on a save to show whether or not it was successful 2009-05-07 15:32:21 +00:00
c59857b802 add config_file as a property to the Config class 2009-05-07 15:09:13 +00:00
007c9bd2a2 finish implementing the edit trackers window 2009-05-05 22:59:34 +00:00
da81704b74 remove pointless if 2009-05-05 22:35:25 +00:00
1480459019 fix tier whilst adding trackers 2009-05-05 22:33:17 +00:00
84b30aa11a add the layouts for the add and edit windows 2009-05-05 21:50:30 +00:00
763a422a15 increase window side and add stubs for the add/edit windows 2009-05-05 20:23:10 +00:00
83ff72490c load the trackers into the grid 2009-05-05 19:29:04 +00:00
712bfcfef1 add edit trackers to the debug list 2009-05-05 19:14:12 +00:00
caafffb484 remove another space 2009-05-05 19:07:05 +00:00
b254385666 remove space in the description 2009-05-05 19:04:53 +00:00
554181a590 add basic edit trackers window 2009-05-05 18:00:32 +00:00
0b1b6d65de update the header 2009-05-05 17:59:38 +00:00
9b25b63664 Add Extractor plugin 2009-05-02 02:13:23 +00:00
9a94b3719d Some changes to the create_plugin script to work properly with 1.2 2009-05-02 02:11:36 +00:00
5b87af0e46 Fix per-torrent move on completed stuff - patch from Plisk 2009-05-02 02:07:11 +00:00
32fc0db2e5 Remove duplicate code 2009-05-01 20:21:25 +00:00
62b0d0b094 Prevent exception when clicking on the Connect button when no host is selected 2009-05-01 17:28:57 +00:00
12dded627e change so INCLUDEDIR not existing in the env won't throw an error 2009-04-30 16:17:50 +00:00
afeb7cf8b1 Use directories listed in INCLUDEDIRS 2009-04-30 16:15:09 +00:00
4c03fad512 change how pages are attached to the preferences window, using the title of the passed in object rather
than having to pass in one
2009-04-30 07:13:23 +00:00
d09cd4908e tidy up the code attaching the script 2009-04-30 07:12:35 +00:00
6669dbb4a0 fix the layout of the options tab 2009-04-29 20:45:07 +00:00
d011c61971 use list comprehension over lambda 2009-04-29 20:15:56 +00:00
e856e65db5 Add path tab-complete to the add command 2009-04-29 02:41:10 +00:00
96b38188fc add a doc string 2009-04-28 15:59:56 +00:00
b4e56e923b don't fire the connect event until the client has finished reloading
it's methods
2009-04-28 09:09:08 +00:00
a579c3b2c7 fix "Expand All" from the context menu 2009-04-28 08:56:03 +00:00
68f5afa89c remove comma causing breakage in IE 2009-04-28 08:54:56 +00:00
d4d7f054f3 remove torrents that are no longer in the update from the grid 2009-04-28 08:39:04 +00:00
78b5c06776 improve the torrents grid, updating existing entries rather than just
reloading the whole grid
2009-04-28 08:35:27 +00:00
7b72d79d32 Made TrackerIcons a component to prevent trying to get an icon multiple
times
Fixed showing the wrong tracker icon in the TorrentView when the icon 
could not be retrieved from the tracker
2009-04-28 02:35:08 +00:00
925dcd43b8 Fix up tab-completion to use the commands 'complete' method 2009-04-28 01:15:12 +00:00
d4cfebadbc fix adding torrents on windows 2009-04-27 22:19:18 +00:00
9ed37e070c Return if bad torrent_info 2009-04-27 22:14:49 +00:00
f2364b8531 add some test web plugin code 2009-04-27 22:02:26 +00:00
16d695f077 enable and disable plugins at start/stop
convert the directories to a list in the lookupresource
2009-04-27 22:01:34 +00:00
137d0f8ebf fix the order of the stylesheets 2009-04-27 21:33:50 +00:00
154e671ecc rebuild 2009-04-27 21:16:15 +00:00
f811fcc549 fix the comment 2009-04-27 21:15:59 +00:00
a7a13636e6 add a loading css style for when the torrent doesn't have its info yet 2009-04-27 21:14:43 +00:00
200e348f7d fix removing torrents from the grid 2009-04-27 20:50:54 +00:00
b88542f105 rebuild the compressed script 2009-04-27 20:49:50 +00:00
858291517e add torrents to be added to the grid before their info has been
retrieved with a url or filename in place of the torrent name
2009-04-27 20:48:39 +00:00
2ac545dec6 Clean-up signal handling since twisted.reactor handles it now 2009-04-27 18:50:41 +00:00
725198fc4d fix handling close on windows 2009-04-27 18:46:30 +00:00
9f2b98bf4b fix showing the add torrent window 2009-04-27 18:14:07 +00:00
6b4f36cbf3 add placeholder file for the infohash window 2009-04-27 18:12:49 +00:00
993c654917 split out Deluge.Add into seperate smaller files
add back adding torrents via file
2009-04-27 18:09:37 +00:00
cb14a2dd22 Remove mapping.py 2009-04-27 18:04:20 +00:00
d856f8501e fix the add window so torrents can be added via url again 2009-04-27 17:43:42 +00:00
370b4ae805 pass the requestOptions to the success and failure callbacks 2009-04-27 17:21:35 +00:00
c267c36b7b Add scrolling with page_up and page_down 2009-04-27 17:17:44 +00:00
204f055c7e clear the cookie rather than setting it to false 2009-04-27 13:56:53 +00:00
e837493757 add basic session support 2009-04-27 13:01:20 +00:00
c4cdd70a4e change the "ready" event to "connected" and fix the failure event
handler
2009-04-27 12:55:42 +00:00
a9392f9002 fix the onLogout handler if the window hasn't been rendered yet 2009-04-27 12:53:58 +00:00
253d08d2f9 fix emptying the panels hash 2009-04-27 11:30:30 +00:00
e6244920e6 Fix typo 2009-04-27 00:30:21 +00:00
5a71e82875 Fix #902 cannot remove torrents 2009-04-26 18:27:46 +00:00
322495cfd5 Fix 'debug' command and update some copyright headers 2009-04-25 22:42:46 +00:00
641ac7356c Clean-up eventlog a bit 2009-04-25 21:11:44 +00:00
a1038203c1 Add support for setting config values 2009-04-25 21:09:07 +00:00
b852051bb7 Add 'is_finished' torrent status key 2009-04-25 07:29:08 +00:00
753b93089f Change color tags to '{! !}'
Add support for viewing config values
2009-04-25 00:31:07 +00:00
6d33ff9902 Add '__getattr__' to CoreConfig to access the dictionary directly 2009-04-25 00:30:11 +00:00
4878743d68 Clean up 2009-04-24 22:53:02 +00:00
c02a647427 Show proper units 2009-04-24 22:52:45 +00:00
64b4255b94 Fix adding torrent to list on TorrentAddedEvent 2009-04-24 22:52:19 +00:00
b2626ea6aa Fix calling 'set_event_interest' when registering a handler after connecting 2009-04-24 22:50:44 +00:00
42242efe66 Fix up formatting of peers list 2009-04-24 21:35:37 +00:00
c846d584a0 improve the new style ui class to start the logging 2009-04-24 19:07:00 +00:00
972393d9ea Fix up info command 2009-04-24 18:50:54 +00:00
4939b8c72e use keys() rather than getKeys() 2009-04-24 18:32:03 +00:00
3b744ae978 set values to blank rather than the initial bogus values first used 2009-04-24 18:31:17 +00:00
1d5bc7669f Fix cursor position when moving through the history 2009-04-24 18:21:31 +00:00
714cd0ed80 Fix missing text if it's before a color tag 2009-04-24 18:19:04 +00:00
9a43ec8258 add a config resource that outputs the uis current configuration
update this in Deluge.js
2009-04-24 18:14:59 +00:00
0523ec1837 assign the cookieprovider to Deluge.UI.cookies 2009-04-24 18:09:58 +00:00
c718c2bf30 Change titlebar update interval to 2 seconds 2009-04-24 17:58:11 +00:00
18950cc1ef add yui compressed version of ext-extensions-debug.css 2009-04-24 14:41:55 +00:00
0a80098576 move ext-extensions to ext-extensions-debug 2009-04-24 14:41:28 +00:00
dbf685f178 Fix uncaught exception when the remove torrent button is pressed when no torrents are selected 2009-04-23 22:55:52 +00:00
45a6ea5a19 Fix deprecation warning 2009-04-23 20:30:09 +00:00
3c47c7ef77 Fix creating torrents in Windows
Fix displaying improper progress when creating torrent
2009-04-23 20:21:01 +00:00
37b3c07025 remove trying to stop the reactor, we can just call reactor.stop() and
shutdown will be called
2009-04-23 12:36:59 +00:00
fac65e9bb0 fix shutdown not being called when killed 2009-04-23 12:33:51 +00:00
465d98eeed add 2 debug log statements 2009-04-23 11:54:42 +00:00
6cd5a7de30 rename Spinner.cs to ext-extensions.css and add in the fileupload and
columntree css
2009-04-23 07:44:19 +00:00
d18a88c46a remove mooui stylesheet 2009-04-23 07:41:20 +00:00
c73966bdd1 fix starting the web via deluge -u web
allow the theme to be specified in the config file
2009-04-23 07:26:14 +00:00
b43e0f6eaa add the layout to the options panel 2009-04-22 07:12:15 +00:00
cadfb5632f fix updating on tab change 2009-04-22 00:12:12 +00:00
6d4eae15a5 add basic options panel 2009-04-22 00:07:55 +00:00
a63e5c594c add the peers tab 2009-04-22 00:04:16 +00:00
d916d36603 remove call to getFields as it's no longer required 2009-04-21 23:46:04 +00:00
8bac2b4597 Add the files tab back 2009-04-21 23:43:46 +00:00
1df462cf0b comment out the debug alert 2009-04-21 23:41:22 +00:00
5db7a5a21b remove the old mootools rpc client 2009-04-21 22:18:11 +00:00
431271d453 update the build script to match the new script names and rebuild the
compressed script
2009-04-21 22:03:40 +00:00
db00f4690d fix changing the limits on via the statusbar menus 2009-04-21 21:59:15 +00:00
9df1ec2193 remove pointless privatising 2009-04-21 21:46:20 +00:00
ee5cfc8cff updated __debug scripts list and some css 2009-04-21 21:45:56 +00:00
1157fc1eeb commit all new-style code so it can be versioned, NB: this is in a
broken state currently.
2009-04-21 21:41:18 +00:00
e1e45753de add a reloadMethods function to use instead of simply creating a new
client
2009-04-21 21:36:32 +00:00
b62a5d7329 fix calling the success/failure callbacks 2009-04-21 20:34:41 +00:00
1f212b8a38 extend Ext.util.Observable rather than reinventing 2009-04-21 20:27:25 +00:00
1be29dc319 ext based Deluge.Events 2009-04-21 20:15:49 +00:00
fb85e76a1f fix missing torrent_id in on_alert_state_changed 2009-04-21 18:32:34 +00:00
cf0d155e99 rewrite the rpcclient using ext 2009-04-21 17:27:55 +00:00
be1a1fc0be Fix loading improperly created torrents with mismatched encodings 2009-04-21 17:16:19 +00:00
4fde1b4a2f Fix typo 2009-04-21 16:32:53 +00:00
0e10f608b9 check to see if .build_data exists in check_file before running the grep
don't remove the concatenated files if the compression fails
2009-04-21 09:27:59 +00:00
10b11f36c7 remove the mootools dependence and also rebuild gettext.js anyway 2009-04-21 09:08:05 +00:00
a60bf912fb fix displaying the host-list 2009-04-21 07:26:20 +00:00
9d583b8c51 completely rework deluge-torrent.js into a self-contained ext class
add .build_data to svn:ignore on js
add in the first build of deluge-yc.js
2009-04-21 07:17:49 +00:00
b72ec252af fix building deluge-yc.js, was including $ALL_FILES rather than
$DELUGE_FILES in the cat
2009-04-21 07:15:32 +00:00
c17af41940 Fix up some commands 2009-04-21 02:43:20 +00:00
9da95552f3 move the progressbar renderer helper method to deluge.js 2009-04-20 22:32:42 +00:00
d795a66ae9 Add missing files 2009-04-20 22:01:52 +00:00
111b64d38b fix checking the free diskspace on windows 7 2009-04-20 21:05:05 +00:00
f82c67f36c fix importing the ui start method 2009-04-20 20:40:44 +00:00
503169ce76 fix serving binary files on windows 2009-04-20 20:26:03 +00:00
2f44899521 add back in the old WebUI class and rename the import in ui.py so
compatibility isn't broken
2009-04-20 20:11:31 +00:00
cd050bf8e7 rename from web to webui 2009-04-20 19:56:35 +00:00
e3dea5ee8a Fix some typos 2009-04-20 19:20:33 +00:00
b605048d23 Force 16x16 pixbufs in tracker column 2009-04-20 18:11:22 +00:00
7bdf8bffd8 Fix the quit command 2009-04-20 03:51:15 +00:00
b3ee54fcdc Clean-up some of the code in the torrentmanager alert handlers to
prevent uncaught exceptions during shutdown
2009-04-20 02:28:06 +00:00
22c9fffad8 Fix issue where cannot resume torrent after doing a 'Pause All' 2009-04-20 00:02:36 +00:00
e08c51e10c Update to asio 1.4.1 2009-04-19 21:40:09 +00:00
73e58c20c8 Add event logging 2009-04-19 19:57:06 +00:00
28bc5c839e Fix displaying lines that are longer than the number of columns 2009-04-19 19:55:40 +00:00
e0f8369e91 Only emit a TorrentStateChangedEvent when the state has actually changed 2009-04-19 19:51:11 +00:00
6c9dd4d5c9 Show a Paused state when a Checking torrent is paused 2009-04-19 19:50:39 +00:00
2589baf0e2 Fix event handler de/registering 2009-04-19 19:50:12 +00:00
b60dc2d4ca start new ui class 2009-04-19 13:46:11 +00:00
0905695910 Add tab completion support 2009-04-18 22:27:54 +00:00
df00d28af4 Remove unused variable 2009-04-18 18:53:16 +00:00
e1c5c0b3ff Re-add input string during refresh
Do not fsize config values
2009-04-18 18:46:01 +00:00
3ac0cace6b Fix starting the console ui 2009-04-18 18:28:35 +00:00
56a1c50bc6 Add a defer property to use to check when the CoreConfig is ready 2009-04-18 18:27:35 +00:00
00d078a5ea Fix some uncaught exceptions if the session is not authorized 2009-04-18 18:19:47 +00:00
99e981dbf8 Add some missing files 2009-04-18 18:14:57 +00:00
2542745c16 Add tracker icon to Tracker column 2009-04-18 17:46:14 +00:00
08b3ce97b3 change it so instead of modifying the list at render it uses a completely seperate list when being run in debug mode 2009-04-18 16:30:14 +00:00
491f4a4438 move the classes in deluge-ext to ext-extensions and remove deluge-ext 2009-04-18 16:20:07 +00:00
843deae4cd move the contents of the spinner files into ext-extensions-debug.js 2009-04-18 16:14:56 +00:00
2ead8be0d4 script to combine and compress the deluge javascript 2009-04-18 16:11:18 +00:00
e5459eda49 move mootools-bridge.js to mootools-bridge-debug.js and create the
yuicompressed mootools-bridge.js
2009-04-18 14:52:13 +00:00
70b7fa908f remove the gettext calls from the dictionary, and add hinting for the
generation script above instead
2009-04-18 13:00:18 +00:00
286619f4e3 add FILE_PRIORITY_CSS and run FILE_PRIORITY through gettext 2009-04-18 12:50:34 +00:00
9cf9d74f5c change Deluge.ProgressBar xtype to deluge-progressbar 2009-04-18 12:49:46 +00:00
067f0c3713 Start work on new Console UI .. Don't expect anything to work, cause most of it doesn't. 2009-04-18 05:35:03 +00:00
a513f9c12a Fix typo 2009-04-17 21:24:49 +00:00
b6f40a8115 Move CoreConfig component out of GtkUI since it's UI independent 2009-04-17 21:09:14 +00:00
8fef414054 begin messing about with the plugin manager 2009-04-16 22:03:50 +00:00
74ac41e686 remove Roar 2009-04-16 20:00:27 +00:00
9be54918fb generate the <script> and <link> tags dynamically 2009-04-16 19:59:34 +00:00
134bed774c fix semi-colon in the login window
change themes back to a static.File resource
2009-04-16 19:38:54 +00:00
427cc63803 create a LookupResource and use this instead of the static file resource
to serve images, javascript, css etc. as it allows plugins to add lookup 
directories.
2009-04-16 19:36:30 +00:00
9d8a104264 give focus back to the password field after the messagebox is closed 2009-04-16 18:17:33 +00:00
23ec87724e add the bandwidth page 2009-04-14 21:50:58 +00:00
9daf288da1 Fix starting the daemon in OS X 2009-04-14 20:40:29 +00:00
7fb5e546e8 partially working preferences window (ui wise) 2009-04-14 20:36:13 +00:00
2e4762a586 tidy up the login window code, extend Ext.Window instead.
focus the password field upon the login window being displayed
2009-04-14 20:09:48 +00:00
b71ac41ff1 Fix displaying IPv6 peers in the Peers tab 2009-04-13 18:02:49 +00:00
3c09d38504 Move some prints to log.info 2009-04-12 20:07:41 +00:00
ad2b771e5d Fix starting the webui with a logfile option 2009-04-12 19:59:54 +00:00
386ca2fa68 Fix #883 segfault if locale is not using UTF-8 encoding 2009-04-09 16:40:52 +00:00
67ee535d09 fix text colour when viewed in epiphany 2009-04-09 09:23:14 +00:00
85ad5314fe Make the autoadd update interval 5 seconds as intended 2009-04-09 00:10:05 +00:00
c28574502c fix page switching 2009-04-08 21:25:46 +00:00
8a51a5e978 make the close button close the window 2009-04-08 20:35:35 +00:00
62375c7109 implement page switching 2009-04-08 20:28:39 +00:00
e3171671f0 remove margins as this is a borderlayout config option 2009-04-08 20:24:50 +00:00
0c0d81e2c3 regenerate gettext.js
add a number of translation fixes
2009-04-08 09:02:26 +00:00
02d7fbd3ba add "Date Added" field 2009-04-08 09:01:37 +00:00
8c93241ef6 fix the line number 2009-04-08 09:01:09 +00:00
908760d3a9 add back the _ alias to the lambda unicode gettext function 2009-04-08 08:52:40 +00:00
c57900d4f6 fix rendering of templates when translations bring in utf-8 characters 2009-04-08 08:39:17 +00:00
030c5b51d4 update the "serving on" string 2009-04-08 08:37:41 +00:00
855385227a set gettext.js's charset to utf-8 in the content-type header
don't use NamedTemporaryFile for the Upload resource as the delete kw 
arg was only added in py2.6
2009-04-08 08:22:02 +00:00
891b1120a3 select first row in the onShow event 2009-04-07 22:07:27 +00:00
c93a3b4680 add the ability to load the ext-all-debug.js by specifying ?debug=true
in the url
2009-04-07 21:26:32 +00:00
4e0a4fabfb begin the preferences window 2009-04-07 20:25:49 +00:00
1c8ebc198a add an alias to Deluge.Formatters.plain 2009-04-07 19:54:40 +00:00
2631f09315 fix the sidebars margins whilst collapsed 2009-04-07 19:54:06 +00:00
b71c31cc46 add script to scan the javascript files for gettext calls and
autogenerate gettext.js
2009-04-07 17:54:57 +00:00
6fb66382cc remove all unused html files
render templates as unicode by default
2009-04-07 15:18:02 +00:00
f7b5b20c63 Show an error message if --config option is not a directory 2009-04-06 23:20:32 +00:00
5541164661 load the options panel form defaults 2009-04-06 21:47:55 +00:00
a9f26e0827 Update LICENSE in trunk too.. 2009-04-06 21:17:26 +00:00
434c69492a remove the border from the form 2009-04-06 20:31:46 +00:00
4ddc92f55d stop the scrollbar being displayed when "compact" is selected 2009-04-06 20:29:45 +00:00
5caeff733e tweak the dimensions to eliminate white space 2009-04-06 20:11:40 +00:00
485a1f3487 add buttons to the form 2009-04-06 20:04:54 +00:00
9885e530cb finalise the layout of the options tab in the add window 2009-04-06 19:46:30 +00:00
5c54aff46e reduce the height of the login window 2009-04-06 18:59:28 +00:00
0501537045 add a tracker renderer 2009-04-06 18:17:04 +00:00
1719ece036 fix the icons path 2009-04-06 18:03:43 +00:00
248eb7341c use the setup.cfg file to tag the build as -dev 2009-04-06 14:54:20 +00:00
5b8f9f29b8 Fix loading torrent files in Windows when the path is non-ascii 2009-04-05 23:10:41 +00:00
3c4b511e6b Fix displaying torrents with non-utf8 encodings in add torrent dialog 2009-04-05 18:31:43 +00:00
322dffa105 begin implementing the options panel logic 2009-04-04 13:02:26 +00:00
5acd9f3f21 actually commit ui.common this time 2009-04-04 11:32:34 +00:00
ca316750e8 tidy up imports 2009-04-04 11:31:07 +00:00
895f16b883 tweak the options form layout 2009-04-02 23:11:01 +00:00
4b8a267c57 fix the l.getSize error caused by the options tab 2009-04-02 22:55:47 +00:00
8ebb9af5fc add more to the options form 2009-04-02 21:50:34 +00:00
d6e9c2141e need to store the filename in the info dict that gets returned by the server 2009-04-02 20:59:15 +00:00
1f63e3de1a remove get_torrent_info from ui.common
add an "as_dict" method to TorrentInfo
utilise the TorrentInfo class rather than get_torrent_info
2009-04-02 20:55:46 +00:00
5162d5d7e2 begin to add the options form and also fix the binds on the got_torrent_info calls 2009-04-02 20:40:24 +00:00
00bfd1a442 disable add by info hash and create torrent buttons 2009-04-02 20:10:59 +00:00
3ce6f6bb88 fix displaying the "Browse..." button next to the file upload field 2009-04-02 20:03:10 +00:00
031ec92799 handle an invalid torrent file and show an error message box 2009-04-02 19:43:08 +00:00
b1c992da61 rename Deluge.Ui to Deluge.UI 2009-04-02 19:40:41 +00:00
b07715862f clear the files tree on add/cancel 2009-04-02 19:28:27 +00:00
a7ad189bd0 add adding a torrent via file upload 2009-04-02 19:26:32 +00:00
df6a905226 handle no file being uploaded cleanly 2009-04-02 18:57:41 +00:00
061c06a164 fix the file upload resource 2009-04-02 18:50:45 +00:00
793e120957 change it so the tracker error filter doesn't have an icon 2009-04-02 18:22:08 +00:00
03dac27147 tweak the options form layout, settings fixed column widths 2009-04-02 18:13:29 +00:00
221d1875ff fix the spacer image trying to be retrieved from extjs.com 2009-04-02 18:09:34 +00:00
7fb8fc40d7 fix the progressbar renderers and move the theme specific code from deluge.css to xtheme-slate.css 2009-04-02 15:02:33 +00:00
c99b4ddfea fix button text color in the gray theme 2009-04-02 15:01:40 +00:00
0cb662cde8 give some default values and limits to the spinners on the options tab 2009-04-02 11:01:10 +00:00
672a4debae fix the options tab form layout 2009-04-02 10:56:49 +00:00
c6deb9ec8b fix rendering the form on the options tab (this fix is a little hacky, might be worth looking at the ext or mootools adapter for a better fix 2009-04-02 10:24:55 +00:00
6897cd8b6b improve removing of torrents by adding a "torrentRemoved" event 2009-04-02 09:54:06 +00:00
71ef3f3ddc change the fileuploadbutton back to just a button, we'll open a new window, it'll be a cleaner solution 2009-04-02 09:37:21 +00:00
d3c6bfe91f fix clearing the tree in IE 2009-04-02 09:33:21 +00:00
29a9253108 fix the options tab layout in IE 2009-04-02 09:29:37 +00:00
929aa64b8c a few IE fixes 2009-04-02 09:10:30 +00:00
fdaf3d0810 remove vista theme as it was for ext 1.x and doesn't work with ext 2
add a stylesheet for the default theme that fixes the button text color when viewed in a browser with a dark theme
2009-04-02 08:20:38 +00:00
100f4c2e9f set the column values on a successful request instead of being lazy and just triggering an update 2009-04-02 07:15:16 +00:00
828a1d339a run some strings through gettext 2009-04-02 07:14:03 +00:00
1cd9f74305 fix favicon 2009-04-01 22:33:26 +00:00
54993784da change the seeders/peers in the status tab to match the torrent grid 2009-04-01 22:04:36 +00:00
b2ff696348 remove some debug alerts i left in 2009-04-01 22:00:40 +00:00
141d254f35 tweak the seeds and peers renderers to match the gtk ones 2009-04-01 21:53:41 +00:00
583d76ca18 change it so multiple files can be changed at a time 2009-04-01 21:51:04 +00:00
4087dd38cb implement setting the file priority via the context menu 2009-04-01 21:31:36 +00:00
8b76cd8a2a add a context menu for the files tree 2009-04-01 20:03:21 +00:00
63427a18cc extend the treenode to provide a method to allow for updating colum values 2009-04-01 19:36:27 +00:00
7462a5e1d8 increase the filename column wdith 2009-04-01 18:46:48 +00:00
0d5c30b5f9 add in the file priorities to the file tree on the details tab
add some icons for the priorities
2009-04-01 18:42:04 +00:00
baf3d283e0 add sorting of the files by filenames, and folders display at the top 2009-04-01 16:33:31 +00:00
de733b0fae begin the layout of the options tab form 2009-04-01 16:31:51 +00:00
9b107359a4 replace the "File" button with a fileuploadbutton 2009-03-31 01:16:17 +00:00
44188cf276 add removing a torrent from the dialog 2009-03-31 00:51:43 +00:00
e608db8ce2 add clearing the tree when the selection is changed 2009-03-31 00:41:05 +00:00
3bd13595be clear the url field after the torrent has been added 2009-03-31 00:33:56 +00:00
0e0bc735eb change the class so the correct icon is displayed 2009-03-31 00:32:03 +00:00
fe5fa703b3 increase the height of the files progress bar 2009-03-31 00:30:07 +00:00
7166cc01b5 add some doc strings and improve the __str__ method of the FileTree class 2009-03-31 00:28:33 +00:00
d0a083b1b1 remove the x-deluge-filters class from a filters panel since we can just use #sidebar 2009-03-31 00:20:16 +00:00
608826ce32 remove commented out class 2009-03-31 00:18:59 +00:00
e0cba5bca3 add a progress bar to the files 2009-03-31 00:17:32 +00:00
e903e14188 remove redundant folder 2009-03-31 00:06:36 +00:00
3d8085310e move all the icons
update the paths in the css/code
begin to use more iconCls rather than icon
2009-03-31 00:04:38 +00:00
a2640a8a32 fix it so the file icon is set using css rather than hard coded 2009-03-30 23:35:11 +00:00
a32b43b414 fix the file icon on files
fix clearing the tree when a different torrent is selected
2009-03-30 23:25:27 +00:00
0b9b261038 remove old classes 2009-03-30 23:24:51 +00:00
0bcb847a00 move the columntree stuff into deluge-ext 2009-03-30 23:24:08 +00:00
49e54e1789 remove obselete stylesheet 2009-03-30 23:19:02 +00:00
f9d24ea6e2 add another class 2009-03-30 22:50:00 +00:00
0c3d0befcd display the torrents files in the files tab 2009-03-30 22:25:16 +00:00
5e4ee41db2 Add the files_tree property to TorrentInfo 2009-03-30 22:15:13 +00:00
cab504c90e fix a typo in a doc string 2009-03-30 22:07:47 +00:00
38acdf7017 reduce to only what is required to achieve the selection 2009-03-30 21:58:21 +00:00
ac911d3ed7 add #sidebar to ensure it only occurs in the sidebar 2009-03-30 21:51:42 +00:00
3342394a37 make the selected item in the sidebar have bold text and rename the messagebox icon styles 2009-03-30 21:48:23 +00:00
63c67b6925 use the "checked" config option to add the checkbox to the tree
disable animation
remove the enabled column
2009-03-30 21:45:40 +00:00
cea7d5bc5b add an icon for files in a file tree 2009-03-30 21:39:40 +00:00
f0a25a3486 add support for displaying a checkbox in the tree 2009-03-30 21:38:39 +00:00
5c7d1e6576 use consts/vars rather than merely numbers 2009-03-30 21:37:16 +00:00
5c35712800 Check for invalid handle on tracker errors/warnings 2009-03-28 22:38:19 +00:00
0204ba426a Fix typo 2009-03-28 04:03:17 +00:00
42dce915df Add PreTorrentRemovedEvent event 2009-03-26 21:23:56 +00:00
8373377c10 Add daemon autoconnecting on startup 2009-03-25 18:01:16 +00:00
7c1d16a51c add a method to return a torrents files as a tree 2009-03-25 09:12:48 +00:00
96e8de6db5 render the checkbox correctly 2009-03-23 23:17:04 +00:00
5dc2809732 raise the exception since if we haven't been able to read the file there's not point in continuing 2009-03-23 23:16:12 +00:00
fe83a95041 correctly render the columns in the tree 2009-03-23 22:49:31 +00:00
2e1cc51f70 display the torrent files in the tree 2009-03-23 22:32:48 +00:00
9808302214 add a FileTree class for generating a file tree 2009-03-23 22:18:01 +00:00
3a558433b9 Fix plugin __init__'s and update create_plugin script 2009-03-23 21:03:43 +00:00
5c5bc9a713 fix __init__ to stop gtk being imported in the core 2009-03-23 20:58:21 +00:00
0ed166647d do a lazy import of gtk to stop the core trying to import it 2009-03-23 19:20:45 +00:00
bb4935ae02 add a notify method to Deluge.Ui 2009-03-23 01:10:57 +00:00
2193905fa6 implement disconnecting from a connected daemon 2009-03-22 23:52:34 +00:00
a0e9fafb8f begin an execute command upon event plugin 2009-03-22 23:37:21 +00:00
3f0a1eb896 use super instead 2009-03-22 23:36:45 +00:00
23bb565259 change width to auto so the details tab displays correctly 2009-03-22 21:03:24 +00:00
96ead0d996 Fix #855 force a resume on a torrent if a 'Force Recheck' is initiated 2009-03-21 18:45:47 +00:00
850807ca43 Fix udp trackers being classified as DHT source 2009-03-21 18:07:19 +00:00
c5cc5c283b add time_added and tracker_host to the torrent grid 2009-03-21 15:25:09 +00:00
b2f01c177f implement basic adding of torrents via url 2009-03-21 12:28:48 +00:00
856cd63421 move the clearing to the selectionchange event of the grid so it happens immediately 2009-03-21 12:02:18 +00:00
c143891c93 clear the details pane when there are no selected torrents in the grid 2009-03-21 11:53:05 +00:00
6adb10b62a increase status column size 2009-03-21 11:50:57 +00:00
6b7302ed4b fix clearing the sidebar so filters can be re-added after a reconnect 2009-03-21 11:49:43 +00:00
3f8ef6c66e fix adding hosts and clearing the form after changing password to _password 2009-03-21 11:21:05 +00:00
0e94c31ca2 turn the port field into a spinner 2009-03-21 11:15:17 +00:00
4179336c63 remove the psds from the ext themes 2009-03-21 10:57:38 +00:00
8464ae9152 tidy up the images folder 2009-03-21 10:34:19 +00:00
f9f2a55d93 implement a basic add connection window
implement remove connection
2009-03-20 22:36:58 +00:00
504f2470ba fix clearing panels on a log out 2009-03-20 20:46:36 +00:00
d5b7616f98 if the client on the server is already connected skip the connection manager 2009-03-20 19:20:07 +00:00
0f44b06197 rename the messagebox classes as they are clashing with the state ones 2009-03-20 19:08:40 +00:00
a97fbbc1ef fix status when a host is connected 2009-03-20 19:00:11 +00:00
2b96aa990e Fix showing connected status in connection manager 2009-03-20 18:55:54 +00:00
9ca7634ec9 make the stop daemon button actually stop the daemon 2009-03-20 18:26:47 +00:00
73d0023ef5 add styles for messagebox icons
fix the style for the login box
2009-03-20 18:25:23 +00:00
bccb7ca66e select a row if there is no row selected when contextmenu is clicked 2009-03-20 17:26:24 +00:00
4852188ce9 change "Sidebar" to "Filters" for the panel title 2009-03-20 17:22:43 +00:00
4c83745295 change the cursor to a pointer when over the filters
add in generating the filters dict and applying it to the update_ui call
2009-03-20 17:15:46 +00:00
89e7198e21 add a logging statement to update_ui 2009-03-20 17:14:28 +00:00
a08a4a4e69 implement updating the filters 2009-03-20 09:22:57 +00:00
846d8a0c8f use the universal classes for states 2009-03-20 08:57:36 +00:00
575efe1495 make the tracker host error filter have an icon 2009-03-20 08:03:54 +00:00
c46c56e784 improve the sidebar to ensure that the icons display correctly 2009-03-20 07:59:39 +00:00
cb1beab159 add a proper renderer for the filters 2009-03-20 00:11:14 +00:00
7fb9af5c3d add a basic implementation of the sidebar 2009-03-19 23:00:07 +00:00
f3fd90253e add a favicon 2009-03-19 22:40:26 +00:00
1229e9a46c add color to input boxes so text is visible whilst using a dark browser theme 2009-03-19 22:29:24 +00:00
f909c2409f begin implementation of the SideBar 2009-03-17 10:33:51 +00:00
5512606f8a remove the now redundant calls 2009-03-17 09:16:35 +00:00
fc68ec2929 add the improvements to the export deco 2009-03-17 01:09:23 +00:00
11e42db767 partially implement adding torrents via url 2009-03-17 01:03:38 +00:00
233ed89318 fix get_torrent_info 2009-03-17 01:03:09 +00:00
306961ed75 fix download_torrent_from_url 2009-03-17 00:45:43 +00:00
7b1fc47f99 tweak the size of the details pane 2009-03-17 00:07:34 +00:00
b00b942fee add the comment field to the Details tab 2009-03-17 00:03:15 +00:00
da318ba450 add more events 2009-03-16 23:57:08 +00:00
bbb9ab69b3 tie up some of the torrent menu events 2009-03-16 23:42:28 +00:00
95ac4397a3 display the torrents menu on the rowcontextmenu event 2009-03-16 22:23:56 +00:00
61d028a8ce add the classes for the menu and 2 more icons 2009-03-16 22:13:25 +00:00
d9d5d2b308 remove all remaining oxygen icons
add the additional required icons from fugue
add the torrents context menu
2009-03-16 17:07:13 +00:00
399f8b3f6f change ajax to web 2009-03-16 15:54:48 +00:00
467afb5d63 slight tweak to the get_hosts method 2009-03-16 15:51:51 +00:00
87b789e3a1 make the gettext javascript render in unicode 2009-03-16 15:34:43 +00:00
db853c7c56 improve the export decorator slightly to allow for it to be used without
being called.
2009-03-16 13:30:55 +00:00
c0f11fbae4 Fix #842 some exceptions when disconnecting/reconnecting to daemon 2009-03-16 00:46:51 +00:00
b0e368c9ab Fix issue where core_config would become {} when adding multiple
torrents externally at once
2009-03-16 00:29:49 +00:00
930c479718 Remove the plugin hooks from the Core.. These are replaced by Events 2009-03-15 20:29:51 +00:00
7533c4bb88 Fix #841 maximum upload slots tooltip 2009-03-15 18:38:08 +00:00
f746b79c99 Remove toolbar's update_buttons method 2009-03-15 18:03:55 +00:00
a0db11f0b8 Add preferences option "Add torrent in paused state" 2009-03-15 17:59:27 +00:00
9814cad0b9 Fix tracker error filtering 2009-03-15 02:09:32 +00:00
f5db9d3534 Add 'Comments' field to the Details tab 2009-03-15 01:35:20 +00:00
f787e013ee Add an Error filter to the Trackers filter list 2009-03-15 00:59:29 +00:00
1c2b06a4f7 Update deps to include xdg-utils 2009-03-15 00:38:08 +00:00
c9bd55b819 Don't always log to file in Windows 2009-03-14 23:34:49 +00:00
86d52ba2e1 Use binary mode on all config files for Windows compat 2009-03-12 21:43:17 +00:00
d63c187dcf Fix loading config files on Windows 2009-03-12 21:33:43 +00:00
01350e0060 add a custom sorter for the address column 2009-03-12 19:04:04 +00:00
0ac64da5c6 move the json resource into its own module
split the json-rpc methods and the rpc server into seperate classes
make the json-rpc server a component to allow for extension
2009-03-12 18:57:35 +00:00
344446a626 Do not return when unable to make a backup of the config file 2009-03-09 16:43:28 +00:00
27298ba8d8 Update About dialog 2009-03-08 21:06:17 +00:00
3cab036b70 Make sure config files, resume data and state are fsync'd when saved. This should help prevent data
losses on crashes/improper shutdowns.
2009-03-08 20:27:58 +00:00
8f4583bc23 Fix #790 tracker hosts not correct for some .uk trackers 2009-03-08 20:19:19 +00:00
849b579316 Label: Fix setting 'Move on completed' folder when connected to a remote daemon 2009-03-08 20:14:42 +00:00
3072fc48da Make sure resume files are fsync'd 2009-03-08 02:35:58 +00:00
9a4bbb771e Make a backup of config files before overwriting and make sure the file is fsync'd without error 2009-03-08 02:33:12 +00:00
e12faf5641 improve the error reporting when a ui fails to load 2009-03-07 17:27:04 +00:00
eaf8183397 Fix up error message when unable to import a UI 2009-03-07 16:55:45 +00:00
8fda4d1fde rework the DelugeWeb class so it's completely self contained 2009-03-07 12:42:09 +00:00
8e62f5b3a8 change default hosts to a list as we'll probably be using it in the connection manager which needs to extend it 2009-03-06 21:30:20 +00:00
3ac9085a73 remove test html file 2009-03-06 20:39:44 +00:00
f524d8e63d edit the web package_data stuff 2009-03-06 20:26:17 +00:00
fe002092bf apply Ghents patch to allow for specifying your deluge config dir whilst
creating a plugin
2009-03-06 17:18:48 +00:00
52b2f334dd update webui entry in the changelog 2009-03-06 15:22:12 +00:00
71ac5884dc attach to signals, make DelugeWeb and JSON components
make the server print out its pid and url like paster does
2009-03-06 15:15:53 +00:00
fe6f045be1 remove old webui 2009-03-06 15:01:05 +00:00
d4bc535027 Remove ssl exception from license header when creating plugins from the
script
2009-03-05 23:57:48 +00:00
204f6ee89e Fix IPCInterface on Windows 2009-03-04 02:08:52 +00:00
80fdc3356c allow the client to figure out the auth for a local connection 2009-03-03 19:05:23 +00:00
8d863f2e3c Fix showing Preferences dialog in Windows 2009-03-02 01:46:22 +00:00
237e44d73f Update ChangeLogs 2009-02-28 22:22:49 +00:00
eb05a47d6a Only emit the TorrentFinished event when the torrent hasn't been previously finished.. e.g. after a force recheck 2009-02-28 22:07:49 +00:00
1375d4f545 Fix torrentmanagers update interval to 5 seconds 2009-02-28 21:59:49 +00:00
b6fe5166a8 Catch exception when removing a checking torrent 2009-02-28 21:05:49 +00:00
60a78c52e2 Do not attempt to pause/remove a checking torrent due to stop at share ratio rules 2009-02-28 21:01:28 +00:00
f6c26d6690 Remove timer in pluginmanager since update calls will be handled by
component now
2009-02-28 17:20:49 +00:00
4eb175ae9c Force str for proxy settings 2009-02-28 17:17:40 +00:00
7a6be9df1e Fix #817 email notifications fail to substitute format strings 2009-02-28 02:18:12 +00:00
e287e3ec33 Fix #655 issue where default torrent options wouldn't be set for new
torrents added to the addtorrentdialog
2009-02-28 01:48:41 +00:00
51ddc35140 Fix displaying file errors when the torrent isn't paused 2009-02-27 21:38:30 +00:00
3f03cb967a Get Label plugin working in the GtkUI 2009-02-27 17:12:53 +00:00
faef89870b Fix preferences window from not closing properly on OK 2009-02-26 20:52:08 +00:00
addaefaf7b Force SSL3 connection 2009-02-26 15:16:36 +00:00
d9f2daa778 Fix classic mode 2009-02-26 05:24:36 +00:00
cb78682415 Fix showing the preferences dialog when not connected to a daemon 2009-02-26 03:42:14 +00:00
f61e86d7b3 Add EventManager to the Core 2009-02-26 03:10:11 +00:00
7d1392ffe5 Clean up some debug statements.
Fix adding torrents from arguments on initial load.
2009-02-26 01:50:30 +00:00
7b682f4f60 Implement new IPC system. There is no longer a dependency on DBUS and this system should work on
all platforms.
2009-02-26 01:47:40 +00:00
72ce4eede7 add the deluge icon to the main title bar 2009-02-25 17:34:59 +00:00
34c91448cd add the columntreeview to the files tab 2009-02-25 17:07:41 +00:00
3de1da44a0 add seperate icons for adding by file, url and magnet
change the add/remove icons to simple plus/minus
remove all 32x32 icons
2009-02-25 16:51:38 +00:00
7459210753 add a fuller layout to the add torrent window 2009-02-25 16:41:13 +00:00
bb4a5f4404 remove unnecessary css class 2009-02-25 15:52:16 +00:00
2fa4c4187a fix the speed renderers so they closer match the gtk grid 2009-02-25 15:16:05 +00:00
0d1fe3370a modify speed modifiers to be the same as the ones in common.py 2009-02-25 15:13:38 +00:00
1566091dd9 add an icon to the connection manager window 2009-02-24 21:06:16 +00:00
22e3b34221 improve the progress bars a little and add a stub for the torrent add window 2009-02-24 20:20:49 +00:00
9b05ec8b5f Get blocklist plugin working 2009-02-24 01:03:02 +00:00
fa77f8403a Fix get_resource 2009-02-24 01:02:28 +00:00
4a6ecde07b Update create_plugin.py script 2009-02-24 00:00:35 +00:00
703e9def05 Change some plugin stuff and add an example plugin 2009-02-23 23:54:06 +00:00
8025889598 Fix building plugins when python isn't in the PATH 2009-02-23 11:25:07 +00:00
9ed0a80679 Catch exceptions while loading the geoip db 2009-02-23 10:22:55 +00:00
7e7944a085 Fix "quit and shutdown daemon" option 2009-02-21 14:03:28 +00:00
0e47cfd49e add a toolbar to the bottom of the connections grid 2009-02-21 13:20:30 +00:00
604ddc092e fix exception if no country is specified 2009-02-21 10:44:20 +00:00
dadb74477e Fix the allocate mode not being preserved when selecting different
torrents in addtorrentdialog
2009-02-21 10:42:59 +00:00
9ec3c9ec91 remove redundant templates folder 2009-02-21 10:40:57 +00:00
5cf1fa9d00 move extended ext classes into their own file 2009-02-21 10:39:47 +00:00
c05def0cf9 Add new installer bmps 2009-02-21 10:11:04 +00:00
ee028f2a52 attach to the "logout" event in the connectionmanager in onRender instead of onShow
fix clearing the torrent grid on logout
2009-02-21 04:35:11 +00:00
0f0c0cef9b report in the peers table whether the peer is a peer or a seed 2009-02-21 04:29:04 +00:00
8280d029aa add progressbar to peers tab and fix adding data to the store 2009-02-21 04:16:08 +00:00
28bbd0cc62 clear all the tabs (that have data) when the client disconnects 2009-02-21 04:04:05 +00:00
4eb70ec484 editing wrong class 2009-02-21 03:46:05 +00:00
72690f5328 remove pointless regex stuff 2009-02-21 03:43:58 +00:00
ce2e089d63 add a progress bar to the torrent grid 2009-02-21 03:42:40 +00:00
8c0ba82e0a add stub for a FilesTreeLoader 2009-02-21 02:57:22 +00:00
1f6ea321b7 make the countries column sortable and tweak the store 2009-02-21 02:41:22 +00:00
4659cf2438 fix speed renderer
alias fspeed, fsize and ftime to the corresponding formatters
improve the peers grid (flags, fixed renders etc.)
2009-02-21 02:31:56 +00:00
26addfd63c add a resource for the country flags 2009-02-21 02:30:58 +00:00
c212bc35e9 add stubs for the files and peers tab 2009-02-21 02:06:46 +00:00
66495f4b06 fix displaying the hash in the details tab 2009-02-21 01:25:26 +00:00
8f0766bfe5 update stats on the details tab and add updating when the tab is changed 2009-02-21 01:23:17 +00:00
372d138a77 add copyright headers after remembering andars death threat 2009-02-21 00:15:48 +00:00
4e5e98d90b add a helper methods to torrents
trigger an update immediately when the torrent is changed in the grid
2009-02-20 23:58:18 +00:00
a9fb98c23a substantially improve the fire method of events, allowing unlimited event args to be passed in now. 2009-02-20 22:59:56 +00:00
7279755f24 add a subclass of Ext.ProgressBar that allows for a percentage value to be used 2009-02-20 22:19:59 +00:00
13343a6b4b don't have any text in the statusbar on creation 2009-02-20 21:58:38 +00:00
3cfeb8a2ef rename tab_statistics to tab_status
update status when a torrent is selected in the grid
tweak status css
2009-02-20 21:57:31 +00:00
4f9e627131 rename getSelection to getSelections 2009-02-20 21:55:51 +00:00
cf2842b623 fix to work with new deluge-torrents layout 2009-02-20 21:55:34 +00:00
8d1a49f11c improve the layout of the deluge-torrents module
delegate updating stats to the individual tabs in the details panel
2009-02-20 20:09:29 +00:00
7c3c1fb767 return if there is no connection selected 2009-02-20 20:04:12 +00:00
d542666f20 Fix some deprecation warnings and imports 2009-02-20 14:32:28 +00:00
2399850e4e Wikified (trunk) changelog 2009-02-20 11:35:17 +00:00
566c6adf3a remove a bunch of the oxygen icons
add a titlebar icon to the login window
2009-02-19 21:50:30 +00:00
376b0daa11 tidy up toolbar event handlers
add a client connection check and act accordingly when its disconnected
2009-02-19 21:36:35 +00:00
eae92d78eb move updating the statusbar into the deluge-bars module
show/hide the additional statusbar info when connected/disconnected
2009-02-19 21:07:14 +00:00
fda01f59a7 fix Deluge.Events.fire 2009-02-19 20:46:08 +00:00
faae99d3d8 improve the statusbar, default to "Not Connected" with an icon 2009-02-19 20:38:06 +00:00
b9d84be341 clear the torrent grid when stopping the ui 2009-02-19 20:12:13 +00:00
815d8aa39f handle the logout button being pressed 2009-02-19 20:10:57 +00:00
2669ade501 add login event and enable the logout button once logged in 2009-02-19 19:22:51 +00:00
5153ad6f78 move over to central event holder 2009-02-19 18:59:14 +00:00
b4cc833044 add help and logout buttons to the toolbar
improve the enabled/disabling of buttons on connect/disconnect
2009-02-19 18:42:19 +00:00
0e78b9c3b1 add help icon 2009-02-19 18:32:03 +00:00
238c9d722d add logout icon 2009-02-19 18:30:15 +00:00
b3d4fd6620 Fix external property for src/ 2009-02-19 11:30:51 +00:00
45b4bc8e28 tidy up including python bindings 2009-02-19 11:23:37 +00:00
17e7ddf66f fix svn:externals properties 2009-02-19 11:17:20 +00:00
b397f99b21 tidy up libtorrent linking to only what we require and also include asio again 2009-02-19 11:03:45 +00:00
8899a683ab set svn:externals property on trunk to grab LT from their svn 2009-02-19 10:07:23 +00:00
7ca5ad1b93 remove LT from trunk 2009-02-19 10:04:27 +00:00
70a810b531 do safe simplejson import in common and use this imported copy in the 2
other places where its used.
2009-02-19 09:39:18 +00:00
8c2b735a8b Fix saving file priorities when switching torrents in the
addtorrentdialog
2009-02-19 06:03:11 +00:00
8ca8c5de05 move torrentAction to onTorrentAction 2009-02-19 02:21:13 +00:00
ea4f734863 move over to a more event driven style 2009-02-19 02:14:35 +00:00
9e19ae79c8 prepare for allowing parts of the ui to subscribe to connect/disconnect events 2009-02-19 01:22:32 +00:00
7344d0b1a3 remove not needed initialize call 2009-02-19 01:21:15 +00:00
6adada01e4 rearrange the details module to make it more managable 2009-02-19 01:12:58 +00:00
4b711883cb Do not set sys.stdout,err and stdin to None if logfile is used 2009-02-19 00:52:04 +00:00
7fb09d922a don't return the username and password for the daemon 2009-02-18 23:40:24 +00:00
d9e67bcebe lt sync 3273 2009-02-18 06:15:15 +00:00
cc272d8dc0 enable the disabled toolbar buttons once the ui connects 2009-02-17 00:04:46 +00:00
1ff29a134c more improvements to the connection manager, ui actually starts running after a connect now. 2009-02-16 23:27:12 +00:00
b6dee74dd5 update to allow for passing in a methods list when initialising 2009-02-16 23:22:36 +00:00
911d95815f Fix hiding bottom pane when no tabs are enabled upon restart 2009-02-16 02:40:50 +00:00
9907909b58 make the connection manager poll 2009-02-16 01:06:08 +00:00
e99dd03dcc more progress on the connection manager 2009-02-16 00:46:16 +00:00
5bd5db4f16 Blocklist now displays a tick when up to date 2009-02-14 03:26:33 +00:00
b73e26344c lt sync 3259 2009-02-13 17:41:09 +00:00
847ad95fd3 begin connection manager 2009-02-13 08:25:55 +00:00
356af2ba0a changed incorrect password window title to "Login Failed" 2009-02-13 07:44:07 +00:00
c7d3275561 forgot to put that it was CC3 2009-02-12 18:58:39 +00:00
49e705af14 remove last remaining silk icon
update license
2009-02-12 18:58:11 +00:00
d6d926d94f replace some of the silk icons with icons from the fugue set 2009-02-12 18:47:17 +00:00
18f7736a22 default most toolbar buttons to being disabled 2009-02-12 00:20:13 +00:00
345b28935f make enter check the password 2009-02-12 00:14:59 +00:00
d0020344f1 improve failed attempt reporting 2009-02-12 00:01:59 +00:00
0b3a04dc6c add a basic login system 2009-02-11 23:55:59 +00:00
7842ad5d3d lt sync 3253 - fix ssl trackers 2009-02-11 15:27:19 +00:00
f521795552 Update README to include current deps 2009-02-11 00:55:30 +00:00
6c00dc5db1 use config manager and add a login method 2009-02-11 00:48:14 +00:00
1d61bb3e94 Revert last change. Hiding the exception isn't a good idea and the error shouldn't be OS-specific. 2009-02-11 00:40:22 +00:00
ee05e18a9a show easy to understand error message on twisted importerror for the not so bright #796 2009-02-11 00:26:25 +00:00
06bb660a10 make the new twisted webui runnable via deluge -u web 2009-02-11 00:17:31 +00:00
ef5790fefe rename webui to server 2009-02-10 22:59:32 +00:00
c720417cb4 change config file format from pickle to json 2009-02-10 22:43:35 +00:00
17ea87be2e conf downgrade script 2009-02-10 22:30:45 +00:00
032b0fa934 remove pointless divs in the html 2009-02-10 12:56:48 +00:00
74d2657750 add doctype and xmlns 2009-02-10 12:52:00 +00:00
b8a8a37571 Append a new line when initially creating auth file 2009-02-10 09:10:14 +00:00
be68515fdc Have the client module automatically try to get the localhost creds in connect() 2009-02-10 08:40:05 +00:00
9175ac16fd Fix issue when a client connection is lost that has been authenticated 2009-02-10 08:35:41 +00:00
8bcc7ea232 lt sync 3243 2009-02-09 23:23:26 +00:00
db23f6a723 Fix missing import 2009-02-09 02:59:24 +00:00
8df39bbcef lt sync 3240 + patch 2009-02-09 00:46:23 +00:00
1394c52a80 Print out the data when a bad message is received 2009-02-09 00:43:11 +00:00
8ee7bf9983 Rename RPC_SIGNAL to RPC_EVENT and fix receiving multiple events 2009-02-08 23:25:57 +00:00
e96b4c4f58 switch over to using twisted-web 2009-02-08 16:56:56 +00:00
ea734931d7 lt sync 3236 2009-02-08 00:08:15 +00:00
44d2fd1f1f lt sync 3232 and patch segfault on start 2009-02-07 00:59:56 +00:00
89b5ca1cfe Fix #790 tracker hosts not correct for some 3rd-level domain names 2009-02-06 09:01:11 +00:00
7cfc54728f Fix queue manipulation 2009-02-06 09:00:20 +00:00
ea5bb29ab5 Fix displaying errors when a torrent is Checking 2009-02-06 07:13:56 +00:00
e2f707f0d7 update setuptools info and up version to one that actually works 2009-02-06 00:25:56 +00:00
85f34614dc fix the queue cell renderer 2009-02-05 22:30:00 +00:00
76f35aee85 A better fix for the preferences dialog 2009-02-05 09:06:48 +00:00
f942d4ee43 Fix preferences window 2009-02-05 08:36:59 +00:00
1003374bb4 Update license on metafile.py to GPL3 2009-02-05 04:46:38 +00:00
d7caea5c31 Change system tray tooltip on disconnect from daemon 2009-02-05 00:01:42 +00:00
cd493c0f08 add the new twisted/ext webui to svn 2009-02-04 18:20:46 +00:00
e861e660a5 Fix queue order changing 2009-02-04 14:55:51 +00:00
b18d9cfed4 Fix issue that could happen when the deferreds created in the connection
manager fire after the dialog has been closed
2009-02-04 06:41:19 +00:00
5ad7c60b65 Remove signalmanager 2009-02-04 06:27:40 +00:00
75efde8439 Fix filtering on trackers 2009-02-04 06:17:09 +00:00
9b0306d5b5 Clean up some stuff when clients disconnect 2009-02-04 03:00:55 +00:00
5fc4948ad2 Fix some issues with event handling on the client side and how arguments are handled in
DelugeEvents
2009-02-04 02:48:50 +00:00
3b6bee1508 Fix up config module to use twisted loop instead of gobject 2009-02-04 02:47:02 +00:00
523d494991 lt sync 3228 2009-02-03 21:58:29 +00:00
e0735cf5ca Only attempt stopping PluginManagers looping call if it's running. 2009-02-03 06:39:33 +00:00
a24738a9ff Implement Events (formerly Signals) which are emitted from the daemon to interested clients. 2009-02-03 04:13:41 +00:00
aa89c653f9 Remove xmlrpc related files 2009-02-02 10:39:33 +00:00
c374e99cdd Fix logging exceptions in the daemon 2009-02-02 02:08:59 +00:00
fe98e1c11e Fix typo 2009-02-02 01:52:15 +00:00
1462795480 Update and fix-up the man pages 2009-02-02 00:20:25 +00:00
ab4fec5573 Fix issue when initializing gettext that would prevent deluge from starting 2009-02-01 22:18:39 +00:00
c399f7c9b3 Move the list_methods rpc to the daemon object and rename it to 'get_method_list' 2009-02-01 20:39:07 +00:00
27cf34f85b trunk lang sync 2009-01-31 21:16:38 +00:00
27937e21dd import stat as it's used in generating ssl keys 2009-01-30 19:26:43 +00:00
c6439e5a22 add a list_methods method so a javascript json-client can be built for
the webui
2009-01-30 14:09:22 +00:00
b3b856bcca Fix double-clicking on host entry to connect 2009-01-30 03:07:22 +00:00
d6fd69eba8 Fix adding torrents 2009-01-29 01:42:48 +00:00
887ef8d7ca Fix component depend on CorePluginManager 2009-01-29 01:19:26 +00:00
6a0594b47d Rename the daemons PluginManager component to CorePluginManager to not
conflict with the gtkui in Classic mode.
2009-01-28 23:10:44 +00:00
e9f8c7b0e8 Get Classic mode working somewhat. There are still some issues to
resolve with it.
2009-01-28 17:59:27 +00:00
9f369388e6 lt sync 3225 2009-01-28 16:19:36 +00:00
44ffcd4499 Automatically get localclient credentials if attempting to connect to a
localhost
2009-01-28 02:31:51 +00:00
464073e596 Update the list 2 seconds after starting the daemon 2009-01-28 01:36:46 +00:00
01fbda7c9e minor connectionmanager fixes on adding hsot 2009-01-28 01:14:29 +00:00
4d2c6881f8 Fix saving hostlist on host remove 2009-01-28 00:57:45 +00:00
6cd05fbbc9 Remove default user/pass from hostlist 2009-01-28 00:52:18 +00:00
089f0afa32 Fix license headers
Remove ui/webui/ssl from package_data since it doesn't exist
2009-01-28 00:36:33 +00:00
865921a677 Fix issue when using 'Active' state 2009-01-28 00:03:14 +00:00
47bb52f72a Remove pythonize module since it's no longer used 2009-01-27 23:44:26 +00:00
eda19c3d60 Update copyright years in aboutdialog 2009-01-27 23:34:03 +00:00
8f12919013 Fix saving files/peers tab state when no column is sorted 2009-01-27 21:45:44 +00:00
b681ca8909 Fix typo 2009-01-27 21:41:48 +00:00
08ea99c233 Fix #761 use proper theme colours in sidebar 2009-01-27 21:21:15 +00:00
3632409b29 Fix import 2009-01-27 20:48:29 +00:00
45669ca703 lt sync 3219 2009-01-27 19:24:07 +00:00
bf4dae61d2 lt sync 3218 2009-01-27 17:27:23 +00:00
42588656fd Implement new DelugeRPC method to replace XMLRPC.
This commit breaks _a lot_ of things including the web and console UIs, please do not expect 
anything to work.
2009-01-27 08:03:39 +00:00
ce1b7b491d Fix up some copyright headers 2009-01-27 00:21:53 +00:00
657ec0756a Remove 'state_upgrade.py' script since this functionality is included in Deluge now. 2009-01-27 00:17:43 +00:00
d727a515b7 Updated for new year 2009-01-26 05:06:08 +00:00
20751de699 ltsync 3211 2009-01-25 02:51:01 +00:00
24e526ce93 Revert unintended change 2009-01-25 02:17:15 +00:00
5697376caa lt sync 3209 2009-01-25 02:10:39 +00:00
082dea9b80 Update python bindings from libtorrent svn 2009-01-24 05:31:45 +00:00
d9ab0ec0ca Fix setting outgoing ports 2009-01-24 05:25:37 +00:00
9df4c84295 lt sync 3205 2009-01-24 04:12:32 +00:00
05141c6f2c Fix when sorting # column, downloads should be on top 2009-01-23 05:25:31 +00:00
7167c0ecca Fix setting file priorities when adding a torrent 2009-01-22 08:22:50 +00:00
71aebaffdf Fix being able to select/deselect files in the add torrent dialog 2009-01-22 06:01:34 +00:00
85b1a86669 Fix setting Peer TOS byte 2009-01-21 14:03:26 +00:00
72601aebf4 Fixed blocklist web ui 2009-01-21 03:56:38 +00:00
3b9b47011c Fixed regression where blocklist no longer checked for update on startup 2009-01-20 13:46:13 +00:00
2403d13ceb Fix torrents not displaying properly after disconnecting and
reconnecting to the daemon
2009-01-20 11:45:43 +00:00
2368a82b13 Fixed regression where blocklist would import empty list 2009-01-20 07:14:25 +00:00
2ea8ca1000 No longer checks for newer blocklist on startup 2009-01-19 10:46:24 +00:00
7c6319b1db Fixed bug where blocklist was reset when not imported
Date is now of remote blocklist (makes checking more precise)
Fixed web ui from crashing (still doesn't work though)
2009-01-19 10:14:33 +00:00
a6de74c858 Blocklist is no longer imported if up to date 2009-01-19 08:12:31 +00:00
1ec3751f91 need_new_blocklist is no longer blocking
removed download arg from import_list
updated gtkui and webui
2009-01-19 07:56:49 +00:00
813063bd12 need_new_blocklist now checks if remote blockist is newer/bigger 2009-01-19 06:02:58 +00:00
58361f4af2 Default to ERROR logging level if the supplied logging level is invalid 2009-01-18 06:24:49 +00:00
40ba6ea2ba lt sync 3187 2009-01-17 22:03:36 +00:00
7c349b1fa9 Fix translating speed units in status tab when a per-torrent limit is
set
2009-01-17 22:02:38 +00:00
a69efdfc56 Fix crashing in AddTorrentDialog when removing torrents from the list
Do not allow duplicate torrents in the AddTorrentDialog
2009-01-17 21:58:02 +00:00
32be4ed4ad Fix being able to connect to a local daemon from another user account 2009-01-16 20:11:05 +00:00
0fa9b491c5 add tooltip to popup about windows 2009-01-16 04:47:44 +00:00
a76550be68 make popup insensitive on windows 2009-01-16 03:41:13 +00:00
8f68fc9e07 Add support for more tracker icons 2009-01-16 03:31:21 +00:00
ebc24e35dd Fix #729 tracker icons not being saved in the correct location 2009-01-16 03:18:43 +00:00
8e5473a91d Fix saving Files tab and Peers tab state 2009-01-16 03:13:37 +00:00
5cef7fe9fc Fix remembering sorted column in the torrent list 2009-01-16 03:01:41 +00:00
2acd470626 Fix opening links from Help menu and others 2009-01-16 02:45:36 +00:00
f16ff06083 Fix the -l, --logfile option 2009-01-16 00:35:07 +00:00
f990fd1a9a Fix [4491] which broke the oldstateupgrade 2009-01-14 02:45:11 +00:00
e42910dbf8 Fix bdecoding some torrent files 2009-01-14 01:15:00 +00:00
c94a13ae17 windows updates to switch to boost 1.37 and python 2.6 2009-01-12 23:30:33 +00:00
855315dfb1 Update bencode.py from BitTorrent-5.2.2. This changes the license to
Python Software Foundation License Version 2.3.
2009-01-12 22:44:27 +00:00
8a6461bef8 Append a new line to the localclient entry 2009-01-12 19:55:57 +00:00
e681c9183e fix get_torrent_status to use filter dictionary 2009-01-11 00:05:50 +00:00
ea3b79bdd5 lt sync 3143 2009-01-10 21:25:43 +00:00
1cd3998350 lang sync 2009-01-10 18:50:44 +00:00
9cbe63c299 update credits for 1.x 2009-01-10 07:37:53 +00:00
9f7018bdfb added copyright info 2009-01-09 23:44:42 +00:00
9ee7562268 fix debian bug #510948 missing dep 2009-01-09 20:00:17 +00:00
ff42ebe0b2 Set 'max_half_open_connections' default to 50 on non-Windows systems 2009-01-09 04:21:26 +00:00
3e92ff026a Tell the user which UI was tried when unable to start 2009-01-08 22:25:46 +00:00
43be3e3e64 Added '-s', '--set-default-ui' option to deluge 2009-01-08 20:27:24 +00:00
b9ae2cb2b9 Update credits and author list 2009-01-08 03:35:22 +00:00
0bd50f9b08 Fix installing 2009-01-08 02:31:01 +00:00
366b5e1f95 add mime icons to the white theme
couple of stubs in the add window
2009-01-07 21:12:05 +00:00
c406ab4eaf add mime images to setup.py 2009-01-07 21:01:38 +00:00
bb8acea3df add mime icons to trunk 2009-01-07 20:51:41 +00:00
c59d0e348e improve the files table in the add torrent window
add some mimetype support in

improve the merge_changes.py script
2009-01-07 20:42:57 +00:00
52485af4f7 Allow torrents to be removed from the add torrent window 2009-01-07 19:06:28 +00:00
c48707a654 more improvements to the options tab 2009-01-07 18:13:05 +00:00
ed03ea52db template update 2009-01-07 03:55:21 +00:00
ad2fc421dc fix gtk-cancel translation setting in remove dialog 2009-01-07 03:41:52 +00:00
69e5fe1d3d add stub for filepicker to trunk
start implementing the options dialog
add another not implemented alert to edit trackers
update changelog
2009-01-07 01:28:19 +00:00
08855ef9d7 merge in change 2009-01-07 01:01:10 +00:00
b10416b8f8 merge webui fixes 2009-01-07 00:48:38 +00:00
2af3869143 Fix issue in get_tracker_host when the torrent has no tracker 2009-01-06 12:50:49 +00:00
3584fa9e41 fix crash on trying to convert *very* old 0.5 config files 2009-01-06 02:42:08 +00:00
cf40455d1c fix notification bug on startup for already finished torrents 2009-01-06 02:27:27 +00:00
89800dd6c1 sort for managibility 2009-01-06 01:43:41 +00:00
373dd2c695 Fix the display of the tracker host when it's an IP address and not a
hostname
2009-01-05 10:14:12 +00:00
7f1a7ea863 Show the Trackers sidebar filter by default 2009-01-04 08:53:06 +00:00
d850b71561 lt sync 3129 2009-01-04 08:48:46 +00:00
5c839a6b20 Fix seeding torrents from moving around when sorting the '#' column 2009-01-04 08:47:26 +00:00
dc17647590 Fix applying proxy settings 2009-01-02 21:25:26 +00:00
76a17a4028 Label: Fix move on completed 2009-01-02 03:25:39 +00:00
83ecface7a Fix folder renaming to display the change properly 2009-01-02 00:56:44 +00:00
388b21d6eb fix depreciation warning in py2.6 2009-01-01 18:28:33 +00:00
f97273e094 Change how the alert name is found to use the class's __name__ property 2008-12-31 02:47:17 +00:00
4471d70d6c Hide the initial test port image 2008-12-30 23:32:39 +00:00
98f0b875ba Fix exception in test open port 2008-12-30 23:28:30 +00:00
c61a6eb34b Add PeerGuardian Text (Gzip) reader 2008-12-30 03:52:18 +00:00
48f445d9a0 Apply blocklist prefs when the buttons are pressed. 2008-12-30 03:51:13 +00:00
a1a82c96a5 Do not continue to show 'Importing 0' progress bar if blocklist fails to
import.
2008-12-30 02:57:21 +00:00
bb4e7e38ae Fix gtkwarning regarding column width 2008-12-29 17:10:11 +00:00
e415829a68 lt sync 3106 2008-12-29 16:58:56 +00:00
daa045a425 going back to vs71 2008-12-29 03:43:50 +00:00
e315d40ddf Change default blocklist url to nipfilter instead of pipfilter 2008-12-28 23:15:01 +00:00
368f94157f Fix issue that prevented torrents from being added 2008-12-28 15:38:28 +00:00
2fb3f4b534 Fix #673 do proper test to determine if remote method requires callback 2008-12-28 04:39:08 +00:00
d00366204e Fix exception in metafile 2008-12-28 04:29:54 +00:00
6359c5d4af Do not use the stored config_location value because it should only be used if the --config option is
set.
2008-12-27 21:24:50 +00:00
e1c5f69d54 Fix exception in label plugin when saving preferences 2008-12-27 21:06:53 +00:00
00e74c9491 Make new release checking much more robust 2008-12-27 00:13:59 +00:00
15802aa432 Remove 'torrent_alert' handler 2008-12-27 00:02:11 +00:00
45e3f12a49 lt sync 3090 2008-12-26 22:47:24 +00:00
f5a6736617 Fix never-ending import in Blocklist on Windows 2008-12-26 22:45:43 +00:00
5cdd1146d1 Fix tooltip for 'Show session speed in titlebar' option 2008-12-26 08:21:13 +00:00
8ae6477a2d Remove revision file from trunk too 2008-12-26 08:05:10 +00:00
7ac25da4bd Fix new version check 2008-12-26 08:04:31 +00:00
7338a5daea change from vs71 to vs90 2008-12-26 04:55:20 +00:00
bb28b70887 vs2008sp1 fix - hydri 2008-12-26 04:52:44 +00:00
0574c5a125 lt sync 3081 2008-12-24 06:01:18 +00:00
d207429f02 Fix #661 show proper tracker host when ending in .co.uk, .com.au, etc.. 2008-12-22 10:07:39 +00:00
db3a05bda4 update translator credits 2008-12-22 02:44:57 +00:00
aed14960a9 Yet another typo fix 2008-12-20 23:19:24 +00:00
a23d877a99 Fix more issues with TorrentOptions 2008-12-20 23:14:06 +00:00
6756c69580 Fix some typos 2008-12-20 23:06:53 +00:00
6083c1655f Clean up has_key method in TorrentOptions 2008-12-20 06:28:44 +00:00
3481d26821 Fix up to __getitem__ in TorrentOptions 2008-12-20 05:49:03 +00:00
4313d84ed8 Fix some typos 2008-12-20 05:20:21 +00:00
04fdd521ea Use the 'allow_remote' config option instead of always using False 2008-12-20 05:00:55 +00:00
97d2f371b3 Import sys in rpcserver 2008-12-20 04:48:01 +00:00
b6822f446a Fix saving dht state 2008-12-20 04:33:47 +00:00
04d14df8c7 Re-org Core and start using RPCServer 2008-12-20 04:27:59 +00:00
8ed2d25ce5 Ignore _* when doing new version check 2008-12-18 07:06:06 +00:00
eb4f1fdb04 Do not fork in osx 2008-12-18 06:14:49 +00:00
2c4f322f61 lang sync 2008-12-18 04:05:21 +00:00
15dc400231 update pots 2008-12-18 03:46:55 +00:00
c3697f95e9 Branch 1.1.0, trunk is now 1.2.0-dev 2008-12-18 02:52:24 +00:00
1558 changed files with 243378 additions and 286088 deletions

9
.gitattributes vendored Normal file
View File

@ -0,0 +1,9 @@
/libtorrent export-ignore
/win32 export-ignore
docs/build export-ignore
docs/source export-ignore
/tests export-ignore
deluge/scripts export-ignore
.gitattributes export-ignore
.gitmodules export-ignore
.gitignore export-ignore

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*~
build
dist
*egg-info
*.egg
*.log
*.pyc
*.tar.*

3
.gitmodules vendored Normal file
View File

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

498
ChangeLog
View File

@ -1,60 +1,450 @@
Deluge 1.1.0 - "" (In Development)
Core:
* Implement #79 ability to change outgoing port range
* Implement #296 ability to change peer TOS byte
* Add per-torrent move on completed settings
* Implement #414 use async save_resume_data method
* FilterManager with torrent filtering in get_torrents_status , for sidebar and plugins.
* Implement #368 add torrents by infohash/magnet uri (trackerless torrents)
* Remove remaining gtk functions in common
* Tracker icons.
* Add ETA for torrents with stop at seed ratio set
* Fix #47 the state and config files are no longer invalidated when there is no diskspace
* Fix #619 return "" instead of "Infinity" if seconds == 0 in ftime
* Add -P, --pidfile option to deluged
=== Deluge 1.2.3 (27 March 2010) ===
==== Core ====
* Fix libtorrent version compare to use a proper numerical compare instead
of string. This fixes a problem where using lt 0.14.10 wouldn't allow
Deluge to start.
* Fix libtorrent 0.15 compatibility
GtkUI:
* Add peer progress to the peers tab
* Add ability to manually add peers
* Sorting # column will place downloaders above seeds
* Remove dependency on libtorrent for add torrent dialog
* Allow adding multiple trackers at once in the edit tracker dialog
* Implement #28 Create Torrent Dialog
* Redesiged sidebar with filters for Active and Tracker (see FilterManager)
* Implement #428 the ability to rename files and directories
* Implement #229 add date added column
* Implement #596 show speeds in title
* Fix #636 not setting the daemon's config directory when using --config= with the UI in classic mode.
* Fix #624 do not allow changing file priorities when using compact allocation
* Fix #602 re-did files/peers tab state saving/loading
* Fix gtk warnings
* Add protocol traffic statusbar item
* Rework the Remove Torrent Dialog to only have 2 options, remove data and remove from session.
* Add "Install Plugin" and "Rescan Plugins" buttons to the Plugins preferences
* Make active port test use internal graphic instead of launching browser
=== Deluge 1.2.2 (19 March 2010) ===
==== Core ====
* Fix #1109 auto add halting when a torrent with invalid filename encoding
is in the directory
WebUi:
* Lots of smaller tweaks.
* All details tabs have the same features as in gtk-ui 1.0.x
* Persistent sessions #486
* Plugin improvements for easy use of templates and images in eggs. #497
* Classic template takes over some style elements from white template.
* https (for users that know how to create certificates)
* Easier apache mod_proxy use.
* Redesigned sidebar
==== GtkUI ====
* Fix #1162 problem with the queued torrents dialog from not properly adding
to the add torrent dialog if set to auto add
* Fix #1172 notify startup complete when adding torrents externally
* Fix issue where the gtkui sometimes won't start if there is a stale lock
file or socket in the ipc/ directory.
AjaxUI:
* Hosted in a webui template.
==== Console ====
* Fix #1143 deluge-console crashes when tab-completing not-existent directory
ConsoleUI:
* New ConsoleUI written by Idoa01
* Callable from command-line for scripts.
=== Deluge 1.2.1 (20 February 2010) ===
==== Core ====
* Make Deluge dependent upon libtorrent 0.14.9 or greater. This is due to
an over-downloading bug in previous versions of libtorrent.
Plugins:
* Stats plugin for graphs.
* Label plugin for grouping torrents and per torrent settings.
==== GtkUI ====
* Fix #1128 Show an error dialog when unable to start a 'deluged' process
* Increased max enterable download / upload limit to 60000 KiB/s
Misc:
* Implement #478 display UI options in usage help
* Fix #547 add description to name field per HIG entry 2.1.1.1
* Fix #531 set default log level to ERROR and add 2 command-line options, "-L, --loglevel" and "-q, --quiet".
==== Console ====
* Fix hanging when using commands from the command-line
==== Web ====
* Fix #1147: Cannot upload a torrent in a multi-user system via the web interface
* Fix #1148: Unable to save execute command in execute plugin
=== Deluge 1.2.0 - "Bursting like an infected kidney" (10 January 2010) ===
==== Core ====
* Fix file renaming
* Fix tracker host filtering (Closes #1106)
* Fix exceptions when gettext/locale cannot be initialized properly
* Change share ratio calculation to use the total done instead of the all time
downloaded value. This change will make the share ratio calculation not
use data downloaded in failed hash checks.
* Fix torrent info name not being utf-8 decoded when root file/folder name
is blank
==== GtkUI ====
* Fix #1104, #735 use path.utf-8 if available
* Fix #1114 test active port not working in classic mode
==== Console ====
* Fix #1115 not showing usage for the 'debug' command
* Fix #1116 not being able to use command aliases when not connected to a daemon
* Fix #1117 can't use the '3' key
==== Windows ====
* Fix displaying folders in the add torrent dialog
* Fix displaying the new release dialog
==== Blocklist ====
* Fix blocklist status icon not opening the blocklist preference
page in certain locales
* Fix blocklist not recognising comments that begin with whitespace
* Minor speedup in parsing blocklists
* Blocklist now attempts to download the URL multiple times before giving
up
* Fix blocklist not being able to open zipped blocklists with python 2.5
==== Web ====
* Put the default password in the manpage.
=== Deluge 1.2.0_rc5 (17 December 2009) ===
==== Web ====
* Swap order of buttons in Remove window (Closes #1083)
* Change the compressed js script to deluge-all.js to avoid naming
conflicts on case-sensitive filesystems.
* Apply patch from adios fixing the cookie date
* Add tooltips to the statusbar items
* Add disk usage to the statusbar
* Add a ToggleField widget and use this on the Downloads preferences
page allowing the movecom/copytorrent/autoadd boxes to be enabled.
* Fix enabling plugins.
* Implement installing plugins.
* Update some icons
* Fixed #1075 (changing priority on a whole folder doesn't work)
==== GtkUI ====
* Attempt to register as the default magnet uri handler in GNOME on startup
* Properly show 100.00% and reduce number of progress bar updates during a
torrent creation
* Fix crash in Windows when creating a torrent
* Add button to Other preferences to associate magnet links with Deluge
* Fix uploading plugins when the daemon is not localhost
* Fix #692 no longer require tray password when quitting from the tray icon
while the window is visible.
* Fix #782 do not ask for tray password when window is not minimized to tray
* Fix #1036 autoconnecting to localhost daemon on start-up
* Fix issue where hosts will show up erroneously as Offline
* Add #891 remove torrents by pressing the Delete key
* Fix issue where stoping a daemon that you aren't connected to causes the
gtkui to shutdown the currently connected daemon.
* Fix #594 tray password dialog freeze in Windows
* Made the password dialog prettier
* Fix #1086 deprecated gtk.Tooltips usage
* Fix #768 save tracker list for create torrent dialog
* Fix #1095 incorrect piece size used when using some non-English languages
==== Console ====
* Fix using the console in Windows, but only in command-line mode
* Fix #823 setting config values to -1.0
==== Label ====
* Fix #1085 only use ints for specific options to prevent unhandled exception
==== Execute ====
* Use the move_completed path if it is different to the save path
in the completed event.
==== Core ====
* Fix the upload_plugin rpc method (was still using XML-RPC stuff)
* Fix possible exception when upgrading from a 0.5 state file
* Use metavar to modify the help output by optparse.
* Partial fix for #1103 if the per-torrent option for stopping at a ratio has
been unchecked, then do not stop it at the global setting.
==== Blocklist ====
* Fix blocklist not working for all locales
* Fix blocklist checking for updates when it shouldn't
=== Deluge 1.2.0_rc4 (24 November 2009) ===
==== Core ====
* Fix deleting old .fastresume files with fresh configs
* Fix files list when using magnet uris
* Fix loading the saved metadata when loading state with magnet uris
==== GtkUI ====
* Fix showing the 'Other' speed dialogs in Windows
* Fix adding torrents from the Queued Torrents dialog
* Fix disabling/enabling plugins after switching daemons
* Reduce height of Add Torrent Dialog by ~80 pixels
* Fix #1071 issue where Deluge will fail to start if there is a stale ipc lockfile
* Fix autoconnecting to the next host in the list if the selected one isn't available
* Fix endless loop when trying to autoconnect to an offline daemon
* Fix exception on startup when the system tray icon is not enabled
* Fix issue where some torrents with special characters could not be added
* Fix issues adding magnet uris
==== Web ====
* Fix installing the deluge-web manpage
* Escape hyphens in the manpage
==== Console ====
* Escape hyphens in the manpage
* Make the delete key work
* Allow ~ to be used in the path in the add command
* Allow commands that are .pyc files to be used
* Fix printing info, help, etc.. on the command line
==== Blocklist ====
* Force blocklist to auto-detect format when a download / import is forced
* Fix blocklist failing on certain PeerGuardian/SafePeer lists
=== Deluge 1.2.0_rc3 (01 November 2009) ===
==== Core ====
* Fix #1047 move completed does not work if saving to non default path
* Fix renamed files not being utf-8 encoded
* Fix torrent name being blank when renaming root folder to /
* Do not include an 'announce-list' key in torrents when there is only one tracker
==== GtkUI ====
* Replace & with &amp; in the details tab to ensure there are no markup errors
* Consider 0 unlimited when displaying limits in the statusbar
* Fix adding torrents when not showing the add torrent dialog in Windows
* Fix crash when removing multiple torrents
==== Web ====
* Fix #1046 changing auto managed via the details tab
* Fix setting torrent options when adding
* Fix setting file priorities when adding
* HTML escape the field values on the details tab
* Fix #215, make infinite eta values display in the correct order
* Fix displaying the protocol upload speed
* Fix #990, showing 0 as a limit when it means unlimited in the statusbar
==== Console ====
* Fix displaying non-ascii strings
* Fix #1052 crash when issuing commands while not connected to a daemon
* Fix crash when string length makes line longer than terminal width
* Improve 'info' command draw speed
=== Deluge 1.2.0_rc2 (25 October 2009) ===
==== GtkUI ====
* Fix path errors when adding torrents externally in Windows
* Fix localclient authentication by stripping the lines read from the auth file
* Do not try to call doIteration() on the reactor if it has already stopped
* Fix 'autostart localhost if needed' option
* Fix starting plugins when the pluginmanager is started
* Fix #799 translate connection status
* Fix #215 ETA sort order
==== Core ====
* Fix saving torrent state on fresh configs
==== Web ====
* Fix changing of the allocation in the preferences.
* Fix updating the Connection Manager when a host is added.
* Add a `--fork` option to allow forking the webui to the background
* Fix the statusbar menu limits
* Fix setting the torrent options via the options tab
* Fix the private flag in the options tab
==== Console ====
* Fix exception when using the 'halt' command
==== Misc ====
* Add man pages for deluge-console, deluge-gtk and deluge-web
==== Extractor ====
* Fix issue where the plugin would not stop extracting files after being disabled
* Add option to create torrent name sub-folders in extract folder
=== Deluge 1.2.0_rc1 (07 October 2009) ===
==== Core ====
* Implement new RPC protocol DelugeRPC replacing XMLRPC
* Move to a twisted framework
* Add an 'Error' filter for Trackers to show trackers that currently have a tracker error
* Use system GeoIP database if available, this is now an optional dependency
==== GtkUI ====
* Remove SignalReceiver
* Implemented a cross-platform IPC method thus removing the DBUS dependency
* Implement a "True" Classic Mode where there is no longer a separate daemon process
* Add preferences option "Add torrent in paused state"
* Add tracker icons to the Tracker column
* Implement #259 show tooltip with country name in the peers tab
* Add an error category to the tracker sidebar list
* Add Find More Plugins button to Plugins preference page
* Fix #518 remove header in add torrent dialog to save vertical space
* Add a Cache preferences page to adjust cache settings and examine cache status
* Add ability to rename files prior to adding them
* Fix shutdown handler with GNOME session manager
* Allow 4 MiB piece sizes when creating a torrent
==== ConsoleUI ====
* Changed to use curses for a more interactive client
==== WebUI ====
* Move over to using Twisted-Web for the webserver.
* Move to only AJAX interface built upon Ext-JS.
==== Plugins ====
* Add Scheduler plugin
* Add Extractor plugin
==== Misc ====
* PyGTK dependency bumped to => 2.12 to use new tooltip system
* Add new scripts for invoking UIs: deluge-gtk, deluge-web, deluge-console
* Remove GeoIP database from the source tree
=== Deluge 1.1.9 - (15 June 2009) ===
==== Core ====
* Only move a torrent due to 'move on complete' when some data has been downloaded
* Update libtorrent for CVE-2009-1760
==== GtkUI ====
* Fix #950 renaming a parent folder into multiple folders
==== WebUI ====
* Fix remote torrent add
=== Deluge 1.1.8 - (21 May 2009) ===
==== Core ====
* Fix pause all/resume all
* Torrent name is now changed when the root folder or file is renamed
==== GtkUI ====
* Fix high cpu usage when displaying speeds in titlebar
* Fix showing non-utf8 encoded torrents in add torrent dialog -- this adds
an additional dependency on chardet.
* Fix exception when timing out trying to send notification email
* Set some sane defaults for peers/file tabs column widths
==== WebUI ====
* Fix starting when -l option is used
=== Deluge 1.1.7 - (25 April 2009) ===
==== Core ====
* Fix issue where cannot resume torrent after doing a 'Pause All'
* Add workaround for 'address_v4 from unsigned long' bug experienced by users
with 64-bit machines. This bug is fixed in libtorrent 0.14.3.
==== GtkUI ====
* Fix #883 segfault if locale is not using UTF-8 encoding
* Fix for adding torrents with invalid filename encodings
* Fix displaying IPv6 peers in the Peers tab
* Fix starting the daemon in OS X
* Fix loading improperly created torrents with mismatched encodings
* Fix displaying improper progress when creating torrent
==== Windows ====
* Fix freezing in create torrent dialog
* Fix creating torrents in Windows
* Fix free space check
=== Deluge 1.1.6 - (06 April 2009) ===
==== Core ====
* Fix udp trackers being classified as DHT source
* Fix #855 force a resume on a torrent if a 'Force Recheck' is initiated
* Fix #862 deluged crash when access http://localhost:58846
==== GtkUI ====
* Fix displaying torrents with non-utf8 encodings in add torrent dialog
==== WebUI ====
* Fix #870 use proper config location for loading ssl cert
==== Misc ====
* Add OpenSSL exception to license
=== Deluge 1.1.5 - (16 March 2009) ===
==== Core ====
* Fix config file saving when no current config file exists
==== GtkUI ====
* Add 'Comments' field to the Details tab
* Fix #841 maximum upload slots tooltip
=== Deluge 1.1.4 - (08 March 2009) ===
==== Core ====
* Fix displaying file errors when the torrent isn't paused
* Fix issue where torrents being check would get removed due to "stop at ratio" rules
* Fix #790 tracker hosts not correct for some .uk trackers
* Make sure config files, resume data and state are fsync'd when saved. This should help prevent data losses on crashes/improper shutdowns.
==== GtkUI ====
* Fix hiding bottom pane when no tabs are enabled upon restart
* Fix saving file priorities when switching torrents in the addtorrentdialog
* Fix the allocate mode not being preserved when selecting different torrents in addtorrentdialog
* Fix #655 issue where default torrent options wouldn't be set for new torrents added to the addtorrentdialog
* Fix #817 email notifications fail to substitute format strings
==== Plugins ====
* Label: Fix setting 'Move on completed' folder when connected to a remote daemon
=== Deluge 1.1.3 - (15 February 2009) ===
==== Core ====
* Fix issue where checking queue would stop
* Fix announcing to SSL trackers
==== Misc ====
* Fix issue when initializing gettext that would prevent deluge from starting
* Fix logging exceptions when starting the daemon
* Fix displaying errors when a torrent is Checking
* Fix #790 tracker hosts not correct for some 3rd-level domain names
=== Deluge 1.1.2 - (31 January 2009) ===
==== Core ====
* Fix issue where torrents get stuck Checking
==== GtkUI ====
* Fix #761 use proper theme colours in sidebar
* Fix saving files/peers tab state when no column is sorted
=== Deluge 1.1.1 - (24 January 2009) ===
==== Core ====
* Fix oldstateupgrader for those upgrading from 0.5.x
* Fix setting Peer TOS byte
* Fix setting outgoing ports
==== GtkUI ====
* Fix opening links from Help menu and others
* Fix remembering sorted column in the torrent list
* Fix saving Files tab and Peers tab state
* Disable popup notification in preferences on Windows
* Fix crashing in Add Torrent Dialog when removing torrents from the list
* Do not allow duplicate torrents in the Add Torrent Dialog
* Fix translating speed units in status tab when a per-torrent limit is set
* Fix torrents not displaying properly after disconnecting and reconnecting to the daemon
* Fix when sorting # column, downloads should be on top
==== Misc ====
* Fix bdecoding some torrent files
* Fix the -l, --logfile option
* Fix #729 tracker icons not being saved in the correct location
* Add support for more tracker icons
* Fix being able to connect to a local daemon from another user account
=== Deluge 1.1.0 - "Time gas!" (10 January 2009) ===
==== Core ====
* Implement #79 ability to change outgoing port range
* Implement #296 ability to change peer TOS byte
* Add per-torrent move on completed settings
* Implement #414 use async save_resume_data method
* Filter Manager with torrent filtering in get_torrents_status , for sidebar and plugins.
* Implement #368 add torrents by infohash/magnet uri (trackerless torrents)
* Remove remaining gtk functions in common
* Tracker icons.
* Add ETA for torrents with stop at seed ratio set
* Fix #47 the state and config files are no longer invalidated when there is no diskspace
* Fix #619 return "" instead of "Infinity" if seconds == 0 in ftime
* Add -P, --pidfile option to deluged
==== GtkUI ====
* Add peer progress to the peers tab
* Add ability to manually add peers
* Sorting # column will place downloaders above seeds
* Remove dependency on libtorrent for add torrent dialog
* Allow adding multiple trackers at once in the edit tracker dialog
* Implement #28 Create Torrent Dialog
* Redesiged sidebar with filters for Active and Tracker (see Filter Manager)
* Implement #428 the ability to rename files and directories
* Implement #229 add date added column
* Implement #596 show speeds in title
* Fix #636 not setting the daemon's config directory when using --config= with the UI in classic mode.
* Fix #624 do not allow changing file priorities when using compact allocation
* Fix #602 re-did files/peers tab state saving/loading
* Fix gtk warnings
* Add protocol traffic statusbar item
* Rework the Remove Torrent Dialog to only have 2 options, remove data and remove from session.
* Add "Install Plugin" and "Rescan Plugins" buttons to the Plugins preferences
* Make active port test use internal graphic instead of launching browser
==== WebUI ====
* Lots of smaller tweaks.
* All details tabs have the same features as in gtk-ui 1.0.x
* Persistent sessions #486
* Plugin improvements for easy use of templates and images in eggs. #497
* Classic template takes over some style elements from white template.
* https (for users that know how to create certificates)
* Easier apache mod_proxy use.
* Redesigned sidebar
==== AjaxUI ====
* Hosted in a webui template.
==== ConsoleUI ====
* New ConsoleUI written by Idoa01
* Callable from command-line for scripts.
==== Plugins ====
* Stats plugin for graphs.
* Label plugin for grouping torrents and per torrent settings.
==== Misc ====
* Implement #478 display UI options in usage help
* Fix #547 add description to name field per HIG entry 2.1.1.1
* Fix #531 set default log level to ERROR and add 2 command-line options, "-L, --loglevel" and "-q, --quiet".

24
DEPENDS Normal file
View File

@ -0,0 +1,24 @@
=== Core ===
* python >= 2.5
* twisted >= 8.1
* twisted-web >= 8.1
* pyopenssl
* simplejson (if python < 2.6)
* setuptools
* gettext
* pyxdg
* geoip-database (optional)
* libtorrent >= 0.14.9
=== UIs ===
* chardet
=== Gtk ===
* python-notify (libnotify python wrapper)
* pygame
* pygtk >= 2.12
* librsvg
* xdg-utils
=== Web ===
* mako

13
LICENSE
View File

@ -1,3 +1,16 @@
Deluge is licensed under the GNU General Public License version 3 with the
addition of the following special exception:
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the OpenSSL
library.
You must obey the GNU General Public License in all respects for all of
the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete
this exception statement from your version. If you delete this exception
statement from all source files in the program, then also delete it here.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

47
README
View File

@ -1,15 +1,15 @@
==========================
Deluge BitTorrent Client
==========================
Authors:
Andrew Resch
Marcos Pinto
Martijn Voncken
Sadrul Habib Chowdhury
Homepage: http://deluge-torrent.org
Authors:
Andrew Resch
Damien Churchill
For past developers and contributers see: http://dev.deluge-torrent.org/wiki/About
==========================
License
@ -26,22 +26,27 @@ Contact/Support:
We have two options available for support:
Our Forum, at http://forum.deluge-torrent.org
Our Forum, at: http://forum.deluge-torrent.org
or
Our IRC Channel, at #deluge on Freenode
Our IRC Channel, at #deluge on Freenode: http://freenode.net
==========================
Installation Instructions:
==========================
For more detailed instructions see: http://dev.deluge-torrent.org/wiki/Installing/Source
See: DEPENDS for a full list of dependencies.
First, make sure you have the proper build dependencies installed. On a normal
Debian or Ubuntu system:
sudo apt-get install g++ make python-all-dev python-all python-dbus \
python-gtk2 python-notify librsvg2-common python-xdg python-support \
subversion libboost-dev libboost-python-dev libboost-iostreams-dev \
subversion libboost-dev libboost-python-dev \
libboost-thread-dev libboost-date-time-dev libboost-filesystem-dev \
libboost-serialization-dev libssl-dev zlib1g-dev python-setuptools
libssl-dev zlib1g-dev python-setuptools \
python-mako python-twisted-web python-chardet python-simplejson
The names of the packages may vary depending on your OS / distro.
@ -50,7 +55,6 @@ Once you have the needed libraries installed, build and install by running:
$ python setup.py build
$ sudo python setup.py install
==========================
FAQ
==========================
@ -58,36 +62,33 @@ FAQ
How to start the various user-interfaces
Gtk:
deluge --ui gtk
deluge-gtk
Console:
deluge --ui null
deluge-console
Web:
deluge --ui web
deluge-web
Go to http://localhost:8112/ default-password = "deluge"
I started "deluge" but i don't see the gtk-ui
The deluge command remembers the last interface it started. Be explicit and type one of the full "deluge -u <interface>" commands listed above.
Why is deluge still listed in my system tray even after I close it ?
You closed the gtk user-interface but you did not close the daemon. Choose "Quit & Shutdown Daemon" to close both Daemon and gtk-ui.
How do I start the daemon ?
How do I start the daemon?
deluged
How do I start the daemon with logging to console ?
How do I start the daemon with logging to console?
deluged -d
deluged -d -L <log level>
I can't connect to the daemon from another machine
* Configure the daemon to allow remote connections
* Add a user to the auth file located in the config folder: ~/.config/deluge/auth
* Restart the daemon.
Note: do not do this on a public ip , use the webui for unsecure networks.
I upgraded from 0.5 and plugin x is missing
1.0 is a rewrite, all old 0.5 plugins have to be rewritten.
For the full FAQ see: http://dev.deluge-torrent.org/wiki/Faq

23
create_potfiles_in.py Normal file
View File

@ -0,0 +1,23 @@
import os
# Paths to exclude
EXCLUSIONS = [
"deluge/scripts"
]
POTFILE_IN = "deluge/i18n/POTFILES.in"
print "Creating " + POTFILE_IN + " .."
to_translate = []
for (dirpath, dirnames, filenames) in os.walk("deluge"):
for filename in filenames:
if os.path.splitext(filename)[1] in (".py", ".glade") and dirpath not in EXCLUSIONS:
to_translate.append(os.path.join(dirpath, filename))
f = open(POTFILE_IN, "wb")
for line in to_translate:
f.write(line + "\n")
f.close()
print "Done"

5
debian/changelog vendored
View File

@ -1,5 +0,0 @@
deluge-torrent (0.9.08-1) unstable; urgency=low
* R8 release
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 26 Aug 2008 16:31:14 -0800

View File

@ -1,5 +0,0 @@
deluge-torrent (0.6.0-svn3235-1) lenny; urgency=low
* Daily Build
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800

View File

@ -1,5 +0,0 @@
deluge-torrent (0.6.0-svn3235-1) unstable; urgency=low
* Daily Build
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800

View File

@ -1,5 +0,0 @@
deluge-torrent (0.6.0-svn3235-1) gutsy; urgency=low
* Daily Build
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800

View File

@ -1,5 +0,0 @@
deluge-torrent (0.6.0-svn3235-1) hardy; urgency=low
* Daily Build
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 17 Jun 2008 16:31:14 -0800

1
debian/compat vendored
View File

@ -1 +0,0 @@
5

21
debian/control vendored
View File

@ -1,21 +0,0 @@
Source: deluge-torrent
Section: net
Priority: optional
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost-dev (>= 1.34.1), libboost-thread-dev (>= 1.34.1), libboost-date-time-dev (>= 1.34.1), libboost-filesystem-dev (>= 1.34.1), libboost-python-dev (>= 1.34.1), libboost-iostreams-dev (>= 1.34.1), zlib1g-dev, libssl-dev, dpatch, python-setuptools
Standards-Version: 3.7.2
Package: deluge-torrent
Architecture: any
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
Conflicts: deluge-torrent-common
Replaces: deluge-torrent-common
Description: A Bittorrent client written in Python/PyGTK
Deluge is a Bittorrent client, created using Python and GTK+.
.
Deluge is intended to bring a native, full-featured client to Linux GTK
desktop environments such as Gnome and XFCE.
.
It uses Rasterbar's version of libtorrent.
.
Homepage: http://www.deluge-torrent.org/

View File

@ -1,19 +0,0 @@
Source: deluge-torrent
Section: net
Priority: optional
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost-dev (>= 1.33.1), libboost-thread-dev (>= 1.33.1), libboost-date-time-dev (>= 1.33.1), libboost-filesystem-dev (>= 1.33.1), libboost-serialization-dev (>= 1.33.1), libboost-program-options-dev (>= 1.33.1), libboost-regex-dev (>= 1.33.1), libboost-python-dev (>= 1.33.1), zlib1g-dev, libssl-dev, dpatch, python-setuptools
Standards-Version: 3.7.2
Package: deluge-torrent
Architecture: any
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
Description: A Bittorrent client written in Python/PyGTK
Deluge is a Bittorrent client, created using Python and GTK+.
.
Deluge is intended to bring a native, full-featured client to Linux GTK
desktop environments such as Gnome and XFCE.
.
It uses Rasterbar's version of libtorrent.
.
Homepage: http://www.deluge-torrent.org/

View File

@ -1,19 +0,0 @@
Source: deluge-torrent
Section: net
Priority: optional
Maintainer: Andrew Resch (andar) <andrewresch@gmail.com>
Build-Depends: debhelper (>= 5.0.37.2), python-all-dev (>= 2.3.5-11), python-all, python-support (>= 0.5.3), libboost1.36-dev (>= 1.36), libboost-thread1.36-dev (>= 1.36), libboost-date-time1.36-dev (>= 1.36), libboost-filesystem1.36-dev (>= 1.36), libboost-serialization1.36-dev (>= 1.36), libboost-program-options1.36-dev (>= 1.36), libboost-regex1.36-dev (>= 1.36), libboost-python1.36-dev (>= 1.36), zlib1g-dev, libssl-dev, dpatch, python-setuptools
Standards-Version: 3.7.2
Package: deluge-torrent
Architecture: any
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
Description: A Bittorrent client written in Python/PyGTK
Deluge is a Bittorrent client, created using Python and GTK+.
.
Deluge is intended to bring a native, full-featured client to Linux GTK
desktop environments such as Gnome and XFCE.
.
It uses Rasterbar's version of libtorrent.
.
Homepage: http://www.deluge-torrent.org/

99
debian/copyright vendored
View File

@ -1,99 +0,0 @@
This package was debianized by Marcos Pinto (markybob) <markybob@gmail.com> on
Fri, 31 Jul 2008 22:03:13 +0100.
It was downloaded from http://www.deluge-torrent.org/
Upstream Authors & Copyright:
Andrew Resch
Marcos Pinto
Sadrul Habib Chowdhury
Martijn Voncken
License:
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the OpenSSL
library.
You must obey the GNU General Public License in all respects for all of
the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete
this exception statement from your version. If you delete this exception
statement from all source files in the program, then also delete it here.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL'.
libtorrent is (C) 2003-2008 Arvid Norberg arvid@cs.umu.se and its
python bindings were initially written by Daniel Wallin in 2006.
It is distributed unders terms of the BSD License below:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
"libtorrent/include/libtorrent/asio*" are (C) 2003-2008 Christopher
M. Kohlhoff <chris@kohlhoff.com> and distributed under terms of the Boost
Software License, Version 1.0 :
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"deluge/i18n/*" are (C) 2006 Rosetta Contributors and Canonical Ltd 2006 and distributed
under the same license as the deluge software.
The Debian packaging is (C) 2006-2008, Marcos Pinto (markybob)
<markybob@gmail.com> and is licensed under GPL3, see above.

2
debian/manpages vendored
View File

@ -1,2 +0,0 @@
deluge/docs/man/deluge.1
deluge/docs/man/deluged.1

3
debian/menu vendored
View File

@ -1,3 +0,0 @@
?package(deluge-torrent): needs="X11" section="Applications/Network/File Transfer" \
title="Deluge BitTorrent Client" longtitle="Bittorrent client written in Python/PyGTK" \
command="/usr/bin/deluge" icon="/usr/share/pixmaps/deluge.png"

View File

1
debian/pyversions vendored
View File

@ -1 +0,0 @@
2.5

View File

@ -1 +0,0 @@
2.5

View File

@ -1 +0,0 @@
2.5

75
debian/rules vendored
View File

@ -1,75 +0,0 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# Dpatch targets
include /usr/share/dpatch/dpatch.make
# Available python (using debian/pyversions) and destdir
PYVERS = 2.5
DESTDIR = $(CURDIR)/debian/deluge-torrent
# We need to known the target arch to enable/disable amd64 hack
ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH_CPU)
ARCH64 = ia64 amd64 alpha kfreebsd-amd64 ppc64
CFLAGS = -Wall -g
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
# python-libtorrent need to define AMD64 to work fine on a 64 bits system
ifneq (,$(findstring $(ARCH),$(ARCH64)))
CFLAGS += -DAMD64
endif
build: patch-stamp $(PYVERS:%=build-stamp%)
build-stamp%: patch-stamp
dh_testdir
CFLAGS="$(CFLAGS)" python$* setup.py build
touch $@
clean: unpatch
dh_testdir
dh_testroot
rm -rf build/
find . -name \*.pyc | xargs rm -f
rm -rf build-stamp*
dh_clean
install: build install-prereq $(PYVERS:%=install-%) install-finish
install-prereq:
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
install-%:
python$* setup.py install --root=$(DESTDIR) --prefix=/usr --no-compile
install-finish:
# Desktop menu
rm -rf $(DESTDIR)/usr/share/applications
install -D -m644 $(CURDIR)/deluge/data/share/applications/deluge.desktop $(DESTDIR)/usr/share/applications/deluge.desktop
binary-indep: build install
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installmenu
dh_strip
dh_compress
dh_fixperms
dh_pysupport
dh_desktop
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

View File

@ -1,595 +0,0 @@
"""Simple XML-RPC Server.
This module can be used to create simple XML-RPC servers
by creating a server and either installing functions, a
class instance, or by extending the SimpleXMLRPCServer
class.
It can also be used to handle XML-RPC requests in a CGI
environment using CGIXMLRPCRequestHandler.
A list of possible usage patterns follows:
1. Install functions:
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.serve_forever()
2. Install an instance:
class MyFuncs:
def __init__(self):
# make all of the string functions available through
# string.func_name
import string
self.string = string
def _listMethods(self):
# implement this method so that system.listMethods
# knows to advertise the strings methods
return list_public_methods(self) + \
['string.' + method for method in list_public_methods(self.string)]
def pow(self, x, y): return pow(x, y)
def add(self, x, y) : return x + y
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_introspection_functions()
server.register_instance(MyFuncs())
server.serve_forever()
3. Install an instance with custom dispatch method:
class Math:
def _listMethods(self):
# this method must be present for system.listMethods
# to work
return ['add', 'pow']
def _methodHelp(self, method):
# this method must be present for system.methodHelp
# to work
if method == 'add':
return "add(2,3) => 5"
elif method == 'pow':
return "pow(x, y[, z]) => number"
else:
# By convention, return empty
# string if no help is available
return ""
def _dispatch(self, method, params):
if method == 'pow':
return pow(*params)
elif method == 'add':
return params[0] + params[1]
else:
raise 'bad method'
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_introspection_functions()
server.register_instance(Math())
server.serve_forever()
4. Subclass SimpleXMLRPCServer:
class MathServer(SimpleXMLRPCServer):
def _dispatch(self, method, params):
try:
# We are forcing the 'export_' prefix on methods that are
# callable through XML-RPC to prevent potential security
# problems
func = getattr(self, 'export_' + method)
except AttributeError:
raise Exception('method "%s" is not supported' % method)
else:
return func(*params)
def export_add(self, x, y):
return x + y
server = MathServer(("localhost", 8000))
server.serve_forever()
5. CGI script:
server = CGIXMLRPCRequestHandler()
server.register_function(pow)
server.handle_request()
"""
# Written by Brian Quinlan (brian@sweetapp.com).
# Based on code written by Fredrik Lundh.
import xmlrpclib
from xmlrpclib import Fault
import SocketServer
import BaseHTTPServer
import sys
import os
try:
import fcntl
except ImportError:
fcntl = None
def resolve_dotted_attribute(obj, attr, allow_dotted_names=True):
"""resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
Resolves a dotted attribute name to an object. Raises
an AttributeError if any attribute in the chain starts with a '_'.
If the optional allow_dotted_names argument is false, dots are not
supported and this function operates similar to getattr(obj, attr).
"""
if allow_dotted_names:
attrs = attr.split('.')
else:
attrs = [attr]
for i in attrs:
if i.startswith('_'):
raise AttributeError(
'attempt to access private attribute "%s"' % i
)
else:
obj = getattr(obj,i)
return obj
def list_public_methods(obj):
"""Returns a list of attribute strings, found in the specified
object, which represent callable attributes"""
return [member for member in dir(obj)
if not member.startswith('_') and
callable(getattr(obj, member))]
def remove_duplicates(lst):
"""remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
Returns a copy of a list without duplicates. Every list
item must be hashable and the order of the items in the
resulting list is not defined.
"""
u = {}
for x in lst:
u[x] = 1
return u.keys()
class SimpleXMLRPCDispatcher:
"""Mix-in class that dispatches XML-RPC requests.
This class is used to register XML-RPC method handlers
and then to dispatch them. There should never be any
reason to instantiate this class directly.
"""
def __init__(self, allow_none, encoding):
self.funcs = {}
self.instance = None
self.allow_none = allow_none
self.encoding = encoding
def register_instance(self, instance, allow_dotted_names=False):
"""Registers an instance to respond to XML-RPC requests.
Only one instance can be installed at a time.
If the registered instance has a _dispatch method then that
method will be called with the name of the XML-RPC method and
its parameters as a tuple
e.g. instance._dispatch('add',(2,3))
If the registered instance does not have a _dispatch method
then the instance will be searched to find a matching method
and, if found, will be called. Methods beginning with an '_'
are considered private and will not be called by
SimpleXMLRPCServer.
If a registered function matches a XML-RPC request, then it
will be called instead of the registered instance.
If the optional allow_dotted_names argument is true and the
instance does not have a _dispatch method, method names
containing dots are supported and resolved, as long as none of
the name segments start with an '_'.
*** SECURITY WARNING: ***
Enabling the allow_dotted_names options allows intruders
to access your module's global variables and may allow
intruders to execute arbitrary code on your machine. Only
use this option on a secure, closed network.
"""
self.instance = instance
self.allow_dotted_names = allow_dotted_names
def register_function(self, function, name = None):
"""Registers a function to respond to XML-RPC requests.
The optional name argument can be used to set a Unicode name
for the function.
"""
if name is None:
name = function.__name__
self.funcs[name] = function
def register_introspection_functions(self):
"""Registers the XML-RPC introspection methods in the system
namespace.
see http://xmlrpc.usefulinc.com/doc/reserved.html
"""
self.funcs.update({'system.listMethods' : self.system_listMethods,
'system.methodSignature' : self.system_methodSignature,
'system.methodHelp' : self.system_methodHelp})
def register_multicall_functions(self):
"""Registers the XML-RPC multicall method in the system
namespace.
see http://www.xmlrpc.com/discuss/msgReader$1208"""
self.funcs.update({'system.multicall' : self.system_multicall})
def _marshaled_dispatch(self, data, dispatch_method = None):
"""Dispatches an XML-RPC method from marshalled (XML) data.
XML-RPC methods are dispatched from the marshalled (XML) data
using the _dispatch method and the result is returned as
marshalled data. For backwards compatibility, a dispatch
function can be provided as an argument (see comment in
SimpleXMLRPCRequestHandler.do_POST) but overriding the
existing method through subclassing is the prefered means
of changing method dispatch behavior.
"""
try:
params, method = xmlrpclib.loads(data)
# generate response
if dispatch_method is not None:
response = dispatch_method(method, params)
else:
response = self._dispatch(method, params)
# wrap response in a singleton tuple
response = (response,)
response = xmlrpclib.dumps(response, methodresponse=1,
allow_none=self.allow_none, encoding=self.encoding)
except Fault, fault:
response = xmlrpclib.dumps(fault, allow_none=self.allow_none,
encoding=self.encoding)
except:
# report exception back to server
response = xmlrpclib.dumps(
xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)),
encoding=self.encoding, allow_none=self.allow_none,
)
return response
def system_listMethods(self):
"""system.listMethods() => ['add', 'subtract', 'multiple']
Returns a list of the methods supported by the server."""
methods = self.funcs.keys()
if self.instance is not None:
# Instance can implement _listMethod to return a list of
# methods
if hasattr(self.instance, '_listMethods'):
methods = remove_duplicates(
methods + self.instance._listMethods()
)
# if the instance has a _dispatch method then we
# don't have enough information to provide a list
# of methods
elif not hasattr(self.instance, '_dispatch'):
methods = remove_duplicates(
methods + list_public_methods(self.instance)
)
methods.sort()
return methods
def system_methodSignature(self, method_name):
"""system.methodSignature('add') => [double, int, int]
Returns a list describing the signature of the method. In the
above example, the add method takes two integers as arguments
and returns a double result.
This server does NOT support system.methodSignature."""
# See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html
return 'signatures not supported'
def system_methodHelp(self, method_name):
"""system.methodHelp('add') => "Adds two integers together"
Returns a string containing documentation for the specified method."""
method = None
if self.funcs.has_key(method_name):
method = self.funcs[method_name]
elif self.instance is not None:
# Instance can implement _methodHelp to return help for a method
if hasattr(self.instance, '_methodHelp'):
return self.instance._methodHelp(method_name)
# if the instance has a _dispatch method then we
# don't have enough information to provide help
elif not hasattr(self.instance, '_dispatch'):
try:
method = resolve_dotted_attribute(
self.instance,
method_name,
self.allow_dotted_names
)
except AttributeError:
pass
# Note that we aren't checking that the method actually
# be a callable object of some kind
if method is None:
return ""
else:
import pydoc
return pydoc.getdoc(method)
def system_multicall(self, call_list):
"""system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \
[[4], ...]
Allows the caller to package multiple XML-RPC calls into a single
request.
See http://www.xmlrpc.com/discuss/msgReader$1208
"""
results = []
for call in call_list:
method_name = call['methodName']
params = call['params']
try:
# XXX A marshalling error in any response will fail the entire
# multicall. If someone cares they should fix this.
results.append([self._dispatch(method_name, params)])
except Fault, fault:
results.append(
{'faultCode' : fault.faultCode,
'faultString' : fault.faultString}
)
except:
results.append(
{'faultCode' : 1,
'faultString' : "%s:%s" % (sys.exc_type, sys.exc_value)}
)
return results
def _dispatch(self, method, params):
"""Dispatches the XML-RPC method.
XML-RPC calls are forwarded to a registered function that
matches the called XML-RPC method name. If no such function
exists then the call is forwarded to the registered instance,
if available.
If the registered instance has a _dispatch method then that
method will be called with the name of the XML-RPC method and
its parameters as a tuple
e.g. instance._dispatch('add',(2,3))
If the registered instance does not have a _dispatch method
then the instance will be searched to find a matching method
and, if found, will be called.
Methods beginning with an '_' are considered private and will
not be called.
"""
func = None
try:
# check to see if a matching function has been registered
func = self.funcs[method]
except KeyError:
if self.instance is not None:
# check for a _dispatch method
if hasattr(self.instance, '_dispatch'):
return self.instance._dispatch(method, params)
else:
# call instance method directly
try:
func = resolve_dotted_attribute(
self.instance,
method,
self.allow_dotted_names
)
except AttributeError:
pass
if func is not None:
return func(*params)
else:
raise Exception('method "%s" is not supported' % method)
class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Simple XML-RPC request handler class.
Handles all HTTP POST requests and attempts to decode them as
XML-RPC requests.
"""
# Class attribute listing the accessible path components;
# paths not on this list will result in a 404 error.
rpc_paths = ('/', '/RPC2')
def is_rpc_path_valid(self):
if self.rpc_paths:
return self.path in self.rpc_paths
else:
# If .rpc_paths is empty, just assume all paths are legal
return True
def do_POST(self):
"""Handles the HTTP POST request.
Attempts to interpret all HTTP POST requests as XML-RPC calls,
which are forwarded to the server's _dispatch method for handling.
"""
# Check that the path is legal
if not self.is_rpc_path_valid():
self.report_404()
return
try:
# Get arguments by reading body of request.
# We read this in chunks to avoid straining
# socket.read(); around the 10 or 15Mb mark, some platforms
# begin to have problems (bug #792570).
max_chunk_size = 10*1024*1024
size_remaining = int(self.headers["content-length"])
L = []
while size_remaining:
chunk_size = min(size_remaining, max_chunk_size)
L.append(self.rfile.read(chunk_size))
size_remaining -= len(L[-1])
data = ''.join(L)
# In previous versions of SimpleXMLRPCServer, _dispatch
# could be overridden in this class, instead of in
# SimpleXMLRPCDispatcher. To maintain backwards compatibility,
# check to see if a subclass implements _dispatch and dispatch
# using that method if present.
response = self.server._marshaled_dispatch(
data, getattr(self, '_dispatch', None)
)
except: # This should only happen if the module is buggy
# internal error, report as HTTP server error
self.send_response(500)
self.end_headers()
else:
# got a valid XML RPC response
self.send_response(200)
self.send_header("Content-type", "text/xml")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
# shut down the connection
self.wfile.flush()
self.connection.shutdown(1)
def report_404 (self):
# Report a 404 error
self.send_response(404)
response = 'No such page'
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
# shut down the connection
self.wfile.flush()
self.connection.shutdown(1)
def log_request(self, code='-', size='-'):
"""Selectively log an accepted request."""
if self.server.logRequests:
BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
class SimpleXMLRPCServer(SocketServer.TCPServer,
SimpleXMLRPCDispatcher):
"""Simple XML-RPC server.
Simple XML-RPC server that allows functions and a single instance
to be installed to handle requests. The default implementation
attempts to dispatch XML-RPC calls to the functions or instance
installed in the server. Override the _dispatch method inhereted
from SimpleXMLRPCDispatcher to change this behavior.
"""
allow_reuse_address = True
def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
logRequests=True, allow_none=False, encoding=None):
self.logRequests = logRequests
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
SocketServer.TCPServer.__init__(self, addr, requestHandler)
# [Bug #1222790] If possible, set close-on-exec flag; if a
# method spawns a subprocess, the subprocess shouldn't have
# the listening socket open.
if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
"""Simple handler for XML-RPC data passed through CGI."""
def __init__(self, allow_none=False, encoding=None):
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
def handle_xmlrpc(self, request_text):
"""Handle a single XML-RPC request"""
response = self._marshaled_dispatch(request_text)
print('Content-Type: text/xml')
print('Content-Length: %d' % len(response))
print(
sys.stdout.write(response))
def handle_get(self):
"""Handle a single HTTP GET request.
Default implementation indicates an error because
XML-RPC uses the POST method.
"""
code = 400
message, explain = \
BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \
{
'code' : code,
'message' : message,
'explain' : explain
}
print('Status: %d %s' % (code, message))
print('Content-Type: text/html')
print('Content-Length: %d' % len(response))
print(
sys.stdout.write(response))
def handle_request(self, request_text = None):
"""Handle a single XML-RPC request passed through a CGI post method.
If no XML data is given then it is read from stdin. The resulting
XML-RPC response is printed to stdout along with the correct HTTP
headers.
"""
if request_text is None and \
os.environ.get('REQUEST_METHOD', None) == 'GET':
self.handle_get()
else:
# POST data is normally available through stdin
if request_text is None:
request_text = sys.stdin.read()
self.handle_xmlrpc(request_text)
if __name__ == '__main__':
print('Running XML-RPC server on port 8000')
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.serve_forever()

20
deluge/__rpcapi.py Normal file
View File

@ -0,0 +1,20 @@
from new import classobj
from deluge.core.core import Core
from deluge.core.daemon import Daemon
class RpcApi:
pass
def scan_for_methods(obj):
methods = {
'__doc__': 'Methods available in %s' % obj.__name__.lower()
}
for d in dir(obj):
if not hasattr(getattr(obj,d), '_rpcserver_export'):
continue
methods[d] = getattr(obj, d)
cobj = classobj(obj.__name__.lower(), (object,), methods)
setattr(RpcApi, obj.__name__.lower(), cobj)
scan_for_methods(Core)
scan_for_methods(Daemon)

60
deluge/_libtorrent.py Normal file
View File

@ -0,0 +1,60 @@
#
# _libtorrent.py
#
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""
This module is used to handle the importing of libtorrent.
We use this module to control what versions of libtorrent this version of Deluge
supports.
** Usage **
>>> from deluge._libtorrent import lt
"""
REQUIRED_VERSION = "0.14.9.0"
def check_version(LT):
from deluge.common import VersionSplit
if VersionSplit(lt.version) < VersionSplit(REQUIRED_VERSION):
raise ImportError("This version of Deluge requires libtorrent >=%s!" % REQUIRED_VERSION)
try:
import deluge.libtorrent as lt
check_version(lt)
except ImportError:
import libtorrent as lt
check_version(lt)

View File

@ -1,7 +1,7 @@
# The contents of this file are subject to the BitTorrent Open Source License
# Version 1.1 (the License). You may not copy or use this file, in either
# source code or executable form, except in compliance with the License. You
# may obtain a copy of the License at http://www.bittorrent.com/license/.
# The contents of this file are subject to the Python Software Foundation
# License Version 2.3 (the License). You may not copy or use this file, in
# either source code or executable form, except in compliance with the License.
# You may obtain a copy of the License at http://www.python.org/license.
#
# Software distributed under the License is distributed on an AS IS basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
@ -10,6 +10,8 @@
# Written by Petru Paler
# Minor modifications made by Andrew Resch to replace the BTFailure errors with Exceptions
def decode_int(x, f):
f += 1
newf = x.index('e', f)
@ -63,8 +65,7 @@ def bdecode(x):
r, l = decode_func[x[0]](x, 0)
except (IndexError, KeyError, ValueError):
raise Exception("not a valid bencoded string")
if l != len(x):
raise Exception("invalid bencoded value (data after valid prefix)")
return r
from types import StringType, IntType, LongType, DictType, ListType, TupleType

View File

@ -19,7 +19,18 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
@ -29,10 +40,33 @@ import os
import time
import subprocess
import platform
import sys
try:
import json
except ImportError:
import simplejson as json
# Do a little hack here just in case the user has json-py installed since it
# has a different api
if not hasattr(json, "dumps"):
json.dumps = json.write
json.loads = json.read
def dump(obj, fp, **kw):
fp.write(json.dumps(obj))
def load(fp, **kw):
return json.loads(fp.read())
json.dump = dump
json.load = load
import pkg_resources
import xdg, xdg.BaseDirectory
from deluge.error import *
LT_TORRENT_STATE = {
"Queued": 0,
"Checking": 1,
@ -41,6 +75,7 @@ LT_TORRENT_STATE = {
"Finished": 4,
"Seeding": 5,
"Allocating": 6,
"Checking Resume Data": 7,
0: "Queued",
1: "Checking",
2: "Downloading Metadata",
@ -48,8 +83,10 @@ LT_TORRENT_STATE = {
4: "Finished",
5: "Seeding",
6: "Allocating",
7: "Checking Resume Data"
}
TORRENT_STATE = [
"Allocating",
"Checking",
@ -79,29 +116,12 @@ def get_version():
:rtype: string
"""
return pkg_resources.require("Deluge")[0].version.split("r")[0]
def get_revision():
"""
The svn revision of the build if available
:returns: the svn revision, or ""
:rtype: string
"""
revision = ""
try:
f = open(pkg_resources.resource_filename("deluge", os.path.join("data", "revision")))
revision = f.read()
f.close()
except IOError, e:
pass
return revision
return pkg_resources.require("Deluge")[0].version
def get_default_config_dir(filename=None):
"""
:param filename: if None, only the config path is returned, if provided, a path including the filename will be returned
:type filename: string
:returns: a file path to the config directory and optional filename
:rtype: string
@ -163,6 +183,7 @@ def get_pixmap(fname):
Provides easy access to files in the deluge/data/pixmaps folder within the Deluge egg
:param fname: the filename to look for
:type fname: string
:returns: a path to a pixmap file included with Deluge
:rtype: string
@ -175,6 +196,7 @@ def open_file(path):
Opens a file or folder using the system configured program
:param path: the path to the file or folder to open
:type path: string
"""
if windows_check():
@ -187,18 +209,11 @@ def open_url_in_browser(url):
Opens a url in the desktop's default browser
:param url: the url to open
:type url: string
"""
def start_browser():
import threading
import webbrowser
class BrowserThread(threading.Thread):
def __init__(self, url):
threading.Thread.__init__(self)
self.url = url
def run(self):
webbrowser.open(self.url)
BrowserThread(url).start()
return False
import webbrowser
webbrowser.open(url)
## Formatting text functions
@ -206,7 +221,8 @@ def fsize(fsize_b):
"""
Formats the bytes value into a string with KiB, MiB or GiB units
:param fsize_b: int, the filesize in bytes
:param fsize_b: the filesize in bytes
:type fsize_b: int
:returns: formatted string in KiB, MiB or GiB units
:rtype: string
@ -229,7 +245,8 @@ def fpcnt(dec):
"""
Formats a string to display a percentage with two decimal places
:param dec: float, the ratio in the range [0.0, 1.0]
:param dec: the ratio in the range [0.0, 1.0]
:type dec: float
:returns: a formatted string representing a percentage
:rtype: string
@ -245,7 +262,8 @@ def fspeed(bps):
"""
Formats a string to display a transfer speed utilizing :func:`fsize`
:param bps: int, bytes per second
:param bps: bytes per second
:type bps: int
:returns: a formatted string representing transfer speed
:rtype: string
@ -261,8 +279,10 @@ def fpeer(num_peers, total_peers):
"""
Formats a string to show 'num_peers' ('total_peers')
:param num_peers: int, the number of connected peers
:param total_peers: int, the total number of peers
:param num_peers: the number of connected peers
:type num_peers: int
:param total_peers: the total number of peers
:type total_peers: int
:returns: a formatted string: num_peers (total_peers), if total_peers < 0, then it will not be shown
:rtype: string
@ -283,7 +303,8 @@ def ftime(seconds):
"""
Formats a string to show time in a human readable form
:param seconds: int, the number of seconds
:param seconds: the number of seconds
:type seconds: int
:returns: a formatted time string, will return '' if seconds == 0
:rtype: string
@ -321,7 +342,8 @@ def fdate(seconds):
"""
Formats a date string in the locale's date representation based on the systems timezone
:param seconds: float, time in seconds since the Epoch
:param seconds: time in seconds since the Epoch
:type seconds: float
:returns: a string in the locale's date representation or "" if seconds < 0
:rtype: string
@ -334,7 +356,8 @@ def is_url(url):
"""
A simple regex test to check if the URL is valid
:param url: string, the url to test
:param url: the url to test
:type url: string
:returns: True or False
:rtype: bool
@ -351,7 +374,8 @@ def is_magnet(uri):
"""
A check to determine if a uri is a valid bittorrent magnet uri
:param uri: string, the uri to check
:param uri: the uri to check
:type uri: string
:returns: True or False
:rtype: bool
@ -369,7 +393,8 @@ def fetch_url(url):
"""
Downloads a torrent file from a given URL and checks the file's validity
:param url: string, the url of the .torrent file to fetch
:param url: the url of the .torrent file to fetch
:type url: string
:returns: the filepath to the downloaded file
:rtype: string
@ -392,9 +417,12 @@ def create_magnet_uri(infohash, name=None, trackers=[]):
"""
Creates a magnet uri
:param infohash: string, the info-hash of the torrent
:param name: string, the name of the torrent (optional)
:param trackers: list of strings, the trackers to announce to (optional)
:param infohash: the info-hash of the torrent
:type infohash: string
:param name: the name of the torrent (optional)
:type name: string
:param trackers: the trackers to announce to (optional)
:type trackers: list of strings
:returns: a magnet uri string
:rtype: string
@ -414,7 +442,8 @@ def get_path_size(path):
"""
Gets the size in bytes of 'path'
:param path: string, the path to check for size
:param path: the path to check for size
:type path: string
:returns: the size in bytes of the path or -1 if the path does not exist
:rtype: int
@ -436,16 +465,21 @@ def free_space(path):
"""
Gets the free space available at 'path'
:param path: string, the path to check
:param path: the path to check
:type path: string
:returns: the free space at path in bytes
:rtype: int
:raises InvalidPathError: if the path is not valid
"""
if not os.path.exists(path):
raise InvalidPathError("%s is not a valid path" % path)
if windows_check():
import win32api
drive = path.split(":")[0]
free = win32api.GetDiskFreeSpaceEx(drive)[0]
return free
import win32file
sectors, bytes, free, total = map(long, win32file.GetDiskFreeSpace(path))
return (free * sectors * bytes)
else:
disk_data = os.statvfs(path)
block_size = disk_data.f_bsize
@ -455,7 +489,8 @@ def is_ip(ip):
"""
A simple test to see if 'ip' is valid
:param ip: string, the ip to check
:param ip: the ip to check
:type ip: string
:returns: True or False
:rtype: bool
@ -479,3 +514,47 @@ def is_ip(ip):
return True
except socket.error:
return False
class VersionSplit(object):
"""
Used for comparing version numbers.
:param ver: the version
:type ver: string
"""
def __init__(self, ver):
ver = ver.lower()
vs = ver.split("_") if "_" in ver else ver.split("-")
self.version = [int(x) for x in vs[0].split(".")]
self.suffix = None
if len(vs) > 1:
for s in ("rc", "alpha", "beta", "dev"):
if s in vs[1][:len(s)]:
self.suffix = vs[1]
def __cmp__(self, ver):
"""
The comparison method.
:param ver: the version to compare with
:type ver: VersionSplit
"""
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

View File

@ -19,11 +19,21 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import gobject
from twisted.internet.task import LoopingCall
from deluge.log import LOG as log
COMPONENT_STATE = [
@ -32,24 +42,29 @@ COMPONENT_STATE = [
"Paused"
]
class Component:
def __init__(self, name, interval=1000, depend=None):
class Component(object):
def __init__(self, name, interval=1, depend=None):
# Register with the ComponentRegistry
register(name, self, depend)
self._interval = interval
self._timer = None
self._state = COMPONENT_STATE.index("Stopped")
self._name = name
def get_state(self):
return self._state
def get_component_name(self):
return self._name
def start(self):
pass
def _start(self):
self._state = COMPONENT_STATE.index("Started")
if self._update():
self._timer = gobject.timeout_add(self._interval, self._update)
if hasattr(self, "update"):
self._timer = LoopingCall(self.update)
self._timer.start(self._interval)
def stop(self):
pass
@ -57,14 +72,14 @@ class Component:
def _stop(self):
self._state = COMPONENT_STATE.index("Stopped")
try:
gobject.source_remove(self._timer)
self._timer.stop()
except:
pass
def _pause(self):
self._state = COMPONENT_STATE.index("Paused")
try:
gobject.source_remove(self._timer)
self._timer.stop()
except:
pass
@ -74,16 +89,6 @@ class Component:
def shutdown(self):
pass
def _update(self):
try:
self.update()
except AttributeError:
# This will stop the timer since the component doesn't have an
# update method.
return False
return True
class ComponentRegistry:
def __init__(self):
self.components = {}
@ -96,6 +101,13 @@ class ComponentRegistry:
if depend != None:
self.depend[name] = depend
def deregister(self, name):
"""Deregisters a component"""
if name in self.components:
log.debug("Deregistering Component: %s", name)
self.stop_component(name)
del self.components[name]
def get(self, name):
"""Returns a reference to the component 'name'"""
return self.components[name]
@ -111,6 +123,7 @@ class ComponentRegistry:
if self.depend.has_key(name):
for depend in self.depend[name]:
self.start_component(depend)
# Only start if the component is stopped.
if self.components[name].get_state() == \
COMPONENT_STATE.index("Stopped"):
@ -120,8 +133,14 @@ class ComponentRegistry:
def stop(self):
"""Stops all components"""
for component in self.components.keys():
self.stop_component(component)
# We create a separate list of the keys and do an additional check to
# make sure the key still exists in the components dict.
# This is because components could be deregistered during a stop and
# the dictionary would get modified while iterating through it.
components = self.components.keys()
for component in components:
if component in self.components:
self.stop_component(component)
def stop_component(self, component):
if self.components[component].get_state() != \
@ -171,7 +190,8 @@ class ComponentRegistry:
try:
self.components[component].shutdown()
except Exception, e:
log.debug("Unable to call shutdown(): %s", e)
log.debug("Unable to call shutdown()")
log.exception(e)
_ComponentRegistry = ComponentRegistry()
@ -180,6 +200,10 @@ def register(name, obj, depend=None):
"""Registers a component with the registry"""
_ComponentRegistry.register(name, obj, depend)
def deregister(name):
"""Deregisters a component"""
_ComponentRegistry.deregister(name)
def start(component=None):
"""Starts all components"""
if component == None:

View File

@ -19,21 +19,63 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""
Deluge Config Module
This module is used for loading and saving of configuration files.. or anything
really.
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
changed the serializer for the content to something different.
The config file version is changed by the 'owner' of the config file. This is
to signify that there is a change in the naming of some config keys or something
similar along those lines.
The content is simply the dict to be saved and will be serialized before being
written.
Converting
Since the format of the config could change, there needs to be a way to have
the Config object convert to newer formats. To do this, you will need to
register conversion functions for various versions of the config file. Note that
this can only be done for the 'config file version' and not for the 'format'
version as this will be done internally.
"""
import cPickle as pickle
import shutil
import os
import gobject
import deluge.common
from deluge.log import LOG as log
json = deluge.common.json
def prop(func):
"""Function decorator for defining property attributes
@ -48,6 +90,37 @@ def prop(func):
"""
return property(doc=func.__doc__, **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
start = s.find("{")
offset = start
if start < 0:
return []
for index, c in enumerate(s[offset:]):
if c == "{":
opens += 1
elif c == "}":
opens -= 1
if opens == 0:
objects.append((start, index+offset+1))
start = index + offset + 1
return objects
class Config(object):
"""
This class is used to access/create/modify config files
@ -59,15 +132,21 @@ class Config(object):
"""
def __init__(self, filename, defaults=None, config_dir=None):
self.__config = {}
self.__previous_config = {}
self.__set_functions = {}
self.__change_callback = None
# This will get set with a gobject.timeout_add whenever a config option
self.__change_callbacks = []
# These hold the version numbers and they will be set when loaded
self.__version = {
"format": 1,
"file": 1
}
# This will get set with a reactor.callLater whenever a config option
# is set.
self.__save_timer = None
self._save_timer = None
if defaults:
self.__config = defaults
self.__config = dict(defaults)
# Load the config from file in the config_dir
if config_dir:
@ -77,6 +156,9 @@ class Config(object):
self.load()
def __contains__(self, item):
return item in self.__config
def __setitem__(self, key, value):
"""
See
@ -88,12 +170,14 @@ class Config(object):
def set_item(self, key, value):
"""
Sets item 'key' to 'value' in the config dictionary, but does not allow
changing the item's type unless it is None
changing the item's type unless it is None. If the types do not match,
it will attempt to convert it to the set type before raising a ValueError.
:param key: string, item to change to change
:param value: the value to change item to, must be same type as what is currently in the config
:raises ValueError: raised when the type of value is not the same as what is currently in the config
:raises ValueError: raised when the type of value is not the same as\
what is currently in the config and it could not convert the value
**Usage**
@ -123,22 +207,25 @@ class Config(object):
log.debug("Setting '%s' to %s of %s", key, value, type(value))
# Make a copy of the current config prior to changing it
self.__previous_config.update(self.__config)
self.__config[key] = value
# Run the set_function for this key if any
from twisted.internet import reactor
try:
gobject.idle_add(self.__set_functions[key], key, value)
for func in self.__set_functions[key]:
reactor.callLater(0, func, key, value)
except KeyError:
pass
try:
gobject.idle_add(self.__change_callback, key, value)
def do_change_callbacks(key, value):
for func in self.__change_callbacks:
func(key, value)
reactor.callLater(0, do_change_callbacks, key, value)
except:
pass
# We set the save_timer for 5 seconds if not already set
if not self.__save_timer:
self.__save_timer = gobject.timeout_add(5000, self.save)
if not self._save_timer or not self._save_timer.active():
self._save_timer = reactor.callLater(5, self.save)
def __getitem__(self, key):
"""
@ -180,7 +267,7 @@ class Config(object):
>>> config.register_change_callback(cb)
"""
self.__change_callback = callback
self.__change_callbacks.append(callback)
def register_set_function(self, key, function, apply_now=True):
"""
@ -201,10 +288,14 @@ class Config(object):
"""
log.debug("Registering function for %s key..", key)
self.__set_functions[key] = function
if key not in self.__set_functions:
self.__set_functions[key] = []
self.__set_functions[key].append(function)
# Run the function now if apply_now is set
if apply_now:
self.__set_functions[key](key, self.__config[key])
function(key, self.__config[key])
return
def apply_all(self):
@ -224,7 +315,20 @@ class Config(object):
"""
log.debug("Calling all set functions..")
for key, value in self.__set_functions.iteritems():
value(key, self.__config[key])
for func in value:
func(key, self.__config[key])
def apply_set_functions(self, key):
"""
Calls set functions for `:param:key`.
:param key: str, the config key
"""
log.debug("Calling set functions for key %s..", key)
if key in self.__set_functions:
for func in self.__set_functions[key]:
func(key, self.__config[key])
def load(self, filename=None):
"""
@ -236,18 +340,49 @@ class Config(object):
"""
if not filename:
filename = self.__config_file
try:
self.__config.update(pickle.load(open(filename, "rb")))
except Exception, e:
log.warning("Unable to load config file: %s", filename)
log.debug("Config %s loaded: %s", filename, self.__config)
try:
data = open(filename, "rb").read()
except IOError, e:
log.warning("Unable to open config file %s: %s", filename, e)
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)
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)
elif len(objects) == 2:
try:
start, end = objects[0]
self.__version.update(json.loads(data[start:end]))
start, end = objects[1]
self.__config.update(json.loads(data[start:end]))
except Exception, e:
log.exception(e)
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)
def save(self, filename=None):
"""
Save configuration to disk
:param filename: if None, uses filename set in object initiliazation
:rtype bool:
:return: whether or not the save succeeded.
"""
if not filename:
@ -255,21 +390,41 @@ class Config(object):
# Check to see if the current config differs from the one on disk
# We will only write a new config file if there is a difference
try:
if self.__config == pickle.load(open(filename, "rb")):
data = open(filename, "rb").read()
objects = find_json_objects(data)
start, end = objects[0]
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 = None
self._save_timer.cancel()
return
except Exception, e:
log.warning("Unable to open config file: %s", filename)
self.__save_timer = None
# Save the new config and make sure it's written to disk
try:
log.debug("Saving new config file %s", filename + ".new")
pickle.dump(self.__config, open(filename + ".new", "wb"))
f = open(filename + ".new", "wb")
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:
log.error("Error writing new config file: %s", e)
return
return False
# Make a backup of the old config
try:
log.debug("Backing up old config file to %s~", filename)
shutil.move(filename, filename + "~")
except Exception, e:
log.error("Error backing up old config..")
# The new config file has been written successfully, so let's move it over
# the existing one.
@ -278,8 +433,50 @@ class Config(object):
shutil.move(filename + ".new", filename)
except Exception, e:
log.error("Error moving new config file: %s", e)
return False
else:
return True
finally:
if self._save_timer and self._save_timer.active():
self._save_timer.cancel()
def run_converter(self, input_range, output_version, func):
"""
Runs a function that will convert file versions in the `:param:input_range`
to the `:param:output_version`.
:param input_range: tuple, (int, int) the range of input versions this
function will accept
:param output_version: int, the version this function will return
:param func: func, the function that will do the conversion, it will take
the config dict as an argument and return the augmented dict
:raises ValueError: if the output_version is less than the input_range
"""
if output_version in input_range or output_version <= max(input_range):
raise ValueError("output_version needs to be greater than input_range")
if self.__version["file"] not in input_range:
log.debug("File version %s is not in input_range %s, ignoring converter function..",
self.__version["file"], input_range)
return
try:
self.__config = func(self.__config)
except Exception, e:
log.exception(e)
log.error("There was an exception try to convert config file %s %s to %s",
self.__config_file, self.__version["file"], output_version)
raise e
else:
self.__version["file"] = output_version
self.save()
@property
def config_file(self):
return self.__config_file
@prop
def config():
"""The config dictionary"""

View File

@ -19,13 +19,21 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import gobject
import os
import os.path
import deluge.common
from deluge.log import LOG as log
@ -35,27 +43,51 @@ class _ConfigManager:
def __init__(self):
log.debug("ConfigManager started..")
self.config_files = {}
self.config_directory = deluge.common.get_default_config_dir()
# Set a 5 minute timer to call save()
gobject.timeout_add(300000, self.save)
self.__config_directory = None
@property
def config_directory(self):
if self.__config_directory is None:
self.__config_directory = deluge.common.get_default_config_dir()
return self.__config_directory
def __del__(self):
log.debug("ConfigManager stopping..")
del self.config_files
def set_config_dir(self, directory):
"""Sets the config directory"""
if directory == None:
return
"""
Sets the config directory.
:param directory: str, the directory where the config info should be
:returns bool: True if successfully changed directory, False if not
"""
if not directory:
return False
log.info("Setting config directory to: %s", directory)
if not os.path.exists(directory):
# Try to create the config folder if it doesn't exist
try:
os.makedirs(directory)
except Exception, e:
log.warning("Unable to make config directory: %s", e)
log.error("Unable to make config directory: %s", e)
return False
elif not os.path.isdir(directory):
log.error("Config directory needs to be a directory!")
return False
self.config_directory = directory
self.__config_directory = directory
# Reset the config_files so we don't get config from old config folder
# XXX: Probably should have it go through the config_files dict and try
# to reload based on the new config directory
self.save()
self.config_files = {}
return True
def get_config_dir(self):
return self.config_directory
@ -69,8 +101,8 @@ class _ConfigManager:
def save(self):
"""Saves all the configs to disk."""
for key in self.config_files.keys():
self.config_files[key].save()
for value in self.config_files.values():
value.save()
# We need to return True to keep the timer active
return True

View File

@ -1,7 +1,7 @@
#
# alertmanager.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -19,36 +19,49 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
"""
"""The AlertManager handles all the libtorrent alerts."""
The AlertManager handles all the libtorrent alerts.
import gobject
This should typically only be used by the Core. Plugins should utilize the
`:mod:EventManager` for similar functionality.
"""
from twisted.internet import reactor
import deluge.component as component
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
from deluge._libtorrent import lt
from deluge.log import LOG as log
class AlertManager(component.Component):
def __init__(self, session):
def __init__(self):
log.debug("AlertManager initialized..")
component.Component.__init__(self, "AlertManager", interval=50)
self.session = session
component.Component.__init__(self, "AlertManager", interval=0.05)
self.session = component.get("Core").session
self.session.set_alert_mask(
lt.alert.category_t.error_notification |
lt.alert.category_t.port_mapping_notification |
lt.alert.category_t.storage_notification |
lt.alert.category_t.tracker_notification |
lt.alert.category_t.status_notification |
lt.alert.category_t.ip_block_notification)
lt.alert.category_t.ip_block_notification |
lt.alert.category_t.performance_warning)
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
self.handlers = {}
@ -56,17 +69,16 @@ class AlertManager(component.Component):
def update(self):
self.handle_alerts()
def shutdown(self):
del self.session
del self.handlers
def register_handler(self, alert_type, handler):
"""Registers a function that will be called when 'alert_type' is pop'd
in handle_alerts. The handler function should look like:
handler(alert)
Where 'alert' is the actual alert object from libtorrent
"""
if alert_type not in self.handlers.keys():
Registers a function that will be called when 'alert_type' is pop'd
in handle_alerts. The handler function should look like: handler(alert)
Where 'alert' is the actual alert object from libtorrent.
:param alert_type: str, this is string representation of the alert name
:param handler: func(alert), the function to be called when the alert is raised
"""
if alert_type not in self.handlers:
# There is no entry for this alert type yet, so lets make it with an
# empty list.
self.handlers[alert_type] = []
@ -76,32 +88,37 @@ class AlertManager(component.Component):
log.debug("Registered handler for alert %s", alert_type)
def deregister_handler(self, handler):
"""De-registers the 'handler' function from all alert types."""
"""
De-registers the `:param:handler` function from all alert types.
:param handler: func, the handler function to deregister
"""
# Iterate through all handlers and remove 'handler' where found
for (key, value) in self.handlers:
for (key, value) in self.handlers.items():
if handler in value:
# Handler is in this alert type list
value.remove(handler)
def handle_alerts(self, wait=False):
"""Pops all libtorrent alerts in the session queue and handles them
appropriately."""
"""
Pops all libtorrent alerts in the session queue and handles them
appropriately.
:param wait: bool, if True then the handler functions will be run right
away and waited to return before processing the next alert
"""
alert = self.session.pop_alert()
# Loop through all alerts in the queue
while alert is not None:
# Loop through all alerts in the queue
# Do some magic to get the alert type as a string
alert_type = str(type(alert)).split("'")[1].split(".")[-1]
alert_type = type(alert).__name__
# Display the alert message
log.debug("%s: %s", alert_type, alert.message())
# Call any handlers for this alert type
if alert_type in self.handlers.keys():
if alert_type in self.handlers:
for handler in self.handlers[alert_type]:
if not wait:
gobject.idle_add(handler, alert)
reactor.callLater(0, handler, alert)
else:
handler(alert)
alert = self.session.pop_alert()
# Return True so that the timer continues
return True

View File

@ -1,7 +1,7 @@
#
# authmanager.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -19,26 +19,50 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import os.path
import os
import random
import stat
import deluge.component as component
import deluge.configmanager as configmanager
import deluge.error
from deluge.log import LOG as log
AUTH_LEVEL_NONE = 0
AUTH_LEVEL_READONLY = 1
AUTH_LEVEL_NORMAL = 5
AUTH_LEVEL_ADMIN = 10
AUTH_LEVEL_DEFAULT = AUTH_LEVEL_NORMAL
class BadLoginError(deluge.error.DelugeError):
pass
class AuthManager(component.Component):
def __init__(self):
component.Component.__init__(self, "AuthManager")
self.auth = {}
self.__auth = {}
def start(self):
self.__load_auth_file()
def stop(self):
self.auth = {}
self.__auth = {}
def shutdown(self):
pass
@ -49,43 +73,74 @@ class AuthManager(component.Component):
:param username: str, username
:param password: str, password
:returns: True or False
:rtype: bool
:returns: int, the auth level for this user
:rtype: int
:raises BadLoginError: if the username does not exist or password does not match
"""
if username not in self.auth:
if username not in self.__auth:
# Let's try to re-load the file.. Maybe it's been updated
self.__load_auth_file()
if username not in self.auth:
return False
if username not in self.__auth:
raise BadLoginError("Username does not exist")
if self.auth[username] == password:
return True
if self.__auth[username][0] == password:
# Return the users auth level
return int(self.__auth[username][1])
else:
raise BadLoginError("Password does not match")
return False
def __create_localclient_account(self):
"""
Returns the string.
"""
# We create a 'localclient' account with a random password
try:
from hashlib import sha1 as sha_hash
except ImportError:
from sha import new as sha_hash
return "localclient:" + sha_hash(str(random.random())).hexdigest() + ":" + str(AUTH_LEVEL_ADMIN) + "\n"
def __load_auth_file(self):
auth_file = configmanager.get_config_dir("auth")
# Check for auth file and create if necessary
if not os.path.exists(auth_file):
# We create a 'localclient' account with a random password
try:
from hashlib import sha1 as sha_hash
except ImportError:
from sha import new as sha_hash
open(auth_file, "w").write("localclient:" + sha_hash(str(random.random())).hexdigest())
localclient = self.__create_localclient_account()
fd = open(auth_file, "w")
fd.write(localclient)
fd.flush()
os.fsync(fd.fileno())
fd.close()
# Change the permissions on the file so only this user can read/write it
os.chmod(auth_file, stat.S_IREAD | stat.S_IWRITE)
f = [localclient]
else:
# Load the auth file into a dictionary: {username: password, ...}
f = open(auth_file, "r").readlines()
# Load the auth file into a dictionary: {username: password, ...}
f = open(auth_file, "r")
for line in f:
if line.startswith("#"):
# This is a comment line
continue
line = line.strip()
try:
username, password = line.split(":")
except ValueError:
lsplit = line.split(":")
except Exception, e:
log.error("Your auth file is malformed: %s", e)
continue
self.auth[username.strip()] = password.strip()
if len(lsplit) == 2:
username, password = lsplit
log.warning("Your auth entry for %s contains no auth level, using AUTH_LEVEL_DEFAULT(%s)..", username, AUTH_LEVEL_DEFAULT)
level = AUTH_LEVEL_DEFAULT
elif len(lsplit) == 3:
username, password, level = lsplit
else:
log.error("Your auth file is malformed: Incorrect number of fields!")
continue
self.__auth[username.strip()] = (password.strip(), level)
if "localclient" not in self.__auth:
open(auth_file, "a").write(self.__create_localclient_account())

View File

@ -19,18 +19,24 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import os
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
from deluge._libtorrent import lt
import deluge.component as component
from deluge.configmanager import ConfigManager
@ -40,7 +46,7 @@ MAX_NUM_ATTEMPTS = 10
class AutoAdd(component.Component):
def __init__(self):
component.Component.__init__(self, "AutoAdd", depend=["TorrentManager"], interval=5000)
component.Component.__init__(self, "AutoAdd", depend=["TorrentManager"], interval=5)
# Get the core config
self.config = ConfigManager("core.conf")
@ -62,14 +68,18 @@ class AutoAdd(component.Component):
return
# Check the auto add folder for new torrents to add
if not os.path.exists(self.config["autoadd_location"]):
if not os.path.isdir(self.config["autoadd_location"]):
log.warning("Invalid AutoAdd folder: %s", self.config["autoadd_location"])
component.pause("AutoAdd")
return
for filename in os.listdir(self.config["autoadd_location"]):
if filename.split(".")[-1] == "torrent":
filepath = os.path.join(self.config["autoadd_location"], filename)
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:
filedump = self.load_torrent(filepath)
except (RuntimeError, Exception), e:

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#
# daemon.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -19,27 +19,188 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
import os
import gettext
import locale
import pkg_resources
from twisted.internet import reactor
import twisted.internet.error
import deluge.component as component
import deluge.configmanager
import deluge.common
from deluge.core.rpcserver import RPCServer, export
from deluge.log import LOG as log
import deluge.error
class Daemon(object):
def __init__(self, options=None, args=None, classic=False):
# Check for another running instance of the daemon
if os.path.isfile(deluge.configmanager.get_config_dir("deluged.pid")):
# Get the PID and the port of the supposedly running daemon
try:
(pid, port) = open(deluge.configmanager.get_config_dir("deluged.pid")).read().strip().split(";")
pid = int(pid)
port = int(port)
except ValueError:
pid = None
port = None
def process_running(pid):
if deluge.common.windows_check():
# Do some fancy WMI junk to see if the PID exists in Windows
from win32com.client import GetObject
def get_proclist():
WMI = GetObject('winmgmts:')
processes = WMI.InstancesOf('Win32_Process')
return [process.Properties_('ProcessID').Value for process in processes]
return pid in get_proclist()
else:
# We can just use os.kill on UNIX to test if the process is running
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True
if pid is not None and process_running(pid):
# Ok, so a process is running with this PID, let's make doubly-sure
# it's a deluged process by trying to open a socket to it's port.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(("127.0.0.1", port))
except socket.error:
# Can't connect, so it must not be a deluged process..
pass
else:
# This is a deluged!
s.close()
raise deluge.error.DaemonRunningError("There is a deluge daemon running with this config directory!")
# Initialize gettext
try:
locale.setlocale(locale.LC_ALL, '')
if hasattr(locale, "bindtextdomain"):
locale.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
if hasattr(locale, "textdomain"):
locale.textdomain("deluge")
gettext.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
gettext.textdomain("deluge")
gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"))
except Exception, e:
log.error("Unable to initialize gettext/locale: %s", e)
import __builtin__
__builtin__.__dict__["_"] = lambda x: x
# Twisted catches signals to terminate, so just have it call the shutdown
# method.
reactor.addSystemEventTrigger("after", "shutdown", self.shutdown)
# Catch some Windows specific signals
if deluge.common.windows_check():
from win32api import SetConsoleCtrlHandler
from win32con import CTRL_CLOSE_EVENT
from win32con import CTRL_SHUTDOWN_EVENT
def win_handler(ctrl_type):
log.debug("ctrl_type: %s", ctrl_type)
if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
self.__shutdown()
return 1
SetConsoleCtrlHandler(win_handler)
class Daemon:
def __init__(self, options, args):
version = deluge.common.get_version()
if deluge.common.get_revision() != "":
version = version + "r" + deluge.common.get_revision()
log.info("Deluge daemon %s", version)
log.debug("options: %s", options)
log.debug("args: %s", args)
# Set the config directory
deluge.configmanager.set_config_dir(options.config)
if options and options.config:
deluge.configmanager.set_config_dir(options.config)
from deluge.core.core import Core
# Start the core as a thread and join it until it's done
self.core = Core(options.port).run()
self.core = Core()
port = self.core.config["daemon_port"]
if options and options.port:
port = options.port
if options and options.ui_interface:
interface = options.ui_interface
else:
interface = ""
self.rpcserver = RPCServer(
port=port,
allow_remote=self.core.config["allow_remote"],
listen=not classic,
interface=interface
)
# Register the daemon and the core RPCs
self.rpcserver.register_object(self.core)
self.rpcserver.register_object(self)
# Make sure we start the PreferencesManager first
component.start("PreferencesManager")
if not classic:
# Write out a pid file all the time, we use this to see if a deluged is running
# We also include the running port number to do an additional test
open(deluge.configmanager.get_config_dir("deluged.pid"), "wb").write(
"%s;%s\n" % (os.getpid(), port))
component.start()
try:
reactor.run()
finally:
self._shutdown()
@export()
def shutdown(self, *args, **kwargs):
reactor.callLater(0, reactor.stop)
def _shutdown(self, *args, **kwargs):
try:
os.remove(deluge.configmanager.get_config_dir("deluged.pid"))
except Exception, e:
log.exception(e)
log.error("Error removing deluged.pid!")
component.shutdown()
try:
reactor.stop()
except twisted.internet.error.ReactorNotRunning:
log.debug("Tried to stop the reactor but it is not running..")
@export()
def info(self):
"""
Returns some info from the daemon.
:returns: str, the version number
"""
return deluge.common.get_version()
@export()
def get_method_list(self):
"""
Returns a list of the exported methods.
"""
return self.rpcserver.get_method_list()

View File

@ -0,0 +1,81 @@
#
# eventmanager.py
#
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import deluge.component as component
from deluge.log import LOG as log
class EventManager(component.Component):
def __init__(self):
component.Component.__init__(self, "EventManager")
self.handlers = {}
def emit(self, event):
"""
Emits the event to interested clients.
:param event: DelugeEvent
"""
# Emit the event to the interested clients
component.get("RPCServer").emit_event(event)
# Call any handlers for the event
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)
def register_event_handler(self, event, handler):
"""
Registers a function to be called when a `:param:event` is emitted.
:param event: str, the event name
:param handler: function, to be called when `:param:event` is emitted
"""
if event not in self.handlers:
self.handlers[event] = []
if handler not in self.handlers[event]:
self.handlers[event].append(handler)
def deregister_event_handler(self, event, handler):
"""
Deregisters an event handler function.
:param event: str, the event name
:param handler: function, currently registered to handle `:param:event`
"""
if event in self.handlers and handler in self.handlers[event]:
self.handlers[event].remove(handler)

View File

@ -19,7 +19,18 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
@ -66,6 +77,24 @@ def filter_one_keyword(torrent_ids, keyword):
yield torrent_id
break
def tracker_error_filter(torrent_ids, values):
filtered_torrent_ids = []
tm = component.get("TorrentManager")
# If this is a tracker_host, then we need to filter on it
if values[0] != "Error":
for torrent_id in torrent_ids:
if values[0] == tm[torrent_id].get_status(["tracker_host"])["tracker_host"]:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
# Check all the torrent's tracker_status for 'Error:' and only return torrent_ids
# that have this substring in their tracker_status
for torrent_id in torrent_ids:
if "Error:" in tm[torrent_id].get_status(["tracker_status"])["tracker_status"]:
filtered_torrent_ids.append(torrent_id)
return filtered_torrent_ids
class FilterManager(component.Component):
"""FilterManager
@ -75,13 +104,17 @@ class FilterManager(component.Component):
component.Component.__init__(self, "FilterManager")
log.debug("FilterManager init..")
self.core = core
self.torrents = core.torrents
self.torrents = core.torrentmanager
self.registered_filters = {}
self.register_filter("keyword", filter_keywords)
self.tree_fields = {}
self.register_tree_field("state", self._init_state_tree)
self.register_tree_field("tracker_host")
def _init_tracker_tree():
return {"Error": 0}
self.register_tree_field("tracker_host", _init_tracker_tree)
self.register_filter("tracker_host", tracker_error_filter)
def filter_torrent_ids(self, filter_dict):
"""
@ -107,6 +140,10 @@ class FilterManager(component.Component):
return torrent_ids
#special purpose: state=Active.
if "state" in filter_dict:
# We need to make sure this is a list for the logic below
filter_dict["state"] = list(filter_dict["state"])
if "state" in filter_dict and "Active" in filter_dict["state"]:
filter_dict["state"].remove("Active")
if not filter_dict["state"]:
@ -129,7 +166,7 @@ class FilterManager(component.Component):
#leftover filter arguments:
#default filter on status fields.
status_func = self.core.export_get_torrent_status #premature optimalisation..
status_func = self.core.get_torrent_status #premature optimalisation..
for torrent_id in list(torrent_ids):
status = status_func(torrent_id, filter_dict.keys()) #status={key:value}
for field, values in filter_dict.iteritems():
@ -144,7 +181,7 @@ class FilterManager(component.Component):
for use in sidebar.
"""
torrent_ids = self.torrents.get_torrent_list()
status_func = self.core.export_get_torrent_status #premature optimalisation..
status_func = self.core.get_torrent_status #premature optimalisation..
tree_keys = list(self.tree_fields.keys())
if hide_cat:
for cat in hide_cat:
@ -159,6 +196,9 @@ class FilterManager(component.Component):
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
if "tracker_host" in items:
items["tracker_host"]["Error"] = len(tracker_error_filter(torrent_ids, ("Error",)))
if "state" in tree_keys and not show_zero_hits:
self._hide_state_items(items["state"])
@ -193,10 +233,11 @@ class FilterManager(component.Component):
self.tree_fields[field] = init_func
def deregister_tree_field(self, field):
del self.tree_fields[field]
if field in self.tree_fields:
del self.tree_fields[field]
def filter_state_active(self, torrent_ids):
get_status = self.core.export_get_torrent_status
get_status = self.core.get_torrent_status
for torrent_id in list(torrent_ids):
status = get_status(torrent_id, ["download_payload_rate", "upload_payload_rate"])
if status["download_payload_rate"] or status["upload_payload_rate"]:
@ -223,6 +264,3 @@ class FilterManager(component.Component):
iy = 99
return ix - iy

View File

@ -19,7 +19,18 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
@ -29,14 +40,9 @@ import pickle
import cPickle
import shutil
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
from deluge._libtorrent import lt
from deluge.configmanager import ConfigManager
from deluge.configmanager import ConfigManager, get_config_dir
import deluge.core.torrentmanager
from deluge.log import LOG as log
@ -63,8 +69,8 @@ class PickleUpgrader(pickle.Unpickler):
class OldStateUpgrader:
def __init__(self):
self.config = ConfigManager("core.conf")
self.state05_location = os.path.join(self.config["config_location"], "persistent.state")
self.state10_location = os.path.join(self.config["state_location"], "torrents.state")
self.state05_location = os.path.join(get_config_dir(), "persistent.state")
self.state10_location = os.path.join(get_config_dir(), "state", "torrents.state")
if os.path.exists(self.state05_location) and not os.path.exists(self.state10_location):
# If the 0.5 state file exists and the 1.0 doesn't, then let's upgrade it
self.upgrade05()
@ -76,9 +82,14 @@ class OldStateUpgrader:
log.debug("Unable to open 0.5 state file: %s", e)
return
# Check to see if we can upgrade this file
if type(state).__name__ == 'list':
log.warning("0.5 state file is too old to upgrade")
return
new_state = deluge.core.torrentmanager.TorrentManagerState()
for ti, uid in state.torrents.items():
torrent_path = os.path.join(self.config["config_location"], "torrentfiles", ti.filename)
torrent_path = os.path.join(get_config_dir(), "torrentfiles", ti.filename)
try:
torrent_info = None
log.debug("Attempting to create torrent_info from %s", torrent_path)
@ -86,11 +97,11 @@ class OldStateUpgrader:
torrent_info = lt.torrent_info(lt.bdecode(_file.read()))
_file.close()
except (IOError, RuntimeError), e:
log.warning("Unable to open %s: %s", filepath, e)
log.warning("Unable to open %s: %s", torrent_path, e)
# Copy the torrent file to the new location
import shutil
shutil.copyfile(torrent_path, os.path.join(self.config["state_location"], str(torrent_info.info_hash()) + ".torrent"))
shutil.copyfile(torrent_path, os.path.join(get_config_dir(), "state", str(torrent_info.info_hash()) + ".torrent"))
# Set the file prioritiy property if not already there
if not hasattr(ti, "priorities"):
@ -116,7 +127,7 @@ class OldStateUpgrader:
try:
log.debug("Saving torrent state file.")
state_file = open(
os.path.join(self.config["state_location"], "torrents.state"), "wb")
os.path.join(get_config_dir(), "state", "torrents.state"), "wb")
cPickle.dump(new_state, state_file)
state_file.close()
except IOError, e:

View File

@ -19,14 +19,27 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""PluginManager for Core"""
import gobject
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from deluge.event import PluginEnabledEvent, PluginDisabledEvent
import deluge.pluginmanagerbase
import deluge.component as component
from deluge.log import LOG as log
@ -37,14 +50,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
functions to access parts of the core."""
def __init__(self, core):
component.Component.__init__(self, "PluginManager")
self.core = core
# Set up the hooks dictionary
self.hooks = {
"post_torrent_add": [],
"post_torrent_remove": [],
"post_session_load": []
}
component.Component.__init__(self, "CorePluginManager")
self.status_fields = {}
@ -56,29 +62,43 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
# Enable plugins that are enabled in the config
self.enable_plugins()
# Set update timer to call update() in plugins every second
self.update_timer = gobject.timeout_add(1000, self.update_plugins)
def stop(self):
# Disable all enabled plugins
self.disable_plugins()
# Stop the update timer
gobject.source_remove(self.update_timer)
def shutdown(self):
self.stop()
def update_plugins(self):
for plugin in self.plugins.keys():
try:
self.plugins[plugin].update()
except AttributeError:
# We don't care if this doesn't work
pass
if hasattr(self.plugins[plugin], "update"):
try:
self.plugins[plugin].update()
except Exception, e:
log.exception(e)
def get_core(self):
"""Returns a reference to the core"""
return self.core
def enable_plugin(self, name):
if name not in self.plugins:
super(PluginManager, self).enable_plugin(name)
if name in self.plugins:
component.get("EventManager").emit(PluginEnabledEvent(name))
def disable_plugin(self, name):
if name in self.plugins:
super(PluginManager, self).disable_plugin(name)
if name not in self.plugins:
component.get("EventManager").emit(PluginDisabledEvent(name))
def get_status(self, torrent_id, fields):
"""Return the value of status fields for the selected torrent_id."""
status = {}
for field in fields:
try:
status[field] = self.status_fields[field](torrent_id)
except KeyError:
log.warning("Status field %s is not registered with the\
PluginManager.", field)
return status
def register_status_field(self, field, function):
"""Register a new status field. This can be used in the same way the
@ -93,62 +113,3 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
del self.status_fields[field]
except:
log.warning("Unable to deregister status field %s", field)
def get_status(self, torrent_id, fields):
"""Return the value of status fields for the selected torrent_id."""
status = {}
for field in fields:
try:
status[field] = self.status_fields[field](torrent_id)
except KeyError:
log.warning("Status field %s is not registered with the\
PluginManager.", field)
return status
def register_hook(self, hook, function):
"""Register a hook function with the plugin manager"""
try:
self.hooks[hook].append(function)
except KeyError:
log.warning("Plugin attempting to register invalid hook.")
def deregister_hook(self, hook, function):
"""Deregisters a hook function"""
try:
self.hooks[hook].remove(function)
except:
log.warning("Unable to deregister hook %s", hook)
def run_post_torrent_add(self, torrent_id):
"""This hook is run after a torrent has been added to the session."""
log.debug("run_post_torrent_add")
for function in self.hooks["post_torrent_add"]:
function(torrent_id)
def run_post_torrent_remove(self, torrent_id):
"""This hook is run after a torrent has been removed from the session.
"""
log.debug("run_post_torrent_remove")
for function in self.hooks["post_torrent_remove"]:
function(torrent_id)
def run_post_session_load(self):
"""This hook is run after all the torrents have been loaded into the
session from the saved state. It is called prior to resuming the
torrents and they all will have a 'Paused' state."""
log.debug("run_post_session_load")
for function in self.hooks["post_session_load"]:
function()
def get_torrent_list(self):
"""Returns a list of torrent_id's in the current session."""
return component.get("TorrentManager").get_torrent_list()
def block_ip_range(self, range):
"""Blocks the ip range in the core"""
return self.core.export_block_ip_range(range)
def reset_ip_filter(self):
"""Resets the ip filter"""
return self.core.export_reset_ip_filter()

View File

@ -19,28 +19,36 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
import os.path
import threading
import gobject
import pkg_resources
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
from deluge._libtorrent import lt
from deluge.event import *
import deluge.configmanager
import deluge.common
import deluge.component as component
from deluge.log import LOG as log
DEFAULT_PREFS = {
"config_location": deluge.configmanager.get_config_dir(),
"send_info": False,
"info_sent": 0.0,
"daemon_port": 58846,
@ -48,10 +56,10 @@ DEFAULT_PREFS = {
"compact_allocation": False,
"download_location": deluge.common.get_default_download_dir(),
"listen_ports": [6881, 6891],
"listen_interface": "",
"copy_torrent_file": False,
"torrentfiles_location": deluge.common.get_default_download_dir(),
"plugins_location": os.path.join(deluge.configmanager.get_config_dir(), "plugins"),
"state_location": os.path.join(deluge.configmanager.get_config_dir(), "state"),
"prioritize_first_last_pieces": False,
"random_port": True,
"dht": True,
@ -68,7 +76,7 @@ DEFAULT_PREFS = {
"max_download_speed": -1.0,
"max_upload_slots_global": 4,
"max_half_open_connections": (lambda: deluge.common.windows_check() and
(lambda: deluge.common.vista_check() and 4 or 8)() or -1)(),
(lambda: deluge.common.vista_check() and 4 or 8)() or 50)(),
"max_connections_per_second": 20,
"ignore_limits_on_local_network": True,
"max_connections_per_torrent": -1,
@ -128,7 +136,10 @@ DEFAULT_PREFS = {
"outgoing_ports": [0, 0],
"random_outgoing_ports": True,
"peer_tos": "0x00",
"rate_limit_ip_overhead": True
"rate_limit_ip_overhead": True,
"geoip_db_location": "/usr/share/GeoIP/GeoIP.dat",
"cache_size": 512,
"cache_expiry": 60
}
class PreferencesManager(component.Component):
@ -141,15 +152,14 @@ class PreferencesManager(component.Component):
self.core = component.get("Core")
self.session = component.get("Core").session
self.settings = component.get("Core").settings
self.signals = component.get("SignalManager")
# Register set functions in the Config
self.config.register_set_function("torrentfiles_location",
self._on_set_torrentfiles_location)
self.config.register_set_function("state_location",
self._on_set_state_location)
self.config.register_set_function("listen_ports",
self._on_set_listen_ports)
self.config.register_set_function("listen_interface",
self._on_set_listen_interface)
self.config.register_set_function("random_port",
self._on_set_random_port)
self.config.register_set_function("outgoing_ports",
@ -208,12 +218,22 @@ class PreferencesManager(component.Component):
self._on_new_release_check)
self.config.register_set_function("rate_limit_ip_overhead",
self._on_rate_limit_ip_overhead)
self.config.register_set_function("geoip_db_location",
self._on_geoip_db_location)
self.config.register_set_function("cache_size",
self._on_cache_size)
self.config.register_set_function("cache_expiry",
self._on_cache_expiry)
self.config.register_change_callback(self._on_config_value_change)
def stop(self):
if self.new_release_timer:
self.new_release_timer.stop()
# Config set functions
def _on_config_value_change(self, key, value):
self.signals.emit("config_value_changed", key, value)
component.get("EventManager").emit(ConfigValueChangedEvent(key, value))
def _on_set_torrentfiles_location(self, key, value):
if self.config["copy_torrent_file"]:
@ -222,18 +242,15 @@ class PreferencesManager(component.Component):
except Exception, e:
log.debug("Unable to make directory: %s", e)
def _on_set_state_location(self, key, value):
if not os.access(value, os.F_OK):
try:
os.makedirs(value)
except Exception, e:
log.debug("Unable to make directory: %s", e)
def _on_set_listen_ports(self, key, value):
# Only set the listen ports if random_port is not true
if self.config["random_port"] is not True:
log.debug("listen port range set to %s-%s", value[0], value[1])
self.session.listen_on(value[0], value[1])
self.session.listen_on(value[0], value[1], str(self.config["listen_interface"]))
def _on_set_listen_interface(self, key, value):
# Call the random_port callback since it'll do what we need
self._on_set_random_port("random_port", self.config["random_port"])
def _on_set_random_port(self, key, value):
log.debug("random port value set to %s", value)
@ -251,12 +268,13 @@ class PreferencesManager(component.Component):
# Set the listen ports
log.debug("listen port range set to %s-%s", listen_ports[0],
listen_ports[1])
self.session.listen_on(listen_ports[0], listen_ports[1])
self.session.listen_on(listen_ports[0], listen_ports[1], str(self.config["listen_interface"]))
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.session.outgoing_ports(value[0], value[1])
self.settings.outgoing_ports = value[0], value[1]
self.session.set_settings(self.settings)
def _on_set_random_outgoing_ports(self, key, value):
if value:
@ -265,7 +283,7 @@ 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 = str(int(value, 16))
self.settings.peer_tos = chr(int(value, 16))
except ValueError, e:
log.debug("Invalid tos byte: %s", e)
return
@ -274,7 +292,7 @@ class PreferencesManager(component.Component):
def _on_set_dht(self, key, value):
log.debug("dht value set to %s", value)
state_file = deluge.common.get_default_config_dir("dht.state")
state_file = deluge.configmanager.get_config_dir("dht.state")
if value:
state = None
try:
@ -435,7 +453,7 @@ class PreferencesManager(component.Component):
platform.machine() + "&python=" + platform.python_version() \
+ "&deluge=" + deluge.common.get_version() \
+ "&os=" + platform.system() \
+ "&plugins=" + quote_plus(self.config["enabled_plugins"])
+ "&plugins=" + quote_plus(":".join(self.config["enabled_plugins"]))
urlopen(url)
except IOError, e:
log.debug("Network error while trying to send info: %s", e)
@ -449,22 +467,23 @@ class PreferencesManager(component.Component):
log.debug("Checking for new release..")
threading.Thread(target=self.core.get_new_release).start()
if self.new_release_timer:
gobject.source_remove(self.new_release_timer)
self.new_release_timer.stop()
# Set a timer to check for a new release every 3 days
self.new_release_timer = gobject.timeout_add(
72 * 60 * 60 * 1000, self._on_new_release_check, "new_release_check", True)
self.new_release_timer = LoopingCall(
self._on_new_release_check, "new_release_check", True)
self.new_release_timer.start(72 * 60 * 60, False)
else:
if self.new_release_timer:
gobject.source.remove(self.new_release_timer)
self.new_release_timer.stop()
def _on_set_proxies(self, key, value):
for k, v in value.items():
if v["type"]:
proxy_settings = lt.proxy_settings()
proxy_settings.proxy_type = lt.proxy_type(v["type"])
proxy_settings.username = v["username"]
proxy_settings.password = v["password"]
proxy_settings.hostname = v["hostname"]
proxy_settings.type = lt.proxy_type(v["type"])
proxy_settings.username = str(v["username"])
proxy_settings.password = str(v["password"])
proxy_settings.hostname = str(v["hostname"])
proxy_settings.port = v["port"]
log.debug("setting %s proxy settings", k)
getattr(self.session, "set_%s_proxy" % k)(proxy_settings)
@ -473,3 +492,31 @@ class PreferencesManager(component.Component):
log.debug("%s: %s", key, value)
self.settings.rate_limit_ip_overhead = value
self.session.set_settings(self.settings)
def _on_geoip_db_location(self, key, value):
log.debug("%s: %s", key, value)
# Load the GeoIP DB for country look-ups if available
geoip_db = ""
if os.path.exists(value):
geoip_db = value
elif os.path.exists(pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat"))):
geoip_db = pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat"))
else:
log.warning("Unable to find GeoIP database file!")
if geoip_db:
try:
self.session.load_country_db(str(geoip_db))
except Exception, e:
log.error("Unable to load geoip database!")
log.exception(e)
def _on_cache_size(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_size = value
self.session.set_settings(self.settings)
def _on_cache_expiry(self, key, value):
log.debug("%s: %s", key, value)
self.settings.cache_expiry = value
self.session.set_settings(self.settings)

View File

@ -1,7 +1,7 @@
#
# rpcserver.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2008,2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -19,96 +19,448 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""RPCServer Module"""
import gobject
import sys
import zlib
import os
import stat
import traceback
from deluge.SimpleXMLRPCServer import SimpleXMLRPCServer
from deluge.SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from SocketServer import ThreadingMixIn
from base64 import decodestring, encodestring
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import ssl, reactor, defer
from OpenSSL import crypto, SSL
from types import FunctionType
import deluge.rencode as rencode
from deluge.log import LOG as log
import deluge.component as component
import deluge.configmanager
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT
def export(func):
func._rpcserver_export = True
return func
RPC_RESPONSE = 1
RPC_ERROR = 2
RPC_EVENT = 3
def export(auth_level=AUTH_LEVEL_DEFAULT):
"""
Decorator function to register an object's method as an RPC. The object
will need to be registered with an :class:`RPCServer` to be effective.
:param func: the function to export
:type func: function
:param auth_level: the auth level required to call this method
:type auth_level: int
"""
def wrap(func, *args, **kwargs):
func._rpcserver_export = True
func._rpcserver_auth_level = auth_level
doc = func.__doc__
func.__doc__ = "**RPC Exported Function** (*Auth Level: %s*)\n\n" % auth_level
if doc:
func.__doc__ += doc
return func
if type(auth_level) is FunctionType:
func = auth_level
auth_level = AUTH_LEVEL_DEFAULT
return wrap(func)
else:
return wrap
class DelugeError(Exception):
pass
class NotAuthorizedError(DelugeError):
pass
class ServerContextFactory(object):
def getContext(self):
"""
Create an SSL context.
This loads the servers cert/private key SSL files for use with the
SSL transport.
"""
ssl_dir = deluge.configmanager.get_config_dir("ssl")
ctx = SSL.Context(SSL.SSLv3_METHOD)
ctx.use_certificate_file(os.path.join(ssl_dir, "daemon.cert"))
ctx.use_privatekey_file(os.path.join(ssl_dir, "daemon.pkey"))
return ctx
class DelugeRPCProtocol(Protocol):
__buffer = None
def dataReceived(self, data):
"""
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 a thread
with :meth:`dispatch`.
:param data: the data from the client. It should be a zlib compressed
rencoded string.
:type data: str
"""
if self.__buffer:
# We have some data from the last dataReceived() so lets prepend it
data = self.__buffer + data
self.__buffer = None
while data:
dobj = zlib.decompressobj()
try:
request = rencode.loads(dobj.decompress(data))
except Exception, e:
#log.debug("Received possible invalid message (%r): %s", data, e)
# This could be cut-off data, so we'll save this in the buffer
# and try to prepend it on the next dataReceived()
self.__buffer = data
return
else:
data = dobj.unused_data
if type(request) is not tuple:
log.debug("Received invalid message: type is not tuple")
return
if len(request) < 1:
log.debug("Received invalid message: there are no items")
return
for call in request:
if len(call) != 4:
log.debug("Received invalid rpc request: number of items in request is %s", len(call))
continue
# Format the RPCRequest message for debug printing
try:
s = call[1] + "("
if call[2]:
s += ", ".join([str(x) for x in call[2]])
if call[3]:
if call[2]:
s += ", "
s += ", ".join([key + "=" + str(value) for key, value in call[3].items()])
s += ")"
except UnicodeEncodeError:
pass
#log.debug("RPCRequest had some non-ascii text..")
else:
pass
#log.debug("RPCRequest: %s", s)
reactor.callLater(0, self.dispatch, *call)
def sendData(self, data):
"""
Sends the data to the client.
:param data: the object that is to be sent to the client. This should
be one of the RPC message types.
"""
self.transport.write(zlib.compress(rencode.dumps(data)))
def connectionMade(self):
"""
This method is called when a new client connects.
"""
peer = self.transport.getPeer()
log.info("Deluge Client connection made from: %s:%s", peer.host, peer.port)
# Set the initial auth level of this session to AUTH_LEVEL_NONE
self.factory.authorized_sessions[self.transport.sessionno] = AUTH_LEVEL_NONE
def connectionLost(self, reason):
"""
This method is called when the client is disconnected.
:param reason: the reason the client disconnected.
:type reason: str
"""
# We need to remove this session from various dicts
del self.factory.authorized_sessions[self.transport.sessionno]
if self.transport.sessionno in self.factory.session_protocols:
del self.factory.session_protocols[self.transport.sessionno]
if self.transport.sessionno in self.factory.interested_events:
del self.factory.interested_events[self.transport.sessionno]
log.info("Deluge client disconnected: %s", reason.value)
def dispatch(self, request_id, method, args, kwargs):
"""
This method is run when a RPC Request is made. It will run the local method
and will send either a RPC Response or RPC Error back to the client.
:param request_id: the request_id from the client (sent in the RPC Request)
:type request_id: int
:param method: the local method to call. It must be registered with
the :class:`RPCServer`.
:type method: str
:param args: the arguments to pass to `method`
:type args: list
:param kwargs: the keyword-arguments to pass to `method`
:type kwargs: dict
"""
def sendError():
"""
Sends an error response with the contents of the exception that was raised.
"""
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
self.sendData((
RPC_ERROR,
request_id,
(exceptionType.__name__,
exceptionValue.args[0] if len(exceptionValue.args) == 1 else "",
"".join(traceback.format_tb(exceptionTraceback)))
))
if method == "daemon.login":
# This is a special case and used in the initial connection process
# We need to authenticate the user here
try:
ret = component.get("AuthManager").authorize(*args, **kwargs)
if ret:
self.factory.authorized_sessions[self.transport.sessionno] = ret
self.factory.session_protocols[self.transport.sessionno] = self
except Exception, e:
sendError()
log.exception(e)
else:
self.sendData((RPC_RESPONSE, request_id, (ret)))
if not ret:
self.transport.loseConnection()
finally:
return
elif method == "daemon.set_event_interest" and self.transport.sessionno in self.factory.authorized_sessions:
# This special case is to allow clients to set which events they are
# interested in receiving.
# We are expecting a sequence from the client.
try:
if self.transport.sessionno not in self.factory.interested_events:
self.factory.interested_events[self.transport.sessionno] = []
self.factory.interested_events[self.transport.sessionno].extend(args[0])
except Exception, e:
sendError()
else:
self.sendData((RPC_RESPONSE, request_id, (True)))
finally:
return
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]
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)
raise NotAuthorizedError("Auth level too low: %s < %s" % (auth_level, method_auth_requirement))
ret = self.factory.methods[method](*args, **kwargs)
except Exception, e:
sendError()
# Don't bother printing out DelugeErrors, because they are just for the client
if not isinstance(e, DelugeError):
log.exception("Exception calling RPC request: %s", e)
else:
# Check if the return value is a deferred, since we'll need to
# wait for it to fire before sending the RPC_RESPONSE
if isinstance(ret, defer.Deferred):
def on_success(result):
self.sendData((RPC_RESPONSE, request_id, result))
return result
def on_fail(failure):
try:
failure.raiseException()
except Exception, e:
sendError()
return failure
ret.addCallbacks(on_success, on_fail)
else:
self.sendData((RPC_RESPONSE, request_id, ret))
class RPCServer(component.Component):
def __init__(self, port):
"""
This class is used to handle rpc requests from the client. Objects are
registered with this class and their methods are exported using the export
decorator.
:param port: the port the RPCServer will listen on
:type port: int
:param interface: the interface to listen on, this may override the `allow_remote` setting
:type interface: str
:param allow_remote: set True if the server should allow remote connections
:type allow_remote: bool
:param listen: if False, will not start listening.. This is only useful in Classic Mode
:type listen: bool
"""
def __init__(self, port=58846, interface="", allow_remote=False, listen=True):
component.Component.__init__(self, "RPCServer")
# Get config
self.config = deluge.configmanager.ConfigManager("core.conf")
self.factory = Factory()
self.factory.protocol = DelugeRPCProtocol
# Holds the registered methods
self.factory.methods = {}
# Holds the session_ids and auth levels
self.factory.authorized_sessions = {}
# Holds the protocol objects with the session_id as key
self.factory.session_protocols = {}
# Holds the interested event list for the sessions
self.factory.interested_events = {}
if port == None:
port = self.config["daemon_port"]
if not listen:
return
if self.config["allow_remote"]:
if allow_remote:
hostname = ""
else:
hostname = "localhost"
# Setup the xmlrpc server
if interface:
hostname = interface
log.info("Starting DelugeRPC server %s:%s", hostname, port)
# Check for SSL keys and generate some if needed
check_ssl_keys()
try:
log.info("Starting XMLRPC server %s:%s", hostname, port)
self.server = XMLRPCServer((hostname, port),
requestHandler=BasicAuthXMLRPCRequestHandler,
logRequests=False,
allow_none=True)
reactor.listenSSL(port, self.factory, ServerContextFactory(), interface=hostname)
except Exception, e:
log.info("Daemon already running or port not available..")
log.error(e)
sys.exit(0)
self.server.register_multicall_functions()
self.server.register_introspection_functions()
self.server.socket.setblocking(False)
gobject.io_add_watch(self.server.socket.fileno(), gobject.IO_IN | gobject.IO_OUT | gobject.IO_PRI | gobject.IO_ERR | gobject.IO_HUP, self._on_socket_activity)
def _on_socket_activity(self, source, condition):
"""This gets called when there is activity on the socket, ie, data to read
or to write."""
self.server.handle_request()
return True
def register_object(self, obj, name=None):
"""
Registers an object to export it's rpc methods. These methods should
be exported with the export decorator prior to registering the object.
:param obj: the object that we want to export
:type obj: object
:param name: the name to use, if None, it will be the class name of the object
:type name: str
"""
if not name:
name = obj.__class__.__name__
name = obj.__class__.__name__.lower()
for d in dir(obj):
if d[0] == "_":
continue
if getattr(getattr(obj, d), '_rpcserver_export', False):
log.debug("Registering method: %s", name + "." + d)
self.server.register_function(getattr(obj, d), name + "." + d)
self.factory.methods[name + "." + d] = getattr(obj, d)
class XMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
def get_request(self):
"""Get the request and client address from the socket.
We override this so that we can get the ip address of the client.
def get_object_method(self, name):
"""
request, client_address = self.socket.accept()
self.client_address = client_address[0]
return (request, client_address)
class BasicAuthXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def do_POST(self):
if "authorization" in self.headers:
auth = self.headers['authorization']
auth = auth.replace("Basic ","")
decoded_auth = decodestring(auth)
# Check authentication here
if component.get("AuthManager").authorize(*decoded_auth.split(":")):
# User authorized, call the real do_POST now
return SimpleXMLRPCRequestHandler.do_POST(self)
Returns a registered method.
# if cannot authenticate, end the connection
self.send_response(401)
self.end_headers()
:param name: the name of the method, usually in the form of 'object.method'
:type name: str
:returns: method
:raises KeyError: if `name` is not registered
"""
return self.factory.methods[name]
def get_method_list(self):
"""
Returns a list of the exported methods.
:returns: the exported methods
:rtype: list
"""
return self.factory.methods.keys()
def emit_event(self, event):
"""
Emits the event to interested clients.
:param event: the event to emit
:type event: :class:`deluge.event.DelugeEvent`
"""
log.debug("intevents: %s", self.factory.interested_events)
# Find sessions interested in this event
for session_id, interest in self.factory.interested_events.iteritems():
if event.name in interest:
log.debug("Emit Event: %s %s", event.name, event.args)
# This session is interested so send a RPC_EVENT
self.factory.session_protocols[session_id].sendData(
(RPC_EVENT, event.name, event.args)
)
def check_ssl_keys():
"""
Check for SSL cert/key and create them if necessary
"""
ssl_dir = deluge.configmanager.get_config_dir("ssl")
if not os.path.exists(ssl_dir):
# The ssl folder doesn't exist so we need to create it
os.makedirs(ssl_dir)
generate_ssl_keys()
else:
for f in ("daemon.pkey", "daemon.cert"):
if not os.path.exists(os.path.join(ssl_dir, f)):
generate_ssl_keys()
break
def generate_ssl_keys():
"""
This method generates a new SSL key/cert.
"""
digest = "md5"
# Generate key pair
pkey = crypto.PKey()
pkey.generate_key(crypto.TYPE_RSA, 1024)
# Generate cert request
req = crypto.X509Req()
subj = req.get_subject()
setattr(subj, "CN", "Deluge Daemon")
req.set_pubkey(pkey)
req.sign(pkey, digest)
# Generate certificate
cert = crypto.X509()
cert.set_serial_number(0)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(60*60*24*365*5) # Five Years
cert.set_issuer(req.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(pkey, digest)
# Write out files
ssl_dir = deluge.configmanager.get_config_dir("ssl")
open(os.path.join(ssl_dir, "daemon.pkey"), "w").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
open(os.path.join(ssl_dir, "daemon.cert"), "w").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
# Make the files only readable by this user
for f in ("daemon.pkey", "daemon.cert"):
os.chmod(os.path.join(ssl_dir, f), stat.S_IREAD | stat.S_IWRITE)

View File

@ -1,108 +0,0 @@
#
# signalmanager.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
import deluge.xmlrpclib as xmlrpclib
import socket
import struct
import gobject
import deluge.component as component
from deluge.log import LOG as log
class Transport(xmlrpclib.Transport):
def make_connection(self, host):
# create a HTTP connection object from a host descriptor
import httplib
host, extra_headers, x509 = self.get_host_info(host)
h = httplib.HTTP(host)
h._conn.connect()
h._conn.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', 1, 0))
return h
class SignalManager(component.Component):
def __init__(self):
component.Component.__init__(self, "SignalManager")
self.clients = {}
self.handlers = {}
def shutdown(self):
self.clients = {}
self.handlers = {}
def register_handler(self, signal, handler):
"""Registers a handler for signals"""
if signal not in self.handler.keys():
self.handler[signal] = []
self.handler[signal].append(handler)
log.debug("Registered signal handler for %s", signal)
def deregister_handler(self, handler):
"""De-registers the 'handler' function from all signal types."""
# Iterate through all handlers and remove 'handler' where found
for (key, value) in self.handlers:
if handler in value:
value.remove(handler)
def deregister_client(self, address):
"""Deregisters a client"""
log.debug("Deregistering %s as a signal reciever..", address)
for client in self.clients.keys():
if client.split("//")[1].split(":")[0] == address:
del self.clients[client]
break
def register_client(self, address, port):
"""Registers a client to emit signals to."""
uri = "http://" + str(address) + ":" + str(port)
log.debug("Registering %s as a signal reciever..", uri)
self.clients[uri] = xmlrpclib.ServerProxy(uri, transport=Transport())
#self.clients[uri].socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
# struct.pack('ii', 1, 0))
def emit(self, signal, *data):
# Run the handlers
if signal in self.handlers.keys():
for handler in self.handlers[signal]:
handler(*data)
for uri in self.clients:
gobject.idle_add(self._emit, uri, signal, 1, *data)
def _emit(self, uri, signal, count, *data):
if uri not in self.clients:
return
client = self.clients[uri]
try:
client.emit_signal(signal, *data)
except (socket.error, Exception), e:
log.warning("Unable to emit signal to client %s: %s (%d)", client, e, count)
if count < 30:
gobject.timeout_add(1000, self._emit, uri, signal, count + 1, *data)
else:
log.info("Removing %s because it couldn't be reached..", uri)
del self.clients[uri]

View File

@ -1,7 +1,7 @@
#
# torrent.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -19,9 +19,18 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
"""Internal Torrent class"""
@ -29,79 +38,39 @@ import os
import time
from urlparse import urlparse
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
from deluge._libtorrent import lt
import deluge.common
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.log import LOG as log
import deluge.xmlrpclib
from deluge.event import *
TORRENT_STATE = deluge.common.TORRENT_STATE
class TorrentOptions(dict):
def __init__(self):
self.config = ConfigManager("core.conf")
self.default_keys = {
"max_download_speed": "max_download_speed_per_torrent",
"max_upload_speed": "max_upload_speed_per_torrent",
"max_connections": "max_connections_per_torrent",
"max_upload_slots": "max_upload_slots_per_torrent",
"prioritize_first_last_pieces": "prioritize_first_last_pieces",
"auto_managed": "auto_managed",
"move_completed": "move_completed",
"move_completed_path": "move_completed_path",
"file_priorities": [],
"compact_allocation": "compact_allocation",
"download_location": "download_location",
"add_paused": "add_paused"
}
super(TorrentOptions, self).__setitem__("stop_at_ratio", False)
super(TorrentOptions, self).__setitem__("stop_ratio", 2.0)
super(TorrentOptions, self).__setitem__("remove_at_ratio", False)
def items(self):
i = super(TorrentOptions, self).items()
for k in self.default_keys:
if k not in super(TorrentOptions, self).keys():
i.append((k, self.__getitem__(k)))
return i
def keys(self):
k = super(TorrentOptions, self).keys()
for key in self.default_keys.keys():
if key not in k:
k.append(key)
return k
def iteritems(self):
return self.items().itermitems()
def has_key(self, key):
if super(TorrentOptions, self).has_key(key):
return True
elif self.default_keys.has_key(key):
return True
return False
def __setitem__(self, key, value):
super(TorrentOptions, self).__setitem__(key, value)
def __getitem__(self, key):
if super(TorrentOptions, self).has_key(key):
return super(TorrentOptions, self).__getitem__(key)
else:
if self.default_keys[key]:
return self.config[self.default_keys[key]]
else:
return self.default_keys[key]
config = ConfigManager("core.conf").config
options_conf_map = {
"max_connections": "max_connections_per_torrent",
"max_upload_slots": "max_upload_slots_per_torrent",
"max_upload_speed": "max_upload_speed_per_torrent",
"max_download_speed": "max_download_speed_per_torrent",
"prioritize_first_last_pieces": "prioritize_first_last_pieces",
"compact_allocation": "compact_allocation",
"download_location": "download_location",
"auto_managed": "auto_managed",
"stop_at_ratio": "stop_seed_at_ratio",
"stop_ratio": "stop_seed_ratio",
"remove_at_ratio": "remove_seed_at_ratio",
"move_completed": "move_completed",
"move_completed_path": "move_completed_path",
"add_paused": "add_paused",
}
for opt_k, conf_k in options_conf_map.iteritems():
self[opt_k] = config[conf_k]
self["file_priorities"] = []
self["mapped_files"] = {}
class Torrent:
"""Torrent holds information about torrents added to the libtorrent session.
@ -111,8 +80,6 @@ class Torrent:
# Get the core config
self.config = ConfigManager("core.conf")
self.signals = component.get("SignalManager")
# Set the libtorrent handle
self.handle = handle
# Set the torrent_id for this torrent
@ -146,9 +113,6 @@ class Torrent:
except RuntimeError:
self.torrent_info = None
# Files dictionary
self.files = self.get_files()
# Default total_uploaded to 0, this may be changed by the state
self.total_uploaded = 0
@ -169,22 +133,22 @@ class Torrent:
# Set the filename
self.filename = state.filename
self.is_finished = state.is_finished
# Set the per-torrent queue options
self.options["stop_at_ratio"] = state.stop_at_ratio
self.options["stop_ratio"] = state.stop_ratio
self.options["remove_at_ratio"] = state.remove_at_ratio
else:
# Tracker list
self.trackers = []
# Create a list of trackers
for value in self.handle.trackers():
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
if lt.version_minor < 15:
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
else:
tracker = value
self.trackers.append(tracker)
# Various torrent options
self.handle.resolve_countries(True)
self.set_options(self.options)
# Status message holds error info about the torrent
@ -196,6 +160,9 @@ class Torrent:
# The tracker status
self.tracker_status = ""
# This gets updated when get_tracker_host is called
self.tracker_host = None
if state:
self.time_added = state.time_added
else:
@ -207,14 +174,14 @@ class Torrent:
def set_options(self, options):
OPTIONS_FUNCS = {
# Functions used for setting options
"max_download_speed": self.set_max_download_speed,
"max_upload_speed": self.set_max_upload_speed,
"max_connections": self.handle.set_max_connections,
"max_upload_slots": self.handle.set_max_uploads,
"prioritize_first_last_pieces": self.set_prioritize_first_last,
"auto_managed": self.set_auto_managed,
"file_priorities": self.set_file_priorities,
"download_location": self.set_save_path,
"file_priorities": self.set_file_priorities,
"max_connections": self.handle.set_max_connections,
"max_download_speed": self.set_max_download_speed,
"max_upload_slots": self.handle.set_max_uploads,
"max_upload_speed": self.set_max_upload_speed,
"prioritize_first_last_pieces": self.set_prioritize_first_last
}
for (key, value) in options.items():
if OPTIONS_FUNCS.has_key(key):
@ -277,8 +244,14 @@ class Torrent:
def set_remove_at_ratio(self, remove_at_ratio):
self.options["remove_at_ratio"] = remove_at_ratio
def set_move_completed(self, move_completed):
self.options["move_completed"] = move_completed
def set_move_completed_path(self, move_completed_path):
self.options["move_completed_path"] = move_completed_path
def set_file_priorities(self, file_priorities):
if len(file_priorities) != len(self.files):
if len(file_priorities) != len(self.get_files()):
log.debug("file_priorities len != num_files")
self.options["file_priorities"] = self.handle.file_priorities()
return
@ -312,11 +285,15 @@ class Torrent:
if trackers == None:
trackers = []
for value in self.handle.trackers():
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
if lt.version_minor < 15:
tracker = {}
tracker["url"] = value.url
tracker["tier"] = value.tier
else:
tracker = value
trackers.append(tracker)
self.trackers = trackers
self.tracker_host = None
return
log.debug("Setting trackers for %s: %s", self.torrent_id, trackers)
@ -326,18 +303,19 @@ class Torrent:
new_entry = lt.announce_entry(tracker["url"])
new_entry.tier = tracker["tier"]
tracker_list.append(new_entry)
self.handle.replace_trackers(tracker_list)
# Print out the trackers
for t in self.handle.trackers():
log.debug("tier: %s tracker: %s", t.tier, t.url)
#for t in self.handle.trackers():
# log.debug("tier: %s tracker: %s", t["tier"], t["url"])
# Set the tracker list in the torrent object
self.trackers = trackers
if len(trackers) > 0:
# Force a reannounce if there is at least 1 tracker
self.force_reannounce()
self.tracker_host = None
### End Options methods ###
def set_save_path(self, save_path):
@ -355,8 +333,22 @@ class Torrent:
log.debug("set_state_based_on_ltstate: %s", deluge.common.LT_TORRENT_STATE[ltstate])
log.debug("session.is_paused: %s", component.get("Core").session.is_paused())
# First we check for an error from libtorrent, and set the state to that
# if any occurred.
if len(self.handle.status().error) > 0:
# This is an error'd torrent
self.state = "Error"
self.set_status_message(self.handle.status().error)
if self.handle.is_paused():
self.handle.auto_managed(False)
return
if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]:
self.state = "Checking"
if self.handle.is_paused():
self.state = "Paused"
else:
self.state = "Checking"
return
elif ltstate == LTSTATE["Downloading"] or ltstate == LTSTATE["Downloading Metadata"]:
self.state = "Downloading"
@ -365,12 +357,7 @@ class Torrent:
elif ltstate == LTSTATE["Allocating"]:
self.state = "Allocating"
if self.handle.is_paused() and len(self.handle.status().error) > 0:
# This is an error'd torrent
self.state = "Error"
self.set_status_message(self.handle.status().error)
self.handle.auto_managed(False)
elif self.handle.is_paused() and self.handle.is_auto_managed() and not component.get("Core").session.is_paused():
if self.handle.is_paused() and self.handle.is_auto_managed() and not component.get("Core").session.is_paused():
self.state = "Queued"
elif component.get("Core").session.is_paused() or (self.handle.is_paused() and not self.handle.is_auto_managed()):
self.state = "Paused"
@ -421,9 +408,7 @@ class Torrent:
else:
status = self.status
if status.all_time_download > 0:
downloaded = status.all_time_download
elif status.total_done > 0:
if status.total_done > 0:
# We use 'total_done' if the downloaded value is 0
downloaded = status.total_done
else:
@ -476,13 +461,13 @@ class Torrent:
country += c
ret.append({
"ip": "%s:%s" % (peer.ip[0], peer.ip[1]),
"up_speed": peer.up_speed,
"down_speed": peer.down_speed,
"country": country,
"client": client,
"country": country,
"down_speed": peer.down_speed,
"ip": "%s:%s" % (peer.ip[0], peer.ip[1]),
"progress": peer.progress,
"seed": peer.flags & peer.seed,
"progress": peer.progress
"up_speed": peer.up_speed,
})
return ret
@ -498,7 +483,7 @@ class Torrent:
file_progress = self.handle.file_progress()
ret = []
for i,f in enumerate(self.files):
for i,f in enumerate(self.get_files()):
try:
ret.append(float(file_progress[i]) / float(f["size"]))
except ZeroDivisionError:
@ -509,6 +494,9 @@ class Torrent:
def get_tracker_host(self):
"""Returns just the hostname of the currently connected tracker
if no tracker is connected, it uses the 1st tracker."""
if self.tracker_host:
return self.tracker_host
if not self.status:
self.status = self.handle.status()
@ -517,12 +505,26 @@ class Torrent:
tracker = self.trackers[0]["url"]
if tracker:
url = urlparse(tracker)
url = urlparse(tracker.replace("udp://", "http://"))
if hasattr(url, "hostname"):
host = (url.hostname or 'DHT')
# Check if hostname is an IP address and just return it if that's the case
import socket
try:
socket.inet_aton(host)
except socket.error:
pass
else:
# This is an IP address because an exception wasn't raised
return url.hostname
parts = host.split(".")
if len(parts) > 2:
host = ".".join(parts[-2:])
if parts[-2] in ("co", "com", "net", "org") or parts[-1] in ("uk"):
host = ".".join(parts[-3:])
else:
host = ".".join(parts[-2:])
self.tracker_host = host
return host
return ""
@ -543,55 +545,66 @@ class Torrent:
#if you add a key here->add it to core.py STATUS_KEYS too.
full_status = {
"distributed_copies": distributed_copies,
"total_done": self.status.total_done,
"total_uploaded": self.status.all_time_upload,
"active_time": self.status.active_time,
"all_time_download": self.status.all_time_download,
"state": self.state,
"paused": self.status.paused,
"progress": progress,
"next_announce": self.status.next_announce.seconds,
"total_payload_download": self.status.total_payload_download,
"total_payload_upload": self.status.total_payload_upload,
"compact": self.options["compact_allocation"],
"distributed_copies": distributed_copies,
"download_payload_rate": self.status.download_payload_rate,
"upload_payload_rate": self.status.upload_payload_rate,
"file_priorities": self.options["file_priorities"],
"hash": self.torrent_id,
"is_auto_managed": self.options["auto_managed"],
"is_finished": self.is_finished,
"max_connections": self.options["max_connections"],
"max_download_speed": self.options["max_download_speed"],
"max_upload_slots": self.options["max_upload_slots"],
"max_upload_speed": self.options["max_upload_speed"],
"message": self.statusmsg,
"move_on_completed_path": self.options["move_completed_path"],
"move_on_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,
"paused": self.status.paused,
"prioritize_first_last": self.options["prioritize_first_last_pieces"],
"progress": progress,
"remove_at_ratio": self.options["remove_at_ratio"],
"save_path": self.options["download_location"],
"seeding_time": self.status.seeding_time,
"seed_rank": self.status.seed_rank,
"state": self.state,
"stop_at_ratio": self.options["stop_at_ratio"],
"stop_ratio": self.options["stop_ratio"],
"time_added": self.time_added,
"total_done": self.status.total_done,
"total_payload_download": self.status.total_payload_download,
"total_payload_upload": self.status.total_payload_upload,
"total_peers": self.status.num_incomplete,
"total_seeds": self.status.num_complete,
"total_uploaded": self.status.all_time_upload,
"total_wanted": self.status.total_wanted,
"tracker": self.status.current_tracker,
"trackers": self.trackers,
"tracker_status": self.tracker_status,
"save_path": self.options["download_location"],
"files": self.files,
"file_priorities": self.options["file_priorities"],
"compact": self.options["compact_allocation"],
"max_connections": self.options["max_connections"],
"max_upload_slots": self.options["max_upload_slots"],
"max_upload_speed": self.options["max_upload_speed"],
"max_download_speed": self.options["max_download_speed"],
"prioritize_first_last": self.options["prioritize_first_last_pieces"],
"message": self.statusmsg,
"hash": self.torrent_id,
"active_time": self.status.active_time,
"seeding_time": self.status.seeding_time,
"seed_rank": self.status.seed_rank,
"is_auto_managed": self.options["auto_managed"],
"stop_ratio": self.options["stop_ratio"],
"stop_at_ratio": self.options["stop_at_ratio"],
"remove_at_ratio": self.options["remove_at_ratio"],
"move_on_completed": self.options["move_completed"],
"move_on_completed_path": self.options["move_completed_path"],
"time_added": self.time_added
"upload_payload_rate": self.status.upload_payload_rate
}
def ti_comment():
if self.handle.has_metadata():
try:
return self.torrent_info.comment().decode("utf8", "ignore")
except UnicodeDecodeError:
return self.torrent_info.comment()
return ""
def ti_name():
if self.handle.has_metadata():
name = self.torrent_info.file_at(0).path.split("/", 1)[0]
if not name:
name = self.torrent_info.name()
try:
return self.torrent_info.name().decode("utf8", "ignore")
return name.decode("utf8", "ignore")
except UnicodeDecodeError:
return self.torrent_info.name()
return name
return self.torrent_id
def ti_priv():
@ -616,19 +629,21 @@ class Torrent:
return 0
fns = {
"comment": ti_comment,
"eta": self.get_eta,
"file_progress": self.get_file_progress,
"files": self.get_files,
"is_seed": self.handle.is_seed,
"name": ti_name,
"private": ti_priv,
"total_size": ti_total_size,
"num_files": ti_num_files,
"num_pieces": ti_num_pieces,
"piece_length": ti_piece_length,
"eta": self.get_eta,
"ratio": self.get_ratio,
"file_progress": self.get_file_progress,
"queue": self.handle.queue_position,
"is_seed": self.handle.is_seed,
"peers": self.get_peers,
"tracker_host": self.get_tracker_host
"piece_length": ti_piece_length,
"private": ti_priv,
"queue": self.handle.queue_position,
"ratio": self.get_ratio,
"total_size": ti_total_size,
"tracker_host": self.get_tracker_host,
}
# Create the desired status dictionary and return it
@ -666,7 +681,7 @@ class Torrent:
# show it as 'Paused'. We need to emit a torrent_paused signal because
# the torrent_paused alert from libtorrent will not be generated.
self.update_state()
self.signals.emit("torrent_paused", self.torrent_id)
component.get("EventManager").emit(TorrentStateChangedEvent(self.torrent_id, "Paused"))
else:
try:
self.handle.pause()
@ -695,7 +710,8 @@ class Torrent:
ratio = self.config["stop_seed_ratio"]
if self.get_ratio() >= ratio:
self.signals.emit("torrent_resume_at_stop_ratio")
#XXX: This should just be returned in the RPC Response, no event
#self.signals.emit_event("torrent_resume_at_stop_ratio")
return
if self.options["auto_managed"]:
@ -733,44 +749,17 @@ class Torrent:
self.handle.save_resume_data()
self.waiting_on_resume_data = True
def write_resume_data(self, resume_data):
"""Writes the .fastresume file for the torrent"""
resume_data = lt.bencode(resume_data)
path = "%s/%s.fastresume" % (
self.config["state_location"],
self.torrent_id)
try:
self.delete_fastresume()
log.debug("Saving fastresume file: %s", path)
fastresume = open(path, "wb")
fastresume.write(resume_data)
fastresume.close()
except IOError:
log.warning("Error trying to save fastresume file")
self.waiting_on_resume_data = False
def delete_fastresume(self):
"""Deletes the .fastresume file"""
path = "%s/%s.fastresume" % (
self.config["state_location"],
self.torrent_id)
log.debug("Deleting fastresume file: %s", path)
try:
os.remove(path)
except Exception, e:
log.warning("Unable to delete the fastresume file: %s", e)
def write_torrentfile(self):
"""Writes the torrent file"""
path = "%s/%s.torrent" % (
self.config["state_location"],
os.path.join(get_config_dir(), "state"),
self.torrent_id)
log.debug("Writing torrent file: %s", path)
try:
ti = self.handle.get_torrent_info()
md = lt.bdecode(ti.metadata())
log.debug("md: %s", md)
self.torrent_info = self.handle.get_torrent_info()
# Regenerate the file priorities
self.set_file_priorities([])
md = lt.bdecode(self.torrent_info.metadata())
torrent_file = {}
torrent_file["info"] = md
open(path, "wb").write(lt.bencode(torrent_file))
@ -780,7 +769,7 @@ class Torrent:
def delete_torrentfile(self):
"""Deletes the .torrent file in the state"""
path = "%s/%s.torrent" % (
self.config["state_location"],
os.path.join(get_config_dir(), "state"),
self.torrent_id)
log.debug("Deleting torrent file: %s", path)
try:
@ -812,6 +801,7 @@ class Torrent:
"""Forces a recheck of the torrents pieces"""
try:
self.handle.force_recheck()
self.handle.resume()
except Exception, e:
log.debug("Unable to force recheck: %s", e)
return False
@ -821,7 +811,7 @@ class Torrent:
"""Renames files in the torrent. 'filenames' should be a list of
(index, filename) pairs."""
for index, filename in filenames:
self.handle.rename_file(index, filename)
self.handle.rename_file(index, filename.encode("utf-8"))
def rename_folder(self, folder, new_folder):
"""Renames a folder within a torrent. This basically does a file rename
@ -839,5 +829,5 @@ class Torrent:
if f["path"].startswith(folder):
# Keep a list of filerenames we're waiting on
wait_on_folder[2].append(f["index"])
self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1))
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)

View File

@ -19,31 +19,40 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""TorrentManager handles Torrent objects"""
import cPickle
import os.path
import os
import time
import shutil
import operator
import gobject
from twisted.internet import reactor
from twisted.internet.task import LoopingCall
try:
import deluge.libtorrent as lt
except ImportError:
import libtorrent as lt
if not (lt.version_major == 0 and lt.version_minor == 14):
raise ImportError("This version of Deluge requires libtorrent 0.14!")
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
from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.torrent import Torrent
from deluge.core.torrent import TorrentOptions
import deluge.core.oldstateupgrader
@ -71,6 +80,8 @@ class TorrentState:
stop_ratio=2.00,
stop_at_ratio=False,
remove_at_ratio=False,
move_completed=False,
move_completed_path=None,
magnet=None,
time_added=-1
):
@ -97,26 +108,34 @@ class TorrentState:
self.stop_ratio = stop_ratio
self.stop_at_ratio = stop_at_ratio
self.remove_at_ratio = remove_at_ratio
self.move_completed = move_completed
self.move_completed_path = move_completed_path
class TorrentManagerState:
def __init__(self):
self.torrents = []
class TorrentManager(component.Component):
"""TorrentManager contains a list of torrents in the current libtorrent
"""
TorrentManager contains a list of torrents in the current libtorrent
session. This object is also responsible for saving the state of the
session for use on restart."""
session for use on restart.
"""
def __init__(self, session, alerts):
component.Component.__init__(self, "TorrentManager", interval=5000, depend=["PluginManager"])
def __init__(self):
component.Component.__init__(self, "TorrentManager", interval=5, depend=["CorePluginManager"])
log.debug("TorrentManager init..")
# Set the libtorrent session
self.session = session
self.session = component.get("Core").session
# Set the alertmanager
self.alerts = alerts
self.alerts = component.get("AlertManager")
# Get the core config
self.config = ConfigManager("core.conf")
# Make sure the state folder has been created
if not os.path.exists(os.path.join(get_config_dir(), "state")):
os.makedirs(os.path.join(get_config_dir(), "state"))
# Create the torrents dict { torrent_id: Torrent }
self.torrents = {}
@ -125,6 +144,12 @@ class TorrentManager(component.Component):
# and that their resume data has been written.
self.shutdown_torrent_pause_list = []
# self.num_resume_data used to save resume_data in bulk
self.num_resume_data = 0
# Keeps track of resume data that needs to be saved to disk
self.resume_data = {}
# Register set functions
self.config.register_set_function("max_connections_per_torrent",
self.on_set_max_connections_per_torrent)
@ -146,7 +171,6 @@ class TorrentManager(component.Component):
self.on_alert_tracker_reply)
self.alerts.register_handler("tracker_announce_alert",
self.on_alert_tracker_announce)
self.alerts.register_handler("tracker_alert", self.on_alert_tracker)
self.alerts.register_handler("tracker_warning_alert",
self.on_alert_tracker_warning)
self.alerts.register_handler("tracker_error_alert",
@ -165,12 +189,12 @@ class TorrentManager(component.Component):
self.on_alert_file_renamed)
self.alerts.register_handler("metadata_received_alert",
self.on_alert_metadata_received)
self.alerts.register_handler("file_error_alert",
self.on_alert_file_error)
def start(self):
# Get the pluginmanager reference
self.plugins = component.get("PluginManager")
self.signals = component.get("SignalManager")
self.plugins = component.get("CorePluginManager")
# Run the old state upgrader before loading state
deluge.core.oldstateupgrader.OldStateUpgrader()
@ -179,19 +203,38 @@ class TorrentManager(component.Component):
self.load_state()
# Save the state every 5 minutes
self.save_state_timer = gobject.timeout_add(300000, self.save_state)
self.save_resume_data_timer = gobject.timeout_add(290000, self.save_resume_data)
self.save_state_timer = LoopingCall(self.save_state)
self.save_state_timer.start(200, False)
self.save_resume_data_timer = LoopingCall(self.save_resume_data)
self.save_resume_data_timer.start(190)
def stop(self):
# Stop timers
if self.save_state_timer.running:
self.save_state_timer.stop()
if self.save_resume_data_timer.running:
self.save_resume_data_timer.stop()
# Save state on shutdown
self.save_state()
# Make another list just to make sure all paused torrents will be
# passed to self.save_resume_data(). With
# self.shutdown_torrent_pause_list it is possible to have a case when
# torrent_id is removed from it in self.on_alert_torrent_paused()
# before we call self.save_resume_data() here.
save_resume_data_list = []
for key in self.torrents.keys():
if not self.torrents[key].handle.is_paused():
# We set auto_managed false to prevent lt from resuming the torrent
self.torrents[key].handle.auto_managed(False)
self.torrents[key].handle.pause()
self.shutdown_torrent_pause_list.append(key)
save_resume_data_list.append(key)
self.save_resume_data(save_resume_data_list)
# We have to wait for all torrents to pause and write their resume data
wait = True
while wait:
@ -210,7 +253,11 @@ 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"]:
if self.config["stop_seed_at_ratio"] or 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"]:
continue
stop_ratio = self.config["stop_seed_ratio"]
if torrent.options["stop_at_ratio"]:
stop_ratio = torrent.options["stop_ratio"]
@ -243,15 +290,12 @@ class TorrentManager(component.Component):
return torrent_info
def get_resume_data_from_file(self, torrent_id):
def legacy_get_resume_data_from_file(self, torrent_id):
"""Returns an entry with the resume data or None"""
fastresume = ""
try:
_file = open(
os.path.join(
self.config["state_location"],
torrent_id + ".fastresume"),
"rb")
_file = open(os.path.join(get_config_dir(), "state",
torrent_id + ".fastresume"), "rb")
fastresume = _file.read()
_file.close()
except IOError, e:
@ -259,8 +303,18 @@ class TorrentManager(component.Component):
return str(fastresume)
def legacy_delete_resume_data(self, torrent_id):
"""Deletes the .fastresume file"""
path = os.path.join(get_config_dir(), "state",
torrent_id + ".fastresume")
log.debug("Deleting fastresume file: %s", path)
try:
os.remove(path)
except Exception, e:
log.warning("Unable to delete the fastresume file: %s", e)
def add(self, torrent_info=None, state=None, options=None, save_state=True,
filedump=None, filename=None, magnet=None):
filedump=None, filename=None, magnet=None, resume_data=None):
"""Add a torrent to the manager and returns it's torrent_id"""
if torrent_info is None and state is None and filedump is None and magnet is None:
@ -275,6 +329,8 @@ class TorrentManager(component.Component):
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except Exception, e:
log.error("Unable to decode torrent file!: %s", e)
# XXX: Probably should raise an exception here..
return
if torrent_info is None and state:
# We have no torrent_info so we need to add the torrent with information
@ -291,20 +347,31 @@ class TorrentManager(component.Component):
options["compact_allocation"] = state.compact
options["download_location"] = state.save_path
options["auto_managed"] = state.auto_managed
options["stop_at_ratio"] = state.stop_at_ratio
options["stop_ratio"] = state.stop_ratio
options["remove_at_ratio"] = state.remove_at_ratio
options["move_completed"] = state.move_completed
options["move_completed_path"] = state.move_completed_path
options["add_paused"] = state.paused
if not state.magnet:
add_torrent_params["ti"] =\
self.get_torrent_info_from_file(
os.path.join(self.config["state_location"], state.torrent_id + ".torrent"))
if not add_torrent_params["ti"]:
log.error("Unable to add torrent!")
return
else:
ti = self.get_torrent_info_from_file(
os.path.join(get_config_dir(),
"state", state.torrent_id + ".torrent"))
if ti:
add_torrent_params["ti"] = ti
elif state.magnet:
magnet = state.magnet
else:
log.error("Unable to add torrent!")
return
add_torrent_params["resume_data"] = self.get_resume_data_from_file(state.torrent_id)
# Handle legacy case with storing resume data in individual files
# for each torrent
if resume_data is None:
resume_data = self.legacy_get_resume_data_from_file(state.torrent_id)
self.legacy_delete_resume_data(state.torrent_id)
add_torrent_params["resume_data"] = resume_data
else:
# We have a torrent_info object so we're not loading from state.
# Check if options is None and load defaults
@ -315,6 +382,13 @@ class TorrentManager(component.Component):
o.update(options)
options = o
# Check for renamed files and if so, rename them in the torrent_info
# before adding to the session.
if options["mapped_files"]:
for index, name in options["mapped_files"].items():
log.debug("renaming file index %s to %s", index, name)
torrent_info.rename_file(index, name.encode("utf-8"))
add_torrent_params["ti"] = torrent_info
add_torrent_params["resume_data"] = ""
@ -378,7 +452,7 @@ class TorrentManager(component.Component):
# Write the .torrent file to the state directory
if filedump:
try:
save_file = open(os.path.join(self.config["state_location"],
save_file = open(os.path.join(get_config_dir(), "state",
torrent.torrent_id + ".torrent"),
"wb")
save_file.write(filedump)
@ -403,7 +477,7 @@ class TorrentManager(component.Component):
self.save_state()
# Emit the torrent_added signal
self.signals.emit("torrent_added", torrent.torrent_id)
component.get("EventManager").emit(TorrentAddedEvent(torrent.torrent_id))
return torrent.torrent_id
@ -415,7 +489,7 @@ class TorrentManager(component.Component):
log.debug("Attempting to open %s for add.", torrent_id)
_file = open(
os.path.join(
self.config["state_location"], torrent_id + ".torrent"),
get_config_dir(), "state", torrent_id + ".torrent"),
"rb")
filedump = lt.bdecode(_file.read())
_file.close()
@ -426,7 +500,27 @@ class TorrentManager(component.Component):
return filedump
def remove(self, torrent_id, remove_data=False):
"""Remove a torrent from the manager"""
"""
Remove a torrent from the session.
:param torrent_id: the torrent to remove
:type torrent_id: string
:param remove_data: if True, remove the downloaded data
:type remove_data: bool
:returns: True if removed successfully, False if not
:rtype: bool
:raises InvalidTorrentError: if the torrent_id is not in the session
"""
if torrent_id not in self.torrents:
raise InvalidTorrentError("torrent_id not in session")
# Emit the signal to the clients
component.get("EventManager").emit(PreTorrentRemovedEvent(torrent_id))
try:
self.session.remove_torrent(self.torrents[torrent_id].handle,
1 if remove_data else 0)
@ -434,8 +528,10 @@ class TorrentManager(component.Component):
log.warning("Error removing torrent: %s", e)
return False
# Remove the .fastresume if it exists
self.torrents[torrent_id].delete_fastresume()
# Remove fastresume data if it is exists
resume_data = self.load_resume_data_file()
resume_data.pop(torrent_id, None)
self.save_resume_data_file(resume_data)
# Remove the .torrent file in the state
self.torrents[torrent_id].delete_torrentfile()
@ -450,7 +546,7 @@ class TorrentManager(component.Component):
self.save_state()
# Emit the signal to the clients
self.signals.emit("torrent_removed", torrent_id)
component.get("EventManager").emit(TorrentRemovedEvent(torrent_id))
return True
@ -461,7 +557,7 @@ class TorrentManager(component.Component):
try:
log.debug("Opening torrent state file for load.")
state_file = open(
os.path.join(self.config["state_location"], "torrents.state"), "rb")
os.path.join(get_config_dir(), "state", "torrents.state"), "rb")
state = cPickle.load(state_file)
state_file.close()
except (EOFError, IOError, Exception), e:
@ -469,33 +565,29 @@ class TorrentManager(component.Component):
# Try to use an old state
try:
if dir(state.torrents[0]) != dir(TorrentState()):
for attr in (set(dir(TorrentState())) - set(dir(state.torrents[0]))):
state_tmp = TorrentState()
if dir(state.torrents[0]) != dir(state_tmp):
for attr in (set(dir(state_tmp)) - set(dir(state.torrents[0]))):
for s in state.torrents:
setattr(s, attr, getattr(TorrentState(), attr, None))
setattr(s, attr, getattr(state_tmp, attr, None))
except Exception, e:
log.warning("Unable to update state file to a compatible version: %s", e)
# Reorder the state.torrents list to add torrents in the correct queue
# order.
ordered_state = []
for torrent_state in state.torrents:
for t in ordered_state:
if torrent_state.queue < t.queue:
ordered_state.insert(ordered_state.index(t), torrent_state)
break
if torrent_state not in ordered_state:
ordered_state.append(torrent_state)
state.torrents.sort(key=operator.attrgetter("queue"))
for torrent_state in ordered_state:
resume_data = self.load_resume_data_file()
for torrent_state in state.torrents:
try:
self.add(state=torrent_state, save_state=False)
self.add(state=torrent_state, save_state=False,
resume_data=resume_data.get(torrent_state.torrent_id))
except AttributeError, e:
log.error("Torrent state file is either corrupt or incompatible!")
log.error("Torrent state file is either corrupt or incompatible! %s", e)
break
# Run the post_session_load plugin hooks
self.plugins.run_post_session_load()
component.get("EventManager").emit(SessionStartedEvent())
def save_state(self):
"""Save the state of the TorrentManager to the torrents.state file"""
@ -526,6 +618,8 @@ class TorrentManager(component.Component):
torrent.options["stop_ratio"],
torrent.options["stop_at_ratio"],
torrent.options["remove_at_ratio"],
torrent.options["move_completed"],
torrent.options["move_completed_path"],
torrent.magnet,
torrent.time_added
)
@ -534,10 +628,11 @@ class TorrentManager(component.Component):
# Pickle the TorrentManagerState object
try:
log.debug("Saving torrent state file.")
state_file = open(
os.path.join(self.config["state_location"], "torrents.state.new"),
"wb")
state_file = open(os.path.join(get_config_dir(),
"state", "torrents.state.new"), "wb")
cPickle.dump(state, state_file)
state_file.flush()
os.fsync(state_file.fileno())
state_file.close()
except IOError:
log.warning("Unable to save state file.")
@ -546,8 +641,8 @@ class TorrentManager(component.Component):
# We have to move the 'torrents.state.new' file to 'torrents.state'
try:
shutil.move(
os.path.join(self.config["state_location"], "torrents.state.new"),
os.path.join(self.config["state_location"], "torrents.state"))
os.path.join(get_config_dir(), "state", "torrents.state.new"),
os.path.join(get_config_dir(), "state", "torrents.state"))
except IOError:
log.warning("Unable to save state file.")
return True
@ -555,10 +650,71 @@ class TorrentManager(component.Component):
# We return True so that the timer thread will continue
return True
def save_resume_data(self):
"""Saves resume data for all the torrents"""
for torrent in self.torrents.values():
torrent.save_resume_data()
def save_resume_data(self, torrent_ids=None):
"""
Saves resume data for list of torrent_ids or for all torrents if
torrent_ids is None
"""
if torrent_ids is None:
torrent_ids = self.torrents.keys()
for torrent_id in torrent_ids:
self.torrents[torrent_id].save_resume_data()
self.num_resume_data = len(torrent_ids)
def load_resume_data_file(self):
resume_data = {}
try:
log.debug("Opening torrents fastresume file for load.")
fastresume_file = open(os.path.join(get_config_dir(), "state",
"torrents.fastresume"), "rb")
resume_data = lt.bdecode(fastresume_file.read())
fastresume_file.close()
except (EOFError, IOError, Exception), e:
log.warning("Unable to load fastresume file: %s", e)
# If the libtorrent bdecode doesn't happen properly, it will return None
# so we need to make sure we return a {}
if resume_data is None:
return {}
return resume_data
def save_resume_data_file(self, resume_data=None):
"""
Saves the resume data file with the contents of self.resume_data. If
`resume_data` is None, then we grab the resume_data from the file on
disk, else, we update `resume_data` with self.resume_data and save
that to disk.
:param resume_data: the current resume_data, this will be loaded from disk if not provided
:type resume_data: dict
"""
# Check to see if we're waiting on more resume data
if self.num_resume_data or not self.resume_data:
return
path = os.path.join(get_config_dir(), "state", "torrents.fastresume")
# First step is to load the existing file and update the dictionary
if resume_data is None:
resume_data = self.load_resume_data_file()
resume_data.update(self.resume_data)
self.resume_data = {}
try:
log.debug("Saving fastresume file: %s", path)
fastresume_file = open(path, "wb")
fastresume_file.write(lt.bencode(resume_data))
fastresume_file.flush()
os.fsync(fastresume_file.fileno())
fastresume_file.close()
except IOError:
log.warning("Error trying to save fastresume file")
def queue_top(self, torrent_id):
"""Queue torrent to top"""
@ -617,150 +773,193 @@ class TorrentManager(component.Component):
## Alert handlers ##
def on_alert_torrent_finished(self, alert):
log.debug("on_alert_torrent_finished")
# Get the torrent_id
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
log.debug("%s is finished..", torrent_id)
# Get the total_download and if it's 0, do not move.. It's likely
# that the torrent wasn't downloaded, but just added.
total_download = torrent.get_status(["total_payload_download"])["total_payload_download"]
# Move completed download to completed folder if needed
if not torrent.is_finished:
if not torrent.is_finished and total_download:
move_path = None
if torrent.options["move_completed"]:
move_path = torrent.options["move_completed_path"]
elif self.config["move_completed"]:
move_path = self.config["move_completed_path"]
if move_path:
if torrent.options["download_location"] != move_path:
torrent.move_storage(move_path)
torrent.is_finished = True
torrent.is_finished = True
component.get("EventManager").emit(TorrentFinishedEvent(torrent_id))
torrent.update_state()
torrent.save_resume_data()
component.get("SignalManager").emit("torrent_finished", torrent_id)
# Only save resume data if it was actually downloaded something. Helps
# on startup with big queues with lots of seeding torrents. Libtorrent
# emits alert_torrent_finished for them, but there seems like nothing
# worth really to save in resume data, we just read it up in
# self.load_state().
if total_download:
self.save_resume_data((torrent_id, ))
def on_alert_torrent_paused(self, alert):
log.debug("on_alert_torrent_paused")
# Get the torrent_id
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent_id = str(alert.handle.info_hash())
# Set the torrent state
self.torrents[torrent_id].update_state()
component.get("SignalManager").emit("torrent_paused", torrent_id)
old_state = torrent.state
torrent.update_state()
if torrent.state != old_state:
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
# Write the fastresume file
self.torrents[torrent_id].save_resume_data()
# Don't save resume data for each torrent after self.stop() was called.
# We save resume data in bulk in self.stop() in this case.
if self.save_resume_data_timer.running:
# Write the fastresume file
self.save_resume_data((torrent_id, ))
if torrent_id in self.shutdown_torrent_pause_list:
self.shutdown_torrent_pause_list.remove(torrent_id)
def on_alert_torrent_checked(self, alert):
log.debug("on_alert_torrent_checked")
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
# Set the torrent state
self.torrents[torrent_id].update_state()
torrent.update_state()
def on_alert_tracker_reply(self, alert):
log.debug("on_alert_tracker_reply: %s", alert.message())
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
# Set the tracker status for the torrent
log.debug("on_alert_tracker_reply: %s", alert.message().decode("utf8"))
try:
if alert.message() != "Got peers from DHT":
self.torrents[torrent_id].set_tracker_status(_("Announce OK"))
except KeyError:
log.debug("torrent_id doesn't exist.")
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
# Set the tracker status for the torrent
if alert.message() != "Got peers from DHT":
torrent.set_tracker_status(_("Announce OK"))
# Check to see if we got any peer information from the tracker
if alert.handle.status().num_complete == -1 or \
alert.handle.status().num_incomplete == -1:
# We didn't get peer information, so lets send a scrape request
self.torrents[torrent_id].scrape_tracker()
torrent.scrape_tracker()
def on_alert_tracker_announce(self, alert):
log.debug("on_alert_tracker_announce")
# Get the torrent_id
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError:
log.debug("Invalid torrent handle.")
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
# Set the tracker status for the torrent
try:
self.torrents[torrent_id].set_tracker_status(_("Announce Sent"))
except KeyError:
log.debug("torrent_id doesn't exist.")
def on_alert_tracker(self, alert):
log.debug("on_alert_tracker")
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
tracker_status = "%s: %s" % \
(_("Alert"), str(alert.message()).strip('"')[8:])
# Set the tracker status for the torrent
try:
self.torrents[torrent_id].set_tracker_status(tracker_status)
except KeyError:
log.debug("torrent_id doesn't exist.")
torrent.set_tracker_status(_("Announce Sent"))
def on_alert_tracker_warning(self, alert):
log.debug("on_alert_tracker_warning")
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
tracker_status = '%s: %s' % (_("Warning"), str(alert.message()))
# Set the tracker status for the torrent
try:
self.torrents[torrent_id].set_tracker_status(tracker_status)
except KeyError:
log.debug("torrent_id doesn't exist.")
torrent.set_tracker_status(tracker_status)
def on_alert_tracker_error(self, alert):
log.debug("on_alert_tracker_error")
torrent = self.torrents[str(alert.handle.info_hash())]
tracker_status = "%s: %s" % (_("Error"), alert.msg)
try:
torrent.set_tracker_status(tracker_status)
except KeyError:
log.debug("torrent_id doesn't exist.")
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
tracker_status = "%s: %s" % (_("Error"), alert.msg)
torrent.set_tracker_status(tracker_status)
def on_alert_storage_moved(self, alert):
log.debug("on_alert_storage_moved")
log.debug("save_path: %s", alert.handle.save_path())
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
try:
log.debug("save_path2: %s", self.torrents[torrent_id].handle.save_path())
self.torrents[torrent_id].set_save_path(alert.handle.save_path())
except KeyError:
log.debug("torrent_id doesn't exist.")
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent.set_save_path(alert.handle.save_path())
def on_alert_torrent_resumed(self, alert):
log.debug("on_alert_torrent_resumed")
torrent = self.torrents[str(alert.handle.info_hash())]
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent_id = str(alert.handle.info_hash())
torrent.is_finished = torrent.handle.is_seed()
old_state = torrent.state
torrent.update_state()
if torrent.state != old_state:
# We need to emit a TorrentStateChangedEvent too
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
component.get("EventManager").emit(TorrentResumedEvent(torrent_id))
def on_alert_state_changed(self, alert):
log.debug("on_alert_state_changed")
torrent_id = str(alert.handle.info_hash())
self.torrents[torrent_id].update_state()
component.get("SignalManager").emit("torrent_state_changed", torrent_id)
try:
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
except:
return
old_state = torrent.state
torrent.update_state()
# Only emit a state changed event if the state has actually changed
if torrent.state != old_state:
component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state))
def on_alert_save_resume_data(self, alert):
log.debug("on_alert_save_resume_data")
torrent = self.torrents[str(alert.handle.info_hash())]
torrent.write_resume_data(alert.resume_data)
torrent_id = str(alert.handle.info_hash())
try:
torrent = self.torrents[torrent_id]
except:
return
# Libtorrent in add_torrent() expects resume_data to be bencoded
self.resume_data[torrent_id] = lt.bencode(alert.resume_data)
self.num_resume_data -= 1
torrent.waiting_on_resume_data = False
self.save_resume_data_file()
def on_alert_save_resume_data_failed(self, alert):
log.debug("on_alert_save_resume_data_failed: %s", alert.message())
torrent = self.torrents[str(alert.handle.info_hash())]
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
self.num_resume_data -= 1
torrent.waiting_on_resume_data = False
self.save_resume_data_file()
def on_alert_file_renamed(self, alert):
log.debug("on_alert_file_renamed")
log.debug("index: %s name: %s", alert.index, alert.name)
log.debug("index: %s name: %s", alert.index, alert.name.decode("utf8"))
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent_id = str(alert.handle.info_hash())
torrent = self.torrents[torrent_id]
torrent.files[alert.index]["path"] = alert.name
# We need to see if this file index is in a waiting_on_folder list
folder_rename = False
@ -769,8 +968,9 @@ class TorrentManager(component.Component):
folder_rename = True
if len(wait_on_folder[2]) == 1:
# This is the last alert we were waiting for, time to send signal
component.get("SignalManager").emit("torrent_folder_renamed", torrent_id, wait_on_folder[0], wait_on_folder[1])
component.get("EventManager").emit(TorrentFolderRenamedEvent(torrent_id, wait_on_folder[0], wait_on_folder[1]))
del torrent.waiting_on_folder_rename[i]
self.save_resume_data((torrent_id,))
break
# This isn't the last file to be renamed in this folder, so just
# remove the index and continue
@ -778,9 +978,21 @@ class TorrentManager(component.Component):
if not folder_rename:
# This is just a regular file rename so send the signal
component.get("SignalManager").emit("torrent_file_renamed", torrent_id, alert.index, alert.name)
component.get("EventManager").emit(TorrentFileRenamedEvent(torrent_id, alert.index, alert.name))
self.save_resume_data((torrent_id,))
def on_alert_metadata_received(self, alert):
log.debug("on_alert_metadata_received")
torrent = self.torrents[str(alert.handle.info_hash())]
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent.write_torrentfile()
def on_alert_file_error(self, alert):
log.debug("on_alert_file_error: %s", alert.message())
try:
torrent = self.torrents[str(alert.handle.info_hash())]
except:
return
torrent.update_state()

View File

@ -1,39 +0,0 @@
There are two licenses, one for the C library software, and one for
the database.
SOFTWARE LICENSE (C library)
The GeoIP C Library is licensed under the LGPL. For details see
the COPYING file.
OPEN DATA LICENSE (GeoLite Country and GeoLite City databases)
Copyright (c) 2008 MaxMind, Inc. All Rights Reserved.
All advertising materials and documentation mentioning features or use of
this database must display the following acknowledgment:
"This product includes GeoLite data created by MaxMind, available from
http://maxmind.com/"
Redistribution and use with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions must retain the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
2. All advertising materials and documentation mentioning features or use of
this database must display the following acknowledgement:
"This product includes GeoLite data created by MaxMind, available from
http://maxmind.com/"
3. "MaxMind" may not be used to endorse or promote products derived from this
database without specific prior written permission.
THIS DATABASE IS PROVIDED BY MAXMIND, INC ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL MAXMIND BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
DATABASE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

View File

View File

@ -3,7 +3,7 @@ Version=1.0
Name=Deluge BitTorrent Client
GenericName=Bittorrent Client
Comment=Transfer files using the Bittorrent protocol
Exec=deluge
Exec=deluge-gtk
Icon=deluge
Terminal=false
Type=Application

View File

@ -1,27 +0,0 @@
.. deluge documentation master file, created by sphinx-quickstart on Tue Nov 4 18:24:06 2008.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to deluge's documentation!
==================================
Contents:
.. toctree::
:maxdepth: 2
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
Modules
=======
.. toctree::
:maxdepth: 2
modules/common
modules/config

View File

@ -1,11 +0,0 @@
:mod:`deluge.config`
====================
.. automodule:: deluge.config
.. autoclass:: Config
:show-inheritance:
:members:
:undoc-members:
.. automethod:: __setitem__
.. automethod:: __getitem__

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

View File

@ -1,833 +0,0 @@
/**
* Sphinx Doc Design
*/
body {
font-family: sans-serif;
font-size: 100%;
background-color: #11303d;
color: #000;
margin: 0;
padding: 0;
}
/* :::: LAYOUT :::: */
div.document {
background-color: #1c4e63;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: white;
padding: 0 20px 30px 20px;
}
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.clearer {
clear: both;
}
div.footer {
color: #fff;
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #fff;
text-decoration: underline;
}
div.related {
background-color: #133f52;
color: #fff;
width: 100%;
height: 30px;
line-height: 30px;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
div.related a {
color: white;
}
/* ::: TOC :::: */
div.sphinxsidebar h3 {
font-family: 'Trebuchet MS', sans-serif;
color: white;
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h4 {
font-family: 'Trebuchet MS', sans-serif;
color: white;
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: white;
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
list-style: none;
color: white;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar a {
color: #98dbcc;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
/* :::: MODULE CLOUD :::: */
div.modulecloud {
margin: -5px 10px 5px 10px;
padding: 10px;
line-height: 160%;
border: 1px solid #cbe7e5;
background-color: #f2fbfd;
}
div.modulecloud a {
padding: 0 5px 0 5px;
}
/* :::: SEARCH :::: */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* :::: COMMON FORM STYLES :::: */
div.actions {
padding: 5px 10px 5px 10px;
border-top: 1px solid #cbe7e5;
border-bottom: 1px solid #cbe7e5;
background-color: #e0f6f4;
}
form dl {
color: #333;
}
form dt {
clear: both;
float: left;
min-width: 110px;
margin-right: 10px;
padding-top: 2px;
}
input#homepage {
display: none;
}
div.error {
margin: 5px 20px 0 0;
padding: 5px;
border: 1px solid #d00;
font-weight: bold;
}
/* :::: INLINE COMMENTS :::: */
div.inlinecomments {
position: absolute;
right: 20px;
}
div.inlinecomments a.bubble {
display: block;
float: right;
background-image: url(style/comment.png);
background-repeat: no-repeat;
width: 25px;
height: 25px;
text-align: center;
padding-top: 3px;
font-size: 0.9em;
line-height: 14px;
font-weight: bold;
color: black;
}
div.inlinecomments a.bubble span {
display: none;
}
div.inlinecomments a.emptybubble {
background-image: url(style/nocomment.png);
}
div.inlinecomments a.bubble:hover {
background-image: url(style/hovercomment.png);
text-decoration: none;
color: #3ca0a4;
}
div.inlinecomments div.comments {
float: right;
margin: 25px 5px 0 0;
max-width: 50em;
min-width: 30em;
border: 1px solid #2eabb0;
background-color: #f2fbfd;
z-index: 150;
}
div#comments {
border: 1px solid #2eabb0;
margin-top: 20px;
}
div#comments div.nocomments {
padding: 10px;
font-weight: bold;
}
div.inlinecomments div.comments h3,
div#comments h3 {
margin: 0;
padding: 0;
background-color: #2eabb0;
color: white;
border: none;
padding: 3px;
}
div.inlinecomments div.comments div.actions {
padding: 4px;
margin: 0;
border-top: none;
}
div#comments div.comment {
margin: 10px;
border: 1px solid #2eabb0;
}
div.inlinecomments div.comment h4,
div.commentwindow div.comment h4,
div#comments div.comment h4 {
margin: 10px 0 0 0;
background-color: #2eabb0;
color: white;
border: none;
padding: 1px 4px 1px 4px;
}
div#comments div.comment h4 {
margin: 0;
}
div#comments div.comment h4 a {
color: #d5f4f4;
}
div.inlinecomments div.comment div.text,
div.commentwindow div.comment div.text,
div#comments div.comment div.text {
margin: -5px 0 -5px 0;
padding: 0 10px 0 10px;
}
div.inlinecomments div.comment div.meta,
div.commentwindow div.comment div.meta,
div#comments div.comment div.meta {
text-align: right;
padding: 2px 10px 2px 0;
font-size: 95%;
color: #538893;
border-top: 1px solid #cbe7e5;
background-color: #e0f6f4;
}
div.commentwindow {
position: absolute;
width: 500px;
border: 1px solid #cbe7e5;
background-color: #f2fbfd;
display: none;
z-index: 130;
}
div.commentwindow h3 {
margin: 0;
background-color: #2eabb0;
color: white;
border: none;
padding: 5px;
font-size: 1.5em;
cursor: pointer;
}
div.commentwindow div.actions {
margin: 10px -10px 0 -10px;
padding: 4px 10px 4px 10px;
color: #538893;
}
div.commentwindow div.actions input {
border: 1px solid #2eabb0;
background-color: white;
color: #135355;
cursor: pointer;
}
div.commentwindow div.form {
padding: 0 10px 0 10px;
}
div.commentwindow div.form input,
div.commentwindow div.form textarea {
border: 1px solid #3c9ea2;
background-color: white;
color: black;
}
div.commentwindow div.error {
margin: 10px 5px 10px 5px;
background-color: #fbe5dc;
display: none;
}
div.commentwindow div.form textarea {
width: 99%;
}
div.commentwindow div.preview {
margin: 10px 0 10px 0;
background-color: #70d0d4;
padding: 0 1px 1px 25px;
}
div.commentwindow div.preview h4 {
margin: 0 0 -5px -20px;
padding: 4px 0 0 4px;
color: white;
font-size: 1.3em;
}
div.commentwindow div.preview div.comment {
background-color: #f2fbfd;
}
div.commentwindow div.preview div.comment h4 {
margin: 10px 0 0 0!important;
padding: 1px 4px 1px 4px!important;
font-size: 1.2em;
}
/* :::: SUGGEST CHANGES :::: */
div#suggest-changes-box input, div#suggest-changes-box textarea {
border: 1px solid #ccc;
background-color: white;
color: black;
}
div#suggest-changes-box textarea {
width: 99%;
height: 400px;
}
/* :::: PREVIEW :::: */
div.preview {
background-image: url(style/preview.png);
padding: 0 20px 20px 20px;
margin-bottom: 30px;
}
/* :::: INDEX PAGE :::: */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* :::: INDEX STYLES :::: */
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
form.pfform {
margin: 10px 0 20px 0;
}
/* :::: GLOBAL STYLES :::: */
.docwarning {
background-color: #ffe4e4;
padding: 10px;
margin: 0 -20px 0 -20px;
border-bottom: 1px solid #f66;
}
p.subhead {
font-weight: bold;
margin-top: 20px;
}
a {
color: #355f7c;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: 'Trebuchet MS', sans-serif;
background-color: #f2f2f2;
font-weight: normal;
color: #20435c;
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
line-height: 130%;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
ul.fakelist {
list-style: none;
margin: 10px 0 10px 20px;
padding: 0;
}
.field-list ul {
padding-left: 1em;
}
.first {
margin-top: 0 !important;
}
/* "Footnotes" heading */
p.rubric {
margin-top: 30px;
font-weight: bold;
}
/* "Topics" */
div.topic {
background-color: #eee;
border: 1px solid #ccc;
padding: 0 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* Admonitions */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
div.admonition p {
display: inline;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
display: inline;
}
p.admonition-title:after {
content: ":";
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
table.docutils {
border: 0;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 0;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
dl {
margin-bottom: 15px;
clear: both;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
.refcount {
color: #060;
}
dt:target,
.highlight {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
th {
text-align: left;
padding-right: 5px;
}
pre {
padding: 5px;
background-color: #efc;
color: #333;
border: 1px solid #ac9;
border-left: none;
border-right: none;
overflow: auto;
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
.footnote:target { background-color: #ffa }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
form.comment {
margin: 0;
padding: 10px 30px 10px 30px;
background-color: #eee;
}
form.comment h3 {
background-color: #326591;
color: white;
margin: -10px -30px 10px -30px;
padding: 5px;
font-size: 1.4em;
}
form.comment input,
form.comment textarea {
border: 1px solid #ccc;
padding: 2px;
font-family: sans-serif;
font-size: 100%;
}
form.comment input[type="text"] {
width: 240px;
}
form.comment textarea {
width: 100%;
height: 200px;
margin-bottom: 10px;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
/* :::: PRINT :::: */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0;
width : 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
div#comments div.new-comment-box,
#top-link {
display: none;
}
}

View File

@ -1,352 +0,0 @@
/// XXX: make it cross browser
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
*/
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {}
}
/**
* small helper function to urldecode strings
*/
jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' ');
}
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s == 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
}
/**
* small function to check if an array contains
* a given item.
*/
jQuery.contains = function(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item)
return true;
}
return false;
}
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) {
var span = document.createElement("span");
span.className = className;
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this)
});
}
}
return this.each(function() {
highlight(this);
});
}
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
/* this.addContextElements(); -- now done statically */
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initModIndex();
this.initComments();
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
for (var i = 1; i <= 6; i++) {
$('h' + i + '[@id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', 'Permalink to this headline').
appendTo(this);
});
}
$('dt[@id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', 'Permalink to this definition').
appendTo(this);
});
},
/**
* workaround a firefox stupidity
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlight');
});
}, 10);
$('<li class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">Hide Search Matches</a></li>')
.appendTo($('.sidebar .this-page-menu'));
}
},
/**
* init the modindex toggle buttons
*/
initModIndex : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
console.log($('tr.cg-' + idnum).toggle());
if (src.substr(-9) == 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) {
togglers.click();
}
},
/**
* init the inline comments
*/
initComments : function() {
$('.inlinecomments div.actions').each(function() {
this.innerHTML += ' | ';
$(this).append($('<a href="#">hide comments</a>').click(function() {
$(this).parent().parent().toggle();
return false;
}));
});
$('.inlinecomments .comments').hide();
$('.inlinecomments a.bubble').each(function() {
$(this).click($(this).is('.emptybubble') ? function() {
var params = $.getQueryParameters(this.href);
Documentation.newComment(params.target[0]);
return false;
} : function() {
$('.comments', $(this).parent().parent()[0]).toggle();
return false;
});
});
$('#comments div.actions a.newcomment').click(function() {
Documentation.newComment();
return false;
});
if (document.location.hash.match(/^#comment-/))
$('.inlinecomments .comments ' + document.location.hash)
.parent().toggle();
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('.sidebar .this-page-menu li.highlight-link').fadeOut(300);
$('span.highlight').removeClass('highlight');
},
/**
* show the comment window for a certain id or the whole page.
*/
newComment : function(id) {
Documentation.CommentWindow.openFor(id || '');
},
/**
* write a new comment from within a comment view box
*/
newCommentFromBox : function(link) {
var params = $.getQueryParameters(link.href);
$(link).parent().parent().fadeOut('slow');
this.newComment(params.target);
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this == '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
},
/**
* class that represents the comment window
*/
CommentWindow : (function() {
var openWindows = {};
var Window = function(sectionID) {
this.url = Documentation.makeURL('@comments/' + Documentation.getCurrentURL()
+ '/?target=' + $.urlencode(sectionID) + '&mode=ajax');
this.sectionID = sectionID;
this.root = $('<div class="commentwindow"></div>');
this.root.appendTo($('body'));
this.title = $('<h3>New Comment</h3>').appendTo(this.root);
this.body = $('<div class="form">please wait...</div>').appendTo(this.root);
this.resizeHandle = $('<div class="resizehandle"></div>').appendTo(this.root);
this.root.Draggable({
handle: this.title[0]
});
this.root.css({
left: window.innerWidth / 2 - $(this.root).width() / 2,
top: window.scrollY + (window.innerHeight / 2 - 150)
});
this.root.fadeIn('slow');
this.updateView();
};
Window.prototype.updateView = function(data) {
var self = this;
function update(data) {
if (data.posted) {
document.location.hash = '#comment-' + data.commentID;
document.location.reload();
}
else {
self.body.html(data.body);
$('div.actions', self.body).append($('<input>')
.attr('type', 'button')
.attr('value', 'Close')
.click(function() { self.close(); })
);
$('div.actions input[@name="preview"]')
.attr('type', 'button')
.click(function() { self.submitForm($('form', self.body)[0], true); });
$('form', self.body).bind("submit", function() {
self.submitForm(this);
return false;
});
if (data.error) {
self.root.Highlight(1000, '#aadee1');
$('div.error', self.root).slideDown(500);
}
}
}
if (typeof data == 'undefined')
$.getJSON(this.url, function(json) { update(json); });
else
$.ajax({
url: this.url,
type: 'POST',
dataType: 'json',
data: data,
success: function(json) { update(json); }
});
}
Window.prototype.getFormValue = function(name) {
return $('*[@name="' + name + '"]', this.body)[0].value;
}
Window.prototype.submitForm = function(form, previewMode) {
this.updateView({
author: form.author.value,
author_mail: form.author_mail.value,
title: form.title.value,
comment_body: form.comment_body.value,
preview: previewMode ? 'yes' : ''
});
}
Window.prototype.close = function() {
var self = this;
delete openWindows[this.sectionID];
this.root.fadeOut('slow', function() {
self.root.remove();
});
}
Window.openFor = function(sectionID) {
if (sectionID in openWindows)
return openWindows[sectionID];
return new Window(sectionID);
}
return Window;
})()
};
$(document).ready(function() {
Documentation.init();
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

View File

@ -1,59 +0,0 @@
.c { color: #408090; font-style: italic } /* Comment */
.err { border: 1px solid #FF0000 } /* Error */
.k { color: #007020; font-weight: bold } /* Keyword */
.o { color: #666666 } /* Operator */
.cm { color: #408090; font-style: italic } /* Comment.Multiline */
.cp { color: #007020 } /* Comment.Preproc */
.c1 { color: #408090; font-style: italic } /* Comment.Single */
.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
.gd { color: #A00000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
.gi { color: #00A000 } /* Generic.Inserted */
.go { color: #303030 } /* Generic.Output */
.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.gt { color: #0040D0 } /* Generic.Traceback */
.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.kp { color: #007020 } /* Keyword.Pseudo */
.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.kt { color: #902000 } /* Keyword.Type */
.m { color: #208050 } /* Literal.Number */
.s { color: #4070a0 } /* Literal.String */
.na { color: #4070a0 } /* Name.Attribute */
.nb { color: #007020 } /* Name.Builtin */
.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.no { color: #60add5 } /* Name.Constant */
.nd { color: #555555; font-weight: bold } /* Name.Decorator */
.ni { color: #d55537; font-weight: bold } /* Name.Entity */
.ne { color: #007020 } /* Name.Exception */
.nf { color: #06287e } /* Name.Function */
.nl { color: #002070; font-weight: bold } /* Name.Label */
.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.nt { color: #062873; font-weight: bold } /* Name.Tag */
.nv { color: #bb60d5 } /* Name.Variable */
.ow { color: #007020; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #208050 } /* Literal.Number.Float */
.mh { color: #208050 } /* Literal.Number.Hex */
.mi { color: #208050 } /* Literal.Number.Integer */
.mo { color: #208050 } /* Literal.Number.Oct */
.sb { color: #4070a0 } /* Literal.String.Backtick */
.sc { color: #4070a0 } /* Literal.String.Char */
.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.s2 { color: #4070a0 } /* Literal.String.Double */
.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.sh { color: #4070a0 } /* Literal.String.Heredoc */
.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.sx { color: #c65d09 } /* Literal.String.Other */
.sr { color: #235388 } /* Literal.String.Regex */
.s1 { color: #4070a0 } /* Literal.String.Single */
.ss { color: #517918 } /* Literal.String.Symbol */
.bp { color: #007020 } /* Name.Builtin.Pseudo */
.vc { color: #bb60d5 } /* Name.Variable.Class */
.vg { color: #bb60d5 } /* Name.Variable.Global */
.vi { color: #bb60d5 } /* Name.Variable.Instance */
.il { color: #208050 } /* Literal.Number.Integer.Long */

View File

@ -1,16 +0,0 @@
/**
* Sphinx Doc Design -- Right Side Bar Overrides
*/
div.sphinxsidebar {
float: right;
}
div.bodywrapper {
margin: 0 230px 0 0;
}
div.inlinecomments {
right: 250px;
}

View File

@ -1,404 +0,0 @@
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, hlwords is the list of normal, unstemmed
* words. the first one is used to find the occurance, the
* latter for highlighting it.
*/
jQuery.makeSearchSummary = function(text, keywords, hlwords) {
var textLower = text.toLowerCase();
var start = 0;
$.each(keywords, function() {
var i = textLower.indexOf(this.toLowerCase());
if (i > -1) {
start = i;
}
});
start = Math.max(start - 120, 0);
var excerpt = ((start > 0) ? '...' : '') +
$.trim(text.substr(start, 240)) +
((start + 240 - text.length) ? '...' : '');
var rv = $('<div class="context"></div>').text(excerpt);
$.each(hlwords, function() {
rv = rv.highlightText(this, 'highlight');
});
return rv;
}
/**
* Porter Stemmer
*/
var PorterStemmer = function() {
var step2list = {
ational: 'ate',
tional: 'tion',
enci: 'ence',
anci: 'ance',
izer: 'ize',
bli: 'ble',
alli: 'al',
entli: 'ent',
eli: 'e',
ousli: 'ous',
ization: 'ize',
ation: 'ate',
ator: 'ate',
alism: 'al',
iveness: 'ive',
fulness: 'ful',
ousness: 'ous',
aliti: 'al',
iviti: 'ive',
biliti: 'ble',
logi: 'log'
};
var step3list = {
icate: 'ic',
ative: '',
alize: 'al',
iciti: 'ic',
ical: 'ic',
ful: '',
ness: ''
};
var c = "[^aeiou]"; // consonant
var v = "[aeiouy]"; // vowel
var C = c + "[^aeiouy]*"; // consonant sequence
var V = v + "[aeiou]*"; // vowel sequence
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
var s_v = "^(" + C + ")?" + v; // vowel in stem
this.stemWord = function (w) {
var stem;
var suffix;
var firstch;
var origword = w;
if (w.length < 3) {
return w;
}
var re;
var re2;
var re3;
var re4;
firstch = w.substr(0,1);
if (firstch == "y") {
w = firstch.toUpperCase() + w.substr(1);
}
// Step 1a
re = /^(.+?)(ss|i)es$/;
re2 = /^(.+?)([^s])s$/;
if (re.test(w)) {
w = w.replace(re,"$1$2");
}
else if (re2.test(w)) {
w = w.replace(re2,"$1$2");
}
// Step 1b
re = /^(.+?)eed$/;
re2 = /^(.+?)(ed|ing)$/;
if (re.test(w)) {
var fp = re.exec(w);
re = new RegExp(mgr0);
if (re.test(fp[1])) {
re = /.$/;
w = w.replace(re,"");
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
re2 = new RegExp(s_v);
if (re2.test(stem)) {
w = stem;
re2 = /(at|bl|iz)$/;
re3 = new RegExp("([^aeiouylsz])\\1$");
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re2.test(w)) {
w = w + "e";
}
else if (re3.test(w)) {
re = /.$/; w = w.replace(re,"");
}
else if (re4.test(w)) {
w = w + "e";
}
}
}
// Step 1c
re = /^(.+?)y$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(s_v);
if (re.test(stem)) { w = stem + "i"; }
}
// Step 2
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem)) {
w = stem + step2list[suffix];
}
}
// Step 3
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem)) {
w = stem + step3list[suffix];
}
}
// Step 4
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
re2 = /^(.+?)(s|t)(ion)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
if (re.test(stem)) {
w = stem;
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1] + fp[2];
re2 = new RegExp(mgr1);
if (re2.test(stem)) {
w = stem;
}
}
// Step 5
re = /^(.+?)e$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
re2 = new RegExp(meq1);
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {
w = stem;
}
}
re = /ll$/;
re2 = new RegExp(mgr1);
if (re.test(w) && re2.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
// and turn initial Y back to y
if (firstch == "y") {
w = firstch.toLowerCase() + w.substr(1);
}
return w;
}
}
/**
* Search Module
*/
var Search = {
init : function() {
var params = $.getQueryParameters();
if (params.q) {
var query = params.q[0];
$('input[@name="q"]')[0].value = query;
this.performSearch(query);
}
},
/**
* perform a search for something
*/
performSearch : function(query) {
// create the required interface elements
var out = $('#search-results');
var title = $('<h2>Searching</h2>').appendTo(out);
var dots = $('<span></span>').appendTo(title);
var status = $('<p style="display: none"></p>').appendTo(out);
var output = $('<ul class="search"/>').appendTo(out);
// spawn a background runner for updating the dots
// until the search has finished
var pulseStatus = 0;
function pulse() {
pulseStatus = (pulseStatus + 1) % 4;
var dotString = '';
for (var i = 0; i < pulseStatus; i++) {
dotString += '.';
}
dots.text(dotString);
if (pulseStatus > -1) {
window.setTimeout(pulse, 500);
}
};
pulse();
// stem the searchwords and add them to the
// correct list
var stemmer = new PorterStemmer();
var searchwords = [];
var excluded = [];
var hlwords = [];
var tmp = query.split(/\s+/);
for (var i = 0; i < tmp.length; i++) {
// stem the word
var word = stemmer.stemWord(tmp[i]).toLowerCase();
// select the correct list
if (word[0] == '-') {
var toAppend = excluded;
word = word.substr(1);
}
else {
var toAppend = searchwords;
hlwords.push(tmp[i].toLowerCase());
}
// only add if not already in the list
if (!$.contains(toAppend, word)) {
toAppend.push(word);
}
};
var highlightstring = '?highlight=' + $.urlencode(hlwords.join(" "));
console.debug('SEARCH: searching for:');
console.info('required: ', searchwords);
console.info('excluded: ', excluded);
// fetch searchindex and perform search
$.getJSON('searchindex.json', function(data) {
// prepare search
var filenames = data[0];
var titles = data[1]
var words = data[2];
var fileMap = {};
var files = null;
// perform the search on the required words
for (var i = 0; i < searchwords.length; i++) {
var word = searchwords[i];
// no match but word was a required one
if ((files = words[word]) == null) {
break;
}
// create the mapping
for (var j = 0; j < files.length; j++) {
var file = files[j];
if (file in fileMap) {
fileMap[file].push(word);
}
else {
fileMap[file] = [word];
}
}
}
// now check if the files are in the correct
// areas and if the don't contain excluded words
var results = [];
for (var file in fileMap) {
var valid = true;
// check if all requirements are matched
if (fileMap[file].length != searchwords.length) {
continue;
}
// ensure that none of the excluded words is in the
// search result.
for (var i = 0; i < excluded.length; i++) {
if ($.contains(words[excluded[i]] || [], file)) {
valid = false;
break;
}
}
// if we have still a valid result we can add it
// to the result list
if (valid) {
results.push([filenames[file], titles[file]]);
}
}
// delete unused variables in order to not waste
// memory until list is retrieved completely
delete filenames, titles, words, data;
// now sort the results by title
results.sort(function(a, b) {
var left = a[1].toLowerCase();
var right = b[1].toLowerCase();
return (left > right) ? -1 : ((left < right) ? 1 : 0);
});
// print the results
var resultCount = results.length;
function displayNextItem() {
// results left, load the summary and display it
if (results.length) {
var item = results.pop();
var listItem = $('<li style="display:none"></li>');
listItem.append($('<a/>').attr(
'href',
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
highlightstring).html(item[1]));
$.get('_sources/' + item[0] + '.txt', function(data) {
listItem.append($.makeSearchSummary(data, searchwords, hlwords));
output.append(listItem);
listItem.slideDown(10, function() {
displayNextItem();
});
});
}
// search finished, update title and status message
else {
pulseStatus = -1;
title.text('Search Results');
if (!resultCount) {
status.text('Your search did not match any documents. ' +
'Please make sure that all words are spelled ' +
'correctly and that you\'ve selected enough ' +
'categories.');
}
else {
status.text('Search finished, found ' + resultCount +
' page' + (resultCount != 1 ? 's' : '') +
' matching the search query.');
}
status.fadeIn(500);
}
}
displayNextItem();
});
}
}
$(document).ready(function() {
Search.init();
});

View File

@ -1,504 +0,0 @@
/**
* Alternate Sphinx design
* Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl.
*/
body {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
font-size: 14px;
letter-spacing: -0.01em;
line-height: 150%;
text-align: center;
/*background-color: #AFC1C4; */
background-color: #BFD1D4;
color: black;
padding: 0;
border: 1px solid #aaa;
margin: 0px 80px 0px 80px;
min-width: 740px;
}
a {
color: #CA7900;
text-decoration: none;
}
a:hover {
color: #2491CF;
}
pre {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;
letter-spacing: 0.015em;
padding: 0.5em;
border: 1px solid #ccc;
background-color: #f8f8f8;
}
td.linenos pre {
padding: 0.5em 0;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
cite, code, tt {
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
font-size: 0.95em;
letter-spacing: 0.01em;
}
hr {
border: 1px solid #abc;
margin: 2em;
}
tt {
background-color: #f2f2f2;
border-bottom: 1px solid #ddd;
color: #333;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
border: 0;
}
tt.descclassname {
background-color: transparent;
border: 0;
}
tt.xref {
background-color: transparent;
font-weight: bold;
border: 0;
}
a tt {
background-color: transparent;
font-weight: bold;
border: 0;
color: #CA7900;
}
a tt:hover {
color: #2491CF;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
.refcount {
color: #060;
}
dt:target,
.highlight {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
pre {
line-height: 120%;
}
pre a {
color: inherit;
text-decoration: underline;
}
.first {
margin-top: 0 !important;
}
div.document {
background-color: white;
text-align: left;
background-image: url(contents.png);
background-repeat: repeat-x;
}
/*
div.documentwrapper {
width: 100%;
}
*/
div.clearer {
clear: both;
}
div.related h3 {
display: none;
}
div.related ul {
background-image: url(navigation.png);
height: 2em;
list-style: none;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 0;
padding-left: 10px;
}
div.related ul li {
margin: 0;
padding: 0;
height: 2em;
float: left;
}
div.related ul li.right {
float: right;
margin-right: 5px;
}
div.related ul li a {
margin: 0;
padding: 0 5px 0 5px;
line-height: 1.75em;
color: #EE9816;
}
div.related ul li a:hover {
color: #3CA8E7;
}
div.body {
margin: 0;
padding: 0.5em 20px 20px 20px;
}
div.bodywrapper {
margin: 0 240px 0 0;
border-right: 1px solid #ccc;
}
div.body a {
text-decoration: underline;
}
div.sphinxsidebar {
margin: 0;
padding: 0.5em 15px 15px 0;
width: 210px;
float: right;
text-align: left;
/* margin-left: -100%; */
}
div.sphinxsidebar h4, div.sphinxsidebar h3 {
margin: 1em 0 0.5em 0;
font-size: 0.9em;
padding: 0.1em 0 0.1em 0.5em;
color: white;
border: 1px solid #86989B;
background-color: #AFC1C4;
}
div.sphinxsidebar ul {
padding-left: 1.5em;
margin-top: 7px;
list-style: none;
padding: 0;
line-height: 130%;
}
div.sphinxsidebar ul ul {
list-style: square;
margin-left: 20px;
}
p {
margin: 0.8em 0 0.5em 0;
}
p.rubric {
font-weight: bold;
}
h1 {
margin: 0;
padding: 0.7em 0 0.3em 0;
font-size: 1.5em;
color: #11557C;
}
h2 {
margin: 1.3em 0 0.2em 0;
font-size: 1.35em;
padding: 0;
}
h3 {
margin: 1em 0 -0.3em 0;
font-size: 1.2em;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
color: black!important;
}
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
display: none;
margin: 0 0 0 0.3em;
padding: 0 0.2em 0 0.2em;
color: #aaa!important;
}
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
h5:hover a.anchor, h6:hover a.anchor {
display: inline;
}
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
h5 a.anchor:hover, h6 a.anchor:hover {
color: #777;
background-color: #eee;
}
table {
border-collapse: collapse;
margin: 0 -0.5em 0 -0.5em;
}
table td, table th {
padding: 0.2em 0.5em 0.2em 0.5em;
}
div.footer {
background-color: #E3EFF1;
color: #86989B;
padding: 3px 8px 3px 0;
clear: both;
font-size: 0.8em;
text-align: right;
}
div.footer a {
color: #86989B;
text-decoration: underline;
}
div.pagination {
margin-top: 2em;
padding-top: 0.5em;
border-top: 1px solid black;
text-align: center;
}
div.sphinxsidebar ul.toc {
margin: 1em 0 1em 0;
padding: 0 0 0 0.5em;
list-style: none;
}
div.sphinxsidebar ul.toc li {
margin: 0.5em 0 0.5em 0;
font-size: 0.9em;
line-height: 130%;
}
div.sphinxsidebar ul.toc li p {
margin: 0;
padding: 0;
}
div.sphinxsidebar ul.toc ul {
margin: 0.2em 0 0.2em 0;
padding: 0 0 0 1.8em;
}
div.sphinxsidebar ul.toc ul li {
padding: 0;
}
div.admonition, div.warning {
font-size: 0.9em;
margin: 1em 0 0 0;
border: 1px solid #86989B;
background-color: #f7f7f7;
}
div.admonition p, div.warning p {
margin: 0.5em 1em 0.5em 1em;
padding: 0;
}
div.admonition pre, div.warning pre {
margin: 0.4em 1em 0.4em 1em;
}
div.admonition p.admonition-title,
div.warning p.admonition-title {
margin: 0;
padding: 0.1em 0 0.1em 0.5em;
color: white;
border-bottom: 1px solid #86989B;
font-weight: bold;
background-color: #AFC1C4;
}
div.warning {
border: 1px solid #940000;
}
div.warning p.admonition-title {
background-color: #CF0000;
border-bottom-color: #940000;
}
div.admonition ul, div.admonition ol,
div.warning ul, div.warning ol {
margin: 0.1em 0.5em 0.5em 3em;
padding: 0;
}
div.versioninfo {
margin: 1em 0 0 0;
border: 1px solid #ccc;
background-color: #DDEAF0;
padding: 8px;
line-height: 1.3em;
font-size: 0.9em;
}
a.headerlink {
color: #c60f0f!important;
font-size: 1em;
margin-left: 6px;
padding: 0 4px 0 4px;
text-decoration: none!important;
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
a.headerlink:hover {
background-color: #ccc;
color: white!important;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
form.pfform {
margin: 10px 0 20px 0;
}
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}

View File

@ -1,19 +0,0 @@
/**
* Sphinx Doc Design -- Sticky sidebar Overrides
*/
div.sphinxsidebar {
top: 30px;
left: 0px;
position: fixed;
margin: 0;
float: none;
}
div.related {
position: fixed;
}
div.documentwrapper {
margin-top: 30px;
}

View File

@ -1,700 +0,0 @@
/**
* Sphinx Doc Design -- traditional python.org style
*/
body {
color: #000;
margin: 0;
padding: 0;
}
/* :::: LAYOUT :::: */
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 230px 0 0;
}
div.body {
background-color: white;
padding: 0 20px 30px 20px;
}
div.sphinxsidebarwrapper {
border: 1px solid #99ccff;
padding: 10px;
margin: 10px 15px 10px 0;
}
div.sphinxsidebar {
float: right;
margin-left: -100%;
width: 230px;
}
div.clearer {
clear: both;
}
div.footer {
clear: both;
width: 100%;
background-color: #99ccff;
padding: 9px 0 9px 0;
text-align: center;
}
div.related {
background-color: #99ccff;
color: #333;
width: 100%;
height: 30px;
line-height: 30px;
border-bottom: 5px solid white;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
font-weight: bold;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* ::: SIDEBAR :::: */
div.sphinxsidebar h3 {
margin: 0;
}
div.sphinxsidebar h4 {
margin: 5px 0 0 0;
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
margin-left: 15px;
padding: 0;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
/* :::: SEARCH :::: */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* :::: COMMON FORM STYLES :::: */
div.actions {
border-top: 1px solid #aaa;
background-color: #ddd;
margin: 10px 0 0 -20px;
padding: 5px 0 5px 20px;
}
form dl {
color: #333;
}
form dt {
clear: both;
float: left;
min-width: 110px;
margin-right: 10px;
padding-top: 2px;
}
input#homepage {
display: none;
}
div.error {
margin: 5px 20px 0 0;
padding: 5px;
border: 1px solid #d00;
/*border: 2px solid #05171e;
background-color: #092835;
color: white;*/
font-weight: bold;
}
/* :::: INLINE COMMENTS :::: */
div.inlinecommentswrapper {
float: right;
max-width: 40%;
}
div.commentmarker {
float: right;
background-image: url(style/comment.png);
background-repeat: no-repeat;
width: 25px;
height: 25px;
text-align: center;
padding-top: 3px;
}
div.nocommentmarker {
float: right;
background-image: url(style/nocomment.png);
background-repeat: no-repeat;
width: 25px;
height: 25px;
}
div.inlinecomments {
margin-left: 10px;
margin-bottom: 5px;
background-color: #eee;
border: 1px solid #ccc;
padding: 5px;
}
div.inlinecomment {
border-top: 1px solid #ccc;
padding-top: 5px;
margin-top: 5px;
}
.inlinecomments p {
margin: 5px 0 5px 0;
}
.inlinecomments .head {
font-weight: bold;
}
.inlinecomments .meta {
font-style: italic;
}
/* :::: COMMENTS :::: */
div#comments h3 {
border-top: 1px solid #aaa;
padding: 5px 20px 5px 20px;
margin: 20px -20px 20px -20px;
background-color: #ddd;
}
/*
div#comments {
background-color: #ccc;
margin: 40px -20px -30px -20px;
padding: 0 0 1px 0;
}
div#comments h4 {
margin: 30px 0 20px 0;
background-color: #aaa;
border-bottom: 1px solid #09232e;
color: #333;
}
div#comments form {
display: block;
margin: 0 0 0 20px;
}
div#comments textarea {
width: 98%;
height: 160px;
}
div#comments div.help {
margin: 20px 20px 10px 0;
background-color: #ccc;
color: #333;
}
div#comments div.help p {
margin: 0;
padding: 0 0 10px 0;
}
div#comments input, div#comments textarea {
font-family: 'Bitstream Vera Sans', 'Arial', sans-serif;
font-size: 13px;
color: black;
background-color: #aaa;
border: 1px solid #092835;
}
div#comments input[type="reset"],
div#comments input[type="submit"] {
cursor: pointer;
font-weight: bold;
padding: 2px;
margin: 5px 5px 5px 0;
background-color: #666;
color: white;
}
div#comments div.comment {
margin: 10px 10px 10px 20px;
padding: 10px;
border: 1px solid #0f3646;
background-color: #aaa;
color: #333;
}
div#comments div.comment p {
margin: 5px 0 5px 0;
}
div#comments div.comment p.meta {
font-style: italic;
color: #444;
text-align: right;
margin: -5px 0 -5px 0;
}
div#comments div.comment h4 {
margin: -10px -10px 5px -10px;
padding: 3px;
font-size: 15px;
background-color: #888;
color: white;
border: 0;
}
div#comments div.comment pre,
div#comments div.comment tt {
background-color: #ddd;
color: #111;
border: none;
}
div#comments div.comment a {
color: #fff;
text-decoration: underline;
}
div#comments div.comment blockquote {
margin: 10px;
padding: 10px;
border-left: 1px solid #0f3646;
/*border: 1px solid #0f3646;
background-color: #071c25;*/
}
div#comments em.important {
color: #d00;
font-weight: bold;
font-style: normal;
}*/
/* :::: SUGGEST CHANGES :::: */
div#suggest-changes-box input, div#suggest-changes-box textarea {
border: 1px solid #ccc;
background-color: white;
color: black;
}
div#suggest-changes-box textarea {
width: 99%;
height: 400px;
}
/* :::: PREVIEW :::: */
div.preview {
background-image: url(style/preview.png);
padding: 0 20px 20px 20px;
margin-bottom: 30px;
}
/* :::: INDEX PAGE :::: */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.5em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
}
/* :::: GENINDEX STYLES :::: */
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
/* :::: GLOBAL STYLES :::: */
p.subhead {
font-weight: bold;
margin-top: 20px;
}
a:link:active { color: #ff0000; }
a:link:hover { background-color: #bbeeff; }
a:visited:hover { background-color: #bbeeff; }
a:visited { color: #551a8b; }
a:link { color: #0000bb; }
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: avantgarde, sans-serif;
font-weight: bold;
}
div.body h1 { font-size: 180%; }
div.body h2 { font-size: 150%; }
div.body h3 { font-size: 120%; }
div.body h4 { font-size: 120%; }
a.headerlink,
a.headerlink,
a.headerlink,
a.headerlink,
a.headerlink,
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
visibility: hidden;
}
*:hover > a.headerlink,
*:hover > a.headerlink,
*:hover > a.headerlink,
*:hover > a.headerlink,
*:hover > a.headerlink,
*:hover > a.headerlink {
visibility: visible;
}
a.headerlink:hover,
a.headerlink:hover,
a.headerlink:hover,
a.headerlink:hover,
a.headerlink:hover,
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
}
div.body td {
text-align: left;
}
ul.fakelist {
list-style: none;
margin: 10px 0 10px 20px;
padding: 0;
}
/* "Footnotes" heading */
p.rubric {
margin-top: 30px;
font-weight: bold;
}
/* "Topics" */
div.topic {
background-color: #eee;
border: 1px solid #ccc;
padding: 0 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* Admonitions */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dd {
margin-bottom: 10px;
}
div.admonition dl {
margin-bottom: 0;
}
div.admonition p {
display: inline;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
display: inline;
}
p.admonition-title:after {
content: ":";
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
table.docutils {
border: 0;
}
table.docutils td, table.docutils th {
padding: 0 8px 2px 0;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
dl {
margin-bottom: 15px;
clear: both;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.refcount {
color: #060;
}
th {
text-align: left;
padding-right: 5px;
}
pre {
font-family: monospace;
padding: 5px;
color: #00008b;
border-left: none;
border-right: none;
}
tt {
font-family: monospace;
background-color: #ecf0f3;
padding: 0 1px 0 1px;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
.footnote:target { background-color: #ffa }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
form.comment {
margin: 0;
padding: 10px 30px 10px 30px;
background-color: #eee;
}
form.comment h3 {
background-color: #326591;
color: white;
margin: -10px -30px 10px -30px;
padding: 5px;
font-size: 1.4em;
}
form.comment input,
form.comment textarea {
border: 1px solid #ccc;
padding: 2px;
font-family: sans-serif;
font-size: 13px;
}
form.comment input[type="text"] {
width: 240px;
}
form.comment textarea {
width: 100%;
height: 200px;
margin-bottom: 10px;
}
/* :::: PRINT :::: */
@media print {
div.documentwrapper {
width: 100%;
}
div.body {
margin: 0;
}
div.sphinxsidebar,
div.related,
div.footer,
div#comments div.new-comment-box,
#top-link {
display: none;
}
}

View File

@ -1,201 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/interface.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="contents.html" />
<link rel="index" title="Global index" href="" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="deluge v1.1.0 documentation" href="index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="index">Index</h1>
<a href="#_"><strong>_</strong></a> | <a href="#A"><strong>A</strong></a> | <a href="#C"><strong>C</strong></a> | <a href="#D"><strong>D</strong></a> | <a href="#F"><strong>F</strong></a> | <a href="#G"><strong>G</strong></a> | <a href="#I"><strong>I</strong></a> | <a href="#L"><strong>L</strong></a> | <a href="#O"><strong>O</strong></a> | <a href="#R"><strong>R</strong></a> | <a href="#S"><strong>S</strong></a> | <a href="#V"><strong>V</strong></a> | <a href="#W"><strong>W</strong></a>
<hr />
<h2 id="_">_</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config.__getitem__">__getitem__() (deluge.config.Config method)</a></dt>
<dt><a href="modules/config.html#deluge.config.Config.__setitem__">__setitem__() (deluge.config.Config method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="A">A</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config.apply_all">apply_all() (deluge.config.Config method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="C">C</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config">Config (class in deluge.config)</a></dt>
<dt><a href="modules/config.html#deluge.config.Config.config">config (deluge.config.Config attribute)</a></dt></dl></td><td width="33%" valign="top"><dl>
<dt><a href="modules/common.html#deluge.common.create_magnet_uri">create_magnet_uri() (in module deluge.common)</a></dt>
</dl></td></tr></table>
<h2 id="D">D</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#module-deluge.common">deluge.common (module)</a></dt>
<dt><a href="modules/config.html#module-deluge.config">deluge.config (module)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="F">F</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.fdate">fdate() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.fetch_url">fetch_url() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.fpcnt">fpcnt() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.fpeer">fpeer() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.free_space">free_space() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
<dt><a href="modules/common.html#deluge.common.fsize">fsize() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.fspeed">fspeed() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.ftime">ftime() (in module deluge.common)</a></dt>
</dl></td></tr></table>
<h2 id="G">G</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.get_default_config_dir">get_default_config_dir() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.get_default_download_dir">get_default_download_dir() (in module deluge.common)</a></dt>
<dt><a href="modules/config.html#deluge.config.Config.get_item">get_item() (deluge.config.Config method)</a></dt>
<dt><a href="modules/common.html#deluge.common.get_path_size">get_path_size() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
<dt><a href="modules/common.html#deluge.common.get_pixmap">get_pixmap() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.get_revision">get_revision() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.get_version">get_version() (in module deluge.common)</a></dt>
</dl></td></tr></table>
<h2 id="I">I</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.is_ip">is_ip() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.is_magnet">is_magnet() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
<dt><a href="modules/common.html#deluge.common.is_url">is_url() (in module deluge.common)</a></dt>
</dl></td></tr></table>
<h2 id="L">L</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config.load">load() (deluge.config.Config method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="O">O</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.open_file">open_file() (in module deluge.common)</a></dt>
<dt><a href="modules/common.html#deluge.common.open_url_in_browser">open_url_in_browser() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
<dt><a href="modules/common.html#deluge.common.osx_check">osx_check() (in module deluge.common)</a></dt>
</dl></td></tr></table>
<h2 id="R">R</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config.register_change_callback">register_change_callback() (deluge.config.Config method)</a></dt>
<dt><a href="modules/config.html#deluge.config.Config.register_set_function">register_set_function() (deluge.config.Config method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="S">S</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/config.html#deluge.config.Config.save">save() (deluge.config.Config method)</a></dt>
<dt><a href="modules/config.html#deluge.config.Config.set_item">set_item() (deluge.config.Config method)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="V">V</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.vista_check">vista_check() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
<h2 id="W">W</h2>
<table width="100%" class="indextable"><tr><td width="33%" valign="top">
<dl>
<dt><a href="modules/common.html#deluge.common.windows_check">windows_check() (in module deluge.common)</a></dt></dl></td><td width="33%" valign="top"><dl>
</dl></td></tr></table>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" /> <input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1,123 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome to deluge&#8217;s documentation! &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/interface.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="contents.html" />
<link rel="index" title="Global index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="deluge v1.1.0 documentation" href="" />
<link rel="next" title="deluge.common" href="modules/common.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="modules/common.html" title="deluge.common"
accesskey="N">next</a> |</li>
<li><a href="">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section">
<h1 id="welcome-to-deluge-s-documentation">Welcome to deluge&#8217;s documentation!<a class="headerlink" href="#welcome-to-deluge-s-documentation" title="Permalink to this headline"></a></h1>
<p>Contents:</p>
</div>
<div class="section">
<h1 id="indices-and-tables">Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><a class="reference" href="genindex.html"><em>Index</em></a></li>
<li><a class="reference" href="modindex.html"><em>Module Index</em></a></li>
<li><a class="reference" href="search.html"><em>Search Page</em></a></li>
</ul>
</div>
<div class="section">
<h1 id="modules">Modules<a class="headerlink" href="#modules" title="Permalink to this headline"></a></h1>
<ul>
<li><a class="reference" href="modules/common.html"><tt class="docutils literal"><span class="pre">deluge.common</span></tt></a></li>
</ul>
<ul>
<li><a class="reference" href="modules/config.html"><tt class="docutils literal"><span class="pre">deluge.config</span></tt></a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3>Table Of Contents</h3>
<ul>
<li><a class="reference" href="">Welcome to deluge&#8217;s documentation!</a><ul>
</ul>
</li>
<li><a class="reference" href="#indices-and-tables">Indices and tables</a></li>
<li><a class="reference" href="#modules">Modules</a><ul>
</ul>
</li>
</ul>
<h4>Next topic</h4>
<p class="topless"><a href="modules/common.html" title="next chapter"><tt class="docutils literal"><span class="pre">deluge.common</span></tt></a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/index.txt">Show Source</a></li>
</ul>
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" /> <input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="modules/common.html" title="deluge.common"
accesskey="N">next</a> |</li>
<li><a href="">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1,102 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Global Module Index &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/interface.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="contents.html" />
<link rel="index" title="Global index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="deluge v1.1.0 documentation" href="index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="global-module-index">Global Module Index</h1>
<a href="#cap-D"><strong>D</strong></a>
<hr/>
<table width="100%" class="indextable" cellspacing="0" cellpadding="2"><tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
<tr class="cap"><td></td><td><a name="cap-D"><strong>D</strong></a></td><td></td></tr><tr>
<td><img src="_static/minus.png" id="toggle-1"
class="toggler" style="display: none" /></td>
<td>
<tt class="xref">deluge</tt></td><td>
<em></em></td></tr><tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="modules/common.html#module-deluge.common"><tt class="xref">deluge.common</tt></a></td><td>
<em></em></td></tr><tr class="cg-1">
<td></td>
<td>&nbsp;&nbsp;&nbsp;
<a href="modules/config.html#module-deluge.config"><tt class="xref">deluge.config</tt></a></td><td>
<em></em></td></tr>
</table>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" /> <input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1,614 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>deluge.common &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/interface.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="../contents.html" />
<link rel="index" title="Global index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="top" title="deluge v1.1.0 documentation" href="../index.html" />
<link rel="next" title="deluge.config" href="config.html" />
<link rel="prev" title="Welcome to deluge&#8217;s documentation!" href="../index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="config.html" title="deluge.config"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../index.html" title="Welcome to deluge&#8217;s documentation!"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section">
<h1 id="module-deluge.common"><tt class="xref docutils literal"><span class="pre">deluge.common</span></tt><a class="headerlink" href="#module-deluge.common" title="Permalink to this headline"></a></h1>
<p>Common functions for various parts of Deluge to use.</p>
<dl class="function">
<dt id="deluge.common.create_magnet_uri">
<!--[deluge.common.create_magnet_uri]--><tt class="descclassname">deluge.common.</tt><tt class="descname">create_magnet_uri</tt><big>(</big><em>infohash</em>, <em>name=None</em>, <em>trackers=</em><span class="optional">[</span><span class="optional">]</span><big>)</big><a class="headerlink" href="#deluge.common.create_magnet_uri" title="Permalink to this definition"></a></dt>
<dd><p>Creates a magnet uri</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>infohash</em> &#8211; string, the info-hash of the torrent</li>
<li><em>name</em> &#8211; string, the name of the torrent (optional)</li>
<li><em>trackers</em> &#8211; list of strings, the trackers to announce to (optional)</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a magnet uri string</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fdate">
<!--[deluge.common.fdate]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fdate</tt><big>(</big><em>seconds</em><big>)</big><a class="headerlink" href="#deluge.common.fdate" title="Permalink to this definition"></a></dt>
<dd><p>Formats a date string in the form of DD/MM/YY based on the systems timezone</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>seconds</em> &#8211; float, time in seconds since the Epoch</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a string in the form of DD/MM/YY or &#8220;&#8221; if seconds &lt; 0</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fetch_url">
<!--[deluge.common.fetch_url]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fetch_url</tt><big>(</big><em>url</em><big>)</big><a class="headerlink" href="#deluge.common.fetch_url" title="Permalink to this definition"></a></dt>
<dd><p>Downloads a torrent file from a given URL and checks the file&#8217;s validity</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>url</em> &#8211; string, the url of the .torrent file to fetch</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">the filepath to the downloaded file</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fpcnt">
<!--[deluge.common.fpcnt]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fpcnt</tt><big>(</big><em>dec</em><big>)</big><a class="headerlink" href="#deluge.common.fpcnt" title="Permalink to this definition"></a></dt>
<dd><p>Formats a string to display a percentage with two decimal places</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>dec</em> &#8211; float, the ratio in the range [0.0, 1.0]</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a formatted string representing a percentage</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fpcnt</span><span class="p">(</span><span class="mf">0.9311</span><span class="p">)</span>
<span class="go">&#39;93.11%&#39;</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fpeer">
<!--[deluge.common.fpeer]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fpeer</tt><big>(</big><em>num_peers</em>, <em>total_peers</em><big>)</big><a class="headerlink" href="#deluge.common.fpeer" title="Permalink to this definition"></a></dt>
<dd><p>Formats a string to show &#8216;num_peers&#8217; (&#8216;total_peers&#8217;)</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>num_peers</em> &#8211; int, the number of connected peers</li>
<li><em>total_peers</em> &#8211; int, the total number of peers</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a formatted string: num_peers (total_peers), if total_peers &lt; 0, then it will not be shown</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fpeer</span><span class="p">(</span><span class="mf">10</span><span class="p">,</span> <span class="mf">20</span><span class="p">)</span>
<span class="go">&#39;10 (20)&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fpeer</span><span class="p">(</span><span class="mf">10</span><span class="p">,</span> <span class="o">-</span><span class="mf">1</span><span class="p">)</span>
<span class="go">&#39;10&#39;</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.free_space">
<!--[deluge.common.free_space]--><tt class="descclassname">deluge.common.</tt><tt class="descname">free_space</tt><big>(</big><em>path</em><big>)</big><a class="headerlink" href="#deluge.common.free_space" title="Permalink to this definition"></a></dt>
<dd><p>Gets the free space available at &#8216;path&#8217;</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>path</em> &#8211; string, the path to check</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">the free space at path in bytes</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">int</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fsize">
<!--[deluge.common.fsize]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fsize</tt><big>(</big><em>fsize_b</em><big>)</big><a class="headerlink" href="#deluge.common.fsize" title="Permalink to this definition"></a></dt>
<dd><p>Formats the bytes value into a string with KiB, MiB or GiB units</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>fsize_b</em> &#8211; int, the filesize in bytes</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">formatted string in KiB, MiB or GiB units</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fsize</span><span class="p">(</span><span class="mf">112245</span><span class="p">)</span>
<span class="go">&#39;109.6 KiB&#39;</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.fspeed">
<!--[deluge.common.fspeed]--><tt class="descclassname">deluge.common.</tt><tt class="descname">fspeed</tt><big>(</big><em>bps</em><big>)</big><a class="headerlink" href="#deluge.common.fspeed" title="Permalink to this definition"></a></dt>
<dd><p>Formats a string to display a transfer speed utilizing <a title="deluge.common.fsize" class="reference" href="#deluge.common.fsize"><tt class="xref docutils literal"><span class="pre">fsize()</span></tt></a></p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>bps</em> &#8211; int, bytes per second</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a formatted string representing transfer speed</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fspeed</span><span class="p">(</span><span class="mf">43134</span><span class="p">)</span>
<span class="go">&#39;42.1 KiB/s&#39;</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.ftime">
<!--[deluge.common.ftime]--><tt class="descclassname">deluge.common.</tt><tt class="descname">ftime</tt><big>(</big><em>seconds</em><big>)</big><a class="headerlink" href="#deluge.common.ftime" title="Permalink to this definition"></a></dt>
<dd><p>Formats a string to show time in a human readable form</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>seconds</em> &#8211; int, the number of seconds</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a formatted time string, will return &#8216;unknown&#8217; for values greater than 10 weeks and &#8216;Infinity&#8217; if seconds == 0</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">ftime</span><span class="p">(</span><span class="mf">23011</span><span class="p">)</span>
<span class="go">&#39;6h 23m&#39;</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_default_config_dir">
<!--[deluge.common.get_default_config_dir]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_default_config_dir</tt><big>(</big><em>filename=None</em><big>)</big><a class="headerlink" href="#deluge.common.get_default_config_dir" title="Permalink to this definition"></a></dt>
<dd><table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>filename</em> &#8211; if None, only the config path is returned, if provided, a path including the filename will be returned</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a file path to the config directory and optional filename</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_default_download_dir">
<!--[deluge.common.get_default_download_dir]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_default_download_dir</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.get_default_download_dir" title="Permalink to this definition"></a></dt>
<dd><table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">the default download directory</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">string</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_path_size">
<!--[deluge.common.get_path_size]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_path_size</tt><big>(</big><em>path</em><big>)</big><a class="headerlink" href="#deluge.common.get_path_size" title="Permalink to this definition"></a></dt>
<dd><p>Gets the size in bytes of &#8216;path&#8217;</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>path</em> &#8211; string, the path to check for size</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">the size in bytes of the path or -1 if the path does not exist</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">int</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_pixmap">
<!--[deluge.common.get_pixmap]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_pixmap</tt><big>(</big><em>fname</em><big>)</big><a class="headerlink" href="#deluge.common.get_pixmap" title="Permalink to this definition"></a></dt>
<dd><p>Provides easy access to files in the deluge/data/pixmaps folder within the Deluge egg</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>fname</em> &#8211; the filename to look for</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">a path to a pixmap file included with Deluge</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">string</p>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_revision">
<!--[deluge.common.get_revision]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_revision</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.get_revision" title="Permalink to this definition"></a></dt>
<dd><p>The svn revision of the build if available</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">the svn revision, or &#8220;&#8221;</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">string</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.get_version">
<!--[deluge.common.get_version]--><tt class="descclassname">deluge.common.</tt><tt class="descname">get_version</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.get_version" title="Permalink to this definition"></a></dt>
<dd><p>Returns the program version from the egg metadata</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">the version of Deluge</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">string</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.is_ip">
<!--[deluge.common.is_ip]--><tt class="descclassname">deluge.common.</tt><tt class="descname">is_ip</tt><big>(</big><em>ip</em><big>)</big><a class="headerlink" href="#deluge.common.is_ip" title="Permalink to this definition"></a></dt>
<dd><p>A simple test to see if &#8216;ip&#8217; is valid</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>ip</em> &#8211; string, the ip to check</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">True or False</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">bool</p>
</td>
</tr>
</tbody>
</table>
<p>** Usage **</p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_ip</span><span class="p">(</span><span class="s">&quot;127.0.0.1&quot;</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.is_magnet">
<!--[deluge.common.is_magnet]--><tt class="descclassname">deluge.common.</tt><tt class="descname">is_magnet</tt><big>(</big><em>uri</em><big>)</big><a class="headerlink" href="#deluge.common.is_magnet" title="Permalink to this definition"></a></dt>
<dd><p>A check to determine if a uri is a valid bittorrent magnet uri</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>uri</em> &#8211; string, the uri to check</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">True or False</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">bool</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_magnet</span><span class="p">(</span><span class="s">&quot;magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN&quot;</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.is_url">
<!--[deluge.common.is_url]--><tt class="descclassname">deluge.common.</tt><tt class="descname">is_url</tt><big>(</big><em>url</em><big>)</big><a class="headerlink" href="#deluge.common.is_url" title="Permalink to this definition"></a></dt>
<dd><p>A simple regex test to check if the URL is valid</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>url</em> &#8211; string, the url to test</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">True or False</p>
</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body"><p class="first last">bool</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">is_url</span><span class="p">(</span><span class="s">&quot;http://deluge-torrent.org&quot;</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</dd></dl>
<dl class="function">
<dt id="deluge.common.open_file">
<!--[deluge.common.open_file]--><tt class="descclassname">deluge.common.</tt><tt class="descname">open_file</tt><big>(</big><em>path</em><big>)</big><a class="headerlink" href="#deluge.common.open_file" title="Permalink to this definition"></a></dt>
<dd><p>Opens a file or folder using the system configured program</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>path</em> &#8211; the path to the file or folder to open</li>
</ul>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.open_url_in_browser">
<!--[deluge.common.open_url_in_browser]--><tt class="descclassname">deluge.common.</tt><tt class="descname">open_url_in_browser</tt><big>(</big><em>url</em><big>)</big><a class="headerlink" href="#deluge.common.open_url_in_browser" title="Permalink to this definition"></a></dt>
<dd><p>Opens a url in the desktop&#8217;s default browser</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>url</em> &#8211; the url to open</li>
</ul>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.osx_check">
<!--[deluge.common.osx_check]--><tt class="descclassname">deluge.common.</tt><tt class="descname">osx_check</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.osx_check" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the current platform is Mac OS X</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">True or False</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">bool</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.vista_check">
<!--[deluge.common.vista_check]--><tt class="descclassname">deluge.common.</tt><tt class="descname">vista_check</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.vista_check" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the current platform is Windows Vista</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">True or False</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">bool</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="function">
<dt id="deluge.common.windows_check">
<!--[deluge.common.windows_check]--><tt class="descclassname">deluge.common.</tt><tt class="descname">windows_check</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.common.windows_check" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the current platform is Windows</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Returns:</th><td class="field-body">True or False</td>
</tr>
<tr class="field"><th class="field-name">Return type:</th><td class="field-body">bool</td>
</tr>
</tbody>
</table>
</dd></dl>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="../index.html" title="previous chapter">Welcome to deluge&#8217;s documentation!</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="config.html" title="next chapter"><tt class="docutils literal"><span class="pre">deluge.config</span></tt></a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/modules/common.txt">Show Source</a></li>
</ul>
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" size="18" /> <input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="config.html" title="deluge.config"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../index.html" title="Welcome to deluge&#8217;s documentation!"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1,290 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>deluge.config &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/interface.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="../contents.html" />
<link rel="index" title="Global index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="top" title="deluge v1.1.0 documentation" href="../index.html" />
<link rel="prev" title="deluge.common" href="common.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="common.html" title="deluge.common"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section">
<h1 id="module-deluge.config"><tt class="xref docutils literal"><span class="pre">deluge.config</span></tt><a class="headerlink" href="#module-deluge.config" title="Permalink to this headline"></a></h1>
<p>Deluge Config Module</p>
<dl class="class">
<dt id="deluge.config.Config">
<!--[deluge.config.Config]-->class <tt class="descclassname">deluge.config.</tt><tt class="descname">Config</tt><big>(</big><em>filename</em>, <em>defaults=None</em>, <em>config_dir=None</em><big>)</big><a class="headerlink" href="#deluge.config.Config" title="Permalink to this definition"></a></dt>
<dd><p>Bases: <tt class="xref docutils literal"><span class="pre">object</span></tt></p>
<p>This class is used to access/create/modify config files</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>filename</em> &#8211; the name of the config file</li>
<li><em>defaults</em> &#8211; dictionary of default values</li>
<li><em>config_dir</em> &#8211; the path to the config directory</li>
</ul>
</td>
</tr>
</tbody>
</table>
<dl class="method">
<dt id="deluge.config.Config.__setitem__">
<!--[deluge.config.Config.__setitem__]--><tt class="descname">__setitem__</tt><big>(</big><em>key</em>, <em>value</em><big>)</big><a class="headerlink" href="#deluge.config.Config.__setitem__" title="Permalink to this definition"></a></dt>
<dd>See
<a title="deluge.config.Config.set_item" class="reference" href="#deluge.config.Config.set_item"><tt class="xref docutils literal"><span class="pre">set_item()</span></tt></a></dd></dl>
<dl class="method">
<dt id="deluge.config.Config.__getitem__">
<!--[deluge.config.Config.__getitem__]--><tt class="descname">__getitem__</tt><big>(</big><em>key</em><big>)</big><a class="headerlink" href="#deluge.config.Config.__getitem__" title="Permalink to this definition"></a></dt>
<dd>See
<a title="deluge.config.Config.get_item" class="reference" href="#deluge.config.Config.get_item"><tt class="xref docutils literal"><span class="pre">get_item()</span></tt></a></dd></dl>
<dl class="method">
<dt id="deluge.config.Config.apply_all">
<!--[deluge.config.Config.apply_all]--><tt class="descname">apply_all</tt><big>(</big><big>)</big><a class="headerlink" href="#deluge.config.Config.apply_all" title="Permalink to this definition"></a></dt>
<dd><p>Calls all set functions</p>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="s">&quot;test.conf&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&quot;test&quot;</span><span class="p">:</span> <span class="mf">5</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">cb</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">print</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="o">.</span><span class="n">register_set_function</span><span class="p">(</span><span class="s">&quot;test&quot;</span><span class="p">,</span> <span class="n">cb</span><span class="p">,</span> <span class="n">apply_now</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="o">.</span><span class="n">apply_all</span><span class="p">()</span>
<span class="go">test 5</span>
</pre></div>
</dd></dl>
<dl class="attribute">
<dt id="deluge.config.Config.config">
<!--[deluge.config.Config.config]--><tt class="descname">config</tt><a class="headerlink" href="#deluge.config.Config.config" title="Permalink to this definition"></a></dt>
<dd>The config dictionary</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.get_item">
<!--[deluge.config.Config.get_item]--><tt class="descname">get_item</tt><big>(</big><em>key</em><big>)</big><a class="headerlink" href="#deluge.config.Config.get_item" title="Permalink to this definition"></a></dt>
<dd><p>Gets the value of item &#8216;key&#8217;</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>key</em> &#8211; the item for which you want it&#8217;s value</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">the value of item &#8216;key&#8217;</p>
</td>
</tr>
<tr class="field"><th class="field-name" colspan="2">Raises KeyError:</th></tr>
<tr><td>&nbsp;</td><td class="field-body"><p class="first last">if &#8216;key&#8217; is not in the config dictionary</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="s">&quot;test.conf&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&quot;test&quot;</span><span class="p">:</span> <span class="mf">5</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="p">[</span><span class="s">&quot;test&quot;</span><span class="p">]</span>
<span class="go">5</span>
</pre></div>
</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.load">
<!--[deluge.config.Config.load]--><tt class="descname">load</tt><big>(</big><em>filename=None</em><big>)</big><a class="headerlink" href="#deluge.config.Config.load" title="Permalink to this definition"></a></dt>
<dd><p>Load a config file</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>filename</em> &#8211; if None, uses filename set in object initialization</li>
</ul>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.register_change_callback">
<!--[deluge.config.Config.register_change_callback]--><tt class="descname">register_change_callback</tt><big>(</big><em>callback</em><big>)</big><a class="headerlink" href="#deluge.config.Config.register_change_callback" title="Permalink to this definition"></a></dt>
<dd><p>Registers a callback function that will be called when a value is changed in the config dictionary</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>callback</em> &#8211; the function, callback(key, value)</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="s">&quot;test.conf&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&quot;test&quot;</span><span class="p">:</span> <span class="mf">5</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">cb</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">print</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="o">.</span><span class="n">register_change_callback</span><span class="p">(</span><span class="n">cb</span><span class="p">)</span>
</pre></div>
</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.register_set_function">
<!--[deluge.config.Config.register_set_function]--><tt class="descname">register_set_function</tt><big>(</big><em>key</em>, <em>function</em>, <em>apply_now=True</em><big>)</big><a class="headerlink" href="#deluge.config.Config.register_set_function" title="Permalink to this definition"></a></dt>
<dd><p>Register a function to be called when a config value changes</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>key</em> &#8211; the item to monitor for change</li>
<li><em>function</em> &#8211; the function to call when the value changes, f(key, value)</li>
<li><em>apply_now</em> &#8211; if True, the function will be called after it&#8217;s registered</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="s">&quot;test.conf&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s">&quot;test&quot;</span><span class="p">:</span> <span class="mf">5</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">cb</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">print</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="o">.</span><span class="n">register_set_function</span><span class="p">(</span><span class="s">&quot;test&quot;</span><span class="p">,</span> <span class="n">cb</span><span class="p">,</span> <span class="n">apply_now</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="go">test 5</span>
</pre></div>
</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.save">
<!--[deluge.config.Config.save]--><tt class="descname">save</tt><big>(</big><em>filename=None</em><big>)</big><a class="headerlink" href="#deluge.config.Config.save" title="Permalink to this definition"></a></dt>
<dd><p>Save configuration to disk</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
<li><em>filename</em> &#8211; if None, uses filename set in object initiliazation</li>
</ul>
</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="method">
<dt id="deluge.config.Config.set_item">
<!--[deluge.config.Config.set_item]--><tt class="descname">set_item</tt><big>(</big><em>key</em>, <em>value</em><big>)</big><a class="headerlink" href="#deluge.config.Config.set_item" title="Permalink to this definition"></a></dt>
<dd><p>Sets item &#8216;key&#8217; to &#8216;value&#8217; in the config dictionary, but does not allow
changing the item&#8217;s type unless it is None</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
<li><em>key</em> &#8211; string, item to change to change</li>
<li><em>value</em> &#8211; the value to change item to, must be same type as what is currently in the config</li>
</ul>
</td>
</tr>
<tr class="field"><th class="field-name" colspan="2">Raises ValueError:</th></tr>
<tr><td>&nbsp;</td><td class="field-body"><p class="first last">raised when the type of value is not the same as what is currently in the config</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Usage</strong></p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="s">&quot;test.conf&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="p">[</span><span class="s">&quot;test&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="mf">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">config</span><span class="p">[</span><span class="s">&quot;test&quot;</span><span class="p">]</span>
<span class="go">5</span>
</pre></div>
</dd></dl>
</dd></dl>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="common.html" title="previous chapter"><tt class="docutils literal docutils literal docutils literal"><span class="pre">deluge.common</span></tt></a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/modules/config.txt">Show Source</a></li>
</ul>
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" size="18" /> <input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li class="right" >
<a href="common.html" title="deluge.common"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1,87 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search &mdash; deluge v1.1.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '1.1.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/interface.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="contents" title="Global table of contents" href="contents.html" />
<link rel="index" title="Global index" href="genindex.html" />
<link rel="search" title="Search" href="" />
<link rel="top" title="deluge v1.1.0 documentation" href="index.html" />
<script type="text/javascript" src="_static/searchtools.js"></script>
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="search-documentation">Search</h1>
<p>
From here you can search these documents. Enter your search
words into the box below and click "search". Note that the search
function will automatically search for all of the words. Pages
containing less words won't appear in the result list.
</p>
<form action="" method="get">
<input type="text" name="q" value="" />
<input type="submit" value="search" />
</form>
<div id="search-results">
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="modindex.html" title="Global Module Index"
accesskey="M">modules</a> |</li>
<li><a href="index.html">deluge v1.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2008, Andrew Resch.
Last updated on Nov 06, 2008.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
</div>
</body>
</html>

View File

@ -1 +0,0 @@
[["index","modules/config","modules/common"],["Welcome to deluge&#8217;s documentation!","<tt class=\"docutils literal docutils literal\"><span class=\"pre\">deluge.config</span></tt>","<tt class=\"docutils literal docutils literal\"><span class=\"pre\">deluge.common</span></tt>"],{"is_ip":[2],"all":[1],"mib":[2],"0":[2],"get_pixmap":[2],"show":[2],"is":[1,2],"when":[1],"fpeer":[2],"invalid":[],"human":[2],"config":[0,1,2],"disk":[1],"dbu":[],"paramet":[1,2],"24":[0],"pixmap":[2],"onli":[2],"btih":[2],"ratio":[2],"monitor":[1],"easi":[2],"common":[0,2],"with":[2],"tt":[1,2],"configur":[1,2],"readabl":[2],"set_item":[1],"should":[0],"to":[0,1,2],"window":[2],"program":[2],"register_change_callback":[1],"4":[0],"bittorr":[2],"folder":[2],"save":[1],"modul":[0,1],"ip":[2],"then":[2],"file":[0,1,2],"liter":[1,2],"return":[1,2],"string":[1,2],"__getitem__":[1],"format":[2],"python":[],"show_other_dialog":[],"pixbuf":[],"initi":[1],"yy":[2],"print":[1],"if":[1,2],"127":[2],"not":[1,2],"nov":[0],"get_item":[1],"mod":[],"register_set_funct":[1],"like":[0],"docutil":[1,2],"list":[2],"magnet":[2],"mm":[2],"form":[2],"either":[],"contain":[0],"x":[2],"get_previous_config":[],"refer":[],"page":[0],"the":[0,1,2],"set":[1],"direct":[0],"percentag":[2],"displai":[2],"fspeed":[2],"delug":[0,1,2],"connect":[2],"toctre":[0],"download":[2],"logo":[],"5":[1],"config_dir":[1],"index":[0],"what":[1],"total":[2],"06":[0],"for":[1,2],"space":[2],"is_url":[2],"per":[2],"18":[0],"current":[1,2],"version":[2],"ftime":[2],"adapt":[0],"total_p":[2],"get_default_config_dir":[2],"content":[0],"su5225urmtueqldxqwrb2eqwn6kltykn":[2],"sphinx":[0],"speed":[2],"metadata":[2],"be":[1,2],"after":[1],"run":[],"kei":[1],"vista_check":[2],"usag":[1,2],"infin":[2],"free":[2],"by":[0],"__setitem__":[1],"base":[1,2],"bp":[2],"dictionari":[1],"peer":[2],"20":[2],"byte":[2],"modifi":[1],"tue":[0],"valu":[1,2],"open_url_in_brows":[2],"search":[0],"create_magnet_uri":[2],"last":[],"43134":[2],"of":[1,2],"valid":[2],"greater":[2],"fetch":[2],"prior":[],"s":[0,1,2],"109":[2],"place":[2],"data":[2],"osx_check":[2],"unknown":[2],"desktop":[2],"chang":[1],"timezon":[2],"infohash":[2],"or":[2],"load":[1],"and":[0,2],"rang":[2],"decim":[2],"within":[2],"cb":[1],"into":[2],"float":[2],"number":[2],"8217":[0],"two":[2],"filenam":[1,2],"initiliaz":[1],"num_peer":[2],"construct":[],"path":[1,2],"announc":[2],"open":[2],"your":[0],"xt":[2],"size":[2],"regex":[2],"avail":[2],"given":[2],"fetch_url":[2],"span":[1,2],"describ":[],"platform":[2],"transfer":[2],"42":[2],"regist":[1],"system":[2],"least":[0],"sinc":[2],"23011":[2],"master":[0],"9311":[2],"basic":[],"var":[],"call":[1],"type":[1,2],"valueerror":[1],"entir":[],"includ":[2],"function":[1,2],"svn":[2],"from":[2],"option":[2],"name":[1,2],"that":[1],"6h":[2],"fsize_b":[2],"6":[2],"keyerror":[1],"but":[0,1],"back":[],"part":[2],"link":[],"translat":[],"apply_al":[1],"93":[2],"an":[],"true":[1,2],"than":[2],"must":[1],"info":[2],"10":[2],"none":[1,2],"look":[2],"is_magnet":[2],"f":[1],"provid":[2],"free_spac":[2],"access":[1,2],"second":[2],"us":[1,2],"windows_check":[2],"will":[1,2],"url":[2],"fpcnt":[2],"can":[0],"fdate":[2],"dec":[2],"root":[0],"torrent":[2],"def":[1],"browser":[2],"pre":[1,2],"files":[2],"gib":[2],"hash":[2],"quickstart":[0],"creat":[0,1,2],"item":[1],"int":[2],"get_default_download_dir":[2],"dure":[],"tabl":[0],"it":[0,1,2],"indic":[0],"repres":[2],"unit":[2],"exist":[2],"at":[0,2],"conf":[1],"in":[1,2],"revis":[2],"check":[2],"as":[1],"get_vers":[2],"11":[2],"vista":[2],"variou":[2],"want":[1],"filepath":[2],"allow":[1],"get":[1,2],"fsize":[2],"same":[1],"get_revis":[2],"1":[2],"fals":[1,2],"epoch":[2],"other":[],"bool":[2],"build":[2],"fname":[2],"test":[1,2],"you":[0,1],"tracker":[2],"simpl":[2],"dd":[2],"complet":[0],"week":[2],"23m":[2],"http":[2],"dialog":[],"see":[1,2],"default":[1,2],"org":[2],"object":[1],"get_logo":[],"mac":[2],"get_config":[],"specifi":[],"thi":[0,1],"date":[2],"kib":[2],"on":[0,2],"unless":[1],"class":[1,2],"shown":[2],"welcom":[0],"a":[1,2],"util":[2],"open_fil":[2],"directori":[1,2],"os":[2],"urn":[2],"no":[],"uri":[2],"rais":[1],"doe":[1,2],"callback":[1],"which":[1],"u":[],"112245":[2],"determin":[2],"time":[2],"apply_now":[1],"2008":[0],"egg":[2],"get_path_s":[2],"document":[0]}]

View File

@ -19,16 +19,32 @@
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
class DelugeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
pass
class NoCoreError(DelugeError):
pass
class DaemonRunningError(DelugeError):
pass
class InvalidTorrentError(DelugeError):
pass
class InvalidPathError(DelugeError):
pass

227
deluge/event.py Normal file
View File

@ -0,0 +1,227 @@
#
# event.py
#
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
#
"""
Event module.
This module describes the types of events that can be generated by the daemon
and subsequently emitted to the clients.
"""
known_events = {}
class DelugeEventMetaClass(type):
"""
This metaclass simply keeps a list of all events classes created.
"""
def __init__(cls, name, bases, dct):
super(DelugeEventMetaClass, cls).__init__(name, bases, dct)
if name != "DelugeEvent":
known_events[name] = cls
class DelugeEvent(object):
"""
The base class for all events.
:prop name: this is the name of the class which is in-turn the event name
:prop args: a list of the attribute values
"""
__metaclass__ = DelugeEventMetaClass
def _get_name(self):
return self.__class__.__name__
def _get_args(self):
if not hasattr(self, "_args"):
return []
return self._args
name = property(fget=_get_name)
args = property(fget=_get_args)
class TorrentAddedEvent(DelugeEvent):
"""
Emitted when a new torrent is successfully added to the session.
"""
def __init__(self, torrent_id):
"""
:param torrent_id: str, the torrent_id of the torrent that was added
"""
self._args = [torrent_id]
class TorrentRemovedEvent(DelugeEvent):
"""
Emitted when a torrent has been removed from the session.
"""
def __init__(self, torrent_id):
"""
:param torrent_id: str, the torrent_id
"""
self._args = [torrent_id]
class PreTorrentRemovedEvent(DelugeEvent):
"""
Emitted when a torrent is about to be removed from the session.
"""
def __init__(self, torrent_id):
"""
:param torrent_id: str, the torrent_id
"""
self._args = [torrent_id]
class TorrentStateChangedEvent(DelugeEvent):
"""
Emitted when a torrent changes state.
"""
def __init__(self, torrent_id, state):
"""
:param torrent_id: str, the torrent_id
:param state: str, the new state
"""
self._args = [torrent_id, state]
class TorrentQueueChangedEvent(DelugeEvent):
"""
Emitted when the queue order has changed.
"""
pass
class TorrentFolderRenamedEvent(DelugeEvent):
"""
Emitted when a folder within a torrent has been renamed.
"""
def __init__(self, torrent_id, old, new):
"""
:param torrent_id: str, the torrent_id
:param old: str, the old folder name
:param new: str, the new folder name
"""
self._args = [torrent_id, old, new]
class TorrentFileRenamedEvent(DelugeEvent):
"""
Emitted when a file within a torrent has been renamed.
"""
def __init__(self, torrent_id, index, name):
"""
:param torrent_id: str, the torrent_id
:param index: int, the index of the file
:param name: str, the new filename
"""
self._args = [torrent_id, index, name]
class TorrentFinishedEvent(DelugeEvent):
"""
Emitted when a torrent finishes downloading.
"""
def __init__(self, torrent_id):
"""
:param torrent_id: str, the torrent_id
"""
self._args = [torrent_id]
class TorrentResumedEvent(DelugeEvent):
"""
Emitted when a torrent resumes from a paused state.
"""
def __init__(self, torrent_id):
"""
:param torrent_id: str, the torrent_id
"""
self._args = [torrent_id]
class NewVersionAvailableEvent(DelugeEvent):
"""
Emitted when a more recent version of Deluge is available.
"""
def __init__(self, new_release):
"""
:param new_release: str, the new version that is available
"""
self._args = [new_release]
class SessionStartedEvent(DelugeEvent):
"""
Emitted when a session has started. This typically only happens once when
the daemon is initially started.
"""
pass
class SessionPausedEvent(DelugeEvent):
"""
Emitted when the session has been paused.
"""
pass
class SessionResumedEvent(DelugeEvent):
"""
Emitted when the session has been resumed.
"""
pass
class ConfigValueChangedEvent(DelugeEvent):
"""
Emitted when a config value changes in the Core.
"""
def __init__(self, key, value):
"""
:param key: str, the key that changed
:param value: the new value of the `:param:key`
"""
self._args = [key, value]
class PluginEnabledEvent(DelugeEvent):
"""
Emitted when a plugin is enabled in the Core.
"""
def __init__(self, name):
"""
:param name: the plugin name
:type name: string
"""
self._args = [name]
class PluginDisabledEvent(DelugeEvent):
"""
Emitted when a plugin is disabled in the Core.
"""
def __init__(self, name):
"""
:param name: the plugin name
:type name: string
"""
self._args = [name]

122
deluge/httpdownloader.py Normal file
View File

@ -0,0 +1,122 @@
#
# httpdownloader.py
#
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
#
from twisted.web import client, http
from twisted.web.error import PageRedirect
from twisted.python.failure import Failure
from twisted.internet import reactor
class HTTPDownloader(client.HTTPDownloader):
"""
Factory class for downloading files and keeping track of progress.
"""
def __init__(self, url, filename, part_callback=None, headers=None):
"""
:param url: the url to download from
:type url: string
:param filename: the filename to save the file as
:type filename: string
:param part_callback: a function to be called when a part of data
is received, it's signature should be: func(data, current_length, total_length)
:type part_callback: function
:param headers: any optional headers to send
:type headers: dictionary
"""
self.__part_callback = part_callback
self.current_length = 0
self.value = filename
client.HTTPDownloader.__init__(self, url, filename, headers=headers)
def gotStatus(self, version, status, message):
self.code = int(status)
client.HTTPDownloader.gotStatus(self, version, status, message)
def gotHeaders(self, headers):
if self.code == http.OK:
if "content-length" in headers:
self.total_length = int(headers["content-length"][0])
else:
self.total_length = 0
elif self.code in (http.TEMPORARY_REDIRECT, http.MOVED_PERMANENTLY):
location = headers["location"][0]
error = PageRedirect(self.code, location=location)
self.noPage(Failure(error))
return client.HTTPDownloader.gotHeaders(self, headers)
def pagePart(self, data):
if self.code == http.OK:
self.current_length += len(data)
if self.__part_callback:
self.__part_callback(data, self.current_length, self.total_length)
return client.HTTPDownloader.pagePart(self, data)
def download_file(url, filename, callback=None, headers=None):
"""
Downloads a file from a specific URL and returns a Deferred. You can also
specify a callback function to be called as parts are received.
:param url: the url to download from
:type url: string
:param filename: the filename to save the file as
:type filename: string
:param callback: a function to be called when a part of data is received,
it's signature should be: func(data, current_length, total_length)
:type callback: function
:param headers: any optional headers to send
:type headers: dictionary
:returns: the filename of the downloaded file
:rtype: Deferred
:raises t.w.e.PageRedirect: when server responds with a temporary redirect
or permanently moved.
:raises t.w.e.Error: for all other HTTP response errors (besides OK)
"""
url = str(url)
filename = str(filename)
if headers:
for key, value in headers.items():
headers[str(key)] = str(value)
scheme, host, port, path = client._parse(url)
factory = HTTPDownloader(url, filename, callback, headers)
if scheme == "https":
from twisted.internet import ssl
reactor.connectSSL(host, port, factory, ssl.ClientContextFactory())
else:
reactor.connectTCP(host, port, factory)
return factory.deferred

View File

@ -1,214 +1,161 @@
deluge/error.py
deluge/common.py
deluge/rencode.py
deluge/httpdownloader.py
deluge/main.py
deluge/configmanager.py
deluge/bencode.py
deluge/__rpcapi.py
deluge/pluginmanagerbase.py
deluge/metafile.py
deluge/event.py
deluge/__init__.py
deluge/_libtorrent.py
deluge/log.py
deluge/component.py
deluge/config.py
deluge/plugins/pluginbase.py
deluge/plugins/init.py
deluge/plugins/__init__.py
deluge/plugins/execute/setup.py
deluge/plugins/execute/execute/common.py
deluge/plugins/execute/execute/core.py
deluge/plugins/execute/execute/gtkui.py
deluge/plugins/execute/execute/__init__.py
deluge/plugins/execute/execute/webui.py
deluge/plugins/execute/execute/data/execute_prefs.glade
deluge/plugins/extractor/setup.py
deluge/plugins/extractor/extractor/common.py
deluge/plugins/extractor/extractor/core.py
deluge/plugins/extractor/extractor/gtkui.py
deluge/plugins/extractor/extractor/__init__.py
deluge/plugins/extractor/extractor/webui.py
deluge/plugins/extractor/extractor/data/extractor_prefs.glade
deluge/plugins/webui/setup.py
deluge/plugins/webui/webui/common.py
deluge/plugins/webui/webui/core.py
deluge/plugins/webui/webui/gtkui.py
deluge/plugins/webui/webui/__init__.py
deluge/plugins/webui/webui/data/config.glade
deluge/plugins/scheduler/setup.py
deluge/plugins/scheduler/scheduler/common.py
deluge/plugins/scheduler/scheduler/core.py
deluge/plugins/scheduler/scheduler/gtkui.py
deluge/plugins/scheduler/scheduler/__init__.py
deluge/plugins/scheduler/scheduler/webui.py
deluge/plugins/label/setup.py
deluge/plugins/label/label/core.py
deluge/plugins/label/label/test.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/data/label_pref.glade
deluge/plugins/label/label/data/label_options.glade
deluge/plugins/label/build/lib/label/data/label_pref.glade
deluge/plugins/label/build/lib/label/data/label_options.glade
deluge/plugins/graph/build/lib/graph/data/config.glade
deluge/plugins/blocklist/build/lib/blocklist/data/blocklist_pref.glade
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
deluge/plugins/stats/build/lib/stats/data/config.glade
deluge/plugins/stats/build/lib/stats/data/tabs.glade
deluge/plugins/stats/stats/data/config.glade
deluge/plugins/stats/stats/data/tabs.glade
deluge/ui/gtkui/glade/add_torrent_dialog.glade
deluge/ui/gtkui/glade/filtertree_menu.glade
deluge/ui/gtkui/glade/torrent_menu.glade
deluge/ui/gtkui/glade/remove_torrent_dialog.glade
deluge/ui/gtkui/glade/preferences_dialog.glade
deluge/ui/gtkui/glade/edit_trackers.glade
deluge/ui/gtkui/glade/queuedtorrents.glade
deluge/ui/gtkui/glade/move_storage_dialog.glade
deluge/ui/gtkui/glade/connection_manager.glade
deluge/ui/gtkui/glade/wizard.glade
deluge/ui/gtkui/glade/create_torrent_dialog.glade
deluge/ui/gtkui/glade/dgtkpopups.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/main_window.glade
deluge/bencode.py
deluge/docs/source/conf.py
deluge/core/autoadd.py
deluge/core/preferencesmanager.py
deluge/core/filtermanager.py
deluge/core/signalmanager.py
deluge/core/torrentmanager.py
deluge/core/daemon.py
deluge/core/torrent.py
deluge/core/pluginmanager.py
deluge/core/oldstateupgrader.py
deluge/core/__init__.py
deluge/core/core.py
deluge/core/alertmanager.py
deluge/core/rpcserver.py
deluge/config.py
deluge/metafile.py
deluge/pluginmanagerbase.py
deluge/SimpleXMLRPCServer.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/test.py
deluge/plugins/label/label/gtkui/label_config.py
deluge/plugins/label/label/gtkui/sidebar_menu.py
deluge/plugins/label/label/gtkui/submenu.py
deluge/plugins/label/label/gtkui/ui.py
deluge/plugins/label/label/gtkui/sidebar_menu.py
deluge/plugins/label/label/gtkui/__init__.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/core.py
deluge/plugins/label/setup.py
deluge/plugins/corepluginbase.py
deluge/plugins/init.py
deluge/plugins/label/label/gtkui/label_config.py
deluge/plugins/blocklist/setup.py
deluge/plugins/blocklist/blocklist/webui.py
deluge/plugins/blocklist/blocklist/gtkui.py
deluge/plugins/blocklist/blocklist/ui.py
deluge/plugins/blocklist/blocklist/text.py
deluge/plugins/blocklist/blocklist/readers.py
deluge/plugins/blocklist/blocklist/peerguardian.py
deluge/plugins/blocklist/blocklist/__init__.py
deluge/plugins/blocklist/blocklist/common.py
deluge/plugins/blocklist/blocklist/detect.py
deluge/plugins/blocklist/blocklist/core.py
deluge/plugins/coreclient.py
deluge/plugins/__init__.py
deluge/plugins/webuipluginbase.py
deluge/plugins/stats/setup.py
deluge/plugins/stats/stats/webui.py
deluge/plugins/stats/stats/gtkui.py
deluge/plugins/stats/stats/test.py
deluge/plugins/stats/stats/graph.py
deluge/plugins/stats/stats/test_total.py
deluge/plugins/stats/stats/__init__.py
deluge/plugins/stats/stats/core.py
deluge/configmanager.py
deluge/plugins/blocklist/blocklist/decompressers.py
deluge/plugins/blocklist/blocklist/gtkui.py
deluge/plugins/blocklist/blocklist/__init__.py
deluge/plugins/blocklist/blocklist/webui.py
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
deluge/ui/ui.py
deluge/ui/common.py
deluge/ui/coreconfig.py
deluge/ui/countries.py
deluge/ui/tracker_icons.py
deluge/ui/client.py
deluge/ui/ui.py
deluge/ui/console/mapping.py
deluge/ui/console/colors.py
deluge/ui/console/commands/resume.py
deluge/ui/console/commands/config.py
deluge/ui/console/commands/halt.py
deluge/ui/console/commands/debug.py
deluge/ui/console/commands/__init__.py
deluge/ui/console/commands/quit.py
deluge/ui/console/commands/connect.py
deluge/ui/console/commands/pause.py
deluge/ui/console/commands/add.py
deluge/ui/console/commands/rm.py
deluge/ui/console/commands/info.py
deluge/ui/console/commands/help.py
deluge/ui/console/main.py
deluge/ui/console/__init__.py
deluge/ui/gtkui/listview.py
deluge/ui/gtkui/options_tab.py
deluge/ui/gtkui/statusbar.py
deluge/ui/gtkui/statistics_tab.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/coreconfig.py
deluge/ui/gtkui/sidebar.py
deluge/ui/gtkui/gtkui.py
deluge/ui/gtkui/aboutdialog.py
deluge/ui/gtkui/systemtray.py
deluge/ui/gtkui/dbusinterface.py
deluge/ui/gtkui/files_tab.py
deluge/ui/gtkui/menubar.py
deluge/ui/gtkui/peers_tab.py
deluge/ui/gtkui/notification.py
deluge/ui/gtkui/toolbar.py
deluge/ui/gtkui/ipcinterface.py
deluge/ui/gtkui/filtertreeview.py
deluge/ui/gtkui/queuedtorrents.py
deluge/ui/gtkui/pluginmanager.py
deluge/ui/gtkui/mainwindow.py
deluge/ui/gtkui/removetorrentdialog.py
deluge/ui/gtkui/common.py
deluge/ui/gtkui/signals.py
deluge/ui/gtkui/torrentdetails.py
deluge/ui/gtkui/__init__.py
deluge/ui/gtkui/edittrackersdialog.py
deluge/ui/gtkui/preferences.py
deluge/ui/gtkui/torrentview.py
deluge/ui/gtkui/new_release_dialog.py
deluge/ui/gtkui/connectionmanager.py
deluge/ui/gtkui/createtorrentdialog.py
deluge/ui/gtkui/details_tab.py
deluge/ui/signalreceiver.py
deluge/ui/common.py
deluge/ui/__init__.py
deluge/ui/webui/components.py
deluge/ui/webui/render.py
deluge/ui/webui/page_decorators.py
deluge/ui/webui/webui.py
deluge/ui/webui/debugerror.py
deluge/ui/webui/webserver_common.py
deluge/ui/webui/config_forms.py
deluge/ui/webui/deluge_webserver.py
deluge/ui/webui/json_api.py
deluge/ui/webui/register_menu.py
deluge/ui/webui/config_tabs_deluge.py
deluge/ui/webui/lib/webpy022/request.py
deluge/ui/webui/lib/webpy022/wsgiserver/__init__.py
deluge/ui/webui/lib/webpy022/db.py
deluge/ui/webui/lib/webpy022/template.py
deluge/ui/webui/lib/webpy022/cheetah.py
deluge/ui/webui/lib/webpy022/debugerror.py
deluge/ui/webui/lib/webpy022/http.py
deluge/ui/webui/lib/webpy022/httpserver.py
deluge/ui/webui/lib/webpy022/utils.py
deluge/ui/webui/lib/webpy022/__init__.py
deluge/ui/webui/lib/webpy022/net.py
deluge/ui/webui/lib/webpy022/wsgi.py
deluge/ui/webui/lib/webpy022/webapi.py
deluge/ui/webui/lib/webpy022/form.py
deluge/ui/webui/lib/json.py
deluge/ui/webui/lib/newforms_plus.py
deluge/ui/webui/lib/pythonize.py
deluge/ui/webui/lib/egg_render.py
deluge/ui/webui/lib/static_handler.py
deluge/ui/webui/lib/__init__.py
deluge/ui/webui/lib/web.py
deluge/ui/webui/lib/newforms_portable/django/core/__init__.py
deluge/ui/webui/lib/newforms_portable/django/core/exceptions.py
deluge/ui/webui/lib/newforms_portable/django/utils/html.py
deluge/ui/webui/lib/newforms_portable/django/utils/http.py
deluge/ui/webui/lib/newforms_portable/django/utils/encoding.py
deluge/ui/webui/lib/newforms_portable/django/utils/translation.py
deluge/ui/webui/lib/newforms_portable/django/utils/safestring.py
deluge/ui/webui/lib/newforms_portable/django/utils/__init__.py
deluge/ui/webui/lib/newforms_portable/django/utils/datastructures.py
deluge/ui/webui/lib/newforms_portable/django/utils/functional.py
deluge/ui/webui/lib/newforms_portable/django/__init__.py
deluge/ui/webui/lib/newforms_portable/forms.py
deluge/ui/webui/lib/newforms_portable/models.py
deluge/ui/webui/lib/newforms_portable/widgets.py
deluge/ui/webui/lib/newforms_portable/fields.py
deluge/ui/webui/lib/newforms_portable/__init__.py
deluge/ui/webui/lib/newforms_portable/util.py
deluge/ui/webui/lib/egg_handler.py
deluge/ui/webui/utils.py
deluge/ui/webui/pages.py
deluge/ui/webui/__init__.py
deluge/ui/webui/tests/test_all.py
deluge/ui/webui/apache.py
deluge/ui/webui/web.py
deluge/ui/webui/torrent_move.py
deluge/ui/webui/config_tabs_webui.py
deluge/ui/webui/torrent_options.py
deluge/ui/webui/torrent_add.py
deluge/ui/webui/scripts/template_strings.py
deluge/ui/webui/scripts/extract_ajax_strings.py
deluge/ui/webui/scripts/copy_icons.py
deluge/ui/webui/scripts/extract_template_strings.py
deluge/ui/null/deluge_shell.py
deluge/ui/null/__init__.py
deluge/common.py
deluge/component.py
deluge/main.py
deluge/error.py
deluge/__init__.py
deluge/tests/test_signalreceiver.py
deluge/tests/test_filters.py
deluge/tests/test_plugin_metadata.py
deluge/tests/test_tracker_icons.py
deluge/tests/test_stats.py
deluge/tests/test_client.py
deluge/log.py
deluge/xmlrpclib.py
deluge/scripts/deluge_remote.py
deluge/scripts/wiki_docgen.py
deluge/scripts/create_plugin.py
deluge/scripts/state_upgrade.py
deluge/ui/gtkui/toolbar.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/removetorrentdialog.py
deluge/ui/gtkui/status_tab.py
deluge/ui/gtkui/common.py
deluge/ui/gtkui/peers_tab.py
deluge/ui/gtkui/connectionmanager.py
deluge/ui/gtkui/systemtray.py
deluge/ui/gtkui/notification.py
deluge/ui/gtkui/new_release_dialog.py
deluge/ui/gtkui/details_tab.py
deluge/ui/gtkui/options_tab.py
deluge/ui/gtkui/torrentdetails.py
deluge/ui/gtkui/sidebar.py
deluge/ui/gtkui/edittrackersdialog.py
deluge/ui/gtkui/mainwindow.py
deluge/ui/gtkui/dialogs.py
deluge/ui/gtkui/aboutdialog.py
deluge/ui/gtkui/listview.py
deluge/ui/gtkui/createtorrentdialog.py
deluge/ui/gtkui/statusbar.py
deluge/ui/gtkui/ipcinterface.py
deluge/ui/gtkui/gtkui.py
deluge/ui/gtkui/torrentview.py
deluge/ui/gtkui/queuedtorrents.py
deluge/ui/gtkui/filtertreeview.py
deluge/ui/gtkui/__init__.py
deluge/ui/gtkui/menubar.py
deluge/ui/gtkui/files_tab.py
deluge/ui/gtkui/preferences.py
deluge/ui/gtkui/pluginmanager.py
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/torrent_menu.glade
deluge/ui/gtkui/glade/edit_trackers.glade
deluge/ui/gtkui/glade/filtertree_menu.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/dgtkpopups.glade
deluge/ui/gtkui/glade/move_storage_dialog.glade
deluge/ui/gtkui/glade/connection_manager.glade
deluge/ui/gtkui/glade/queuedtorrents.glade
deluge/ui/gtkui/glade/add_torrent_dialog.glade
deluge/ui/gtkui/glade/preferences_dialog.glade
deluge/ui/web/gen_gettext.py
deluge/ui/web/web.py
deluge/ui/web/common.py
deluge/ui/web/auth.py
deluge/ui/web/server.py
deluge/ui/web/__init__.py
deluge/ui/web/json_api.py
deluge/ui/web/pluginmanager.py
deluge/ui/console/eventlog.py
deluge/ui/console/main.py
deluge/ui/console/statusbars.py
deluge/ui/console/colors.py
deluge/ui/console/__init__.py
deluge/ui/console/screen.py
deluge/ui/console/commands/quit.py
deluge/ui/console/commands/help.py
deluge/ui/console/commands/add.py
deluge/ui/console/commands/pause.py
deluge/ui/console/commands/resume.py
deluge/ui/console/commands/halt.py
deluge/ui/console/commands/recheck.py
deluge/ui/console/commands/cache.py
deluge/ui/console/commands/connect.py
deluge/ui/console/commands/plugin.py
deluge/ui/console/commands/info.py
deluge/ui/console/commands/__init__.py
deluge/ui/console/commands/rm.py
deluge/ui/console/commands/config.py
deluge/ui/console/commands/debug.py
deluge/core/torrent.py
deluge/core/alertmanager.py
deluge/core/filtermanager.py
deluge/core/authmanager.py
deluge/core/core.py
deluge/core/preferencesmanager.py
deluge/core/torrentmanager.py
deluge/core/oldstateupgrader.py
deluge/core/__init__.py
deluge/core/rpcserver.py
deluge/core/daemon.py
deluge/core/eventmanager.py
deluge/core/pluginmanager.py
deluge/core/autoadd.py

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3125
deluge/i18n/be.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3121
deluge/i18n/bn.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

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