Compare commits

..

203 Commits

Author SHA1 Message Date
d1e6935555 Tag 1.0.4 release 2008-10-30 17:27:19 +00:00
b72ae5d5cc lt sync 2881 2008-10-30 17:23:36 +00:00
a2add60684 Tag 1.0.4 release 2008-10-30 17:06:50 +00:00
bacb57a795 Prep for release 2008-10-30 16:57:19 +00:00
45eecc5c25 lt 2879-storage cleanup and truncating files that are larger than they should be 2008-10-30 06:38:25 +00:00
8a092a2f79 lt 2876 - support for UPnP routers that don't provide a urlbase 2008-10-29 02:42:45 +00:00
12a6be4e20 Update bindings 2008-10-28 22:20:46 +00:00
bf7b9ec09f 2873 upnp fix 2008-10-28 21:37:33 +00:00
10181dc7ee update translator credits 2008-10-28 03:18:57 +00:00
30cb3673f1 update list of files for pot 2008-10-27 23:19:42 +00:00
5ce2bbcbcc lt sync 2868 2008-10-27 06:06:51 +00:00
feaee5f344 Have torrent.get_ratio return -1 when downloaded bytes is 0.
Have torrentview and statistics_tab display an infinity character when 
ratio is -1
2008-10-26 21:10:03 +00:00
97fb9f8aee Better fix for #565 2008-10-24 07:43:34 +00:00
dd86ac9bcc Fix #565 wait for the deluged process to start to prevent defunct
processes
2008-10-24 07:39:14 +00:00
1fbf983ff6 Fix #545 use proper values in ratio calculation 2008-10-23 16:52:09 +00:00
e4c72c7dce Fix #560 force an int value for global max connections 2008-10-23 16:19:28 +00:00
0c9a3751e4 Fix and clean-up os checking functions 2008-10-23 11:27:37 +00:00
0e9c61d4be Fix locale stuff on OS X 2008-10-23 08:21:25 +00:00
b5fdadc2aa Windows build system fixes 2008-10-23 08:13:08 +00:00
7d10b60811 Handle OS X better in the build system - patch from hydri 2008-10-23 08:05:02 +00:00
87e77565fc add darwin check to common 2008-10-23 07:22:08 +00:00
ce191efc54 fix problem that sometimes occured when switching back and forth between daemons without disconnecting first 2008-10-22 08:54:26 +00:00
3360c9c754 Fix the alert_type magic to work when libtorrent is not in the deluge
module
2008-10-19 05:43:58 +00:00
63c314843e lang sync 2008-10-19 00:09:47 +00:00
be2b266ba8 lt sync 2836 2008-10-18 23:57:39 +00:00
1458db6b03 Re-add "Max Connections per Second" setting 2008-10-18 23:55:27 +00:00
16ba61dbf5 Prep for release 2008-10-18 21:38:54 +00:00
46352b6f13 ly sync 2832 2008-10-18 21:22:44 +00:00
82d15c856a maid service 2008-10-17 21:42:09 +00:00
5315620ca2 lt sync 2824 - fix segfault when passing None to torrent_info() 2008-10-17 19:38:33 +00:00
40d6716e74 Remove max connections per second from config dialog. 2008-10-17 18:38:19 +00:00
efec531c75 lt sync 2823 2008-10-17 17:54:07 +00:00
cc7e6d1ff2 Deluge will now use a system libtorrent library if available. 2008-10-17 17:52:12 +00:00
e2b9d5d936 fix bad opera fix 2008-10-16 17:19:58 +00:00
5f8fef7996 changelog 2008-10-16 17:17:27 +00:00
03a37062d4 fix opera tested on 2008-10-16 17:12:22 +00:00
0534b24609 Fix IP filter 2008-10-15 23:57:03 +00:00
130d7c08a0 lt sync 2803 2008-10-15 20:55:20 +00:00
ea6a6ec9bc Use "127.0.0.1" instead of "localhost" when starting the SignalReceiver 2008-10-15 19:19:12 +00:00
d0da82de21 Change to use 'all_time_upload' and 'all_time_download' due to change
in recent libtorrent revision
2008-10-15 18:49:51 +00:00
8cc74af9c3 lt sync 2802 2008-10-15 18:45:35 +00:00
f75c0cf096 lt sync 2796 2008-10-14 16:13:23 +00:00
244ba86b8a use multithreaded ssl on windows 2008-10-11 07:30:18 +00:00
054cc120de lang sync 2008-10-11 04:45:42 +00:00
fbdb1479ad Update for release 2008-10-10 22:45:41 +00:00
ec8c45e940 Fix issue where torrents will not be properly added to the session 2008-10-10 22:01:10 +00:00
1b29b6bfc9 Updates for release 2008-10-10 05:11:46 +00:00
158bfbcb6e lt sync 2781 2008-10-10 05:00:40 +00:00
a37d739b0b Properly line wrap tracker messages 2008-10-09 07:26:48 +00:00
353795f02a Change max connections default setting to 200 2008-10-09 03:41:06 +00:00
798b27cf34 Fix freezing on start-up issues on systems that do not have a properly
configured localhost entry.
2008-10-08 13:32:02 +00:00
acd64e6381 Prevent being able to set file priorities for compactly allocated
torrents as it is not intended to work.
2008-10-08 12:42:59 +00:00
70c588dba6 lt sync 2776 2008-10-08 12:40:46 +00:00
8d10642ec7 Changed max half-open connections default limit to 8 on XP/2000 and 4 on
Vista
2008-10-07 08:54:19 +00:00
76eac8b51c Removed the 'Maximum Connections Per Second' setting and replaced it
with a default setting of 20.  This should alleviate speed issues some are 
experiencing.
2008-10-07 08:44:06 +00:00
a168265753 Update python bindings in RC branch 2008-10-07 08:42:51 +00:00
eafb404b7b Set max connections per second default to 20 since this seems to fix
the slow speed issue that some people experience.
2008-10-06 10:58:28 +00:00
fa42b06e34 lt sync 2749 2008-10-01 19:11:13 +00:00
56b806ce78 Fix add_torrent_url() to download the torrent file in a thread to
prevent the main thread from blocking and causing the daemon to freeze.
2008-10-01 18:31:55 +00:00
c2427ccb7d Prevent libtorrent from starting the default plugins and features. 2008-10-01 02:19:44 +00:00
090de9bfa8 lt sync 2744 2008-09-30 22:37:50 +00:00
cd2084b421 Improve performance of files tab by only updating when values change 2008-09-29 23:52:53 +00:00
4b5dc6bc28 Fix display of tracker error messages 2008-09-29 23:11:17 +00:00
9486b24907 Change the default max global upload slots to 4 instead of -1 since
libtorrent will automatically open more slots to meet the upload speed 
limit.
2008-09-29 19:12:27 +00:00
7ee5547066 add enable auto add checkbox 2008-09-28 00:16:01 +00:00
c432b82e69 lt sync 2726 2008-09-25 20:45:31 +00:00
26d58d4057 Fix #503 change the boost lib detection logic to first look for -mt
and if not available, fall back to regular boost lib (non-multithreaded)
2008-09-25 03:30:08 +00:00
1cf863a022 Fix #187 set a 5 second timer to save the config file after a config
value has been changed.
2008-09-25 02:11:02 +00:00
8660209d28 fix missing gtk-add 2008-09-22 21:46:11 +00:00
bbd862e086 lang updates 2008-09-21 03:06:21 +00:00
f7f00de52c lt sync 2696 2008-09-21 01:44:11 +00:00
baaafefb89 Prepping for release 2008-09-21 01:40:29 +00:00
262279b27f Fix upgrading from 0.5.x state where torrents would have no trackers 2008-09-21 01:38:43 +00:00
3c33018079 add classic tooltip 2008-09-20 21:28:55 +00:00
fb23f229fb Remove more un-used files 2008-09-20 02:25:55 +00:00
2e3a9ce28c lt sync 2690 2008-09-19 22:57:05 +00:00
a0f90acfc8 Include GeoIP database for country look-ups 2008-09-19 20:11:50 +00:00
34d34b785c lt sync 2676 2008-09-16 02:39:03 +00:00
90053270d5 Convert unicode to str before saving to config. This should fix unicode
path issues.
2008-09-15 19:50:49 +00:00
a1df9626e5 Update dates 2008-09-14 21:41:53 +00:00
84e58626a9 Workaround bad cast in listen_failed alert 2008-09-14 21:33:03 +00:00
761586b2a8 Fix setting file priorities on folders 2008-09-14 20:49:45 +00:00
57f1409a55 Only show the error when displaying the tracker_error 2008-09-14 20:31:21 +00:00
14bfebdb98 Fix move_storage when using unicode path 2008-09-14 20:16:35 +00:00
95e40aa64b Fix #475 the use of unicode paths when adding torrents 2008-09-14 20:08:19 +00:00
b246457b91 include faq 2008-09-14 19:02:06 +00:00
0c39331295 force local only 2008-09-13 23:01:53 +00:00
66c986c305 fix status bar wtf 2008-09-13 02:31:45 +00:00
ccfead4e6c fix invariant 2008-09-13 02:24:10 +00:00
88e5c07564 allow network mounts 2008-09-13 00:31:59 +00:00
40633277d8 Update changelog 2008-09-12 21:52:59 +00:00
d60c595599 up date 2008-09-10 03:59:11 +00:00
fc6edca315 Updates for RC9 2008-09-10 03:20:52 +00:00
bd8dcbce91 lt sync 2667 2008-09-07 10:44:46 +00:00
7adf503bb6 Prevent libtorrent from crashing when 'announce' is not in the tracker
url.
2008-09-07 08:46:41 +00:00
67c0069c7a Fix last by just always deleting the fastresume file before writing a
new one
2008-09-06 22:24:35 +00:00
4094601f6e fix problem with old fastresume files not being replaced causing loss of data and dont resave fastresume for seed files 2008-09-06 20:11:12 +00:00
3178582312 lt sync 2650 2008-09-01 02:02:04 +00:00
2f6d98693d add missing of last 2008-08-31 23:37:49 +00:00
1e4f53b716 add gtk stock clearing script and update glade files 2008-08-31 23:37:02 +00:00
4731d4814f Fix various issues when not using English 2008-08-31 20:20:16 +00:00
584226db96 Fix add torrent dialog closing preventing another dialog from being
shown
2008-08-28 20:42:19 +00:00
135a0ca7e9 Fix typo in [3766] 2008-08-28 04:03:39 +00:00
892e642502 lt sync 2642 2008-08-28 03:56:28 +00:00
6f7e814e76 Remove test plugin 2008-08-28 01:56:00 +00:00
39e8fd772b Have setup use boost-mt libraries if boost libs are not found 2008-08-28 01:53:17 +00:00
2a5e346313 lang sync 2008-08-27 01:17:39 +00:00
4fb8fe54c9 up version in debs 2008-08-27 01:04:41 +00:00
acf59dd287 Prep for RC8 2008-08-27 01:03:50 +00:00
f2d80343c7 Fix #453 allow showing of text in the toolbar buttons 2008-08-26 23:11:47 +00:00
f15971bdeb Fix setting file priorities on folders 2008-08-26 23:00:12 +00:00
6afe33d584 Tracker errors now change the tracker status 2008-08-26 22:38:22 +00:00
53853f043e Fix #455 force recheck on completed torrents causing crash 2008-08-26 21:34:51 +00:00
bc0612d951 lt sync 2637 2008-08-26 01:03:39 +00:00
edb60072f5 lt sync 2630 2008-08-25 16:42:22 +00:00
b1dbca37c3 Change default 'torrentfiles_location' to just the default download
directory
2008-08-25 03:26:38 +00:00
7bde1e549a translator updates 2008-08-24 10:37:15 +00:00
9e04988422 lang sync 2008-08-24 10:04:28 +00:00
cccd1b8436 Fix bug in Blocklist that prevented downloading of new file every X days 2008-08-23 13:00:35 +00:00
5f20e2139d lt sync 2626 2008-08-23 08:09:52 +00:00
ab9842e4c1 Sort filenames alphabetically in add torrent dialog 2008-08-23 03:57:37 +00:00
240c60aa74 lang updates 2008-08-22 07:57:20 +00:00
d8bdaff0cc lang updates 2008-08-22 07:56:33 +00:00
4a4ffdab63 Attempt to upgrade a 0.5.x state file to new format. 2008-08-21 20:43:01 +00:00
d83a748401 lt sync 2613 2008-08-19 07:45:23 +00:00
dac94c5038 Fix #407 possible negative ETA 2008-08-18 00:36:19 +00:00
ed5e080b6d Expand root folder in files tab by default 2008-08-17 23:31:54 +00:00
cbab9cd823 Fix not displaying file list when state changes 2008-08-17 23:24:16 +00:00
971308416b Update ChangeLog 2008-08-17 22:44:23 +00:00
8564f45e59 fix open folder/file in windows 2008-08-17 22:40:59 +00:00
6948c81d01 Fix torrentview sorting to be persistent 2008-08-17 22:26:48 +00:00
7665f5394a rc prep 2008-08-17 21:55:32 +00:00
7b31434287 Fix #415 crash when using 'config-set' with no parameters 2008-08-17 18:06:08 +00:00
bba9c1a54f Fix size units to be more accurate 2008-08-17 17:51:31 +00:00
73b3ff8a0f Fix to prevent Deluge from segfaulting when trying to autoadd an
incomplete torrent file
2008-08-17 17:27:56 +00:00
67b85a9f89 Fix properly shutting Deluge down when system shuts down 2008-08-17 04:51:28 +00:00
165b97751d Fix not showing new torrents if you don't use the All label first 2008-08-17 04:18:59 +00:00
26fc7cf13f lang updates 2008-08-17 02:58:45 +00:00
c0cced9747 Fix-up the main startup code a bit so that Windows is always logging to
a file and config folders are properly created for the daemon
2008-08-17 00:56:29 +00:00
cd391ca749 lt sync 2607 - fixes upnp 2008-08-17 00:10:56 +00:00
8ecc336152 Fix loading torrents from state when fastresume file is missing 2008-08-16 23:55:45 +00:00
9280a9609e Fix hiding the bottom pane when disabling all the tabs 2008-08-16 05:28:12 +00:00
a118d3e7d5 Improve performance of initial torrent list load 2008-08-15 03:50:25 +00:00
61b9e4ae0e Fix Vista slowness fix, by not actually changing the 'uri', but simply
replacing 'localhost' with '127.0.0.1' when creating the xmlrpc object.
2008-08-14 07:03:04 +00:00
1a9376b7ea add 'edit' tracker to edit trackers dialog 2008-08-14 01:27:23 +00:00
2edaeae60e Fix Vista slowness issue 2008-08-13 19:40:41 +00:00
01ed7d6012 Add missing file 2008-08-13 19:14:30 +00:00
3152dd1a9a cpu fix to changelog 2008-08-13 03:24:36 +00:00
560604ade9 up for release 2008-08-13 03:21:30 +00:00
766a055d65 asio changeset 48031 - cpu spike fix (hopefully) 2008-08-13 02:37:14 +00:00
073f8ff544 lt sync 2599 2008-08-12 10:16:00 +00:00
43982adc3a Fix building python bindings 2008-08-12 08:46:28 +00:00
922e34f025 lt sync 2598 2008-08-12 08:45:25 +00:00
bf69584b99 lang sync 2008-08-12 08:26:24 +00:00
470deeb8ed lang updates 2008-08-12 08:17:35 +00:00
d880015eae more gpl3 switches 2008-08-09 00:04:27 +00:00
f6b6a44d4c change copyright notices to gpl3 2008-08-08 05:59:07 +00:00
4332627a33 lang sync 2008-08-08 05:19:55 +00:00
6182d5f14b Fix homepage link in about dialog 2008-08-07 00:37:48 +00:00
40ab319f64 Fix move storage dialog when connected to a remote daemon 2008-08-05 01:17:56 +00:00
a2e0eae18a Prep for next release 2008-08-04 09:22:25 +00:00
f5b398aaea Fix changelog overwrite 2008-08-03 20:25:45 +00:00
9402ab1781 Fix drag n' drop in windows 2008-08-03 20:12:35 +00:00
e10a02b4e2 tweak alphabetical order 2008-08-03 07:17:28 +00:00
26eb9e9658 up version for rc5 2008-08-02 23:31:07 +00:00
4d1ff54c03 remove ajax_demo template 2008-08-02 10:20:32 +00:00
c861110047 add translators to credits 2008-08-02 07:19:25 +00:00
1170675310 fix libtorrent portion of license 2008-08-02 06:18:10 +00:00
7e56c5568c fix typo 2008-08-02 06:07:43 +00:00
8eb7eb7dae update control to gpl3 and copyright info 2008-08-02 06:04:53 +00:00
f23520664a revert last 2008-08-02 05:55:09 +00:00
ce638455fd add json to dependency list 2008-08-02 05:51:26 +00:00
21050caaa6 lang sync 2008-08-02 05:44:28 +00:00
325746bfa0 Fix queue order shuffling on restart 2008-08-02 04:31:30 +00:00
f853ac209b Handle shutting down more cleanly in the gtkui 2008-08-02 03:25:34 +00:00
da309c66c3 Save resume data periodically 2008-08-02 03:12:15 +00:00
897ef1135d Fix blocklist file info when no file is downloaded 2008-08-02 02:32:16 +00:00
ab89338dac Improve Blocklist preferences page 2008-07-29 08:00:50 +00:00
537c596e21 Fix deluged running with ssh X forwarding by removing the Gnome lib
import
2008-07-29 04:22:03 +00:00
d03d1f1483 Prep for RC5 2008-07-28 23:58:27 +00:00
af25aee9e2 fix process_args 2008-07-28 23:51:48 +00:00
ad6f16f69d Double-clicking on host in ConnectionManager now will connect to that
host
2008-07-28 23:38:24 +00:00
78eabc66a8 Fix signalreceiver when switching between daemons 2008-07-28 12:02:01 +00:00
feb54cd785 Fix view options to be persistent between sessions 2008-07-26 08:12:34 +00:00
c873360ca6 Fix last again 2008-07-26 04:17:43 +00:00
10ad76b2f4 Fix last 2008-07-26 04:16:56 +00:00
63ede39505 Add drag n' drop support for torrent file adding 2008-07-26 04:06:35 +00:00
f26f9c6331 Fix do not create torrentfiles folder unless 'copy_torrent_file' is True 2008-07-26 03:51:53 +00:00
2102c0b910 lang sync 2008-07-25 22:05:14 +00:00
d71b4a132e Fix displaying of torrents when language is not English 2008-07-24 05:57:00 +00:00
e3a55b8923 revert tab i18n 2008-07-23 22:27:50 +00:00
a5178a875c make tab names i18n 2008-07-23 22:07:24 +00:00
9d416efbd2 add translations to rc 2008-07-23 21:54:58 +00:00
e481be0ccd Modify files tab right-click menu behaviour to that of torrentviews 2008-07-23 02:57:16 +00:00
4abb436e34 Fix last 2008-07-22 07:27:21 +00:00
753f624805 Display 'total_wanted' instead of 'total_size' in Size column 2008-07-22 06:44:28 +00:00
063564655e Update version for next RC 2008-07-22 06:26:49 +00:00
54a3e04e26 Fix building with gcc 4.3 2008-07-22 06:26:31 +00:00
bbee37f54f Fix right-click selecting torrents. Behaviour is now similar to Nautilus. 2008-07-22 04:01:37 +00:00
ca7ad6daf3 Update 2008-07-21 09:16:49 +00:00
f4ccc4bd79 Set 'send_redundant_have' to True 2008-07-21 06:36:34 +00:00
fc717fbc0e Include LICENSE file
Change license type in setup.py to GPLv3
2008-07-21 00:58:10 +00:00
0e6f48d1de Branch off 1.0.0_RC. Trunk will now become 1.1.0. 2008-07-20 20:38:05 +00:00
696 changed files with 222870 additions and 225921 deletions

329
ChangeLog
View File

@ -1,241 +1,20 @@
=== 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 ====
* Fix issue in get_tracker_host when the torrent has no tracker
* Fix crash while trying to convert very old 0.5 config files
==== GtkUI ====
* Fix translation setting in remove torrent dialog
* Fix notification bug on startup for already finished torrents
==== AjaxUI ====
* Fix loading on iPods.
* Fix sorting on the name column.
* Add "Not Implemented" alerts to some functions.
* Improve the options tab on the Add Torrent dialog
==== ConsoleUI ====
* Fix auto-complete feature for torrents.
==== Misc ====
* Added '-s', '--set-default-ui' option to deluge
=== Deluge 1.1.0_RC3 (05 January 2009) ===
==== Core ====
* Fix applying proxy settings
* Fix the display of the tracker host when it's an IP address and not a hostname
==== GtkUI ====
* Fix folder renaming to display the change properly
* Fix seeding torrents from moving around when sorting the '#' column
==== Plugins ====
* Label: Fix move on completed
* Add 'Peer Guardian Text (GZip)' reader to the Blocklist plugin
* Apply Blocklist preferences when clicking on the buttons
=== Deluge 1.1.0_RC2 (29 December 2008) ===
==== Core ====
* Fix new version check
* Fix issue that prevented torrents from being added
==== GtkUI ====
* Fix tooltip for 'Show session speed in titlebar' option
==== Plugins ====
* Remove Stats plugin since it wasn't intended to be in this release
* Fix never-ending import in Blocklist on Windows
==== Windows ====
* Fix double-click association on Windows
* Fix Pidgin icon interference
=== Deluge 1.1.0_RC1 (23 December 2008) ===
==== 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
* Basic authentication for remote access to daemon, see: http://dev.deluge-torrent.org/wiki/Authentication
==== 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
==== Web UI ====
* 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".
=== Deluge 1.0.7 (10 December 2008) ===
==== GtkUI ====
* Fix #636 not setting the daemon's config directory when using --config= with the UI in classic mode.
* Fix some minor bugs in Connection Manager
==== Debian ====
* Fix #571 notification-daemon-xfce dependency circle
==== Misc ====
* Fix #547 add description to name field per HIG entry 2.1.1.1
* libtorrent updates
==== Plugins ====
* Point default blocklist url to our server and up interval to 4 days
=== Deluge 1.0.6 (01 December 2008) ===
==== Core ====
* Fix #475 catch unicode decoding errors
* Add an option to not include IP overhead in rate limiting (this is equivalent
to how 0.5.x behaves)
* Have default blocklist url point to our server
==== GtkUI ====
* Display the proper downloaded value in the statistics tab
==== Windows ====
* Fix broken graphic in new release dialog
=== Deluge 1.0.5 (09 November 2008) ===
==== GtkUI ====
* Increase the per-torrent stop share ratio max to 99999.0
* Fix #528 make sure gtkui config file is written before exiting
* Fix UDP tracker support
==== Web UI ====
* Javascript auto refresh for both templates.
==== Windows ====
* Fix #577 adding torrents by drag n' drop
* Fix association in Vista
* Fix WebUI launch
==== Debian ====
* SID packages now requires Boost 1.36
==== Ubuntu ====
* Jaunty packages are now provided
=== Deluge 1.0.4 (31 October 2008) ===
==== Core ====
Deluge 1.0.4 (31 October 2008)
Core:
* Fix #560 force an int value for global max connections
* Fix #545 use proper values in ratio calculation
* Fix UPnP again..
==== GtkUI ====
GtkUI:
* Fix #565 wait for the deluged process to start to prevent defunct processes
==== OS X ====
OS X:
* Fix issues with gettext
==== Windows ====
Windows:
* Fix starting on non-English versions of Windows
=== Deluge 1.0.3 (18 October 2008) ===
==== Core ====
Deluge 1.0.3 (18 October 2008)
Core:
* Fix upnp - it should work on more routers now too
* Fix issue where Deluge would send improper stats to the tracker after a
pause/resume.
@ -243,23 +22,23 @@
would cause the torrent to be rechecked on every startup.
* Fix ip filtering
==== GtkUI ====
GtkUI:
* Re-add the "Max Connections Per Second" option with a default setting of 20
==== WebUI ====
WebUI:
* Fix White template for Opera
==== Misc ====
Misc:
* Deluge will now use a system libtorrent library if available.
* The build system will no longer build libtorrent if a system library is
detected.
=== Deluge 1.0.2 (10 October 2008) ===
==== Core ====
Deluge 1.0.2 (10 October 2008)
Core:
* Fix issue where torrents will not be properly added to the session
=== Deluge 1.0.1 (10 October 2008) ===
==== Core ====
Deluge 1.0.1 (10 October 2008)
Core:
* Change the default max global upload slots to 4 instead of -1 since libtorrent
will automatically open more slots to meet the upload speed limit.
* Fix display of tracker error messages
@ -276,57 +55,57 @@
* Fix issue with invalid bencoding from some trackers
* Plenty of libtorrent updates that should improve core stability
==== GtkUI ====
GtkUI:
* Improve performance of files tab by only updating when values change
==== Misc ====
Misc:
* Fix #187 set a 5 second timer to save the config file after a config value
has been changed.
* Fix #503 change the boost lib detection logic to first look for -mt and
if not available, fall back to regular boost lib (non-multithreaded)
==== WebUI ====
WebUI:
* Add enable "Auto Add" checkbox
=== Deluge 1.0.0 - "Sharks Are Bulletproof" (21 September 2008) ===
==== Core ====
Deluge 1.0.0 - "Sharks Are Bulletproof" (21 September 2008)
Core:
* Include GeoIP database for country look-ups
* Fix upgrading from 0.5.x state where torrents would have no trackers
=== Deluge 0.9.09 - "1.0.0_RC9" (15 September 2008) ===
==== Core ====
Deluge 0.9.09 - "1.0.0_RC9" (15 September 2008)
Core:
* Bug fixes in libtorrent including a crash when the tracker doesn't
have 'announce' in it's url.
* Fix fastresume issue causing loss of data by deleting the fastresume file
before writing a new one
* Fix #475 the use of unicode paths when adding torrents
==== GtkUI ====
GtkUI:
* Fix add torrent dialog closing preventing another dialog from being shown
* Fix various issues when not using English
* Fix setting file priorities on folders
=== Deluge 0.9.08 - "1.0.0_RC8" (27 August 2008) ===
==== Core ====
Deluge 0.9.08 - "1.0.0_RC8" (27 August 2008)
Core:
* Attempt to automatically upgrade a 0.5.x state file to new format
* Tracker errors now change the tracker status
==== Plugins ====
Plugins:
* Fix bug in Blocklist that prevented downloading a new file every X days
==== GtkUI ====
GtkUI:
* Sort filenames alphabetically in add torrent dialog
* Fix setting file priorities on folders
* Fix #453 allow showing of text in the toolbar buttons
=== Deluge 0.9.07 - "1.0.0_RC7" (18 August 2008) ===
==== Core ====
Deluge 0.9.07 - "1.0.0_RC7" (18 August 2008)
Core:
* Fix loading torrents from state when fastresume file is missing
* Fix UPnP
* Fix to prevent Deluge from segfaulting when trying to autoadd an incomplete torrent file
* Fix #407 possible negative ETA
==== GtkUI ====
GtkUI:
* Add 'edit' to edit trackers dialog
* Improve performance of initial torrent list load
* Fix hiding the bottom pane when disabling all the tabs
@ -336,45 +115,45 @@
* Fix not displaying file list when state changes
* Expand root folder in files tab by default
==== Null ====
Null:
* Fix #415 crash when using 'config-set' with no parameters
==== Windows ====
Windows:
* Fix Vista slowness issue
* Fix properly shutting Deluge down when system shuts down
* Fix opening folders/files
=== Deluge 0.9.06 - "1.0.0_RC6" (13 August 2008) ===
==== Core ====
Deluge 0.9.06 - "1.0.0_RC6" (13 August 2008)
Core:
* Fix CPU spikes
==== GtkUI ====
GtkUI:
* Fix move storage dialog when connected to a remote daemon
=== Deluge 0.9.05 - "1.0.0_RC5" (04 August 2008) ===
==== Core ====
Deluge 0.9.05 - "1.0.0_RC5" (04 August 2008)
Core:
* Fix deluged running with ssh X forwarding by removing the Gnome lib import
* Save resume data periodically to help prevent data loss
* Fix queue order shuffling on restart
==== GtkUI ====
GtkUI:
* Handle shutting down more cleanly
* Add translators to credits
==== Plugins ====
Plugins:
* Improve the Blocklist plugin preferences page.
==== Windows ====
Windows:
* Fix drag n' drop support
=== Deluge 0.9.04 - "1.0.0_RC4" (29 July 2008) ===
==== Core ====
Deluge 0.9.04 - "1.0.0_RC4" (29 July 2008)
Core:
* Fix building with gcc 4.3
* Fix do not create torrentfiles folder unless 'copy_torrent_file' is True
==== GtkUI ====
GtkUI:
* Add drag n' drop support for adding .torrent files
* Double-clicking on host in Connection Manager now will connect to that host
* Double-clicking on host in ConnectionManager now will connect to that host
* Fix selecting torrents when right-clicking on them in torrentview and filestab
* Fix new release check
* Display 'total_wanted' instead of 'total_size' in Size column
@ -382,39 +161,39 @@
* Fix the view options to be persistent between sessions
* Fix signalreceiver when switching between daemons
=== Deluge 0.9.03 - "1.0.0_RC3" (21 July 2008) ===
==== Core ====
Deluge 0.9.03 - "1.0.0_RC3" (21 July 2008)
Core:
* File progress fixes from libtorrent
* Fix building on FreeBSD
* Fix #350 stop seeds when stop ratio is reached
* Fix #358 properly emit torrent_removed signal when remove_at_ratio happens
==== UI ====
UI:
* Default to gtkui when running 'deluge' instead of defaulting to last used.
==== GtkUI ====
GtkUI:
* Fix open folder
* Fix #349 tab ordering when hiding/showing
==== Windows ====
Windows:
* Fix torrent file association and adding files from command line
==== Plugins ====
Plugins:
* Blocklist plugin has been rewritten
==== Misc ====
Misc:
* Some changes for python 2.6 compatibility
=== Deluge 0.9.02 - "1.0.0_RC2" (15 July 2008) ===
==== Core ====
Deluge 0.9.02 - "1.0.0_RC2" (15 July 2008)
Core:
* Fix displaying of file progress
* Fix files to have proper read/write permissions
==== WebUI ====
WebUI:
* Include missing 'classic' template
* Update options tab to include queue settings
==== Windows ====
Windows:
* Fix displaying of tray icon
* Fix scrolling of tray menu
* Fix hiding of tray icon when shutting down

20
README
View File

@ -10,16 +10,6 @@ Authors:
Homepage: http://deluge-torrent.org
==========================
License
==========================
Deluge is under the GNU GPLv3 license.
Icon data/pixmaps/deluge.svg and derivatives in data/icons are copyright
Andrew Wedderburn and are under the GNU GPLv3.
All other icons in data/pixmaps are copyright Andrew Resch and are under
the GNU GPLv3.
==========================
Contact/Support:
==========================
@ -34,7 +24,7 @@ We have two options available for support:
Installation Instructions:
==========================
First, make sure you have the proper build dependencies installed. On a normal
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 \
@ -69,11 +59,11 @@ 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 ?
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
@ -81,10 +71,10 @@ How do I start the daemon with logging to console ?
deluged -d
I can't connect to the daemon from another machine
I can't connect to the daemon from another machine
* Configure the daemon to allow remote connections
* Restart the daemon.
* Restart the daemon.
Note: do not do this on a public ip , use the webui for unsecure networks.

6
debian/changelog vendored
View File

@ -1,5 +1,5 @@
deluge-torrent (1.1.2-1) unstable; urgency=low
deluge-torrent (1.0.4-1) unstable; urgency=low
* 1.1.2 final
* 1.0.4
-- Andrew Resch (andar) <andrewresch@gmail.com> Sat, 31 Jan 2008 16:31:14 -0800
-- Andrew Resch (andar) <andrewresch@gmail.com> Fri, 31 Oct 2008 02:10:00 -0000

2
debian/control vendored
View File

@ -7,7 +7,7 @@ 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, python-pkg-resources
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools
Conflicts: deluge-torrent-common
Replaces: deluge-torrent-common
Description: A Bittorrent client written in Python/PyGTK

View File

@ -7,7 +7,7 @@ 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
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon, 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+.
.

View File

@ -2,12 +2,12 @@ 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
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
Depends: ${shlibs:Depends}, ${python:Depends}, python-gtk2, python-glade2, python-xdg, python-notify, notification-daemon, 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+.
.

19
debian/control.ubuntu-gutsy vendored Normal file
View File

@ -0,0 +1,19 @@
Source: deluge-torrent
Section: universe/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, 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/

19
debian/control.ubuntu-hardy vendored Normal file
View File

@ -0,0 +1,19 @@
Source: deluge-torrent
Section: universe/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, 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/

3
debian/manpages vendored
View File

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

1
debian/pyversions.debian-lenny vendored Normal file
View File

@ -0,0 +1 @@
2.5

1
debian/pyversions.debian-sid vendored Normal file
View File

@ -0,0 +1 @@
2.5

75
debian/rules.debian-lenny vendored Executable file
View File

@ -0,0 +1,75 @@
#!/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.4
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

75
debian/rules.debian-sid vendored Executable file
View File

@ -0,0 +1,75 @@
#!/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.4
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

75
debian/rules.ubuntu-gutsy vendored Executable file
View File

@ -0,0 +1,75 @@
#!/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

75
debian/rules.ubuntu-hardy vendored Executable file
View File

@ -0,0 +1,75 @@
#!/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,129 +0,0 @@
# 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
# for the specific language governing rights and limitations under the
# License.
# 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)
n = int(x[f:newf])
if x[f] == '-':
if x[f + 1] == '0':
raise ValueError
elif x[f] == '0' and newf != f+1:
raise ValueError
return (n, newf+1)
def decode_string(x, f):
colon = x.index(':', f)
n = int(x[f:colon])
if x[f] == '0' and colon != f+1:
raise ValueError
colon += 1
return (x[colon:colon+n], colon+n)
def decode_list(x, f):
r, f = [], f+1
while x[f] != 'e':
v, f = decode_func[x[f]](x, f)
r.append(v)
return (r, f + 1)
def decode_dict(x, f):
r, f = {}, f+1
while x[f] != 'e':
k, f = decode_string(x, f)
r[k], f = decode_func[x[f]](x, f)
return (r, f + 1)
decode_func = {}
decode_func['l'] = decode_list
decode_func['d'] = decode_dict
decode_func['i'] = decode_int
decode_func['0'] = decode_string
decode_func['1'] = decode_string
decode_func['2'] = decode_string
decode_func['3'] = decode_string
decode_func['4'] = decode_string
decode_func['5'] = decode_string
decode_func['6'] = decode_string
decode_func['7'] = decode_string
decode_func['8'] = decode_string
decode_func['9'] = decode_string
def bdecode(x):
try:
r, l = decode_func[x[0]](x, 0)
except (IndexError, KeyError, ValueError):
raise Exception("not a valid bencoded string")
return r
from types import StringType, IntType, LongType, DictType, ListType, TupleType
class Bencached(object):
__slots__ = ['bencoded']
def __init__(self, s):
self.bencoded = s
def encode_bencached(x,r):
r.append(x.bencoded)
def encode_int(x, r):
r.extend(('i', str(x), 'e'))
def encode_bool(x, r):
if x:
encode_int(1, r)
else:
encode_int(0, r)
def encode_string(x, r):
r.extend((str(len(x)), ':', x))
def encode_list(x, r):
r.append('l')
for i in x:
encode_func[type(i)](i, r)
r.append('e')
def encode_dict(x,r):
r.append('d')
ilist = x.items()
ilist.sort()
for k, v in ilist:
r.extend((str(len(k)), ':', k))
encode_func[type(v)](v, r)
r.append('e')
encode_func = {}
encode_func[Bencached] = encode_bencached
encode_func[IntType] = encode_int
encode_func[LongType] = encode_int
encode_func[StringType] = encode_string
encode_func[ListType] = encode_list
encode_func[TupleType] = encode_list
encode_func[DictType] = encode_dict
try:
from types import BooleanType
encode_func[BooleanType] = encode_bool
except ImportError:
pass
def bencode(x):
r = []
encode_func[type(x)](x, r)
return ''.join(r)

View File

@ -1,32 +1,39 @@
#
# common.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <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.
"""Common functions for various parts of Deluge to use."""
import os
import time
import subprocess
import platform
@ -72,23 +79,10 @@ FILE_PRIORITY = {
}
def get_version():
"""
Returns the program version from the egg metadata
:returns: the version of Deluge
:rtype: string
"""
return pkg_resources.require("Deluge")[0].version
"""Returns the program version from the egg metadata"""
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")))
@ -96,15 +90,12 @@ def get_revision():
f.close()
except IOError, e:
pass
return revision
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
:returns: a file path to the config directory and optional filename
:rtype: string
""" Returns the config path if no filename is specified
Returns the config directory + filename as a path if filename is specified
"""
if windows_check():
if filename:
@ -118,101 +109,165 @@ def get_default_config_dir(filename=None):
return xdg.BaseDirectory.save_config_path("deluge")
def get_default_download_dir():
"""
:returns: the default download directory
:rtype: string
"""
"""Returns the default download directory"""
if windows_check():
return os.path.expanduser("~")
else:
return os.environ.get("HOME")
def windows_check():
"""
Checks if the current platform is Windows
:returns: True or False
:rtype: bool
"""
"""Checks if the current platform is Windows. Returns True if it is Windows
and False if not."""
return platform.system() in ('Windows', 'Microsoft')
def vista_check():
"""
Checks if the current platform is Windows Vista
:returns: True or False
:rtype: bool
"""
return platform.release() == "Vista"
def osx_check():
"""
Checks if the current platform is Mac OS X
:returns: True or False
:rtype: bool
"""
return platform.system() == "Darwin"
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
:returns: a path to a pixmap file included with Deluge
:rtype: string
"""
"""Returns a pixmap file included with deluge"""
return pkg_resources.resource_filename("deluge", os.path.join("data", \
"pixmaps", fname))
def get_logo(size):
"""Returns a deluge logo pixbuf based on the size parameter."""
import gtk
if windows_check():
return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.png"), \
size, size)
else:
return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.svg"), \
size, size)
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
"""
"""Opens a file or folder."""
if windows_check():
os.startfile("%s" % path)
else:
subprocess.Popen(["xdg-open", "%s" % path])
def open_url_in_browser(url):
"""
Opens a url in the desktop's default browser
"""Opens link in the desktop's default browser"""
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 gobject
gobject.idle_add(start_browser)
:param url: the url to open
"""
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()
def build_menu_radio_list(value_list, callback, pref_value=None,
suffix=None, show_notset=False, notset_label=None, notset_lessthan=0,
show_other=False, show_activated=False, activated_label=None):
# Build a menu with radio menu items from a list and connect them to
# the callback. The pref_value is what you would like to test for the
# default active radio item.
import gtk
if notset_label is None:
notset_label = _("Unlimited")
if activated_label is None:
activated_label = _("Activated")
menu = gtk.Menu()
group = None
if show_activated is False:
if pref_value > -1 and pref_value not in value_list:
value_list.pop()
value_list.append(pref_value)
for value in sorted(value_list):
if suffix != None:
menuitem = gtk.RadioMenuItem(group, str(value) + " " + \
suffix)
else:
menuitem = gtk.RadioMenuItem(group, str(value))
group = menuitem
if value == pref_value and pref_value != None:
menuitem.set_active(True)
if callback != None:
menuitem.connect("toggled", callback)
menu.append(menuitem)
if show_activated is True:
for value in sorted(value_list):
menuitem = gtk.RadioMenuItem(group, str(activated_label))
group = menuitem
if value == pref_value and pref_value != None:
menuitem.set_active(True)
if callback != None:
menuitem.connect("toggled", callback)
menu.append(menuitem)
if show_notset:
menuitem = gtk.RadioMenuItem(group, notset_label)
menuitem.set_name(notset_label)
if pref_value < notset_lessthan and pref_value != None:
menuitem.set_active(True)
if show_activated and pref_value == 1:
menuitem.set_active(True)
menuitem.connect("toggled", callback)
menu.append(menuitem)
# Add the Other... menuitem
if show_other is True:
menuitem = gtk.SeparatorMenuItem()
menu.append(menuitem)
menuitem = gtk.MenuItem(_("Other..."))
menuitem.set_name(_("Other..."))
menuitem.connect("activate", callback)
menu.append(menuitem)
return menu
def show_other_dialog(string, default=None):
"""Shows a dialog to get an 'other' speed and return the value"""
import gtk
import gtk.glade
dialog_glade = gtk.glade.XML(
pkg_resources.resource_filename("deluge.ui.gtkui",
"glade/dgtkpopups.glade"))
speed_dialog = dialog_glade.get_widget("speed_dialog")
spin_title = dialog_glade.get_widget("spin_title")
spin_title.set_text(_("%s" % string))
spin_speed = dialog_glade.get_widget("spin_speed")
if default != None:
spin_speed.set_value(default)
spin_speed.select_region(0, -1)
response = speed_dialog.run()
if response == 1: # OK Response
value = spin_speed.get_value()
else:
speed_dialog.destroy()
return None
speed_dialog.destroy()
return value
## Formatting text functions
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
:returns: formatted string in KiB, MiB or GiB units
:rtype: string
**Usage**
>>> fsize(112245)
'109.6 KiB'
"""Returns formatted string describing filesize
fsize_b should be in bytes
Returned value will be in either KiB, MiB, or GiB
"""
fsize_kb = fsize_b / 1024.0
if fsize_kb < 1024:
@ -224,154 +279,52 @@ def fsize(fsize_b):
return "%.1f GiB" % fsize_gb
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]
:returns: a formatted string representing a percentage
:rtype: string
**Usage**
>>> fpcnt(0.9311)
'93.11%'
"""
"""Returns a formatted string representing a percentage"""
return '%.2f%%' % (dec * 100)
def fspeed(bps):
"""
Formats a string to display a transfer speed utilizing :func:`fsize`
:param bps: int, bytes per second
:returns: a formatted string representing transfer speed
:rtype: string
**Usage**
>>> fspeed(43134)
'42.1 KiB/s'
"""
"""Returns a formatted string representing transfer speed"""
return '%s/s' % (fsize(bps))
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
:returns: a formatted string: num_peers (total_peers), if total_peers < 0, then it will not be shown
:rtype: string
**Usage**
>>> fpeer(10, 20)
'10 (20)'
>>> fpeer(10, -1)
'10'
"""
"""Returns a formatted string num_peers (total_peers)"""
if total_peers > -1:
return "%d (%d)" % (num_peers, total_peers)
else:
return "%d" % num_peers
def ftime(seconds):
"""
Formats a string to show time in a human readable form
:param seconds: int, the number of seconds
:returns: a formatted time string, will return '' if seconds == 0
:rtype: string
**Usage**
>>> ftime(23011)
'6h 23m'
"""
"""Returns a formatted time string"""
if seconds == 0:
return ""
return "Infinity"
if seconds < 60:
return '%ds' % (seconds)
minutes = seconds / 60
seconds = seconds % 60
if minutes < 60:
seconds = seconds % 60
return '%dm %ds' % (minutes, seconds)
hours = minutes / 60
minutes = minutes % 60
if hours < 24:
minutes = minutes % 60
return '%dh %dm' % (hours, minutes)
days = hours / 24
hours = hours % 24
if days < 7:
hours = hours % 24
return '%dd %dh' % (days, hours)
weeks = days / 7
if weeks < 52:
days = days % 7
days = days % 7
if weeks < 10:
return '%dw %dd' % (weeks, days)
years = weeks / 52
weeks = weeks % 52
return '%dy %dw' % (years, weeks)
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
:returns: a string in the locale's date representation or "" if seconds < 0
:rtype: string
"""
if seconds < 0:
return ""
return time.strftime("%x", time.localtime(seconds))
return 'unknown'
def is_url(url):
"""
A simple regex test to check if the URL is valid
:param url: string, the url to test
:returns: True or False
:rtype: bool
**Usage**
>>> is_url("http://deluge-torrent.org")
True
"""
"""A simple regex test to check if the URL is valid."""
import re
return bool(re.search('^(https?|ftp|udp)://', url))
def is_magnet(uri):
"""
A check to determine if a uri is a valid bittorrent magnet uri
:param uri: string, the uri to check
:returns: True or False
:rtype: bool
**Usage**
>>> is_magnet("magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN")
True
"""
if uri[:20] == "magnet:?xt=urn:btih:":
return True
return False
return bool(re.search('^(https?|ftp)://', url))
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
:returns: the filepath to the downloaded file
:rtype: string
"""
"""Downloads a torrent file from a given
URL and checks the file's validity."""
import urllib
from deluge.log import LOG as log
try:
@ -385,95 +338,19 @@ def fetch_url(url):
else:
log.debug("URL doesn't appear to be a valid torrent file: %s", url)
return None
def pythonize(var):
"""Translates DBUS types back to basic Python types."""
if isinstance(var, list):
return [pythonize(value) for value in var]
if isinstance(var, tuple):
return tuple([pythonize(value) for value in var])
if isinstance(var, dict):
return dict(
[(pythonize(key), pythonize(value)) for key, value in var.iteritems()]
)
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)
:returns: a magnet uri string
:rtype: string
"""
from base64 import b32encode
uri = "magnet:?xt=urn:btih:" + b32encode(infohash.decode("hex"))
if name:
uri = uri + "&dn=" + name
if trackers:
for t in trackers:
uri = uri + "&tr=" + t
return uri
def get_path_size(path):
"""
Gets the size in bytes of 'path'
:param path: string, the path to check for size
:returns: the size in bytes of the path or -1 if the path does not exist
:rtype: int
"""
if not os.path.exists(path):
return -1
if os.path.isfile(path):
return os.path.getsize(path)
dir_size = 0
for (p, dirs, files) in os.walk(path):
for file in files:
filename = os.path.join(p, file)
dir_size += os.path.getsize(filename)
return dir_size
def free_space(path):
"""
Gets the free space available at 'path'
:param path: string, the path to check
:returns: the free space at path in bytes
:rtype: int
"""
if windows_check():
import win32api
drive = path.split(":")[0]
free = win32api.GetDiskFreeSpaceEx(drive)[0]
return free
else:
disk_data = os.statvfs(path)
block_size = disk_data.f_bsize
return disk_data.f_bavail * block_size
def is_ip(ip):
"""
A simple test to see if 'ip' is valid
:param ip: string, the ip to check
:returns: True or False
:rtype: bool
** Usage **
>>> is_ip("127.0.0.1")
True
"""
import socket
#first we test ipv4
try:
if socket.inet_pton(socket.AF_INET, "%s" % (ip)):
return True
except socket.error:
if not socket.has_ipv6:
return False
#now test ipv6
try:
if socket.inet_pton(socket.AF_INET6, "%s" % (ip)):
return True
except socket.error:
return False
for klass in [unicode, str, bool, int, float, long]:
if isinstance(var, klass):
return klass(var)
return var

View File

@ -1,27 +1,35 @@
#
# component.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <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 gobject
from deluge.log import LOG as log
@ -39,18 +47,18 @@ class Component:
self._interval = interval
self._timer = None
self._state = COMPONENT_STATE.index("Stopped")
def get_state(self):
return self._state
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)
def stop(self):
pass
@ -60,20 +68,20 @@ class Component:
gobject.source_remove(self._timer)
except:
pass
def _pause(self):
self._state = COMPONENT_STATE.index("Paused")
try:
gobject.source_remove(self._timer)
except:
pass
def _resume(self):
self._start()
def shutdown(self):
pass
def _update(self):
try:
self.update()
@ -82,29 +90,29 @@ class Component:
# update method.
return False
return True
class ComponentRegistry:
def __init__(self):
self.components = {}
self.depend = {}
def register(self, name, obj, depend):
"""Registers a component.. depend must be list or None"""
log.debug("Registered %s with ComponentRegistry..", name)
self.components[name] = obj
if depend != None:
self.depend[name] = depend
def get(self, name):
"""Returns a reference to the component 'name'"""
return self.components[name]
def start(self):
"""Starts all components"""
for component in self.components.keys():
self.start_component(component)
def start_component(self, name):
"""Starts a component"""
# Check to see if this component has any dependencies
@ -117,24 +125,24 @@ class ComponentRegistry:
log.debug("Starting component %s..", name)
self.components[name].start()
self.components[name]._start()
def stop(self):
"""Stops all components"""
for component in self.components.keys():
self.stop_component(component)
def stop_component(self, component):
if self.components[component].get_state() != \
COMPONENT_STATE.index("Stopped"):
log.debug("Stopping component %s..", component)
self.components[component].stop()
self.components[component]._stop()
def pause(self):
"""Pauses all components. Stops calling update()"""
for component in self.components.keys():
self.pause_component(component)
def pause_component(self, component):
if self.components[component].get_state() not in \
[COMPONENT_STATE.index("Paused"), COMPONENT_STATE.index("Stopped")]:
@ -145,11 +153,11 @@ class ComponentRegistry:
"""Resumes all components. Starts calling update()"""
for component in self.components.keys():
self.resume_component(component)
def resume_component(self, component):
if self.components[component].get_state() == COMPONENT_STATE.index("Paused"):
log.debug("Resuming component %s..", component)
self.components[component]._resume()
self.components[component]._resume()
def update(self):
"""Updates all components"""
@ -158,9 +166,9 @@ class ComponentRegistry:
if self.components[component].get_state() == \
COMPONENT_STATE.index("Started"):
self.components[component].update()
return True
def shutdown(self):
"""Shuts down all components. This should be called when the program
exits so that components can do any necessary clean-up."""
@ -172,8 +180,8 @@ class ComponentRegistry:
self.components[component].shutdown()
except Exception, e:
log.debug("Unable to call shutdown(): %s", e)
_ComponentRegistry = ComponentRegistry()
def register(name, obj, depend=None):
@ -207,7 +215,7 @@ def resume(component=None):
_ComponentRegistry.resume()
else:
_ComponentRegistry.resume_component(component)
def update():
"""Updates all components"""
_ComponentRegistry.update()
@ -215,7 +223,7 @@ def update():
def shutdown():
"""Shutdowns all components"""
_ComponentRegistry.shutdown()
def get(component):
"""Return a reference to the component"""
return _ComponentRegistry.get(component)

View File

@ -1,303 +1,188 @@
#
# config.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007 Andrew Resch ('andar') <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.
"""Configuration class used to access/create/modify configuration files."""
"""
Deluge Config Module
"""
import cPickle
import os.path
import cPickle as pickle
import shutil
import os
import gobject
import deluge.common
from deluge.log import LOG as log
def prop(func):
"""Function decorator for defining property attributes
The decorated function is expected to return a dictionary
containing one or more of the following pairs:
fget - function for getting attribute value
fset - function for setting attribute value
fdel - function for deleting attribute
This can be conveniently constructed by the locals() builtin
function; see:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/205183
"""
return property(doc=func.__doc__, **func())
class Config(object):
"""
This class is used to access/create/modify config files
:param filename: the name of the config file
:param defaults: dictionary of default values
:param config_dir: the path to the config directory
"""
class Config:
"""This class is used to access configuration files."""
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
# is set.
self.__save_timer = None
if defaults:
self.__config = defaults
log.debug("Config created with filename: %s", filename)
log.debug("Config defaults: %s", defaults)
self.config = {}
self.previous_config = {}
self.set_functions = {}
self._change_callback = None
# If defaults is not None then we need to use "defaults".
if defaults != None:
self.config = defaults
# Load the config from file in the config_dir
if config_dir:
self.__config_file = os.path.join(config_dir, filename)
if config_dir == None:
self.config_file = deluge.common.get_default_config_dir(filename)
else:
self.__config_file = deluge.common.get_default_config_dir(filename)
self.load()
def __setitem__(self, key, value):
"""
See
:meth:`set_item`
"""
return self.set_item(key, value)
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
: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
**Usage**
>>> config = Config("test.conf")
>>> config["test"] = 5
>>> config["test"]
5
"""
if not self.__config.has_key(key):
self.__config[key] = value
log.debug("Setting '%s' to %s of %s", key, value, type(value))
return
if self.__config[key] == value:
return
# Do not allow the type to change unless it is None
oldtype, newtype = type(self.__config[key]), type(value)
if value is not None and oldtype != type(None) and oldtype != newtype:
try:
value = oldtype(value)
except ValueError:
log.warning("Type '%s' invalid for '%s'", newtype, key)
raise
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
try:
gobject.idle_add(self.__set_functions[key], key, value)
except KeyError:
pass
try:
gobject.idle_add(self.__change_callback, 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)
def __getitem__(self, key):
"""
See
:meth:`get_item`
"""
return self.get_item(key)
def get_item(self, key):
"""
Gets the value of item 'key'
:param key: the item for which you want it's value
:return: the value of item 'key'
:raises KeyError: if 'key' is not in the config dictionary
**Usage**
>>> config = Config("test.conf", defaults={"test": 5})
>>> config["test"]
5
"""
return self.__config[key]
def register_change_callback(self, callback):
"""
Registers a callback function that will be called when a value is changed in the config dictionary
:param callback: the function, callback(key, value)
**Usage**
>>> config = Config("test.conf", defaults={"test": 5})
>>> def cb(key, value):
... print key, value
...
>>> config.register_change_callback(cb)
"""
self.__change_callback = callback
def register_set_function(self, key, function, apply_now=True):
"""
Register a function to be called when a config value changes
:param key: the item to monitor for change
:param function: the function to call when the value changes, f(key, value)
:keyword apply_now: if True, the function will be called after it's registered
**Usage**
>>> config = Config("test.conf", defaults={"test": 5})
>>> def cb(key, value):
... print key, value
...
>>> config.register_set_function("test", cb, apply_now=True)
test 5
"""
log.debug("Registering function for %s key..", key)
self.__set_functions[key] = function
# Run the function now if apply_now is set
if apply_now:
self.__set_functions[key](key, self.__config[key])
return
def apply_all(self):
"""
Calls all set functions
**Usage**
>>> config = Config("test.conf", defaults={"test": 5})
>>> def cb(key, value):
... print key, value
...
>>> config.register_set_function("test", cb, apply_now=False)
>>> config.apply_all()
test 5
"""
log.debug("Calling all set functions..")
for key, value in self.__set_functions.iteritems():
value(key, self.__config[key])
self.config_file = os.path.join(config_dir, filename)
self.load(self.config_file)
# Save
self.save()
# This will get set with a gobject.timeout_add whenever a config option
# is set.
self.save_timer = None
def __del__(self):
self.save()
def load(self, filename=None):
"""
Load a config file
:param filename: if None, uses filename set in object initialization
"""
if not filename:
filename = self.__config_file
"""Load a config file either by 'filename' or the filename set during
construction of this object."""
# Use self.config_file if filename is None
if filename is None:
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)
# Un-pickle the file and update the config dictionary
pkl_file = open(filename, "rb")
filedump = cPickle.load(pkl_file)
self.config.update(filedump)
pkl_file.close()
except IOError:
log.warning("IOError: Unable to load file '%s'", filename)
except EOFError:
pkl_file.close()
def save(self, filename=None):
"""
Save configuration to disk
:param filename: if None, uses filename set in object initiliazation
"""
if not filename:
filename = self.__config_file
"""Save configuration to either 'filename' or the filename set during
construction of this object."""
# Saves the config dictionary
if filename is None:
filename = self.config_file
# 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")):
pkl_file = open(filename, "rb")
filedump = cPickle.load(pkl_file)
pkl_file.close()
if filedump == self.config:
# The config has not changed so lets just return
self.__save_timer = None
self.save_timer = None
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
except (EOFError, IOError):
log.warning("IOError: Unable to open file: '%s'", filename)
try:
log.debug("Saving new config file %s", filename + ".new")
f = open(filename + ".new", "w")
pickle.dump(self.__config, f)
f.flush()
os.fsync(f.fileno())
f.close()
except Exception, e:
log.error("Error writing new config file: %s", e)
return
pkl_file = open(filename, "wb")
cPickle.dump(self.config, pkl_file)
pkl_file.close()
except IOError:
log.warning("IOError: Unable to save file '%s'", filename)
self.save_timer = None
def set(self, key, value):
"""Set the 'key' with 'value'."""
# Sets the "key" with "value" in the config dict
if self.config[key] != value:
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 = self.config.copy()
self.config[key] = value
# Run the set_function for this key if any
try:
gobject.idle_add(self.set_functions[key], key, value)
except KeyError:
pass
try:
gobject.idle_add(self._change_callback, key, value)
except:
pass
# Make a backup of the old config
# We set the save_timer for 5 seconds if not already set
log.debug("save_timer: %s", self.save_timer)
if not self.save_timer:
self.save_timer = gobject.timeout_add(5000, self.save)
def get(self, key):
"""Get the value of 'key'. If it is an invalid key then get() will
return None."""
# Attempts to get the "key" value and returns None if the key is
# invalid
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..")
return
value = self.config[key]
log.debug("Getting '%s' as %s of %s", key, value, type(value))
return value
except KeyError:
log.warning("Key does not exist, returning None")
return None
# The new config file has been written successfully, so let's move it over
# the existing one.
try:
log.debug("Moving new config file %s to %s..", filename + ".new", filename)
shutil.move(filename + ".new", filename)
except Exception, e:
log.error("Error moving new config file: %s", e)
return
def get_config(self):
"""Returns the entire configuration as a dictionary."""
return self.config
def get_previous_config(self):
"""Returns the config prior to the last set()"""
return self.previous_config
def register_change_callback(self, callback):
"""Registers a callback that will be called when a value is changed"""
self._change_callback = callback
def register_set_function(self, key, function, apply_now=True):
"""Register a function to be run when a config value changes."""
log.debug("Registering function for %s key..", key)
self.set_functions[key] = function
# Run the function now if apply_now is set
if apply_now:
self.set_functions[key](key, self.config[key])
return
def apply_all(self):
"""Runs all set functions"""
log.debug("Running all set functions..")
for key in self.set_functions.keys():
self.set_functions[key](key, self.config[key])
def __getitem__(self, key):
return self.config[key]
def __setitem__(self, key, value):
self.set(key, value)
@prop
def config():
"""The config dictionary"""
def fget(self):
return self.__config
def fdel(self):
return self.save()
return locals()

View File

@ -1,27 +1,35 @@
#
# configmanager.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007 Andrew Resch ('andar') <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 gobject
import os
@ -54,35 +62,36 @@ class _ConfigManager:
os.makedirs(directory)
except Exception, e:
log.warning("Unable to make config directory: %s", e)
self.config_directory = directory
def get_config_dir(self):
log.debug("get_config_dir: %s", self.config_directory)
return self.config_directory
def close(self, config):
"""Closes a config file."""
try:
del self.config_files[config]
except KeyError:
pass
def save(self):
"""Saves all the configs to disk."""
for key in self.config_files.keys():
self.config_files[key].save()
# We need to return True to keep the timer active
return True
def get_config(self, config_file, defaults=None):
"""Get a reference to the Config object for this filename"""
log.debug("Getting config '%s'", config_file)
# Create the config object if not already created
if config_file not in self.config_files.keys():
self.config_files[config_file] = Config(config_file, defaults, self.config_directory)
return self.config_files[config_file]
# Singleton functions
_configmanager = _ConfigManager()
@ -98,6 +107,6 @@ def get_config_dir(filename=None):
return os.path.join(_configmanager.get_config_dir(), filename)
else:
return _configmanager.get_config_dir()
def close(config):
return _configmanager.close(config)

View File

@ -1,27 +1,35 @@
#
# alertmanager.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007 Andrew Resch ('andar') <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.
"""The AlertManager handles all the libtorrent alerts."""
@ -29,12 +37,9 @@ import gobject
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!")
except ImportError:
import deluge.libtorrent as lt
from deluge.log import LOG as log
class AlertManager(component.Component):
@ -49,17 +54,17 @@ class AlertManager(component.Component):
lt.alert.category_t.tracker_notification |
lt.alert.category_t.status_notification |
lt.alert.category_t.ip_block_notification)
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
self.handlers = {}
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:
@ -70,11 +75,11 @@ class AlertManager(component.Component):
# There is no entry for this alert type yet, so lets make it with an
# empty list.
self.handlers[alert_type] = []
# Append the handler to the list in the handlers dictionary
self.handlers[alert_type].append(handler)
log.debug("Registered handler for alert %s", alert_type)
def deregister_handler(self, handler):
"""De-registers the 'handler' function from all alert types."""
# Iterate through all handlers and remove 'handler' where found
@ -82,7 +87,7 @@ class AlertManager(component.Component):
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."""
@ -92,7 +97,11 @@ class AlertManager(component.Component):
# Do some magic to get the alert type as a string
alert_type = str(type(alert)).split("'")[1].split(".")[-1]
# Display the alert message
log.debug("%s: %s", alert_type, alert.message())
try:
log.debug("%s: %s", alert_type, alert.message())
except RuntimeError:
log.debug("%s", alert_type)
# Call any handlers for this alert type
if alert_type in self.handlers.keys():
for handler in self.handlers[alert_type]:
@ -100,7 +109,7 @@ class AlertManager(component.Component):
gobject.idle_add(handler, alert)
else:
handler(alert)
alert = self.session.pop_alert()
# Return True so that the timer continues

View File

@ -1,91 +0,0 @@
#
# authmanager.py
#
# Copyright (C) 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 os.path
import random
import stat
import deluge.component as component
import deluge.configmanager as configmanager
class AuthManager(component.Component):
def __init__(self):
component.Component.__init__(self, "AuthManager")
self.auth = {}
def start(self):
self.__load_auth_file()
def stop(self):
self.auth = {}
def shutdown(self):
pass
def authorize(self, username, password):
"""
Authorizes users based on username and password
:param username: str, username
:param password: str, password
:returns: True or False
:rtype: bool
"""
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 self.auth[username] == password:
return True
return False
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() + "\n")
# Change the permissions on the file so only this user can read/write it
os.chmod(auth_file, stat.S_IREAD | stat.S_IWRITE)
# 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
try:
username, password = line.split(":")
except ValueError:
continue
self.auth[username.strip()] = password.strip()

View File

@ -1,37 +1,42 @@
#
# autoadd.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2008 Andrew Resch ('andar') <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 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!")
except ImportError:
import deluge.libtorrent as lt
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.log import LOG as log
@ -43,7 +48,7 @@ class AutoAdd(component.Component):
component.Component.__init__(self, "AutoAdd", depend=["TorrentManager"], interval=5000)
# Get the core config
self.config = ConfigManager("core.conf")
# A list of filenames
self.invalid_torrents = []
# Filename:Attempts
@ -54,25 +59,25 @@ class AutoAdd(component.Component):
self._on_autoadd_enable, apply_now=True)
self.config.register_set_function("autoadd_location",
self._on_autoadd_location)
def update(self):
if not self.config["autoadd_enable"]:
# We shouldn't be updating because autoadd is not enabled
component.pause("AutoAdd")
return
# Check the auto add folder for new torrents to add
if not os.path.exists(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:
filedump = self.load_torrent(filepath)
except (RuntimeError, Exception), e:
except Exception, e:
# If the torrent is invalid, we keep track of it so that we
# can try again on the next pass. This is because some
# torrents may not be fully saved during the pass.
@ -83,16 +88,16 @@ class AutoAdd(component.Component):
os.rename(filepath, filepath + ".invalid")
del self.attempts[filename]
self.invalid_torrents.remove(filename)
else:
else:
self.invalid_torrents.append(filename)
self.attempts[filename] = 1
continue
# The torrent looks good, so lets add it to the session
component.get("TorrentManager").add(filedump=filedump, filename=filename)
os.remove(filepath)
def load_torrent(self, filename):
try:
log.debug("Attempting to open %s for add.", filename)
@ -104,10 +109,10 @@ class AutoAdd(component.Component):
except IOError, e:
log.warning("Unable to open %s: %s", filename, e)
raise e
# Get the info to see if any exceptions are raised
info = lt.torrent_info(lt.bdecode(filedump))
return filedump
def _on_autoadd_enable(self, key, value):

View File

@ -1,7 +1,7 @@
#
# core.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -21,13 +21,20 @@
# 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 gettext
import locale
import pkg_resources
import sys
import glob
import shutil
import os
import os.path
@ -40,11 +47,9 @@ import threading
import socket
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!")
except ImportError:
import deluge.libtorrent as lt
import deluge.configmanager
import deluge.common
@ -53,23 +58,65 @@ from deluge.core.torrentmanager import TorrentManager
from deluge.core.pluginmanager import PluginManager
from deluge.core.alertmanager import AlertManager
from deluge.core.signalmanager import SignalManager
from deluge.core.filtermanager import FilterManager
from deluge.core.preferencesmanager import PreferencesManager
from deluge.core.autoadd import AutoAdd
from deluge.core.authmanager import AuthManager
from deluge.core.rpcserver import BasicAuthXMLRPCRequestHandler
from deluge.log import LOG as log
STATUS_KEYS = ['active_time', 'compact', 'distributed_copies', 'download_payload_rate', 'eta',
'file_priorities', 'file_progress', 'files', 'hash', 'is_auto_managed', 'is_seed', 'max_connections',
'max_download_speed', 'max_upload_slots', 'max_upload_speed', 'message', 'move_on_completed',
'move_on_completed_path', 'name', 'next_announce', 'num_files', 'num_peers', 'num_pieces',
'num_seeds', 'paused', 'peers', 'piece_length', 'prioritize_first_last', 'private', 'progress',
'queue', 'ratio', 'remove_at_ratio', 'save_path', 'seed_rank', 'seeding_time', 'state', 'stop_at_ratio',
'stop_ratio', 'time_added', 'total_done', 'total_payload_download', 'total_payload_upload', 'total_peers',
'total_seeds', 'total_size', 'total_uploaded', 'total_wanted', 'tracker', 'tracker_host',
'tracker_status', 'trackers', 'upload_payload_rate']
DEFAULT_PREFS = {
"config_location": deluge.configmanager.get_config_dir(),
"send_info": False,
"info_sent": 0.0,
"daemon_port": 58846,
"allow_remote": False,
"compact_allocation": False,
"download_location": deluge.common.get_default_download_dir(),
"listen_ports": [6881, 6891],
"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,
"upnp": True,
"natpmp": True,
"utpex": True,
"lsd": True,
"enc_in_policy": 1,
"enc_out_policy": 1,
"enc_level": 2,
"enc_prefer_rc4": True,
"max_connections_global": 200,
"max_upload_speed": -1.0,
"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)(),
"max_connections_per_second": 20,
"ignore_limits_on_local_network": True,
"max_connections_per_torrent": -1,
"max_upload_slots_per_torrent": -1,
"max_upload_speed_per_torrent": -1,
"max_download_speed_per_torrent": -1,
"enabled_plugins": [],
"autoadd_location": deluge.common.get_default_download_dir(),
"autoadd_enable": False,
"add_paused": False,
"max_active_seeding": 5,
"max_active_downloading": 3,
"max_active_limit": 8,
"dont_count_slow_torrents": False,
"queue_new_to_top": False,
"stop_seed_at_ratio": False,
"remove_seed_at_ratio": False,
"stop_seed_ratio": 2.00,
"share_ratio_limit": 2.00,
"seed_time_ratio_limit": 7.00,
"seed_time_limit": 180,
"auto_managed": True,
"move_completed": False,
"move_completed_path": deluge.common.get_default_download_dir(),
"new_release_check": True,
}
class Core(
ThreadingMixIn,
@ -80,10 +127,8 @@ class Core(
component.Component.__init__(self, "Core")
self.client_address = None
self.prefmanager = PreferencesManager()
# Get config
self.config = deluge.configmanager.ConfigManager("core.conf")
self.config = deluge.configmanager.ConfigManager("core.conf", DEFAULT_PREFS)
if port == None:
port = self.config["daemon_port"]
@ -97,9 +142,7 @@ class Core(
try:
log.info("Starting XMLRPC server on port %s", port)
SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(
self, (hostname, port),
requestHandler=BasicAuthXMLRPCRequestHandler,
logRequests=False, allow_none=True)
self, (hostname, port), logRequests=False, allow_none=True)
except:
log.info("Daemon already running or port not available..")
sys.exit(0)
@ -114,18 +157,22 @@ class Core(
self.register_introspection_functions()
# Initialize gettext
try:
if deluge.common.windows_check() or deluge.common.osx_check():
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)
else:
locale.setlocale(locale.LC_MESSAGES, '')
locale.bindtextdomain("deluge",
pkg_resources.resource_filename(
"deluge", "i18n"))
locale.textdomain("deluge")
gettext.bindtextdomain("deluge",
pkg_resources.resource_filename(
"deluge", "i18n"))
gettext.textdomain("deluge")
gettext.install("deluge",
pkg_resources.resource_filename(
"deluge", "i18n"))
# Setup signals
signal.signal(signal.SIGINT, self._shutdown)
signal.signal(signal.SIGTERM, self._shutdown)
@ -167,22 +214,14 @@ class Core(
log.debug("Starting libtorrent session..")
self.session = lt.session(fingerprint, flags=0)
# Load the session state if available
self.load_session_state()
# Load the GeoIP DB for country look-ups if available
geoip_db = pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat"))
if os.path.exists(geoip_db):
try:
self.session.load_country_db(geoip_db)
except Exception, e:
log.error("Unable to load geoip database!")
log.exception(e)
# Set the user agent
self.settings = lt.session_settings()
self.settings.user_agent = "Deluge %s" % deluge.common.get_version()
# Load the GeoIP DB for country look-ups
self.session.load_country_db(
pkg_resources.resource_filename("deluge", os.path.join("data", "GeoIP.dat")))
# Set session settings
self.settings.lazy_bitfields = 1
self.settings.send_redundant_have = True
@ -196,9 +235,65 @@ class Core(
# Load metadata extension
self.session.add_extension(lt.create_metadata_plugin)
self.session.add_extension(lt.create_ut_metadata_plugin)
self.session.add_extension(lt.create_smart_ban_plugin)
# 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("random_port",
self._on_set_random_port)
self.config.register_set_function("dht", self._on_set_dht)
self.config.register_set_function("upnp", self._on_set_upnp)
self.config.register_set_function("natpmp", self._on_set_natpmp)
self.config.register_set_function("utpex", self._on_set_utpex)
self.config.register_set_function("lsd", self._on_set_lsd)
self.config.register_set_function("enc_in_policy",
self._on_set_encryption)
self.config.register_set_function("enc_out_policy",
self._on_set_encryption)
self.config.register_set_function("enc_level",
self._on_set_encryption)
self.config.register_set_function("enc_prefer_rc4",
self._on_set_encryption)
self.config.register_set_function("max_connections_global",
self._on_set_max_connections_global)
self.config.register_set_function("max_upload_speed",
self._on_set_max_upload_speed)
self.config.register_set_function("max_download_speed",
self._on_set_max_download_speed)
self.config.register_set_function("max_upload_slots_global",
self._on_set_max_upload_slots_global)
self.config.register_set_function("max_half_open_connections",
self._on_set_max_half_open_connections)
self.config.register_set_function("max_connections_per_second",
self._on_set_max_connections_per_second)
self.config.register_set_function("ignore_limits_on_local_network",
self._on_ignore_limits_on_local_network)
self.config.register_set_function("share_ratio_limit",
self._on_set_share_ratio_limit)
self.config.register_set_function("seed_time_ratio_limit",
self._on_set_seed_time_ratio_limit)
self.config.register_set_function("seed_time_limit",
self._on_set_seed_time_limit)
self.config.register_set_function("max_active_downloading",
self._on_set_max_active_downloading)
self.config.register_set_function("max_active_seeding",
self._on_set_max_active_seeding)
self.config.register_set_function("max_active_limit",
self._on_set_max_active_limit)
self.config.register_set_function("dont_count_slow_torrents",
self._on_set_dont_count_slow_torrents)
self.config.register_set_function("send_info",
self._on_send_info)
self.new_release = None
self.new_release_timer = None
self.config.register_set_function("new_release_check",
self._on_new_release_check)
self.config.register_change_callback(self._on_config_value_change)
# Start the AlertManager
self.alerts = AlertManager(self.session)
@ -211,19 +306,9 @@ class Core(
# Start the TorrentManager
self.torrents = TorrentManager(self.session, self.alerts)
# Start the FilterManager
self.filtermanager = FilterManager(self)
# Create the AutoAdd component
self.autoadd = AutoAdd()
# Start the AuthManager
self.authmanager = AuthManager()
# New release check information
self.new_release = None
component.start("PreferencesManager")
component.start()
self._should_shutdown = False
@ -248,21 +333,10 @@ class Core(
except Exception, e:
log.debug("handle_thread: %s", e)
def shutdown(self):
pass
def _shutdown(self, *data):
"""This is called by a thread from shutdown()"""
log.info("Shutting down core..")
self._should_shutdown = True
# Save the DHT state if necessary
if self.config["dht"]:
self.save_dht_state()
# Save the libtorrent session state
self.save_session_state()
# Shutdown the socket
try:
self.socket.shutdown(socket.SHUT_RDWR)
@ -281,79 +355,10 @@ class Core(
del deluge.configmanager
del self.session
self.loop.quit()
def save_session_state(self):
"""Saves the libtorrent session state"""
try:
open(deluge.common.get_default_config_dir("session.state"), "wb").write(
lt.bencode(self.session.state()))
except Exception, e:
log.warning("Failed to save lt state: %s", e)
def load_session_state(self):
"""Loads the libtorrent session state"""
try:
self.session.load_state(lt.bdecode(
open(deluge.common.get_default_config_dir("session.state"), "rb").read()))
except Exception, e:
log.warning("Failed to load lt state: %s", e)
def save_dht_state(self):
"""Saves the dht state to a file"""
try:
dht_data = open(deluge.common.get_default_config_dir("dht.state"), "wb")
dht_data.write(lt.bencode(self.session.dht_state()))
dht_data.close()
except Exception, e:
log.warning("Failed to save dht state: %s", e)
def get_new_release(self):
log.debug("get_new_release")
from urllib2 import urlopen
try:
self.new_release = urlopen(
"http://download.deluge-torrent.org/version-1.0").read().strip()
except Exception, e:
log.debug("Unable to get release info from website: %s", e)
return
self.check_new_release()
def check_new_release(self):
if self.new_release:
log.debug("new_release: %s", self.new_release)
class VersionSplit(object):
def __init__(self, ver):
ver = ver.lower()
vs = ver.split("_") if "_" in ver else ver.split("-")
self.version = vs[0]
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):
if self.version > ver.version or (self.suffix and self.suffix[:3] == "dev"):
return 1
if self.version < ver.version:
return -1
if self.version == ver.version:
if self.suffix == ver.suffix:
return 0
if self.suffix is None:
return 1
if ver.suffix is None:
return -1
if self.suffix < ver.suffix:
return -1
if self.suffix > ver.suffix:
return 1
if VersionSplit(self.new_release) > VersionSplit(deluge.common.get_version()):
self.signals.emit("new_version_available", self.new_release)
return self.new_release
return False
self.gnome_client.disconnect()
except:
pass
# Exported Methods
def export_ping(self):
@ -402,43 +407,6 @@ class Core(
# Run the plugin hooks for 'post_torrent_add'
self.plugins.run_post_torrent_add(torrent_id)
def export_get_stats(self):
"""
document me!!!
"""
stats = self.export_get_session_status(["payload_download_rate", "payload_upload_rate",
"dht_nodes", "has_incoming_connections", "download_rate", "upload_rate"])
stats.update({
#dynamic stats:
"num_connections":self.session.num_connections(),
"free_space":deluge.common.free_space(self.config["download_location"]),
#max config values:
"max_download":self.config["max_download_speed"],
"max_upload":self.config["max_upload_speed"],
"max_num_connections":self.config["max_connections_global"],
})
return stats
def export_get_session_status(self, keys):
"""
Gets the session status values for 'keys'
:param keys: list of strings, the keys for which we want values
:returns: a dictionary of {key: value, ...}
:rtype: dict
"""
status = {}
session_status = self.session.status()
for key in keys:
status[key] = getattr(session_status, key)
return status
def export_add_torrent_url(self, url, options):
log.info("Attempting to add url %s", url)
@ -463,23 +431,10 @@ class Core(
# Add the torrent to session
return callback(filename, filedump, options)
def export_add_torrent_magnets(self, uris, options):
for uri in uris:
log.debug("Attempting to add by magnet uri: %s", uri)
try:
option = options[uris.index(uri)]
except IndexError:
option = None
torrent_id = self.torrents.add(magnet=uri, options=option)
# Run the plugin hooks for 'post_torrent_add'
self.plugins.run_post_torrent_add(torrent_id)
def export_remove_torrent(self, torrent_ids, remove_data):
def export_remove_torrent(self, torrent_ids, remove_torrent, remove_data):
log.debug("Removing torrent %s from the core.", torrent_ids)
for torrent_id in torrent_ids:
if self.torrents.remove(torrent_id, remove_data):
if self.torrents.remove(torrent_id, remove_torrent, remove_data):
# Run the plugin hooks for 'post_torrent_remove'
self.plugins.run_post_torrent_remove(torrent_id)
@ -494,11 +449,6 @@ class Core(
if not self.torrents[torrent_id].pause():
log.warning("Error pausing torrent %s", torrent_id)
def export_connect_peer(self, torrent_id, ip, port):
log.debug("adding peer %s to %s", ip, torrent_id)
if not self.torrents[torrent_id].connect_peer(ip, port):
log.warning("Error adding peer %s:%s to %s", ip, port, torrent_id)
def export_move_storage(self, torrent_ids, dest):
log.debug("Moving storage %s to %s", torrent_ids, dest)
for torrent_id in torrent_ids:
@ -507,27 +457,28 @@ class Core(
def export_pause_all_torrents(self):
"""Pause all torrents in the session"""
self.session.pause()
if not self.torrents.pause_all():
log.warning("Error pausing all torrents..")
def export_resume_all_torrents(self):
"""Resume all torrents in the session"""
self.session.resume()
self.signals.emit("torrent_all_resumed")
if self.torrents.resume_all():
# Emit the 'torrent_all_resumed' signal
self.torrent_all_resumed()
def export_resume_torrent(self, torrent_ids):
log.debug("Resuming: %s", torrent_ids)
for torrent_id in torrent_ids:
self.torrents[torrent_id].resume()
def export_get_status_keys(self):
"""
returns all possible keys for the keys argument in get_torrent(s)_status.
"""
return STATUS_KEYS + self.plugins.status_fields.keys()
if self.torrents[torrent_id].resume():
self.torrent_resumed(torrent_id)
def export_get_torrent_status(self, torrent_id, keys):
# Build the status dictionary
status = self.torrents[torrent_id].get_status(keys)
try:
status = self.torrents[torrent_id].get_status(keys)
except KeyError:
# The torrent_id is not found in the torrentmanager, so return None
return None
# Get the leftover fields and ask the plugin manager to fill them
leftover_fields = list(set(keys) - set(status.keys()))
@ -535,26 +486,25 @@ class Core(
status.update(self.plugins.get_status(torrent_id, leftover_fields))
return status
def export_get_torrents_status(self, filter_dict, keys):
"""
returns all torrents , optionally filtered by filter_dict.
"""
torrent_ids = self.filtermanager.filter_torrent_ids(filter_dict)
def export_get_torrents_status(self, torrent_ids, keys):
status_dict = {}.fromkeys(torrent_ids)
# Get the torrent status for each torrent_id
for torrent_id in torrent_ids:
status_dict[torrent_id] = self.export_get_torrent_status(torrent_id, keys)
try:
status = self.torrents[torrent_id].get_status(keys)
except KeyError:
return None
# Get the leftover fields and ask the plugin manager to fill them
leftover_fields = list(set(keys) - set(status.keys()))
if len(leftover_fields) > 0:
status.update(
self.plugins.get_status(torrent_id, leftover_fields))
status_dict[torrent_id] = status
# Emit the torrent_status signal to the clients
return status_dict
def export_get_filter_tree(self , show_zero_hits=True, hide_cat=None):
"""
returns {field: [(value,count)] }
for use in sidebar(s)
"""
return self.filtermanager.get_filter_tree(show_zero_hits, hide_cat)
def export_get_session_state(self):
"""Returns a list of torrent_ids in the session."""
# Get the torrent list from the TorrentManager
@ -567,7 +517,7 @@ class Core(
def export_get_config(self):
"""Get all the preferences as a dictionary"""
return self.config.config
return self.config.get_config()
def export_get_config_value(self, key):
"""Get the config value for key"""
@ -578,19 +528,9 @@ class Core(
return value
def export_get_config_values(self, keys):
"""Get the config values for the entered keys"""
config = {}
for key in keys:
try:
config[key] = self.config[key]
except KeyError:
pass
return config
def export_set_config(self, config):
"""Set the config with values from dictionary"""
config = deluge.common.pythonize(config)
# Load all the values into the configuration
for key in config.keys():
if isinstance(config[key], unicode) or isinstance(config[key], str):
@ -638,11 +578,6 @@ class Core(
for torrent_id in torrent_ids:
self.torrents[torrent_id].force_recheck()
def export_set_torrent_options(self, torrent_ids, options):
"""Sets the torrent options for torrent_ids"""
for torrent_id in torrent_ids:
self.torrents[torrent_id].set_options(options)
def export_set_torrent_trackers(self, torrent_id, trackers):
"""Sets a torrents tracker list. trackers will be [{"url", "tier"}]"""
return self.torrents[torrent_id].set_trackers(trackers)
@ -687,14 +622,6 @@ class Core(
"""Sets the torrent to be removed at 'stop_ratio'"""
return self.torrents[torrent_id].set_remove_at_ratio(value)
def export_set_torrent_move_on_completed(self, torrent_id, value):
"""Sets the torrent to be moved when completed"""
return self.torrents[torrent_id].set_move_on_completed(value)
def export_set_torrent_move_on_completed_path(self, torrent_id, value):
"""Sets the path for the torrent to be moved when completed"""
return self.torrents[torrent_id].set_move_on_completed_path(value)
def export_block_ip_range(self, range):
"""Block an ip range"""
self.ip_filter.add_rule(range[0], range[1], 1)
@ -713,69 +640,6 @@ class Core(
"""Returns True if we have established incoming connections"""
return self.session.status().has_incoming_connections
def export_get_path_size(self, path):
"""Returns the size of the file or folder 'path' and -1 if the path is
unaccessible (non-existent or insufficient privs)"""
return deluge.common.get_path_size(path)
def export_create_torrent(self, path, tracker, piece_length, comment, target,
url_list, private, created_by, httpseeds, add_to_session):
log.debug("creating torrent..")
threading.Thread(target=_create_torrent_thread,
args=(
path,
tracker,
piece_length,
comment,
target,
url_list,
private,
created_by,
httpseeds,
add_to_session)).start()
def _create_torrent_thread(self, path, tracker, piece_length, comment, target,
url_list, private, created_by, httpseeds, add_to_session):
import deluge.metafile
deluge.metafile.make_meta_file(
path,
tracker,
piece_length,
comment=comment,
target=target,
url_list=url_list,
private=private,
created_by=created_by,
httpseeds=httpseeds)
log.debug("torrent created!")
if add_to_session:
self.export_add_torrent_file(os.path.split(target)[1], open(target, "rb").read(), None)
def export_upload_plugin(self, filename, plugin_data):
"""This method is used to upload new plugins to the daemon. It is used
when connecting to the daemon remotely and installing a new plugin on
the client side. 'plugin_data' is a xmlrpc.Binary object of the file data,
ie, plugin_file.read()"""
f = open(os.path.join(self.config["config_location"], "plugins", filename), "wb")
f.write(plugin_data.data)
f.close()
component.get("PluginManager").scan_for_plugins()
def export_rescan_plugins(self):
"""Rescans the plugin folders for new plugins"""
component.get("PluginManager").scan_for_plugins()
def export_rename_files(self, torrent_id, filenames):
"""Renames files in 'torrent_id'. The 'filenames' parameter should be a
list of (index, filename) pairs."""
self.torrents[torrent_id].rename_files(filenames)
def export_rename_folder(self, torrent_id, folder, new_folder):
"""Renames the 'folder' to 'new_folder' in 'torrent_id'."""
self.torrents[torrent_id].rename_folder(folder, new_folder)
## Queueing functions ##
def export_queue_top(self, torrent_ids):
log.debug("Attempting to queue %s to top", torrent_ids)
@ -783,7 +647,7 @@ class Core(
try:
# If the queue method returns True, then we should emit a signal
if self.torrents.queue_top(torrent_id):
self.signals.emit("torrent_queue_changed")
self._torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
@ -795,7 +659,7 @@ class Core(
try:
# If the queue method returns True, then we should emit a signal
if self.torrents.queue_up(torrent_id):
self.signals.emit("torrent_queue_changed")
self._torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
@ -807,7 +671,7 @@ class Core(
try:
# If the queue method returns True, then we should emit a signal
if self.torrents.queue_down(torrent_id):
self.signals.emit("torrent_queue_changed")
self._torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
@ -817,21 +681,271 @@ class Core(
try:
# If the queue method returns True, then we should emit a signal
if self.torrents.queue_bottom(torrent_id):
self.signals.emit("torrent_queue_changed")
self._torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue", torrent_id)
def export_glob(self, path):
return glob.glob(path)
# Signals
def torrent_removed(self, torrent_id):
"""Emitted when a torrent has been removed from the core"""
log.debug("torrent_remove signal emitted")
self.signals.emit("torrent_removed", torrent_id)
def export_test_listen_port(self):
""" Checks if active port is open """
import urllib
port = self.export_get_listen_port()
try:
status = urllib.urlopen("http://deluge-torrent.org/test_port.php?port=%s" % port).read()
except IOError:
log.debug("Network error while trying to check status of port %s", port)
return 0
def torrent_paused(self, torrent_id):
"""Emitted when a torrent is paused"""
log.debug("torrent_paused signal emitted")
self.signals.emit("torrent_paused", torrent_id)
def torrent_resumed(self, torrent_id):
"""Emitted when a torrent is resumed"""
log.debug("torrent_resumed signal emitted")
self.signals.emit("torrent_resumed", torrent_id)
def torrent_all_paused(self):
"""Emitted when all torrents have been paused"""
log.debug("torrent_all_paused signal emitted")
self.signals.emit("torrent_all_paused")
def torrent_all_resumed(self):
"""Emitted when all torrents have been resumed"""
log.debug("torrent_all_resumed signal emitted")
self.signals.emit("torrent_all_resumed")
def config_value_changed(self, key, value):
"""Emitted when a config value has changed"""
log.debug("config_value_changed signal emitted")
self.signals.emit("config_value_changed", key, value)
def _torrent_queue_changed(self):
"""Emitted when a torrent queue position is changed"""
log.debug("torrent_queue_changed signal emitted")
self.signals.emit("torrent_queue_changed")
# Config set functions
def _on_config_value_change(self, key, value):
self.config_value_changed(key, value)
def _on_set_torrentfiles_location(self, key, value):
if self.config["copy_torrent_file"]:
try:
os.makedirs(value)
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])
def _on_set_random_port(self, key, value):
log.debug("random port value set to %s", value)
# We need to check if the value has been changed to true and false
# and then handle accordingly.
if value:
import random
listen_ports = []
randrange = lambda: random.randrange(49152, 65525)
listen_ports.append(randrange())
listen_ports.append(listen_ports[0]+10)
else:
return int(status)
listen_ports = self.config["listen_ports"]
# 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])
def _on_set_dht(self, key, value):
log.debug("dht value set to %s", value)
if value:
self.session.start_dht(None)
self.session.add_dht_router("router.bittorrent.com", 6881)
self.session.add_dht_router("router.utorrent.com", 6881)
self.session.add_dht_router("router.bitcomet.com", 6881)
else:
self.session.stop_dht()
def _on_set_upnp(self, key, value):
log.debug("upnp value set to %s", value)
if value:
self.session.start_upnp()
else:
self.session.stop_upnp()
def _on_set_natpmp(self, key, value):
log.debug("natpmp value set to %s", value)
if value:
self.session.start_natpmp()
else:
self.session.stop_natpmp()
def _on_set_lsd(self, key, value):
log.debug("lsd value set to %s", value)
if value:
self.session.start_lsd()
else:
self.session.stop_lsd()
def _on_set_utpex(self, key, value):
log.debug("utpex value set to %s", value)
if value:
self.session.add_extension(lt.create_ut_pex_plugin)
def _on_set_encryption(self, key, value):
log.debug("encryption value %s set to %s..", key, value)
pe_settings = lt.pe_settings()
pe_settings.out_enc_policy = \
lt.enc_policy(self.config["enc_out_policy"])
pe_settings.in_enc_policy = lt.enc_policy(self.config["enc_in_policy"])
pe_settings.allowed_enc_level = lt.enc_level(self.config["enc_level"])
pe_settings.prefer_rc4 = self.config["enc_prefer_rc4"]
self.session.set_pe_settings(pe_settings)
set = self.session.get_pe_settings()
log.debug("encryption settings:\n\t\t\tout_policy: %s\n\t\t\
in_policy: %s\n\t\t\tlevel: %s\n\t\t\tprefer_rc4: %s",
set.out_enc_policy,
set.in_enc_policy,
set.allowed_enc_level,
set.prefer_rc4)
def _on_set_max_connections_global(self, key, value):
log.debug("max_connections_global set to %s..", value)
# Add this in to overwrite bad float values in the config, to prevent
# future issues with 1.1
if type(value) is not int:
self.config[key] = int(value)
self.session.set_max_connections(int(value))
def _on_set_max_upload_speed(self, key, value):
log.debug("max_upload_speed set to %s..", value)
# We need to convert Kb/s to B/s
self.session.set_upload_rate_limit(int(value * 1024))
def _on_set_max_download_speed(self, key, value):
log.debug("max_download_speed set to %s..", value)
# We need to convert Kb/s to B/s
self.session.set_download_rate_limit(int(value * 1024))
def _on_set_max_upload_slots_global(self, key, value):
log.debug("max_upload_slots_global set to %s..", value)
self.session.set_max_uploads(value)
def _on_set_max_half_open_connections(self, key, value):
self.session.set_max_half_open_connections(value)
def _on_set_max_connections_per_second(self, key, value):
self.settings.connection_speed = value
self.session.set_settings(self.settings)
def _on_ignore_limits_on_local_network(self, key, value):
self.settings.ignore_limits_on_local_network = value
self.session.set_settings(self.settings)
def _on_set_share_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.share_ratio_limit = value
self.session.set_settings(self.settings)
def _on_set_seed_time_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.seed_time_ratio_limit = value
self.session.set_settings(self.settings)
def _on_set_seed_time_limit(self, key, value):
log.debug("%s set to %s..", key, value)
# This value is stored in minutes in deluge, but libtorrent wants seconds
self.settings.seed_time_limit = int(value * 60)
self.session.set_settings(self.settings)
def _on_set_max_active_downloading(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_downloads: %s", self.settings.active_downloads)
self.settings.active_downloads = value
self.session.set_settings(self.settings)
def _on_set_max_active_seeding(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_seeds: %s", self.settings.active_seeds)
self.settings.active_seeds = value
self.session.set_settings(self.settings)
def _on_set_max_active_limit(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_limit: %s", self.settings.active_limit)
self.settings.active_limit = value
self.session.set_settings(self.settings)
def _on_set_dont_count_slow_torrents(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.dont_count_slow_torrents = value
self.session.set_settings(self.settings)
def _on_send_info(self, key, value):
log.debug("Sending anonymous stats..")
"""sends anonymous stats home"""
class Send_Info_Thread(threading.Thread):
def __init__(self, config):
self.config = config
threading.Thread.__init__(self)
def run(self):
import time
now = time.time()
# check if we've done this within the last week or never
if (now - self.config["info_sent"]) >= (60 * 60 * 24 * 7):
import deluge.common
from urllib import quote_plus
from urllib2 import urlopen
import platform
try:
url = "http://deluge-torrent.org/stats_get.php?processor=" + \
platform.machine() + "&python=" + platform.python_version() \
+ "&deluge=" + deluge.common.get_version() \
+ "&os=" + platform.system() \
+ "&plugins=" + quote_plus(self.config["enabled_plugins"])
urlopen(url)
except IOError, e:
log.debug("Network error while trying to send info: %s", e)
else:
self.config["info_sent"] = now
if value:
Send_Info_Thread(self.config).start()
def get_new_release(self):
log.debug("get_new_release")
from urllib2 import urlopen
try:
self.new_release = urlopen(
"http://download.deluge-torrent.org/version").read().strip()
except Exception, e:
log.debug("Unable to get release info from website: %s", e)
return
self.check_new_release()
def check_new_release(self):
if self.new_release:
log.debug("new_release: %s", self.new_release)
if self.new_release > deluge.common.get_version():
self.signals.emit("new_version_available", self.new_release)
return self.new_release
return False
def _on_new_release_check(self, key, value):
if value:
log.debug("Checking for new release..")
threading.Thread(target=self.get_new_release).start()
if self.new_release_timer:
gobject.source_remove(self.new_release_timer)
# 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)
else:
if self.new_release_timer:
gobject.source.remove(self.new_release_timer)

View File

@ -1,27 +1,35 @@
#
# daemon.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007 Andrew Resch ('andar') <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.configmanager
import deluge.common
@ -31,8 +39,8 @@ class Daemon:
def __init__(self, options, args):
version = deluge.common.get_version()
if deluge.common.get_revision() != "":
version = version + "r" + 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)

View File

@ -1,228 +0,0 @@
#
# core.py
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@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.component as component
from deluge.log import LOG as log
STATE_SORT = ["All", "Downloading", "Seeding", "Active", "Paused", "Queued"]
#special purpose filters:
def filter_keywords(torrent_ids, values):
#cleanup.
keywords = ",".join([v.lower() for v in values])
keywords = keywords.split(",")
for keyword in keywords:
torrent_ids = filter_one_keyword(torrent_ids, keyword)
return torrent_ids
def filter_one_keyword(torrent_ids, keyword):
"""
search torrent on keyword.
searches title,state,tracker-status,tracker,files
"""
all_torrents = component.get("TorrentManager").torrents
#filter:
found = False
for torrent_id in torrent_ids:
torrent = all_torrents[torrent_id]
if keyword in torrent.filename.lower():
yield torrent_id
elif keyword in torrent.state.lower():
yield torrent_id
elif torrent.trackers and keyword in torrent.trackers[0]["url"]:
yield torrent_id
elif keyword in torrent_id:
yield torrent_id
#i want to find broken torrents (search on "error", or "unregistered")
elif keyword in torrent.tracker_status.lower():
yield torrent_id
else:
for t_file in torrent.get_files():
if keyword in t_file["path"].lower():
yield torrent_id
break
class FilterManager(component.Component):
"""FilterManager
"""
def __init__(self, core):
component.Component.__init__(self, "FilterManager")
log.debug("FilterManager init..")
self.core = core
self.torrents = core.torrents
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 filter_torrent_ids(self, filter_dict):
"""
returns a list of torrent_id's matching filter_dict.
core filter method
"""
if not filter_dict:
return self.torrents.get_torrent_list()
#sanitize input: filter-value must be a list of strings
for key, value in filter_dict.items():
if isinstance(value, str):
filter_dict[key] = [value]
if "id"in filter_dict: #optimized filter for id:
torrent_ids = filter_dict["id"]
del filter_dict["id"]
else:
torrent_ids = self.torrents.get_torrent_list()
if not filter_dict: #return if there's nothing more to filter
return torrent_ids
#special purpose: state=Active.
if "state" in filter_dict and "Active" in filter_dict["state"]:
filter_dict["state"].remove("Active")
if not filter_dict["state"]:
del filter_dict["state"]
torrent_ids = self.filter_state_active(torrent_ids)
if not filter_dict: #return if there's nothing more to filter
return torrent_ids
#Registered filters:
for field, values in filter_dict.items():
if field in self.registered_filters:
# a set filters out the doubles.
torrent_ids = list(set(self.registered_filters[field](torrent_ids, values)))
del filter_dict[field]
if not filter_dict: #return if there's nothing more to filter
return torrent_ids
#leftover filter arguments:
#default filter on status fields.
status_func = self.core.export_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():
if (not status[field] in values) and torrent_id in torrent_ids:
torrent_ids.remove(torrent_id)
return torrent_ids
def get_filter_tree(self, show_zero_hits=True, hide_cat=None):
"""
returns {field: [(value,count)] }
for use in sidebar.
"""
torrent_ids = self.torrents.get_torrent_list()
status_func = self.core.export_get_torrent_status #premature optimalisation..
tree_keys = list(self.tree_fields.keys())
if hide_cat:
for cat in hide_cat:
tree_keys.remove(cat)
items = dict( (field, self.tree_fields[field]()) for field in tree_keys)
#count status fields.
for torrent_id in list(torrent_ids):
status = status_func(torrent_id, tree_keys) #status={key:value}
for field in tree_keys:
value = status[field]
items[field][value] = items[field].get(value, 0) + 1
if "state" in tree_keys and not show_zero_hits:
self._hide_state_items(items["state"])
#return a dict of tuples:
sorted_items = {}
for field in tree_keys:
sorted_items[field] = sorted(items[field].iteritems())
if "state" in tree_keys:
sorted_items["state"].sort(self._sort_state_items)
return sorted_items
def _init_state_tree(self):
return {"All":len(self.torrents.get_torrent_list()),
"Downloading":0,
"Seeding":0,
"Paused":0,
"Checking":0,
"Queued":0,
"Error":0,
"Active":len(self.filter_state_active(self.torrents.get_torrent_list()))
}
def register_filter(self, id, filter_func, filter_value = None):
self.registered_filters[id] = filter_func
def deregister_filter(self, id):
del self.registered_filters[id]
def register_tree_field(self, field, init_func = lambda : {}):
self.tree_fields[field] = init_func
def deregister_tree_field(self, field):
del self.tree_fields[field]
def filter_state_active(self, torrent_ids):
get_status = self.core.export_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"]:
pass #ok
else:
torrent_ids.remove(torrent_id)
return torrent_ids
def _hide_state_items(self, state_items):
"for hide(show)-zero hits"
for (value, count) in state_items.items():
if value != "All" and count == 0:
del state_items[value]
def _sort_state_items(self, x, y):
""
if x[0] in STATE_SORT:
ix = STATE_SORT.index(x[0])
else:
ix = 99
if y[0] in STATE_SORT:
iy = STATE_SORT.index(y[0])
else:
iy = 99
return ix - iy

View File

@ -1,27 +1,35 @@
#
# oldstateupgrader.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2008 Andrew Resch ('andar') <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 os
import os.path
@ -30,12 +38,9 @@ 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!")
except ImportError:
import deluge.libtorrent as lt
from deluge.configmanager import ConfigManager
import deluge.core.torrentmanager
from deluge.log import LOG as log
@ -68,19 +73,14 @@ class OldStateUpgrader:
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()
def upgrade05(self):
try:
state = PickleUpgrader(open(self.state05_location, "rb")).load()
except Exception, e:
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)
@ -92,7 +92,7 @@ class OldStateUpgrader:
_file.close()
except (IOError, RuntimeError), e:
log.warning("Unable to open %s: %s", filepath, 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"))
@ -116,7 +116,7 @@ class OldStateUpgrader:
)
# Append the object to the state list
new_state.torrents.append(new_torrent)
# Now we need to write out the new state file
try:
log.debug("Saving torrent state file.")
@ -127,7 +127,7 @@ class OldStateUpgrader:
except IOError, e:
log.warning("Unable to save state file: %s", e)
return
# Rename the persistent.state file
try:
os.rename(self.state05_location, self.state05_location + ".old")

View File

@ -1,27 +1,35 @@
#
# pluginmanager.py
#
# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007 Andrew Resch ('andar') <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.
"""PluginManager for Core"""
@ -31,11 +39,11 @@ import deluge.pluginmanagerbase
import deluge.component as component
from deluge.log import LOG as log
class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
component.Component):
"""PluginManager handles the loading of plugins and provides plugins with
functions to access parts of the core."""
def __init__(self, core):
component.Component.__init__(self, "PluginManager")
self.core = core
@ -45,7 +53,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
"post_torrent_remove": [],
"post_session_load": []
}
self.status_fields = {}
# Call the PluginManagerBase constructor
@ -55,19 +63,19 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
def start(self):
# 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()
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:
@ -79,13 +87,13 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
def get_core(self):
"""Returns a reference to the core"""
return self.core
def register_status_field(self, field, function):
"""Register a new status field. This can be used in the same way the
client requests other status information from core."""
log.debug("Registering status field %s with PluginManager", field)
self.status_fields[field] = function
def deregister_status_field(self, field):
"""Deregisters a status field"""
log.debug("Deregistering status field %s with PluginManager", field)
@ -93,7 +101,7 @@ 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 = {}
@ -104,27 +112,27 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
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.
"""
@ -139,16 +147,16 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
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

@ -1,476 +0,0 @@
#
# preferencesmanager.py
#
# Copyright (C) 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 os.path
import threading
import gobject
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!")
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,
"allow_remote": False,
"compact_allocation": False,
"download_location": deluge.common.get_default_download_dir(),
"listen_ports": [6881, 6891],
"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,
"upnp": True,
"natpmp": True,
"utpex": True,
"lsd": True,
"enc_in_policy": 1,
"enc_out_policy": 1,
"enc_level": 2,
"enc_prefer_rc4": True,
"max_connections_global": 200,
"max_upload_speed": -1.0,
"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 50)(),
"max_connections_per_second": 20,
"ignore_limits_on_local_network": True,
"max_connections_per_torrent": -1,
"max_upload_slots_per_torrent": -1,
"max_upload_speed_per_torrent": -1,
"max_download_speed_per_torrent": -1,
"enabled_plugins": [],
"autoadd_location": deluge.common.get_default_download_dir(),
"autoadd_enable": False,
"add_paused": False,
"max_active_seeding": 5,
"max_active_downloading": 3,
"max_active_limit": 8,
"dont_count_slow_torrents": False,
"queue_new_to_top": False,
"stop_seed_at_ratio": False,
"remove_seed_at_ratio": False,
"stop_seed_ratio": 2.00,
"share_ratio_limit": 2.00,
"seed_time_ratio_limit": 7.00,
"seed_time_limit": 180,
"auto_managed": True,
"move_completed": False,
"move_completed_path": deluge.common.get_default_download_dir(),
"new_release_check": True,
"proxies": {
"peer": {
"type": 0,
"hostname": "",
"username": "",
"password": "",
"port": 8080
},
"web_seed": {
"type": 0,
"hostname": "",
"username": "",
"password": "",
"port": 8080
},
"tracker": {
"type": 0,
"hostname": "",
"username": "",
"password": "",
"port": 8080
},
"dht": {
"type": 0,
"hostname": "",
"username": "",
"password": "",
"port": 8080
},
},
"outgoing_ports": [0, 0],
"random_outgoing_ports": True,
"peer_tos": "0x00",
"rate_limit_ip_overhead": True
}
class PreferencesManager(component.Component):
def __init__(self):
component.Component.__init__(self, "PreferencesManager")
self.config = deluge.configmanager.ConfigManager("core.conf", DEFAULT_PREFS)
def start(self):
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("random_port",
self._on_set_random_port)
self.config.register_set_function("outgoing_ports",
self._on_set_outgoing_ports)
self.config.register_set_function("random_outgoing_ports",
self._on_set_random_outgoing_ports)
self.config.register_set_function("peer_tos",
self._on_set_peer_tos)
self.config.register_set_function("dht", self._on_set_dht)
self.config.register_set_function("upnp", self._on_set_upnp)
self.config.register_set_function("natpmp", self._on_set_natpmp)
self.config.register_set_function("utpex", self._on_set_utpex)
self.config.register_set_function("lsd", self._on_set_lsd)
self.config.register_set_function("enc_in_policy",
self._on_set_encryption)
self.config.register_set_function("enc_out_policy",
self._on_set_encryption)
self.config.register_set_function("enc_level",
self._on_set_encryption)
self.config.register_set_function("enc_prefer_rc4",
self._on_set_encryption)
self.config.register_set_function("max_connections_global",
self._on_set_max_connections_global)
self.config.register_set_function("max_upload_speed",
self._on_set_max_upload_speed)
self.config.register_set_function("max_download_speed",
self._on_set_max_download_speed)
self.config.register_set_function("max_upload_slots_global",
self._on_set_max_upload_slots_global)
self.config.register_set_function("max_half_open_connections",
self._on_set_max_half_open_connections)
self.config.register_set_function("max_connections_per_second",
self._on_set_max_connections_per_second)
self.config.register_set_function("ignore_limits_on_local_network",
self._on_ignore_limits_on_local_network)
self.config.register_set_function("share_ratio_limit",
self._on_set_share_ratio_limit)
self.config.register_set_function("seed_time_ratio_limit",
self._on_set_seed_time_ratio_limit)
self.config.register_set_function("seed_time_limit",
self._on_set_seed_time_limit)
self.config.register_set_function("max_active_downloading",
self._on_set_max_active_downloading)
self.config.register_set_function("max_active_seeding",
self._on_set_max_active_seeding)
self.config.register_set_function("max_active_limit",
self._on_set_max_active_limit)
self.config.register_set_function("dont_count_slow_torrents",
self._on_set_dont_count_slow_torrents)
self.config.register_set_function("send_info",
self._on_send_info)
self.config.register_set_function("proxies",
self._on_set_proxies)
self.new_release_timer = None
self.config.register_set_function("new_release_check",
self._on_new_release_check)
self.config.register_set_function("rate_limit_ip_overhead",
self._on_rate_limit_ip_overhead)
self.config.register_change_callback(self._on_config_value_change)
# Config set functions
def _on_config_value_change(self, key, value):
self.signals.emit("config_value_changed", key, value)
def _on_set_torrentfiles_location(self, key, value):
if self.config["copy_torrent_file"]:
try:
os.makedirs(value)
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])
def _on_set_random_port(self, key, value):
log.debug("random port value set to %s", value)
# We need to check if the value has been changed to true and false
# and then handle accordingly.
if value:
import random
listen_ports = []
randrange = lambda: random.randrange(49152, 65525)
listen_ports.append(randrange())
listen_ports.append(listen_ports[0]+10)
else:
listen_ports = self.config["listen_ports"]
# 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])
def _on_set_outgoing_ports(self, key, value):
if not self.config["random_outgoing_ports"]:
log.debug("outgoing port range set to %s-%s", value[0], value[1])
self.settings.outgoing_ports = value[0], value[1]
self.session.set_settings(self.settings)
def _on_set_random_outgoing_ports(self, key, value):
if value:
self.session.outgoing_ports(0, 0)
def _on_set_peer_tos(self, key, value):
log.debug("setting peer_tos to: %s", value)
try:
self.settings.peer_tos = chr(int(value, 16))
except ValueError, e:
log.debug("Invalid tos byte: %s", e)
return
self.session.set_settings(self.settings)
def _on_set_dht(self, key, value):
log.debug("dht value set to %s", value)
state_file = deluge.common.get_default_config_dir("dht.state")
if value:
state = None
try:
state = lt.bdecode(open(state_file, "rb").read())
except Exception, e:
log.warning("Unable to read DHT state file: %s", e)
try:
self.session.start_dht(state)
except Exception, e:
log.warning("Restoring old DHT state failed: %s", e)
self.session.start_dht(None)
self.session.add_dht_router("router.bittorrent.com", 6881)
self.session.add_dht_router("router.utorrent.com", 6881)
self.session.add_dht_router("router.bitcomet.com", 6881)
else:
self.core.save_dht_state()
self.session.stop_dht()
def _on_set_upnp(self, key, value):
log.debug("upnp value set to %s", value)
if value:
self.session.start_upnp()
else:
self.session.stop_upnp()
def _on_set_natpmp(self, key, value):
log.debug("natpmp value set to %s", value)
if value:
self.session.start_natpmp()
else:
self.session.stop_natpmp()
def _on_set_lsd(self, key, value):
log.debug("lsd value set to %s", value)
if value:
self.session.start_lsd()
else:
self.session.stop_lsd()
def _on_set_utpex(self, key, value):
log.debug("utpex value set to %s", value)
if value:
self.session.add_extension(lt.create_ut_pex_plugin)
def _on_set_encryption(self, key, value):
log.debug("encryption value %s set to %s..", key, value)
pe_settings = lt.pe_settings()
pe_settings.out_enc_policy = \
lt.enc_policy(self.config["enc_out_policy"])
pe_settings.in_enc_policy = lt.enc_policy(self.config["enc_in_policy"])
pe_settings.allowed_enc_level = lt.enc_level(self.config["enc_level"])
pe_settings.prefer_rc4 = self.config["enc_prefer_rc4"]
self.session.set_pe_settings(pe_settings)
set = self.session.get_pe_settings()
log.debug("encryption settings:\n\t\t\tout_policy: %s\n\t\t\
in_policy: %s\n\t\t\tlevel: %s\n\t\t\tprefer_rc4: %s",
set.out_enc_policy,
set.in_enc_policy,
set.allowed_enc_level,
set.prefer_rc4)
def _on_set_max_connections_global(self, key, value):
log.debug("max_connections_global set to %s..", value)
self.session.set_max_connections(value)
def _on_set_max_upload_speed(self, key, value):
log.debug("max_upload_speed set to %s..", value)
# We need to convert Kb/s to B/s
if value < 0:
v = -1
else:
v = int(value * 1024)
self.session.set_upload_rate_limit(v)
def _on_set_max_download_speed(self, key, value):
log.debug("max_download_speed set to %s..", value)
# We need to convert Kb/s to B/s
if value < 0:
v = -1
else:
v = int(value * 1024)
self.session.set_download_rate_limit(v)
def _on_set_max_upload_slots_global(self, key, value):
log.debug("max_upload_slots_global set to %s..", value)
self.session.set_max_uploads(value)
def _on_set_max_half_open_connections(self, key, value):
self.session.set_max_half_open_connections(value)
def _on_set_max_connections_per_second(self, key, value):
self.settings.connection_speed = value
self.session.set_settings(self.settings)
def _on_ignore_limits_on_local_network(self, key, value):
self.settings.ignore_limits_on_local_network = value
self.session.set_settings(self.settings)
def _on_set_share_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.share_ratio_limit = value
self.session.set_settings(self.settings)
def _on_set_seed_time_ratio_limit(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.seed_time_ratio_limit = value
self.session.set_settings(self.settings)
def _on_set_seed_time_limit(self, key, value):
log.debug("%s set to %s..", key, value)
# This value is stored in minutes in deluge, but libtorrent wants seconds
self.settings.seed_time_limit = int(value * 60)
self.session.set_settings(self.settings)
def _on_set_max_active_downloading(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_downloads: %s", self.settings.active_downloads)
self.settings.active_downloads = value
self.session.set_settings(self.settings)
def _on_set_max_active_seeding(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_seeds: %s", self.settings.active_seeds)
self.settings.active_seeds = value
self.session.set_settings(self.settings)
def _on_set_max_active_limit(self, key, value):
log.debug("%s set to %s..", key, value)
log.debug("active_limit: %s", self.settings.active_limit)
self.settings.active_limit = value
self.session.set_settings(self.settings)
def _on_set_dont_count_slow_torrents(self, key, value):
log.debug("%s set to %s..", key, value)
self.settings.dont_count_slow_torrents = value
self.session.set_settings(self.settings)
def _on_send_info(self, key, value):
log.debug("Sending anonymous stats..")
"""sends anonymous stats home"""
class Send_Info_Thread(threading.Thread):
def __init__(self, config):
self.config = config
threading.Thread.__init__(self)
def run(self):
import time
now = time.time()
# check if we've done this within the last week or never
if (now - self.config["info_sent"]) >= (60 * 60 * 24 * 7):
import deluge.common
from urllib import quote_plus
from urllib2 import urlopen
import platform
try:
url = "http://deluge-torrent.org/stats_get.php?processor=" + \
platform.machine() + "&python=" + platform.python_version() \
+ "&deluge=" + deluge.common.get_version() \
+ "&os=" + platform.system() \
+ "&plugins=" + quote_plus(self.config["enabled_plugins"])
urlopen(url)
except IOError, e:
log.debug("Network error while trying to send info: %s", e)
else:
self.config["info_sent"] = now
if value:
Send_Info_Thread(self.config).start()
def _on_new_release_check(self, key, value):
if value:
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)
# 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)
else:
if self.new_release_timer:
gobject.source.remove(self.new_release_timer)
def _on_set_proxies(self, key, value):
for k, v in value.items():
if v["type"]:
proxy_settings = lt.proxy_settings()
proxy_settings.type = lt.proxy_type(v["type"])
proxy_settings.username = v["username"]
proxy_settings.password = v["password"]
proxy_settings.hostname = v["hostname"]
proxy_settings.port = v["port"]
log.debug("setting %s proxy settings", k)
getattr(self.session, "set_%s_proxy" % k)(proxy_settings)
def _on_rate_limit_ip_overhead(self, key, value):
log.debug("%s: %s", key, value)
self.settings.rate_limit_ip_overhead = value
self.session.set_settings(self.settings)

View File

@ -1,114 +0,0 @@
#
# rpcserver.py
#
# Copyright (C) 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 gobject
from deluge.SimpleXMLRPCServer import SimpleXMLRPCServer
from deluge.SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from SocketServer import ThreadingMixIn
from base64 import decodestring, encodestring
from deluge.log import LOG as log
import deluge.component as component
import deluge.configmanager
def export(func):
func._rpcserver_export = True
return func
class RPCServer(component.Component):
def __init__(self, port):
component.Component.__init__(self, "RPCServer")
# Get config
self.config = deluge.configmanager.ConfigManager("core.conf")
if port == None:
port = self.config["daemon_port"]
if self.config["allow_remote"]:
hostname = ""
else:
hostname = "localhost"
# Setup the xmlrpc server
try:
log.info("Starting XMLRPC server %s:%s", hostname, port)
self.server = XMLRPCServer((hostname, port),
requestHandler=BasicAuthXMLRPCRequestHandler,
logRequests=False,
allow_none=True)
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):
if not name:
name = obj.__class__.__name__
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)
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.
"""
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)
# if cannot authenticate, end the connection
self.send_response(401)
self.end_headers()

View File

@ -1,72 +1,51 @@
#
# signalmanager.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <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.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"""
@ -80,16 +59,9 @@ class SignalManager(component.Component):
"""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))
self.clients[uri] = xmlrpclib.ServerProxy(uri)
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)
@ -106,3 +78,4 @@ class SignalManager(component.Component):
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, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
#
# Deluge is free software.
#
@ -21,91 +21,36 @@
# 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.
"""Internal Torrent class"""
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!")
except ImportError:
import deluge.libtorrent as lt
import deluge.common
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.log import LOG as log
import deluge.xmlrpclib
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().iteritems()
def has_key(self, key):
return super(TorrentOptions, self).has_key(key) or key in self.default_keys
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)
elif key in self.default_keys:
if self.default_keys[key] and self.default_keys[key] in self.config.config:
return self.config[self.default_keys[key]]
else:
return self.default_keys[key]
else:
raise KeyError
class Torrent:
"""Torrent holds information about torrents added to the libtorrent session.
"""
def __init__(self, handle, options, state=None, filename=None, magnet=None):
def __init__(self, handle, options, state=None, filename=None):
log.debug("Creating torrent object %s", str(handle.info_hash()))
# Get the core config
self.config = ConfigManager("core.conf")
@ -117,50 +62,37 @@ class Torrent:
# Set the torrent_id for this torrent
self.torrent_id = str(handle.info_hash())
# Let's us know if we're waiting on a lt alert
self.waiting_on_resume_data = False
# Keep a list of file indexes we're waiting for file_rename alerts on
# This also includes the old_folder and new_folder to know what signal to send
# This is so we can send one folder_renamed signal instead of multiple
# file_renamed signals.
# [(old_folder, new_folder, [*indexes]), ...]
self.waiting_on_folder_rename = []
# We store the filename just in case we need to make a copy of the torrentfile
if not filename:
# If no filename was provided, then just use the infohash
filename = self.torrent_id
self.filename = filename
# Store the magnet uri used to add this torrent if available
self.magnet = magnet
# Holds status info so that we don't need to keep getting it from lt
self.status = self.handle.status()
try:
self.torrent_info = self.handle.get_torrent_info()
except RuntimeError:
self.torrent_info = None
self.torrent_info = self.handle.get_torrent_info()
# Files dictionary
self.files = self.get_files()
# Set the default file priorities to normal
self.file_priorities = [1]* len(self.files)
# Default total_uploaded to 0, this may be changed by the state
self.total_uploaded = 0
# Set the default options
self.options = TorrentOptions()
self.options.update(options)
# Set default auto_managed value
self.auto_managed = options["auto_managed"]
if not handle.is_paused():
handle.auto_managed(self.auto_managed)
# We need to keep track if the torrent is finished in the state to prevent
# some weird things on state load.
self.is_finished = False
# Queueing options
self.stop_at_ratio = False
self.stop_ratio = 2.00
self.remove_at_ratio = False
# Load values from state if we have it
if state:
if state is not None:
# This is for saving the total uploaded between sessions
self.total_uploaded = state.total_uploaded
# Set the trackers
@ -169,9 +101,9 @@ class Torrent:
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
self.set_stop_at_ratio(state.stop_at_ratio)
self.set_stop_ratio(state.stop_ratio)
self.set_remove_at_ratio(state.remove_at_ratio)
else:
# Tracker list
self.trackers = []
@ -182,10 +114,21 @@ class Torrent:
tracker["tier"] = value.tier
self.trackers.append(tracker)
# Various torrent options
self.handle.resolve_countries(True)
self.set_options(self.options)
# Set the allocation mode
self.compact = options["compact_allocation"]
# Various torrent options
self.set_max_connections(options["max_connections_per_torrent"])
self.set_max_upload_slots(options["max_upload_slots_per_torrent"])
self.set_max_upload_speed(options["max_upload_speed_per_torrent"])
self.set_max_download_speed(options["max_download_speed_per_torrent"])
self.set_prioritize_first_last(options["prioritize_first_last_pieces"])
self.handle.resolve_countries(True)
if options.has_key("file_priorities"):
self.set_file_priorities(options["file_priorities"])
# Where the torrent is being saved to
self.save_path = options["download_location"]
# Status message holds error info about the torrent
self.statusmsg = "OK"
@ -195,86 +138,54 @@ class Torrent:
# The tracker status
self.tracker_status = ""
if state:
self.time_added = state.time_added
else:
self.time_added = time.time()
log.debug("Torrent object created.")
## Options methods ##
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,
}
for (key, value) in options.items():
if OPTIONS_FUNCS.has_key(key):
OPTIONS_FUNCS[key](value)
self.options.update(options)
def get_options(self):
return self.options
def set_tracker_status(self, status):
"""Sets the tracker status"""
self.tracker_status = status
def set_max_connections(self, max_connections):
self.options["max_connections"] = int(max_connections)
self.handle.set_max_connections(max_connections)
self.max_connections = int(max_connections)
self.handle.set_max_connections(self.max_connections)
def set_max_upload_slots(self, max_slots):
self.options["max_upload_slots"] = int(max_slots)
self.handle.set_max_uploads(max_slots)
self.max_upload_slots = int(max_slots)
self.handle.set_max_uploads(self.max_upload_slots)
def set_max_upload_speed(self, m_up_speed):
self.options["max_upload_speed"] = m_up_speed
if m_up_speed < 0:
v = -1
else:
v = int(m_up_speed * 1024)
self.handle.set_upload_limit(v)
self.max_upload_speed = m_up_speed
self.handle.set_upload_limit(int(m_up_speed * 1024))
def set_max_download_speed(self, m_down_speed):
self.options["max_download_speed"] = m_down_speed
if m_down_speed < 0:
v = -1
else:
v = int(m_down_speed * 1024)
self.handle.set_download_limit(v)
self.max_download_speed = m_down_speed
self.handle.set_download_limit(int(m_down_speed * 1024))
def set_prioritize_first_last(self, prioritize):
self.options["prioritize_first_last_pieces"] = prioritize
if prioritize:
if self.handle.has_metadata():
if self.handle.get_torrent_info().num_files() == 1:
# We only do this if one file is in the torrent
priorities = [1] * self.handle.get_torrent_info().num_pieces()
priorities[0] = 7
priorities[-1] = 7
self.handle.prioritize_pieces(priorities)
self.prioritize_first_last = prioritize
if self.prioritize_first_last:
if self.handle.get_torrent_info().num_files() == 1:
# We only do this if one file is in the torrent
priorities = [1] * self.handle.get_torrent_info().num_pieces()
priorities[0] = 7
priorities[-1] = 7
self.handle.prioritize_pieces(priorities)
def set_save_path(self, save_path):
self.save_path = save_path
def set_auto_managed(self, auto_managed):
self.options["auto_managed"] = auto_managed
if not (self.handle.is_paused() and not self.handle.is_auto_managed()):
self.handle.auto_managed(auto_managed)
self.update_state()
self.auto_managed = auto_managed
self.handle.auto_managed(auto_managed)
self.update_state()
def set_stop_ratio(self, stop_ratio):
self.options["stop_ratio"] = stop_ratio
self.stop_ratio = stop_ratio
def set_stop_at_ratio(self, stop_at_ratio):
self.options["stop_at_ratio"] = stop_at_ratio
self.stop_at_ratio = stop_at_ratio
def set_remove_at_ratio(self, remove_at_ratio):
self.options["remove_at_ratio"] = remove_at_ratio
self.remove_at_ratio = remove_at_ratio
def set_file_priorities(self, file_priorities):
if len(file_priorities) != len(self.files):
@ -282,29 +193,29 @@ class Torrent:
self.options["file_priorities"] = self.handle.file_priorities()
return
if self.options["compact_allocation"]:
if self.compact:
log.debug("setting file priority with compact allocation does not work!")
self.options["file_priorities"] = self.handle.file_priorities()
self.file_priorities = self.handle.file_priorities()
return
log.debug("setting %s's file priorities: %s", self.torrent_id, file_priorities)
self.handle.prioritize_files(file_priorities)
if 0 in self.options["file_priorities"]:
if 0 in self.file_priorities:
# We have previously marked a file 'Do Not Download'
# Check to see if we have changed any 0's to >0 and change state accordingly
for index, priority in enumerate(self.options["file_priorities"]):
for index, priority in enumerate(self.file_priorities):
if priority == 0 and file_priorities[index] > 0:
# We have a changed 'Do Not Download' to a download priority
self.is_finished = False
self.update_state()
break
self.options["file_priorities"] = file_priorities
self.file_priorities = file_priorities
# Set the first/last priorities if needed
self.set_prioritize_first_last(self.options["prioritize_first_last_pieces"])
self.set_prioritize_first_last(self.prioritize_first_last)
def set_trackers(self, trackers):
"""Sets trackers"""
@ -337,33 +248,13 @@ class Torrent:
# Force a reannounce if there is at least 1 tracker
self.force_reannounce()
### End Options methods ###
def set_save_path(self, save_path):
self.options["download_location"] = save_path
def set_tracker_status(self, status):
"""Sets the tracker status"""
self.tracker_status = self.get_tracker_host() + ": " + status
def update_state(self):
"""Updates the state based on what libtorrent's state for the torrent is"""
# Set the initial state based on the lt state
LTSTATE = deluge.common.LT_TORRENT_STATE
ltstate = int(self.handle.status().state)
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
log.debug("set_state_based_on_ltstate: %s", ltstate)
if ltstate == LTSTATE["Queued"] or ltstate == LTSTATE["Checking"]:
self.state = "Checking"
@ -375,9 +266,14 @@ class Torrent:
elif ltstate == LTSTATE["Allocating"]:
self.state = "Allocating"
if self.handle.is_paused() and self.handle.is_auto_managed() and not component.get("Core").session.is_paused():
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():
self.state = "Queued"
elif component.get("Core").session.is_paused() or (self.handle.is_paused() and not self.handle.is_auto_managed()):
elif self.handle.is_paused() and not self.handle.is_auto_managed():
self.state = "Paused"
def set_state(self, state):
@ -399,14 +295,6 @@ class Torrent:
else:
status = self.status
if self.is_finished and (self.options["stop_at_ratio"] or self.config["stop_seed_at_ratio"]):
# We're a seed, so calculate the time to the 'stop_share_ratio'
if not status.upload_payload_rate:
return 0
stop_ratio = self.config["stop_seed_ratio"] if self.config["stop_seed_at_ratio"] else self.options["stop_ratio"]
return ((status.all_time_download * stop_ratio) - status.all_time_upload) / status.upload_payload_rate
left = status.total_wanted - status.total_done
if left <= 0 or status.download_payload_rate == 0:
@ -426,33 +314,25 @@ class Torrent:
else:
status = self.status
if status.all_time_download > 0:
downloaded = status.all_time_download
elif status.total_done > 0:
# We use 'total_done' if the downloaded value is 0
downloaded = status.total_done
else:
# Return -1.0 to signify infinity
# Return -1.0 if the downloaded bytes is 0, this is to represent infinity
if status.all_time_download == 0:
return -1.0
return float(status.all_time_upload) / float(downloaded)
return float(status.all_time_upload) / float(status.all_time_download)
def get_files(self):
"""Returns a list of files this torrent contains"""
if self.torrent_info == None and self.handle.has_metadata():
if self.torrent_info == None:
torrent_info = self.handle.get_torrent_info()
else:
torrent_info = self.torrent_info
if not torrent_info:
return []
ret = []
files = torrent_info.files()
for index, file in enumerate(files):
ret.append({
'index': index,
'path': file.path.decode("utf8", "ignore"),
'path': file.path,
'size': file.size,
'offset': file.offset
})
@ -486,8 +366,7 @@ class Torrent:
"down_speed": peer.down_speed,
"country": country,
"client": client,
"seed": peer.flags & peer.seed,
"progress": peer.progress
"seed": peer.flags & peer.seed
})
return ret
@ -498,9 +377,6 @@ class Torrent:
def get_file_progress(self):
"""Returns the file progress as a list of floats.. 0.0 -> 1.0"""
if not self.handle.has_metadata():
return 0.0
file_progress = self.handle.file_progress()
ret = []
for i,f in enumerate(self.files):
@ -511,45 +387,11 @@ class Torrent:
return ret
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 not self.status:
self.status = self.handle.status()
tracker = self.status.current_tracker
if not tracker and self.trackers:
tracker = self.trackers[0]["url"]
if tracker:
url = urlparse(tracker)
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:
if parts[-2] in ("co", "com", "net", "org") or parts[-1] in ("uk"):
host = ".".join(parts[-3:])
else:
host = ".".join(parts[-2:])
return host
return ""
def get_status(self, keys):
"""Returns the status of the torrent based on the keys provided"""
# Create the full dictionary
self.status = self.handle.status()
if self.handle.has_metadata():
self.torrent_info = self.handle.get_torrent_info()
self.torrent_info = self.handle.get_torrent_info()
# Adjust progress to be 0-100 value
progress = self.status.progress * 100
@ -559,12 +401,10 @@ class Torrent:
if distributed_copies < 0:
distributed_copies = 0.0
#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,
"all_time_download": self.status.all_time_download,
"state": self.state,
"paused": self.status.paused,
"progress": progress,
@ -581,74 +421,44 @@ class Torrent:
"tracker": self.status.current_tracker,
"trackers": self.trackers,
"tracker_status": self.tracker_status,
"save_path": self.options["download_location"],
"save_path": self.save_path,
"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"],
"file_priorities": self.file_priorities,
"compact": self.compact,
"max_connections": self.max_connections,
"max_upload_slots": self.max_upload_slots,
"max_upload_speed": self.max_upload_speed,
"max_download_speed": self.max_download_speed,
"prioritize_first_last": self.prioritize_first_last,
"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
"is_auto_managed": self.auto_managed,
"stop_ratio": self.stop_ratio,
"stop_at_ratio": self.stop_at_ratio,
"remove_at_ratio": self.remove_at_ratio
}
def ti_name():
if self.handle.has_metadata():
try:
return self.torrent_info.name().decode("utf8", "ignore")
except UnicodeDecodeError:
return self.torrent_info.name()
return self.torrent_id
def ti_priv():
if self.handle.has_metadata():
return self.torrent_info.priv()
return False
def ti_total_size():
if self.handle.has_metadata():
return self.torrent_info.total_size()
return 0
def ti_num_files():
if self.handle.has_metadata():
return self.torrent_info.num_files()
return 0
def ti_num_pieces():
if self.handle.has_metadata():
return self.torrent_info.num_pieces()
return 0
def ti_piece_length():
if self.handle.has_metadata():
return self.torrent_info.piece_length()
return 0
fns = {
"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,
"name": self.torrent_info.name,
"private": self.torrent_info.priv,
"total_size": self.torrent_info.total_size,
"num_files": self.torrent_info.num_files,
"num_pieces": self.torrent_info.num_pieces,
"piece_length": self.torrent_info.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
}
self.status = None
self.torrent_info = None
# Create the desired status dictionary and return it
status_dict = {}
@ -706,9 +516,9 @@ class Torrent:
if self.handle.is_finished():
# If the torrent has already reached it's 'stop_seed_ratio' then do not do anything
if self.config["stop_seed_at_ratio"] or self.options["stop_at_ratio"]:
if self.options["stop_at_ratio"]:
ratio = self.options["stop_ratio"]
if self.config["stop_seed_at_ratio"] or self.stop_at_ratio:
if self.stop_at_ratio:
ratio = self.stop_ratio
else:
ratio = self.config["stop_seed_ratio"]
@ -716,7 +526,7 @@ class Torrent:
self.signals.emit("torrent_resume_at_stop_ratio")
return
if self.options["auto_managed"]:
if self.auto_managed:
# This torrent is to be auto-managed by lt queueing
self.handle.auto_managed(True)
@ -727,15 +537,6 @@ class Torrent:
return True
def connect_peer(self, ip, port):
"""adds manual peer"""
try:
self.handle.connect_peer((ip, int(port)), 0)
except Exception, e:
log.debug("Unable to connect to peer: %s", e)
return False
return True
def move_storage(self, dest):
"""Move a torrent's storage location"""
try:
@ -745,31 +546,21 @@ class Torrent:
return True
def save_resume_data(self):
"""Signals libtorrent to build resume data for this torrent, it gets
returned in a libtorrent alert"""
self.handle.save_resume_data()
self.waiting_on_resume_data = True
def write_resume_data(self, resume_data):
def write_fastresume(self):
"""Writes the .fastresume file for the torrent"""
resume_data = lt.bencode(resume_data)
resume_data = lt.bencode(self.handle.write_resume_data())
path = "%s/%s.fastresume" % (
self.config["state_location"],
self.torrent_id)
log.debug("Saving fastresume file: %s", path)
try:
self.delete_fastresume()
log.debug("Saving fastresume file: %s", path)
fastresume = open(path, "wb")
fastresume.write(resume_data)
fastresume.flush()
os.fsync(fastresume.fileno())
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" % (
@ -781,22 +572,6 @@ class Torrent:
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"],
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)
torrent_file = {}
torrent_file["info"] = md
open(path, "wb").write(lt.bencode(torrent_file))
except Exception, e:
log.warning("Unable to save torrent file: %s", e)
def delete_torrentfile(self):
"""Deletes the .torrent file in the state"""
path = "%s/%s.torrent" % (
@ -836,28 +611,3 @@ class Torrent:
log.debug("Unable to force recheck: %s", e)
return False
return True
def rename_files(self, filenames):
"""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)
def rename_folder(self, folder, new_folder):
"""Renames a folder within a torrent. This basically does a file rename
on all of the folders children."""
log.debug("attempting to rename folder: %s to %s", folder, new_folder)
if len(new_folder) < 1:
log.error("Attempting to rename a folder with an invalid folder name: %s", new_folder)
return
if new_folder[-1:] != "/":
new_folder += "/"
wait_on_folder = (folder, new_folder, [])
for f in self.get_files():
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.waiting_on_folder_rename.append(wait_on_folder)

View File

@ -1,27 +1,35 @@
#
# torrentmanager.py
#
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <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.
"""TorrentManager handles Torrent objects"""
@ -29,23 +37,18 @@ import cPickle
import os.path
import os
import time
import shutil
import gobject
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!")
except ImportError:
import deluge.libtorrent as lt
import deluge.common
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.core.torrent import Torrent
from deluge.core.torrent import TorrentOptions
import deluge.core.oldstateupgrader
from deluge.log import LOG as log
@ -57,7 +60,7 @@ class TorrentState:
total_uploaded=0,
trackers=None,
compact=False,
paused=False,
paused=False,
save_path=None,
max_connections=-1,
max_upload_slots=-1,
@ -70,9 +73,7 @@ class TorrentState:
is_finished=False,
stop_ratio=2.00,
stop_at_ratio=False,
remove_at_ratio=False,
magnet=None,
time_added=-1
remove_at_ratio=False
):
self.torrent_id = torrent_id
self.filename = filename
@ -80,8 +81,6 @@ class TorrentState:
self.trackers = trackers
self.queue = queue
self.is_finished = is_finished
self.magnet = magnet
self.time_added = time_added
# Options
self.compact = compact
@ -106,7 +105,7 @@ class TorrentManager(component.Component):
"""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."""
def __init__(self, session, alerts):
component.Component.__init__(self, "TorrentManager", interval=5000, depend=["PluginManager"])
log.debug("TorrentManager init..")
@ -119,12 +118,12 @@ class TorrentManager(component.Component):
# Create the torrents dict { torrent_id: Torrent }
self.torrents = {}
# This is a list of torrent_id when we shutdown the torrentmanager.
# We use this list to determine if all active torrents have been paused
# and that their resume data has been written.
self.shutdown_torrent_pause_list = []
# Register set functions
self.config.register_set_function("max_connections_per_torrent",
self.on_set_max_connections_per_torrent)
@ -134,9 +133,9 @@ class TorrentManager(component.Component):
self.on_set_max_upload_speed_per_torrent)
self.config.register_set_function("max_download_speed_per_torrent",
self.on_set_max_download_speed_per_torrent)
# Register alert functions
self.alerts.register_handler("torrent_finished_alert",
self.alerts.register_handler("torrent_finished_alert",
self.on_alert_torrent_finished)
self.alerts.register_handler("torrent_paused_alert",
self.on_alert_torrent_paused)
@ -153,25 +152,15 @@ class TorrentManager(component.Component):
self.on_alert_tracker_error)
self.alerts.register_handler("storage_moved_alert",
self.on_alert_storage_moved)
self.alerts.register_handler("torrent_resumed_alert",
self.alerts.register_handler("torrent_resumed_alert",
self.on_alert_torrent_resumed)
self.alerts.register_handler("state_changed_alert",
self.on_alert_state_changed)
self.alerts.register_handler("save_resume_data_alert",
self.on_alert_save_resume_data)
self.alerts.register_handler("save_resume_data_failed_alert",
self.on_alert_save_resume_data_failed)
self.alerts.register_handler("file_renamed_alert",
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")
# Run the old state upgrader before loading state
@ -183,41 +172,31 @@ class TorrentManager(component.Component):
# 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)
def stop(self):
# Save state on shutdown
self.save_state()
component.pause("AlertManager")
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)
# We have to wait for all torrents to pause and write their resume data
wait = True
while wait:
if self.shutdown_torrent_pause_list:
wait = True
else:
wait = False
for torrent in self.torrents.values():
if torrent.waiting_on_resume_data:
wait = True
break
time.sleep(0.01)
while self.shutdown_torrent_pause_list:
time.sleep(0.1)
# Wait for all alerts
self.alerts.handle_alerts(True)
def update(self):
for torrent_id, torrent in self.torrents.items():
if self.config["stop_seed_at_ratio"] or torrent.options["stop_at_ratio"] and torrent.state not in ("Checking", "Allocating"):
if self.config["stop_seed_at_ratio"] or torrent.stop_at_ratio:
stop_ratio = self.config["stop_seed_ratio"]
if torrent.options["stop_at_ratio"]:
stop_ratio = torrent.options["stop_ratio"]
if torrent.stop_at_ratio:
stop_ratio = torrent.stop_ratio
if torrent.get_ratio() >= stop_ratio and torrent.is_finished:
if self.config["remove_seed_at_ratio"] or torrent.options["remove_at_ratio"]:
if self.config["remove_seed_at_ratio"] or torrent.remove_at_ratio:
self.remove(torrent_id)
break
if not torrent.handle.is_paused():
@ -226,11 +205,11 @@ class TorrentManager(component.Component):
def __getitem__(self, torrent_id):
"""Return the Torrent with torrent_id"""
return self.torrents[torrent_id]
def get_torrent_list(self):
"""Returns a list of torrent_ids"""
return self.torrents.keys()
def get_torrent_info_from_file(self, filepath):
"""Returns a torrent_info for the file specified or None"""
torrent_info = None
@ -242,16 +221,16 @@ class TorrentManager(component.Component):
_file.close()
except (IOError, RuntimeError), e:
log.warning("Unable to open %s: %s", filepath, e)
return torrent_info
def 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"],
self.config["state_location"],
torrent_id + ".fastresume"),
"rb")
fastresume = _file.read()
@ -260,127 +239,128 @@ class TorrentManager(component.Component):
log.debug("Unable to load .fastresume: %s", e)
return str(fastresume)
def add(self, torrent_info=None, state=None, options=None, save_state=True,
filedump=None, filename=None, magnet=None):
filedump=None, filename=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:
log.debug("You must specify a valid torrent_info, torrent state or magnet.")
if torrent_info is None and state is None and filedump is None:
log.debug("You must specify a valid torrent_info or a torrent state object!")
return
log.debug("torrentmanager.add")
add_torrent_params = {}
if filedump is not None:
try:
torrent_info = lt.torrent_info(lt.bdecode(filedump))
except Exception, e:
log.error("Unable to decode torrent file!: %s", e)
if torrent_info is None and state:
if torrent_info is None:
# We have no torrent_info so we need to add the torrent with information
# from the state object.
# Populate the options dict from state
options = TorrentOptions()
options["max_connections"] = state.max_connections
options["max_upload_slots"] = state.max_upload_slots
options["max_upload_speed"] = state.max_upload_speed
options["max_download_speed"] = state.max_download_speed
options = {}
options["max_connections_per_torrent"] = state.max_connections
options["max_upload_slots_per_torrent"] = state.max_upload_slots
options["max_upload_speed_per_torrent"] = state.max_upload_speed
options["max_download_speed_per_torrent"] = state.max_download_speed
options["prioritize_first_last_pieces"] = state.prioritize_first_last
options["file_priorities"] = state.file_priorities
options["compact_allocation"] = state.compact
options["download_location"] = state.save_path
options["auto_managed"] = state.auto_managed
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:
magnet = 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
add_torrent_params["resume_data"] = self.get_resume_data_from_file(state.torrent_id)
else:
# We have a torrent_info object so we're not loading from state.
# Check if options is None and load defaults
options_keys = [
"compact_allocation",
"max_connections_per_torrent",
"max_upload_slots_per_torrent",
"max_upload_speed_per_torrent",
"max_download_speed_per_torrent",
"prioritize_first_last_pieces",
"download_location",
"add_paused",
"auto_managed"
]
if options == None:
options = TorrentOptions()
options = {}
for key in options_keys:
options[key] = self.config[key]
else:
o = TorrentOptions()
o.update(options)
options = o
for key in options_keys:
if not options.has_key(key):
options[key] = self.config[key]
add_torrent_params["ti"] = torrent_info
add_torrent_params["resume_data"] = ""
#log.info("Adding torrent: %s", filename)
log.debug("options: %s", options)
# Set the right storage_mode
if options["compact_allocation"]:
storage_mode = lt.storage_mode_t(2)
else:
storage_mode = lt.storage_mode_t(1)
try:
# Try to encode this as utf8 if needed
options["download_location"] = options["download_location"].encode("utf8")
except UnicodeDecodeError:
pass
# Fill in the rest of the add_torrent_params dictionary
add_torrent_params["save_path"] = options["download_location"]
add_torrent_params["save_path"] = options["download_location"].encode("utf8")
add_torrent_params["storage_mode"] = storage_mode
add_torrent_params["paused"] = True
add_torrent_params["auto_managed"] = False
add_torrent_params["duplicate_is_error"] = True
# We need to pause the AlertManager momentarily to prevent alerts
# for this torrent being generated before a Torrent object is created.
component.pause("AlertManager")
handle = None
try:
if magnet:
handle = lt.add_magnet_uri(self.session, magnet, add_torrent_params)
else:
handle = self.session.add_torrent(add_torrent_params)
handle = self.session.add_torrent(add_torrent_params)
except RuntimeError, e:
log.warning("Error adding torrent: %s", e)
if not handle or not handle.is_valid():
log.debug("torrent handle is invalid!")
# The torrent was not added to the session
component.resume("AlertManager")
return
log.debug("handle id: %s", str(handle.info_hash()))
# Set auto_managed to False because the torrent is paused
handle.auto_managed(False)
# Create a Torrent object
torrent = Torrent(handle, options, state, filename, magnet)
torrent = Torrent(handle, options, state, filename)
# Add the torrent object to the dictionary
self.torrents[torrent.torrent_id] = torrent
if self.config["queue_new_to_top"]:
handle.queue_position_top()
component.resume("AlertManager")
# Resume the torrent if needed
if not options["add_paused"]:
torrent.resume()
handle.resume()
handle.auto_managed(options["auto_managed"])
# 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(self.config["state_location"],
torrent.torrent_id + ".torrent"),
"wb")
save_file.write(filedump)
@ -403,10 +383,10 @@ class TorrentManager(component.Component):
if save_state:
# Save the session state
self.save_state()
# Emit the torrent_added signal
self.signals.emit("torrent_added", torrent.torrent_id)
return torrent.torrent_id
def load_torrent(self, torrent_id):
@ -417,45 +397,83 @@ 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"),
self.config["state_location"], torrent_id + ".torrent"),
"rb")
filedump = lt.bdecode(_file.read())
_file.close()
except (IOError, RuntimeError), e:
log.warning("Unable to open %s: %s", torrent_id, e)
return False
return filedump
def remove(self, torrent_id, remove_data=False):
def remove(self, torrent_id, remove_torrent=False, remove_data=False):
"""Remove a torrent from the manager"""
try:
self.session.remove_torrent(self.torrents[torrent_id].handle,
1 if remove_data else 0)
# Remove from libtorrent session
option = 0
# Remove data if set
if remove_data:
option = 1
self.session.remove_torrent(self.torrents[torrent_id].handle,
option)
except (RuntimeError, KeyError), e:
log.warning("Error removing torrent: %s", e)
return False
# Remove the .torrent file if requested
if remove_torrent:
try:
torrent_file = os.path.join(
self.config["torrentfiles_location"],
self.torrents[torrent_id].filename)
os.remove(torrent_file)
except Exception, e:
log.warning("Unable to remove .torrent file: %s", e)
# Remove the .fastresume if it exists
self.torrents[torrent_id].delete_fastresume()
# Remove the .torrent file in the state
self.torrents[torrent_id].delete_torrentfile()
# Remove the torrent from deluge's session
try:
del self.torrents[torrent_id]
except KeyError, ValueError:
return False
# Save the session state
self.save_state()
# Emit the signal to the clients
self.signals.emit("torrent_removed", torrent_id)
return True
def pause_all(self):
"""Pauses all torrents.. Returns a list of torrents paused."""
torrent_was_paused = False
for key in self.torrents.keys():
try:
self.torrents[key].pause()
torrent_was_paused = True
except:
log.warning("Unable to pause torrent %s", key)
return torrent_was_paused
def resume_all(self):
"""Resumes all torrents.. Returns True if at least 1 torrent is resumed"""
torrent_was_resumed = False
for key in self.torrents.keys():
if self.torrents[key].resume():
torrent_was_resumed = True
else:
log.warning("Unable to resume torrent %s", key)
return torrent_was_resumed
def load_state(self):
"""Load the state of the TorrentManager from the torrents.state file"""
state = TorrentManagerState()
@ -468,7 +486,7 @@ class TorrentManager(component.Component):
state_file.close()
except (EOFError, IOError, Exception), e:
log.warning("Unable to load state file: %s", e)
# Try to use an old state
try:
if dir(state.torrents[0]) != dir(TorrentState()):
@ -477,7 +495,7 @@ class TorrentManager(component.Component):
setattr(s, attr, getattr(TorrentState(), 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 = []
@ -488,14 +506,14 @@ class TorrentManager(component.Component):
break
if torrent_state not in ordered_state:
ordered_state.append(torrent_state)
for torrent_state in ordered_state:
try:
self.add(state=torrent_state, save_state=False)
except AttributeError, e:
log.error("Torrent state file is either corrupt or incompatible!")
break
# Run the post_session_load plugin hooks
self.plugins.run_post_session_load()
@ -507,63 +525,49 @@ class TorrentManager(component.Component):
paused = False
if torrent.state == "Paused":
paused = True
torrent_state = TorrentState(
torrent.torrent_id,
torrent.filename,
torrent.get_status(["total_uploaded"])["total_uploaded"],
torrent.get_status(["total_uploaded"])["total_uploaded"],
torrent.trackers,
torrent.options["compact_allocation"],
paused,
torrent.options["download_location"],
torrent.options["max_connections"],
torrent.options["max_upload_slots"],
torrent.options["max_upload_speed"],
torrent.options["max_download_speed"],
torrent.options["prioritize_first_last_pieces"],
torrent.options["file_priorities"],
torrent.compact,
paused,
torrent.save_path,
torrent.max_connections,
torrent.max_upload_slots,
torrent.max_upload_speed,
torrent.max_download_speed,
torrent.prioritize_first_last,
torrent.file_priorities,
torrent.get_queue_position(),
torrent.options["auto_managed"],
torrent.auto_managed,
torrent.is_finished,
torrent.options["stop_ratio"],
torrent.options["stop_at_ratio"],
torrent.options["remove_at_ratio"],
torrent.magnet,
torrent.time_added
torrent.stop_ratio,
torrent.stop_at_ratio,
torrent.remove_at_ratio
)
state.torrents.append(torrent_state)
# Pickle the TorrentManagerState object
try:
log.debug("Saving torrent state file.")
state_file = open(
os.path.join(self.config["state_location"], "torrents.state.new"),
os.path.join(self.config["state_location"], "torrents.state"),
"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.")
return True
# 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"))
except IOError:
log.warning("Unable to save state file.")
return True
# 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()
torrent.write_fastresume()
def queue_top(self, torrent_id):
"""Queue torrent to top"""
if self.torrents[torrent_id].get_queue_position() == 0:
@ -584,7 +588,7 @@ class TorrentManager(component.Component):
"""Queue torrent down one position"""
if self.torrents[torrent_id].get_queue_position() == (len(self.torrents) - 1):
return False
self.torrents[torrent_id].handle.queue_position_down()
return True
@ -595,13 +599,13 @@ class TorrentManager(component.Component):
self.torrents[torrent_id].handle.queue_position_bottom()
return True
def on_set_max_connections_per_torrent(self, key, value):
"""Sets the per-torrent connection limit"""
log.debug("max_connections_per_torrent set to %s..", value)
for key in self.torrents.keys():
self.torrents[key].set_max_connections(value)
def on_set_max_upload_slots_per_torrent(self, key, value):
"""Sets the per-torrent upload slot limit"""
log.debug("max_upload_slots_per_torrent set to %s..", value)
@ -612,7 +616,7 @@ class TorrentManager(component.Component):
log.debug("max_upload_speed_per_torrent set to %s..", value)
for key in self.torrents.keys():
self.torrents[key].set_max_upload_speed(value)
def on_set_max_download_speed_per_torrent(self, key, value):
log.debug("max_download_speed_per_torrent set to %s..", value)
for key in self.torrents.keys():
@ -626,21 +630,15 @@ class TorrentManager(component.Component):
torrent = self.torrents[torrent_id]
log.debug("%s is finished..", torrent_id)
# Move completed download to completed folder if needed
if not torrent.is_finished:
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
component.get("SignalManager").emit("torrent_finished", torrent_id)
if self.config["move_completed"] and not torrent.is_finished:
if torrent.save_path != self.config["move_completed_path"]:
torrent.move_storage(self.config["move_completed_path"])
torrent.is_finished = True
torrent.update_state()
torrent.save_resume_data()
torrent.write_fastresume()
component.get("SignalManager").emit("torrent_finished", torrent_id)
def on_alert_torrent_paused(self, alert):
log.debug("on_alert_torrent_paused")
# Get the torrent_id
@ -648,31 +646,31 @@ class TorrentManager(component.Component):
# Set the torrent state
self.torrents[torrent_id].update_state()
component.get("SignalManager").emit("torrent_paused", torrent_id)
# Write the fastresume file
self.torrents[torrent_id].save_resume_data()
self.torrents[torrent_id].write_fastresume()
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())
# Set the torrent state
self.torrents[torrent_id].update_state()
def on_alert_tracker_reply(self, alert):
log.debug("on_alert_tracker_reply: %s", alert.message())
log.debug("on_alert_tracker_reply")
# Get the torrent_id
torrent_id = str(alert.handle.info_hash())
# Set the tracker status for the torrent
try:
if alert.message() != "Got peers from DHT":
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.")
# 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:
@ -687,7 +685,7 @@ class TorrentManager(component.Component):
except RuntimeError:
log.debug("Invalid torrent handle.")
return
# Set the tracker status for the torrent
try:
self.torrents[torrent_id].set_tracker_status(_("Announce Sent"))
@ -705,7 +703,7 @@ class TorrentManager(component.Component):
self.torrents[torrent_id].set_tracker_status(tracker_status)
except KeyError:
log.debug("torrent_id doesn't exist.")
def on_alert_tracker_warning(self, alert):
log.debug("on_alert_tracker_warning")
# Get the torrent_id
@ -725,7 +723,7 @@ class TorrentManager(component.Component):
torrent.set_tracker_status(tracker_status)
except KeyError:
log.debug("torrent_id doesn't exist.")
def on_alert_storage_moved(self, alert):
log.debug("on_alert_storage_moved")
log.debug("save_path: %s", alert.handle.save_path())
@ -742,59 +740,10 @@ class TorrentManager(component.Component):
torrent = self.torrents[str(alert.handle.info_hash())]
torrent.is_finished = torrent.handle.is_seed()
torrent.update_state()
def on_alert_state_changed(self, alert):
log.debug("on_alert_state_changed")
try:
torrent_id = str(alert.handle.info_hash())
except RuntimeError:
return
if torrent_id in self.torrents:
self.torrents[torrent_id].update_state()
component.get("SignalManager").emit("torrent_state_changed", torrent_id)
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)
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())]
torrent.waiting_on_resume_data = False
def on_alert_file_renamed(self, alert):
log.debug("on_alert_file_renamed")
log.debug("index: %s name: %s", alert.index, alert.name)
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
for i, wait_on_folder in enumerate(torrent.waiting_on_folder_rename):
if alert.index in wait_on_folder[2]:
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])
del torrent.waiting_on_folder_rename[i]
break
# This isn't the last file to be renamed in this folder, so just
# remove the index and continue
torrent.waiting_on_folder_rename[i][2].remove(alert.index)
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)
def on_alert_metadata_received(self, alert):
log.debug("on_alert_metadata_received")
torrent = self.torrents[str(alert.handle.info_hash())]
torrent.write_torrentfile()
def on_alert_file_error(self, alert):
log.debug("on_alert_file_error: %s", alert.message())
torrent = self.torrents[str(alert.handle.info_hash())]
torrent.update_state()
self.torrents[torrent_id].update_state()
component.get("SignalManager").emit("torrent_state_changed", torrent_id)

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.

View File

@ -1,150 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg4848"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/active16.png"
inkscape:export-xdpi="1.7055545"
inkscape:export-ydpi="1.7055545"
sodipodi:docname="active.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs4850">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective4856" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5467">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.69776249;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 792.51261,596.13496 C 1787.1961,462.38583 1788.2786,460.03989 1788.2786,460.03989 L 2050.3447,889.51678 C 1692.1626,1024.6476 1428.8778,1128.1462 1119.6165,1246.9702 L 792.51261,596.13496 z"
id="path5469"
sodipodi:nodetypes="ccccc" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5471">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.69776249;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 792.51261,596.13496 C 1787.1961,462.38583 1788.2786,460.03989 1788.2786,460.03989 L 2050.3447,889.51678 C 1692.1626,1024.6476 1428.8778,1128.1462 1119.6165,1246.9702 L 792.51261,596.13496 z"
id="path5473"
sodipodi:nodetypes="ccccc" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5475">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.69776249;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 792.51261,596.13496 C 1787.1961,462.38583 1788.2786,460.03989 1788.2786,460.03989 L 2050.3447,889.51678 C 1692.1626,1024.6476 1428.8778,1128.1462 1119.6165,1246.9702 L 792.51261,596.13496 z"
id="path5477"
sodipodi:nodetypes="ccccc" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="798.86898"
inkscape:cy="436.74575"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1280"
inkscape:window-height="958"
inkscape:window-x="1280"
inkscape:window-y="0" />
<metadata
id="metadata4853">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
style="opacity:1"
id="g4871">
<path
inkscape:export-ydpi="1.7060417"
inkscape:export-xdpi="1.7060417"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
sodipodi:nodetypes="ccccc"
id="path2069"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
style="fill:#5599ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:export-ydpi="1.7060417"
inkscape:export-xdpi="1.7060417"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
sodipodi:nodetypes="ccccc"
id="path2071"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<path
inkscape:export-ydpi="1.7060417"
inkscape:export-xdpi="1.7060417"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
id="rect2634"
d="M 359.0208,369.47132 C 289.64507,437.53055 219.98727,505.41409 150.61154,573.47313 C 187.93874,573.54143 225.35922,573.40503 262.68661,573.47313 C 262.68661,654.06643 262.68661,734.65974 262.68661,815.25304 C 329.00806,815.25304 395.32971,815.25304 461.65134,815.25304 C 461.65134,734.86969 461.65134,654.48632 461.65134,574.10276 C 496.04273,574.16582 530.52013,574.0399 564.91152,574.10276 C 496.30183,505.79126 427.63028,437.78301 359.0208,369.47132 z"
style="fill:#93beff;fill-opacity:1;stroke:#000000;stroke-width:14.10382843;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
style="fill:#8dd35f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 1211.4629,48.95108 L 1486.8943,380.28348 C 1685.809,601.93264 1572.6117,871.37308 1269.7125,891.97968 C 843.5417,903.12256 866.584,556.04398 984.1842,396.83304 L 1211.4629,48.95108 z"
id="path4864"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417"
clip-path="url(#clipPath5475)"
transform="translate(-876,68)" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 1214.0279,98.39492 L 1461.5813,397.19306 C 1650.317,617.09928 1529.7344,842.54714 1260.2405,863.49918 C 880.4842,873.20083 905.3951,571.73736 1001.5905,422.6843 L 1214.0279,98.39492 z"
id="path4866"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417"
clip-path="url(#clipPath5471)"
transform="translate(-876,68)" />
<path
style="fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-width:14.1288912;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 1235.158,785.66485 C 1165.4485,716.69801 1095.4555,647.90922 1025.7459,578.94258 C 1063.2527,578.87336 1100.8533,579.01159 1138.3603,578.94258 C 1138.3603,497.27453 1138.3603,415.60647 1138.3603,333.93841 C 1205.0008,333.93841 1271.6416,333.93841 1338.2823,333.93841 C 1338.2823,415.39371 1338.2823,496.84903 1338.2823,578.30455 C 1372.8392,578.24065 1407.4825,578.36825 1442.0394,578.30455 C 1373.0995,647.52701 1304.0976,716.44219 1235.158,785.66485 z"
id="path4868"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417"
clip-path="url(#clipPath5467)"
transform="matrix(0.9958235,0,0,1.0000914,-871.02338,67.589213)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 742 B

View File

@ -2,95 +2,359 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg5684"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/alert16.png"
inkscape:export-xdpi="1.7055545"
inkscape:export-ydpi="1.7055545"
inkscape:version="0.45"
sodipodi:docbase="/home/andrew"
sodipodi:docname="alert.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
inkscape:export-filename="/home/andrew/alert16.png"
inkscape:export-xdpi="32.603073"
inkscape:export-ydpi="32.603073"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
sodipodi:modified="TRUE">
<defs
id="defs5686">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5692" />
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2973">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2975" />
<stop
style="stop-color:#eeeeec;stop-opacity:0;"
offset="1"
id="stop2977" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4128" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4130" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4114">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4116" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4118" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop3964" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4134" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4346" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop3966" />
</linearGradient>
<radialGradient
r="13.994944"
fy="33.506763"
fx="-10.089286"
cy="33.506763"
cx="-10.089286"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
gradientUnits="userSpaceOnUse"
id="radialGradient4019"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
gradientUnits="userSpaceOnUse"
id="radialGradient4004"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
id="radialGradient3999"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
r="13.994946"
fy="24.241488"
fx="61.662098"
cy="24.241488"
cx="61.662098"
id="radialGradient3943"
xlink:href="#linearGradient1312"
inkscape:collect="always" />
<linearGradient
id="linearGradient1312">
<stop
id="stop1314"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1316"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3995" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3997" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient3866"
cx="-22.375"
cy="18.499998"
fx="-22.375"
fy="18.499998"
r="14.33462"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="12.289036"
fy="63.965388"
fx="15.115514"
cy="63.965388"
cx="15.115514"
gradientTransform="scale(1.643990,0.608276)"
id="radialGradient5000"
xlink:href="#linearGradient4114"
inkscape:collect="always" />
<linearGradient
id="linearGradient4989">
<stop
id="stop4991"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4993"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4995"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop4997"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
id="stop4979"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4981"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
<linearGradient
id="linearGradient4825"
inkscape:collect="always">
<stop
id="stop4827"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop4829"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4114"
id="radialGradient6090"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1.64399,0.608276)"
cx="15.115514"
cy="63.965388"
fx="15.115514"
fy="63.965388"
r="12.289036" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4825"
id="radialGradient6098"
gradientUnits="userSpaceOnUse"
cx="12.071323"
cy="12.493138"
fx="12.071323"
fy="12.493138"
r="6.7175145" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6103"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.25463,-0.898371,0.979785,0.277703,-18.00903,32.03312)"
cx="17.903898"
cy="40.159222"
fx="17.903898"
fy="40.159222"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6106"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.583269,-0.431533,0.577146,0.78008,-5.80022,4.004109)"
cx="12.525543"
cy="38.09042"
fx="12.525543"
fy="38.09042"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1312"
id="radialGradient6109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.768231,1.13675,-0.820972,0.554824,-3.72248,-85.07126)"
cx="65.800331"
cy="27.16758"
fx="65.800331"
fy="27.16758"
r="12.972491" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="807.63627"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:zoom="7.4062501"
inkscape:cx="11.667315"
inkscape:cy="19.059135"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="686"
inkscape:window-height="711"
inkscape:window-x="1395"
inkscape:window-y="223" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1024"
inkscape:window-height="693"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:showpageshadow="false" />
<metadata
id="metadata5689">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
inkscape:groupmode="layer">
<path
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891000000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z "
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123984999999919;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022000000000"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<text
xml:space="preserve"
style="font-size:1091.49255371px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ff7878;fill-opacity:1;stroke:#000000;stroke-width:13.65081787;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="20.453644"
y="1303.4996"
style="font-size:55.97062302px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ff7878;fill-opacity:1;stroke:#000000;stroke-width:0.70000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="5.0072942"
y="59.560848"
id="text2767"
transform="scale(1.4928735,0.6698491)"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan2769"
x="20.453644"
y="1303.4996"
style="font-size:1091.49255371px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;stroke-width:13.65081787;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;font-family:Bitstream Vera Sans">!</tspan></text>
x="5.0072942"
y="59.560848"
style="font-size:55.97062302px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;stroke-width:0.70000001;font-family:Bitstream Vera Sans;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:round">!</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 586 B

View File

@ -1,191 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg3001"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="all.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3003">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3009" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="375"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="640"
inkscape:window-height="711"
inkscape:window-x="1594"
inkscape:window-y="77" />
<metadata
id="metadata3006">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g3011"
transform="matrix(7.4849593,0,0,7.4849593,52.997244,360.31942)"
inkscape:export-filename="/home/andrew/g3060.png"
inkscape:export-xdpi="2.4250078"
inkscape:export-ydpi="2.4250078">
<path
sodipodi:nodetypes="ccccc"
id="path2069"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
id="path2071"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<text
sodipodi:linespacing="125%"
transform="scale(1.4928735,0.6698491)"
id="text2767"
y="59.560848"
x="5.0072942"
style="font-size:55.97062302px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ff7878;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:55.97062302px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;font-family:Bitstream Vera Sans"
y="59.560848"
x="5.0072942"
id="tspan2769"
sodipodi:role="line">!</tspan></text>
</g>
<g
id="g3022"
transform="matrix(7.874057,0,0,7.874057,232.39499,356.39427)"
inkscape:export-filename="/home/andrew/g3060.png"
inkscape:export-xdpi="2.4250078"
inkscape:export-ydpi="2.4250078">
<path
sodipodi:nodetypes="ccccc"
id="path3030"
d="M 23.854535,1.0445221 L 37.242155,18.355109 C 46.910607,29.935258 41.408532,44.012279 26.685812,45.088879 C 5.971353,45.671043 6.4202348,27.463218 11.166925,18.697769 L 23.854535,1.0445221 z"
style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
id="path3032"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<g
transform="matrix(0.9616363,0,0,0.855461,0.9207282,3.9296533)"
id="g3590">
<rect
style="fill:#cfcfcf;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4415"
width="7.7589664"
height="14.866735"
x="14.548919"
y="19.754131" />
<rect
style="fill:#cfcfcf;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4417"
width="7.7589664"
height="14.866735"
x="25.692116"
y="19.754131" />
</g>
</g>
<g
id="g3037"
transform="matrix(8.0037561,0,0,8.0037561,-22.312009,464.83023)"
inkscape:export-filename="/home/andrew/g3060.png"
inkscape:export-xdpi="2.4250078"
inkscape:export-ydpi="2.4250078">
<path
sodipodi:nodetypes="ccccc"
id="path3043"
d="M 23.854535,1.0445221 L 37.242155,18.355109 C 46.910607,29.935258 41.408532,44.012279 26.685812,45.088879 C 5.971353,45.671043 6.4202348,27.463218 11.166925,18.697769 L 23.854535,1.0445221 z"
style="fill:#d0b31d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
id="path3045"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<path
id="rect2634"
d="M 24.821384,15.512309 C 22.21433,17.952223 19.604921,20.381297 16.997867,22.821211 C 18.304685,22.818964 19.61477,22.823457 20.921589,22.821211 C 20.921589,25.684801 20.921589,28.548391 20.921589,31.411981 C 19.61477,31.409734 18.304685,31.414228 16.997867,31.411981 C 19.604921,33.851895 22.21433,36.280969 24.821384,38.720883 C 27.457552,36.289986 30.104432,33.865368 32.740602,31.43447 C 31.322226,31.432031 29.900305,31.43691 28.481929,31.43447 C 28.481929,28.555887 28.481929,25.677306 28.481929,22.798722 C 29.900305,22.796282 31.322226,22.80116 32.740602,22.798722 C 30.104432,20.367823 27.457552,17.943206 24.821384,15.512309 z"
style="fill:#e1cf6f;fill-opacity:1;stroke:#000000;stroke-width:0.56882578;stroke-linecap:round;stroke-linejoin:round;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g3048"
transform="matrix(7.6146585,0,0,7.6146585,318.27879,494.48113)"
inkscape:export-filename="/home/andrew/g3060.png"
inkscape:export-xdpi="2.4250078"
inkscape:export-ydpi="2.4250078">
<path
sodipodi:nodetypes="ccccc"
id="path3054"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z"
style="fill:#5599ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
id="path3056"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<path
id="path3058"
d="M 24.3125,14.9375 C 20.869248,18.315409 17.412003,21.684591 13.96875,25.0625 C 15.821373,25.065889 17.678627,25.059111 19.53125,25.0625 C 19.53125,29.0625 19.53125,33.0625 19.53125,37.0625 C 22.822917,37.0625 26.114582,37.0625 29.40625,37.0625 C 29.40625,33.072917 29.40625,29.083333 29.40625,25.09375 C 31.113161,25.096872 32.824339,25.090627 34.53125,25.09375 C 31.126025,21.703313 27.717725,18.327937 24.3125,14.9375 z"
style="fill:#93beff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g3060"
transform="matrix(8.2631545,0,0,8.2631545,133.25792,542.4325)"
inkscape:export-xdpi="2.4250078"
inkscape:export-ydpi="2.4250078">
<path
sodipodi:nodetypes="ccccc"
id="path3066"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z"
style="fill:#8dd35f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
id="path3068"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<path
id="path3070"
d="M 19.34375,17.5625 C 19.34375,21.552083 19.34375,25.541668 19.34375,29.53125 C 17.636839,29.528128 15.925661,29.534372 14.21875,29.53125 C 17.623975,32.921687 21.032275,36.297063 24.4375,39.6875 C 27.880752,36.309591 31.337996,32.94041 34.78125,29.5625 C 32.928627,29.559111 31.071373,29.565889 29.21875,29.5625 C 29.21875,25.5625 29.21875,21.562501 29.21875,17.5625 C 25.927083,17.5625 22.635418,17.562501 19.34375,17.5625 z"
style="fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

View File

@ -6,83 +6,292 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg6930"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/checking16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417"
sodipodi:docbase="/home/andrew/Projects/deluge-icons"
sodipodi:docname="checking.svg"
inkscape:export-filename="/home/andrew/checking16.png"
inkscape:export-xdpi="32.603073"
inkscape:export-ydpi="32.603073"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs6932">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective6938" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="284.02575"
inkscape:cy="416.27643"
inkscape:document-units="px"
inkscape:zoom="8"
inkscape:cx="37.674028"
inkscape:cy="16.114442"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="686"
inkscape:window-height="711"
inkscape:window-x="1387"
inkscape:window-y="128" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="768"
inkscape:window-height="722"
inkscape:window-x="4"
inkscape:window-y="25"
inkscape:showpageshadow="false" />
<defs
id="defs3">
<inkscape:perspective
id="perspective2513"
inkscape:persp3d-origin="24 : 16 : 1"
inkscape:vp_z="48 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 24 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient2973"
inkscape:collect="always">
<stop
id="stop2975"
offset="0"
style="stop-color:#eeeeec;stop-opacity:1;" />
<stop
id="stop2977"
offset="1"
style="stop-color:#eeeeec;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
id="stop4128"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4130"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
<linearGradient
id="linearGradient4114"
inkscape:collect="always">
<stop
id="stop4116"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop4118"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
id="stop3964"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4134"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4346"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop3966"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3993"
id="radialGradient4019"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
cx="-10.089286"
cy="33.506763"
fx="-10.089286"
fy="33.506763"
r="13.994944" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3993"
id="radialGradient4004"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
cx="-10.323107"
cy="31.329016"
fx="-10.323107"
fy="31.329016"
r="14.057444" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3993"
id="radialGradient3999"
cx="-10.323107"
cy="31.329016"
fx="-10.323107"
fy="31.329016"
r="14.057444"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1312"
id="radialGradient3943"
cx="61.662098"
cy="24.241488"
fx="61.662098"
fy="24.241488"
r="13.994946"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient1312">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop1314" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop1316" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
id="stop3995"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3997"
offset="1"
style="stop-color:#000000;stop-opacity:0" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
r="14.33462"
fy="18.499998"
fx="-22.375"
cy="18.499998"
cx="-22.375"
id="radialGradient3866"
xlink:href="#linearGradient2973"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4114"
id="radialGradient5000"
gradientTransform="scale(1.643990,0.608276)"
cx="15.115514"
cy="63.965388"
fx="15.115514"
fy="63.965388"
r="12.289036"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4989">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4991" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4993" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4995" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop4997" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4979" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4981" />
</linearGradient>
</defs>
<metadata
id="metadata6935">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<path
style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891000000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
sodipodi:nodetypes="ccccc"
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/checking16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
d="M 23.854535,1.0445221 L 37.242155,18.355109 C 46.910607,29.935258 41.408532,44.012279 26.685812,45.088879 C 5.971353,45.671043 6.4202348,27.463218 11.166925,18.697769 L 23.854535,1.0445221 z "
style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123984999999919;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022000000000"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
sodipodi:nodetypes="ccccc"
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022" />
<path
sodipodi:nodetypes="ccccccccc"
style="fill:#cfcfcf;fill-opacity:1;stroke:#000000;stroke-width:0.65121293;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 11.907735,28.259103 C 15.765379,27.553911 20.775812,26.031856 24.400866,26.377315 C 22.598873,25.111024 22.522108,24.694978 21.821837,23.470303 C 26.445155,22.178774 28.937476,23.679964 34.217776,26.922312 C 35.006715,25.3802 35.778476,24.67098 36.817957,22.869809 C 31.198009,18.792719 25.868522,17.760268 20.454911,19.207042 C 19.842813,18.404348 19.795799,17.541278 19.728831,15.812086 C 17.778356,18.179212 14.825215,22.457523 11.907735,28.259103 C 11.907735,28.259103 11.907735,28.259103 11.907735,28.259103"
id="path3463" />
<path
style="fill:#cfcfcf;fill-opacity:1;stroke:#000000;stroke-width:11.50416565;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 170.93275,447.12091 C 174.01359,451.92804 181.6932,659.85017 179.71907,656.9136 C 178.40947,654.12718 411.7223,649.25335 412.30092,648.76646 C 411.08134,648.85003 338.31478,584.63588 338.93986,585.53435 C 410.72174,567.77973 462.65633,588.73801 481.03861,645.01437 C 484.19544,690.33553 466.3409,711.71891 434.77285,736.14895 C 385.89389,754.17146 322.59241,745.84878 312.37017,673.09575 C 312.32389,674.48492 156.52907,675.28833 153.0572,676.51233 C 202.03372,799.5504 269.9646,882.62913 421.73005,870.01325 C 463.0283,867.02946 568.27041,836.89042 606.41655,717.64626 C 627.84208,623.51263 596.80367,549.4096 547.34944,496.26853 C 457.7753,416.4389 296.11292,421.8444 245.11698,507.64417 C 247.55313,508.23771 173.58263,449.35852 170.93275,447.12091 z"
id="path3485"
sodipodi:nodetypes="ccccccccccccc" />
d="M 36.668898,28.597896 C 32.811254,29.303088 27.800821,30.825143 24.175767,30.479684 C 25.97776,31.745975 26.054525,32.162021 26.754796,33.386696 C 22.131478,34.678225 19.639157,33.177035 14.358857,29.934687 C 13.569918,31.476799 12.798157,32.186019 11.758676,33.98719 C 17.378624,38.06428 22.708111,39.096731 28.121722,37.649957 C 28.73382,38.452651 28.780834,39.315721 28.847802,41.044913 C 30.798277,38.677787 33.751418,34.399476 36.668898,28.597896 C 36.668898,28.597896 36.668898,28.597896 36.668898,28.597896"
style="fill:#cfcfcf;fill-opacity:1;stroke:#000000;stroke-width:0.65121293;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="ccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

After

Width:  |  Height:  |  Size: 683 B

View File

@ -1,433 +0,0 @@
/* XPM */
static char * deluge_xpm[] = {
"32 32 398 2",
" c None",
". c #7B869E",
"+ c #7B869D",
"@ c #A5ADBE",
"# c #A7AFBE",
"$ c #8894A9",
"% c #A4ADBD",
"& c #A7AFBF",
"* c #95A0B4",
"= c #6F7E99",
"- c #A0AABD",
"; c #8594AD",
"> c #8A98B1",
", c #A7B3C6",
"' c #8496AF",
") c #5B6F90",
"! c #8F9EB6",
"~ c #8194AF",
"{ c #7C91AF",
"] c #8096B3",
"^ c #859BB8",
"/ c #A0B1C8",
"( c #728CAD",
"_ c #758BAA",
": c #849AB7",
"< c #6F8AAE",
"[ c #7591B3",
"} c #7995B8",
"| c #7A97B9",
"1 c #86A0C0",
"2 c #93ABC7",
"3 c #6585AE",
"4 c #5A78A0",
"5 c #879FBE",
"6 c #6485AF",
"7 c #698CB5",
"8 c #6E91BA",
"9 c #7295BD",
"0 c #7497BF",
"a c #7296BF",
"b c #89A6C8",
"c c #809FC4",
"d c #436B9C",
"e c #7B99BE",
"f c #5378A6",
"g c #446A9A",
"h c #4B6F9C",
"i c #5577A2",
"j c #6183AE",
"k c #6D92BD",
"l c #7097C3",
"m c #6E96C1",
"n c #8DACCF",
"o c #6C93BF",
"p c #587DA9",
"q c #446592",
"r c #1B4075",
"s c #204478",
"t c #2F5081",
"u c #496791",
"v c #4F6B94",
"w c #5879A4",
"x c #6B93BE",
"y c #6E97C2",
"z c #8EADCF",
"A c #5E89BA",
"B c #3E669A",
"C c #567198",
"D c #24477A",
"E c #315281",
"F c #365685",
"G c #3A5A86",
"H c #405E8A",
"I c #567197",
"J c #577298",
"K c #516E97",
"L c #6187B3",
"M c #7098C4",
"N c #85A7CC",
"O c #5280B6",
"P c #305C92",
"Q c #5A759B",
"R c #2B4D7E",
"S c #3B5A88",
"T c #4C6991",
"U c #597397",
"V c #60799D",
"W c #5C769A",
"X c #587298",
"Y c #637C9E",
"Z c #5D769B",
"` c #526F96",
" . c #5B84B0",
".. c #759BC6",
"+. c #7398C4",
"@. c #325D95",
"#. c #4C6A94",
"$. c #3B5B87",
"%. c #44628C",
"&. c #5B7599",
"*. c #6D84A5",
"=. c #647D9F",
"-. c #6784A8",
";. c #7194BD",
">. c #769EC9",
",. c #709AC4",
"'. c #7293B8",
"). c #6D86A9",
"!. c #526E96",
"~. c #5782B1",
"{. c #7A9EC8",
"]. c #5D8ABC",
"^. c #325485",
"/. c #4F6C94",
"(. c #3D5C88",
"_. c #5E779B",
":. c #7489A8",
"<. c #667FA1",
"[. c #8BA3C1",
"}. c #8BAED4",
"|. c #83A9D3",
"1. c #82A8D2",
"2. c #7FA6D1",
"3. c #7CA4CE",
"4. c #7AA0CC",
"5. c #708EB4",
"6. c #5F789C",
"7. c #4E6C96",
"8. c #5986B9",
"9. c #7FA2CA",
"0. c #4B7CB2",
"a. c #2B5387",
"b. c #567199",
"c. c #305282",
"d. c #506B93",
"e. c #7187A5",
"f. c #6F85A3",
"g. c #8EA4BF",
"h. c #9DBBDC",
"i. c #8EB2D9",
"j. c #8DB1D8",
"k. c #8AAED6",
"l. c #84AAD3",
"m. c #7EA5D0",
"n. c #779FCC",
"o. c #6C8BB0",
"p. c #5E779A",
"q. c #5178A6",
"r. c #5C89BC",
"s. c #7198C4",
"t. c #325486",
"u. c #4C6993",
"v. c #5E789B",
"w. c #778CA8",
"x. c #7389A7",
"y. c #B6CADF",
"z. c #9ABBDF",
"A. c #9BBCE0",
"B. c #9ABCDF",
"C. c #97B9DE",
"D. c #93B6DB",
"E. c #8CB1D8",
"F. c #85ABD4",
"G. c #7CA4CF",
"H. c #749BC9",
"I. c #6783A6",
"J. c #56739C",
"K. c #5283B8",
"L. c #6F96C3",
"M. c #4E7BAE",
"N. c #42618D",
"O. c #3E5C88",
"P. c #667E9F",
"Q. c #7288A7",
"R. c #8EA1BA",
"S. c #B9CFE7",
"T. c #A6C5E6",
"U. c #A7C6E6",
"V. c #A5C4E6",
"W. c #A1C1E3",
"X. c #93B6DC",
"Y. c #8AAFD7",
"Z. c #80A7D1",
"`. c #769FCC",
" + c #6992BF",
".+ c #5D789D",
"++ c #5483B9",
"@+ c #5281B7",
"#+ c #688FBB",
"$+ c #557198",
"%+ c #1E4277",
"&+ c #3F5E88",
"*+ c #687FA0",
"=+ c #6F85A5",
"-+ c #A0B2C8",
";+ c #BFD5ED",
">+ c #B3CFED",
",+ c #B2CFED",
"'+ c #AFCCEB",
")+ c #A9C8E8",
"!+ c #A2C2E4",
"~+ c #99BADF",
"{+ c #78A1CD",
"]+ c #6C97C6",
"^+ c #5D88B7",
"/+ c #4779B2",
"(+ c #7295BE",
"_+ c #3C6699",
":+ c #2B4F83",
"<+ c #59749A",
"[+ c #657D9E",
"}+ c #6C83A3",
"|+ c #A3B4CA",
"1+ c #C7DDF2",
"2+ c #BFD9F4",
"3+ c #BDD7F2",
"4+ c #B8D3F0",
"5+ c #B0CDEC",
"6+ c #9CBDE0",
"7+ c #91B4DA",
"8+ c #79A1CD",
"9+ c #5F8DBF",
"0+ c #4578B1",
"a+ c #6B90BA",
"b+ c #446A9B",
"c+ c #2D5184",
"d+ c #577299",
"e+ c #305181",
"f+ c #5B749A",
"g+ c #6C82A2",
"h+ c #98AAC3",
"i+ c #D2E5F6",
"j+ c #CAE2FA",
"k+ c #C6DEF8",
"l+ c #BED8F3",
"m+ c #B4D0EE",
"n+ c #9EBEE1",
"o+ c #92B5DB",
"p+ c #78A0CD",
"q+ c #6B96C5",
"r+ c #5D8BBE",
"s+ c #5081B7",
"t+ c #4276AF",
"u+ c #6489B4",
"v+ c #4B6E9B",
"w+ c #2C5284",
"x+ c #234679",
"y+ c #4C6990",
"z+ c #6C82A3",
"A+ c #738AA9",
"B+ c #D9E9F9",
"C+ c #D3E9FF",
"D+ c #CCE3FB",
"E+ c #C2DBF5",
"F+ c #B6D2EF",
"G+ c #AAC8E8",
"H+ c #9DBEE1",
"I+ c #90B3DA",
"J+ c #759ECB",
"K+ c #6893C4",
"L+ c #5A89BC",
"M+ c #4D7EB5",
"N+ c #3F73AD",
"O+ c #6386B1",
"P+ c #486A96",
"Q+ c #2A5082",
"R+ c #58739A",
"S+ c #375685",
"T+ c #5F789B",
"U+ c #ADBED3",
"V+ c #D4E9FE",
"W+ c #CFE6FD",
"X+ c #C2DCF6",
"Y+ c #A8C7E7",
"Z+ c #719BC9",
"`+ c #6490C1",
" @ c #5685BA",
".@ c #487AB2",
"+@ c #3F70A8",
"@@ c #6B8BB2",
"#@ c #3F608D",
"$@ c #536F97",
"%@ c #1F4377",
"&@ c #224679",
"*@ c #46638D",
"=@ c #6880A0",
"-@ c #6F86A5",
";@ c #BBCDE0",
">@ c #CEE4FC",
",@ c #C0DAF4",
"'@ c #A5C4E5",
")@ c #96B9DD",
"!@ c #88AED6",
"~@ c #7CA3CE",
"{@ c #719BC8",
"]@ c #6692C2",
"^@ c #5987BA",
"/@ c #4C7CB3",
"(@ c #4672A5",
"_@ c #728DB1",
":@ c #385884",
"<@ c #3C5C89",
"[@ c #385886",
"}@ c #26497B",
"|@ c #4B6790",
"1@ c #6980A1",
"2@ c #768BA9",
"3@ c #9CB1CA",
"4@ c #B9D3EE",
"5@ c #ADCAEA",
"6@ c #9EBFE2",
"7@ c #90B4DA",
"8@ c #87ACD5",
"9@ c #7EA4CE",
"0@ c #749CC8",
"a@ c #6993C1",
"b@ c #5C89BB",
"c@ c #4F7DB1",
"d@ c #5D80AC",
"e@ c #617EA4",
"f@ c #3A547B",
"g@ c #2A4C7E",
"h@ c #1C4176",
"i@ c #27497B",
"j@ c #45628D",
"k@ c #60799C",
"l@ c #7288A6",
"m@ c #7D91AD",
"n@ c #859FBE",
"o@ c #93B4D7",
"p@ c #8FB2D8",
"q@ c #86ABD2",
"r@ c #7EA4CD",
"s@ c #759CC8",
"t@ c #6A94C2",
"u@ c #5C89BA",
"v@ c #547EAE",
"w@ c #7994B6",
"x@ c #44628A",
"y@ c #375786",
"z@ c #476590",
"A@ c #4C6890",
"B@ c #5B7498",
"C@ c #667EA0",
"D@ c #6F86A7",
"E@ c #738CAD",
"F@ c #7592B7",
"G@ c #779AC1",
"H@ c #779DC7",
"I@ c #6993C0",
"J@ c #5B86B6",
"K@ c #7B97BB",
"L@ c #5A769E",
"M@ c #394E6E",
"N@ c #21426C",
"O@ c #45638E",
"P@ c #496691",
"Q@ c #1D4176",
"R@ c #41608B",
"S@ c #4C6891",
"T@ c #506D95",
"U@ c #4E6B94",
"V@ c #4B6A95",
"W@ c #5176A3",
"X@ c #7C99BC",
"Y@ c #6280A8",
"Z@ c #3E567A",
"`@ c #25446F",
" # c #395987",
".# c #214579",
"+# c #294C7E",
"@# c #315383",
"## c #3D5C8A",
"$# c #43618D",
"%# c #5C769C",
"&# c #6D84A6",
"*# c #405E8B",
"=# c #375179",
"-# c #1B304F",
";# c #2E5181",
"># c #415F8C",
",# c #547098",
"'# c #486590",
")# c #43618E",
"!# c #476690",
"~# c #6981A4",
"{# c #677FA3",
"]# c #496690",
"^# c #2E5283",
"/# c #294467",
"(# c #32507C",
"_# c #325684",
":# c #335484",
"<# c #3F5E8B",
"[# c #3E5F8D",
"}# c #345887",
"|# c #305383",
"1# c #2A4466",
" ",
" . + ",
" @ # ",
" $ % & * ",
" = - ; > , ' ",
" ) ! ~ { ] ^ / ( ",
" _ : < [ } | 1 2 3 ",
" 4 5 6 7 8 9 0 a b c ",
" d e f g h i j k l m n o ",
" p q r r s t u v w x y z A ",
" B C r D E F G H I J K L M N O ",
" P Q R S T U V W I X Y Z ` ...+. ",
" @.#.$.%.&.*.=.-.;.>.,.'.).V !.~.{.]. ",
" ^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0. ",
" a.b.c.d.e.f.g.h.i.i.j.k.l.m.n.o.p.q.r.s. ",
" t.u.F v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M. ",
" N.c.O.P.Q.R.S.T.U.V.W.A.X.Y.Z.`. +.+++@+#+ ",
" $+%+&+*+=+-+;+>+,+'+)+!+~+i.|.{+]+^+++/+(+_+ ",
" :+<+r G [+}+|+1+2+3+4+5+T.6+7+F.8+]+9+K.0+a+b+ ",
" c+d+r e+f+g+h+i+j+k+l+m+)+n+o+l.p+q+r+s+t+u+v+ ",
" w+Q r x+y+z+A+B+C+D+E+F+G+H+I+|.J+K+L+M+N+O+P+ ",
" Q+R+r r S+T+*+U+V+W+X+F+Y+A.j.2.Z+`+ @.@+@@@#@ ",
" $@%@r &@*@=@-@;@>@,@,+'@)@!@~@{@]@^@/@(@_@:@ ",
" <@[@r r }@|@1@2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@ ",
" g@b.h@r r i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@ ",
" y@z@r r r %@y@A@B@C@D@E@F@G@H@I@J@K@L@M@ ",
" N@O@P@Q@r r r s e+R@S@T@` U@V@W@X@Y@Z@ ",
" `@ #Q y@Q@r r .#+#@#[@##$#%#&#*#=# ",
" -#;#>#d+,#'#)#!#u.Q ~#{#]#^#/# ",
" (#_#:# #<#$#[#}#|#1# ",
" ",
" "};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

View File

@ -1,173 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docbase="/home/andrew"
sodipodi:docname="dht.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/dht16.png"
inkscape:export-xdpi="1.9579109"
inkscape:export-ydpi="1.9579109">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10561" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="217.74745"
inkscape:cy="658.24369"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:window-width="1024"
inkscape:window-height="711"
inkscape:window-x="1280"
inkscape:window-y="0"
showgrid="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="arc"
style="opacity:1;fill:#8dd35f;fill-opacity:1;stroke:#000000;stroke-width:2.48568825;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3437"
sodipodi:cx="325.71429"
sodipodi:cy="215.21933"
sodipodi:rx="85.714287"
sodipodi:ry="85.714287"
d="M 411.42858,215.21933 A 85.714287,85.714287 0 1 1 240.00001,215.21933 A 85.714287,85.714287 0 1 1 411.42858,215.21933 z"
transform="matrix(1.6800176,0,0,1.6800176,-275.15013,-73.06899)"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#5599ff;fill-opacity:1;stroke:#000000;stroke-width:2.81711386;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3439"
sodipodi:cx="325.71429"
sodipodi:cy="215.21933"
sodipodi:rx="85.714287"
sodipodi:ry="85.714287"
d="M 411.42858,215.21933 A 85.714287,85.714287 0 1 1 240.00001,215.21933 A 85.714287,85.714287 0 1 1 411.42858,215.21933 z"
transform="matrix(1.4823682,0,0,1.4823682,82.877111,311.11956)"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#8dd35f;fill-opacity:1;stroke:#000000;stroke-width:3.2505155;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3441"
sodipodi:cx="325.71429"
sodipodi:cy="215.21933"
sodipodi:rx="85.714287"
sodipodi:ry="85.714287"
d="M 411.42858,215.21933 A 85.714287,85.714287 0 1 1 240.00001,215.21933 A 85.714287,85.714287 0 1 1 411.42858,215.21933 z"
transform="matrix(1.2847193,0,0,1.2847193,-104.04248,489.18828)"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#5599ff;fill-opacity:1;stroke:#000000;stroke-width:3.29273035;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3443"
sodipodi:cx="325.71429"
sodipodi:cy="215.21933"
sodipodi:rx="85.714287"
sodipodi:ry="85.714287"
d="M 411.42858,215.21933 A 85.714287,85.714287 0 1 1 240.00001,215.21933 A 85.714287,85.714287 0 1 1 411.42858,215.21933 z"
transform="matrix(1.2682484,0,0,1.2682484,-282.25061,288.22576)"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:4.08935796;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3445"
sodipodi:cx="325.71429"
sodipodi:cy="215.21933"
sodipodi:rx="85.714287"
sodipodi:ry="85.714287"
d="M 411.42858,215.21933 A 85.714287,85.714287 0 1 1 240.00001,215.21933 A 85.714287,85.714287 0 1 1 411.42858,215.21933 z"
transform="matrix(1.0211872,0,0,1.0211872,244.38469,139.31302)"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922" />
<path
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:10.04848194;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 409.97291,329.4348 L 487.75261,344.44338"
id="path3691"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922"
sodipodi:nodetypes="cc" />
<path
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:8.96934509;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 423.06163,747.83054 L 464.53048,708.21583"
id="path3693"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922"
sodipodi:nodetypes="cc" />
<path
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:11.37722969;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 315.62445,431.58184 L 310.19863,651.84005"
id="path3695"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922"
sodipodi:nodetypes="cc" />
<path
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:10.04848194;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 143.15025,452.25537 L 171.01599,395.38786"
id="path3697"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922"
sodipodi:nodetypes="cc" />
<path
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:11.37722969;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 360.45007,405.53416 L 474.8177,539.94039"
id="path3699"
inkscape:export-filename="/home/andrew/dht16-2.png"
inkscape:export-xdpi="3.8918922"
inkscape:export-ydpi="3.8918922"
sodipodi:nodetypes="cc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 793 B

After

Width:  |  Height:  |  Size: 607 B

View File

@ -2,89 +2,349 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg3535"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/downloading16.png"
inkscape:export-xdpi="1.7075963"
inkscape:export-ydpi="1.7075963"
sodipodi:docname="downloading.svg"
inkscape:version="0.45.1"
sodipodi:docbase="/home/andrew/Projects/deluge-icons"
sodipodi:docname="downloading-border.svg"
inkscape:export-filename="/home/andrew/Projects/deluge-icons/downloading16.png"
inkscape:export-xdpi="32.603073"
inkscape:export-ydpi="32.603073"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3537">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3543" />
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2973">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2975" />
<stop
style="stop-color:#eeeeec;stop-opacity:0;"
offset="1"
id="stop2977" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4128" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4130" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4114">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4116" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4118" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop3964" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4134" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4346" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop3966" />
</linearGradient>
<radialGradient
r="13.994944"
fy="33.506763"
fx="-10.089286"
cy="33.506763"
cx="-10.089286"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
gradientUnits="userSpaceOnUse"
id="radialGradient4019"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
gradientUnits="userSpaceOnUse"
id="radialGradient4004"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
id="radialGradient3999"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
r="13.994946"
fy="24.241488"
fx="61.662098"
cy="24.241488"
cx="61.662098"
id="radialGradient3943"
xlink:href="#linearGradient1312"
inkscape:collect="always" />
<linearGradient
id="linearGradient1312">
<stop
id="stop1314"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1316"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3995" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3997" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient3866"
cx="-22.375"
cy="18.499998"
fx="-22.375"
fy="18.499998"
r="14.33462"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="12.289036"
fy="63.965388"
fx="15.115514"
cy="63.965388"
cx="15.115514"
gradientTransform="scale(1.643990,0.608276)"
id="radialGradient5000"
xlink:href="#linearGradient4114"
inkscape:collect="always" />
<linearGradient
id="linearGradient4989">
<stop
id="stop4991"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4993"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4995"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop4997"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
id="stop4979"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4981"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
<linearGradient
id="linearGradient4825"
inkscape:collect="always">
<stop
id="stop4827"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop4829"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4114"
id="radialGradient6090"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1.64399,0.608276)"
cx="15.115514"
cy="63.965388"
fx="15.115514"
fy="63.965388"
r="12.289036" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4825"
id="radialGradient6098"
gradientUnits="userSpaceOnUse"
cx="12.071323"
cy="12.493138"
fx="12.071323"
fy="12.493138"
r="6.7175145" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6103"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.25463,-0.898371,0.979785,0.277703,-18.00903,32.03312)"
cx="17.903898"
cy="40.159222"
fx="17.903898"
fy="40.159222"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6106"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.583269,-0.431533,0.577146,0.78008,-5.80022,4.004109)"
cx="12.525543"
cy="38.09042"
fx="12.525543"
fy="38.09042"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1312"
id="radialGradient6109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.768231,1.13675,-0.820972,0.554824,-3.72248,-85.07126)"
cx="65.800331"
cy="27.16758"
fx="65.800331"
fy="27.16758"
r="12.972491" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="183.87749"
inkscape:cy="492.74541"
inkscape:document-units="px"
inkscape:zoom="8"
inkscape:cx="34.258571"
inkscape:cy="32.884169"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="686"
inkscape:window-height="711"
inkscape:window-x="1941"
inkscape:window-y="99" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1266"
inkscape:window-height="944"
inkscape:window-x="12"
inkscape:window-y="34"
inkscape:showpageshadow="false" />
<metadata
id="metadata3540">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
inkscape:groupmode="layer">
<path
style="fill:#8dd35f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891000000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 337.34641,113.574 L 612.77782,444.9064 C 811.69255,666.55556 698.49522,935.996 395.596,956.6026 C -30.5748,967.74548 -7.5325,620.6669 110.06775,461.45596 L 337.34641,113.574 z"
style="fill:#8dd35f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z "
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 339.91139,163.01784 L 587.46485,461.81598 C 776.20058,681.7222 655.61789,907.17006 386.12406,928.1221 C 6.36766,937.82375 31.27865,636.36028 127.47397,487.30722 L 339.91139,163.01784 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-width:14.10382843;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 362.09611,847.31541 C 292.72038,779.25618 223.06258,711.37264 153.68685,643.3136 C 191.01405,643.2453 228.43453,643.3817 265.76192,643.3136 C 265.76192,562.7203 265.76192,482.12699 265.76192,401.53369 C 332.08337,401.53369 398.40502,401.53369 464.72665,401.53369 C 464.72665,481.91704 464.72665,562.30041 464.72665,642.68397 C 499.11804,642.62091 533.59544,642.74683 567.98683,642.68397 C 499.37714,710.99547 430.70559,779.00372 362.09611,847.31541 z"
id="rect2634"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
style="fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-opacity:1;marker-end:none;stroke-width:0.7;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-linecap:round;stroke-linejoin:round"
d="M 19.34375 17.5625 C 19.34375 21.552083 19.34375 25.541668 19.34375 29.53125 C 17.636839 29.528128 15.925661 29.534372 14.21875 29.53125 C 17.623975 32.921687 21.032275 36.297063 24.4375 39.6875 C 27.880752 36.309591 31.337996 32.94041 34.78125 29.5625 C 32.928627 29.559111 31.071373 29.565889 29.21875 29.5625 C 29.21875 25.5625 29.21875 21.562501 29.21875 17.5625 C 25.927083 17.5625 22.635418 17.562501 19.34375 17.5625 z "
id="rect2634" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 686 B

After

Width:  |  Height:  |  Size: 662 B

View File

@ -1,2 +1,2 @@
From: http://famfamfam.com/lab/icons/flags/
"These flag icons are available for free use for any purpose with no requirement for attribution."
Flag images found at http://www.hahn-hotel.com/flags/
"All sets provided by us are free to use to anyone, for commercial or non-commercial websites."

View File

@ -2,86 +2,283 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg8143"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/inactive16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417"
sodipodi:docname="inactive.svg"
inkscape:version="0.45.1"
sodipodi:docbase="/home/andrew/Projects/deluge-icons"
sodipodi:docname="inactive-border.svg"
inkscape:export-filename="/home/andrew/Projects/deluge-icons/inactive16.png"
inkscape:export-xdpi="32.603073"
inkscape:export-ydpi="32.603073"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs8145">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective8151" />
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2973">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2975" />
<stop
style="stop-color:#eeeeec;stop-opacity:0;"
offset="1"
id="stop2977" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4128" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4130" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4114">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4116" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4118" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop3964" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4134" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4346" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop3966" />
</linearGradient>
<radialGradient
r="13.994944"
fy="33.506763"
fx="-10.089286"
cy="33.506763"
cx="-10.089286"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
gradientUnits="userSpaceOnUse"
id="radialGradient4019"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
gradientUnits="userSpaceOnUse"
id="radialGradient4004"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
id="radialGradient3999"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
r="13.994946"
fy="24.241488"
fx="61.662098"
cy="24.241488"
cx="61.662098"
id="radialGradient3943"
xlink:href="#linearGradient1312"
inkscape:collect="always" />
<linearGradient
id="linearGradient1312">
<stop
id="stop1314"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1316"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3995" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3997" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient3866"
cx="-22.375"
cy="18.499998"
fx="-22.375"
fy="18.499998"
r="14.33462"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="12.289036"
fy="63.965388"
fx="15.115514"
cy="63.965388"
cx="15.115514"
gradientTransform="scale(1.643990,0.608276)"
id="radialGradient5000"
xlink:href="#linearGradient4114"
inkscape:collect="always" />
<linearGradient
id="linearGradient4989">
<stop
id="stop4991"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4993"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4995"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop4997"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
id="stop4979"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4981"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="873.57143"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:zoom="8"
inkscape:cx="36.250498"
inkscape:cy="23.072085"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="686"
inkscape:window-height="711"
inkscape:window-x="1280"
inkscape:window-y="0" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1278"
inkscape:window-height="978"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:showpageshadow="false" />
<metadata
id="metadata8148">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
inkscape:groupmode="layer">
<path
style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891000000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 23.854535,1.0445221 L 37.242155,18.355109 C 46.910607,29.935258 41.408532,44.012279 26.685812,45.088879 C 5.971353,45.671043 6.4202348,27.463218 11.166925,18.697769 L 23.854535,1.0445221 z "
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123984999999919;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022000000000"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<g
id="g3590"
transform="matrix(20.545052,0,0,22.803542,-135.93838,20.962309)">
transform="matrix(0.9616363,0,0,0.855461,0.9207282,3.9296533)">
<rect
y="19.754131"
x="14.548919"

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 588 B

View File

@ -2,86 +2,294 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg9374"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/queued16.png"
inkscape:export-xdpi="1.7309855"
inkscape:export-ydpi="1.7309855"
inkscape:version="0.45.1"
sodipodi:docbase="/home/andrew/Projects/deluge/branches/deluge-0.6/deluge/data/pixmaps"
sodipodi:docname="queued.svg"
inkscape:export-filename="/home/andrew/Projects/deluge-icons/queued16.png"
inkscape:export-xdpi="32.684196"
inkscape:export-ydpi="32.684196"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs9376">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective9382" />
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2973">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2975" />
<stop
style="stop-color:#eeeeec;stop-opacity:0;"
offset="1"
id="stop2977" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4128" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4130" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4114">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4116" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4118" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop3964" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4134" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4346" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop3966" />
</linearGradient>
<radialGradient
r="13.994944"
fy="33.506763"
fx="-10.089286"
cy="33.506763"
cx="-10.089286"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
gradientUnits="userSpaceOnUse"
id="radialGradient4019"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
gradientUnits="userSpaceOnUse"
id="radialGradient4004"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
id="radialGradient3999"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
r="13.994946"
fy="24.241488"
fx="61.662098"
cy="24.241488"
cx="61.662098"
id="radialGradient3943"
xlink:href="#linearGradient1312"
inkscape:collect="always" />
<linearGradient
id="linearGradient1312">
<stop
id="stop1314"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1316"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3995" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3997" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient3866"
cx="-22.375"
cy="18.499998"
fx="-22.375"
fy="18.499998"
r="14.33462"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="12.289036"
fy="63.965388"
fx="15.115514"
cy="63.965388"
cx="15.115514"
gradientTransform="scale(1.643990,0.608276)"
id="radialGradient5000"
xlink:href="#linearGradient4114"
inkscape:collect="always" />
<linearGradient
id="linearGradient4989">
<stop
id="stop4991"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4993"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4995"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop4997"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
id="stop4979"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4981"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="726.34279"
inkscape:cy="746.86589"
inkscape:document-units="px"
inkscape:zoom="16"
inkscape:cx="18.120679"
inkscape:cy="25.176047"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="686"
inkscape:window-height="711"
inkscape:window-x="1859"
inkscape:window-y="122" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1280"
inkscape:window-height="974"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:showpageshadow="false"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="vertical"
position="8.375"
id="guide4206" />
<sodipodi:guide
orientation="vertical"
position="42.125"
id="guide2203" />
</sodipodi:namedview>
<metadata
id="metadata9379">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
inkscape:groupmode="layer">
<path
style="fill:#bfba14;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891000000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
style="fill:#d0b31d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 23.854535,1.0445221 L 37.242155,18.355109 C 46.910607,29.935258 41.408532,44.012279 26.685812,45.088879 C 5.971353,45.671043 6.4202348,27.463218 11.166925,18.697769 L 23.854535,1.0445221 z "
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123984999999919;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022000000000"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:#d6d36a;fill-opacity:1;stroke:#000000;stroke-width:12.60815144000000032;stroke-linecap:round;stroke-linejoin:round;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 356.08237,358.00767 C 298.29629,412.08893 240.45811,465.9299 182.67226,520.01115 C 211.63823,519.96135 240.67645,520.06093 269.64241,520.01115 C 269.64241,583.48327 269.64241,646.95538 269.64241,710.42751 C 240.67645,710.3777 211.63823,710.4773 182.67226,710.42751 C 240.45811,764.50876 298.29629,818.34973 356.08237,872.43098 C 414.51345,818.5496 473.18214,764.80739 531.61344,710.92598 C 500.17495,710.87193 468.65776,710.98006 437.21906,710.92598 C 437.21906,647.12155 437.21906,583.31714 437.21906,519.51267 C 468.65776,519.45859 500.17495,519.56671 531.61344,519.51267 C 473.18214,465.63124 414.51345,411.88906 356.08237,358.00767 z"
style="fill:#e1cf6f;fill-opacity:1;stroke:#000000;stroke-width:0.56882578;stroke-linecap:round;stroke-linejoin:round;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 24.821384,15.512309 C 22.21433,17.952223 19.604921,20.381297 16.997867,22.821211 C 18.304685,22.818964 19.61477,22.823457 20.921589,22.821211 C 20.921589,25.684801 20.921589,28.548391 20.921589,31.411981 C 19.61477,31.409734 18.304685,31.414228 16.997867,31.411981 C 19.604921,33.851895 22.21433,36.280969 24.821384,38.720883 C 27.457552,36.289986 30.104432,33.865368 32.740602,31.43447 C 31.322226,31.432031 29.900305,31.43691 28.481929,31.43447 C 28.481929,28.555887 28.481929,25.677306 28.481929,22.798722 C 29.900305,22.796282 31.322226,22.80116 32.740602,22.798722 C 30.104432,20.367823 27.457552,17.943206 24.821384,15.512309 z "
id="rect2634" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 659 B

View File

@ -2,89 +2,349 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2527"
width="48px"
height="48px"
id="svg3440"
sodipodi:version="0.32"
inkscape:version="0.46"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7075963"
inkscape:export-ydpi="1.7075963"
sodipodi:docname="seeding.svg"
inkscape:version="0.45.1"
sodipodi:docbase="/home/andrew/Projects/deluge-icons"
sodipodi:docname="seeding-border.png.svg"
inkscape:export-filename="/home/andrew/Projects/deluge-icons/seeding16.png"
inkscape:export-xdpi="32.603073"
inkscape:export-ydpi="32.603073"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs2529">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2535" />
id="defs3">
<linearGradient
inkscape:collect="always"
id="linearGradient2973">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2975" />
<stop
style="stop-color:#eeeeec;stop-opacity:0;"
offset="1"
id="stop2977" />
</linearGradient>
<linearGradient
id="linearGradient4126">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop4128" />
<stop
style="stop-color:#ffffff;stop-opacity:0.16494845;"
offset="1.0000000"
id="stop4130" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4114">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4116" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4118" />
</linearGradient>
<linearGradient
id="linearGradient3962">
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop3964" />
<stop
style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
offset="0.15517241"
id="stop4134" />
<stop
style="stop-color:#4074ae;stop-opacity:1.0000000;"
offset="0.75000000"
id="stop4346" />
<stop
style="stop-color:#36486c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop3966" />
</linearGradient>
<radialGradient
r="13.994944"
fy="33.506763"
fx="-10.089286"
cy="33.506763"
cx="-10.089286"
gradientTransform="matrix(1,0,0,0.791446,-14.01786,-11.28667)"
gradientUnits="userSpaceOnUse"
id="radialGradient4019"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
gradientTransform="matrix(1,0,0,0.792374,-19.58761,2.818569)"
gradientUnits="userSpaceOnUse"
id="radialGradient4004"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.792374,0,6.785475)"
r="14.057444"
fy="31.329016"
fx="-10.323107"
cy="31.329016"
cx="-10.323107"
id="radialGradient3999"
xlink:href="#linearGradient3993"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.341185,-0.153831,1.08001,2.395374,-15.42222,-25.62103)"
r="13.994946"
fy="24.241488"
fx="61.662098"
cy="24.241488"
cx="61.662098"
id="radialGradient3943"
xlink:href="#linearGradient1312"
inkscape:collect="always" />
<linearGradient
id="linearGradient1312">
<stop
id="stop1314"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop1316"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3993">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3995" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3997" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient3866"
cx="-22.375"
cy="18.499998"
fx="-22.375"
fy="18.499998"
r="14.33462"
gradientTransform="matrix(1,0,0,1.140022,40.17678,1.347091)"
gradientUnits="userSpaceOnUse" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="12.289036"
fy="63.965388"
fx="15.115514"
cy="63.965388"
cx="15.115514"
gradientTransform="scale(1.643990,0.608276)"
id="radialGradient5000"
xlink:href="#linearGradient4114"
inkscape:collect="always" />
<linearGradient
id="linearGradient4989">
<stop
id="stop4991"
offset="0.0000000"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4993"
offset="0.15517241"
style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
<stop
id="stop4995"
offset="0.75000000"
style="stop-color:#4074ae;stop-opacity:1.0000000;" />
<stop
id="stop4997"
offset="1.0000000"
style="stop-color:#36486c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4977">
<stop
id="stop4979"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop4981"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:0.16494845;" />
</linearGradient>
<linearGradient
id="linearGradient4825"
inkscape:collect="always">
<stop
id="stop4827"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop4829"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4114"
id="radialGradient6090"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1.64399,0.608276)"
cx="15.115514"
cy="63.965388"
fx="15.115514"
fy="63.965388"
r="12.289036" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4825"
id="radialGradient6098"
gradientUnits="userSpaceOnUse"
cx="12.071323"
cy="12.493138"
fx="12.071323"
fy="12.493138"
r="6.7175145" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6103"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.25463,-0.898371,0.979785,0.277703,-18.00903,32.03312)"
cx="17.903898"
cy="40.159222"
fx="17.903898"
fy="40.159222"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2973"
id="radialGradient6106"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.583269,-0.431533,0.577146,0.78008,-5.80022,4.004109)"
cx="12.525543"
cy="38.09042"
fx="12.525543"
fy="38.09042"
r="14.33681" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1312"
id="radialGradient6109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.768231,1.13675,-0.820972,0.554824,-3.72248,-85.07126)"
cx="65.800331"
cy="27.16758"
fx="65.800331"
fy="27.16758"
r="12.972491" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
borderopacity="0.17254902"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="453.37202"
inkscape:cy="461.7376"
inkscape:document-units="px"
inkscape:zoom="8"
inkscape:cx="18.75"
inkscape:cy="24"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="640"
inkscape:window-height="711"
inkscape:window-x="1712"
inkscape:window-y="100" />
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1278"
inkscape:window-height="978"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:showpageshadow="false" />
<metadata
id="metadata2532">
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Internet Category</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Tuomas Kuosmanen</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>internet</rdf:li>
<rdf:li>tools</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>category</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
inkscape:groupmode="layer">
<path
style="fill:#5599ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.07523891px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 335.10794,116.43168 L 610.53935,447.76408 C 809.45408,669.41324 696.25675,938.85368 393.35753,959.46028 C -32.813273,970.60316 -9.7709676,623.52458 107.82928,464.31364 L 335.10794,116.43168 z"
d="M 23.942923,0.9561338 L 37.330543,18.266721 C 46.998995,29.84687 41.49692,43.923891 26.7742,45.000491 C 6.0597413,45.582655 6.5086231,27.37483 11.255313,18.609381 L 23.942923,0.9561338 z "
id="path2069"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:21.67123985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 337.67292,165.87552 L 585.22638,464.67366 C 773.96211,684.57988 653.37942,910.02774 383.88559,930.97978 C 4.1291863,940.68143 29.040179,639.21796 125.2355,490.1649 L 337.67292,165.87552 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.1000706;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.36612022"
d="M 23.996861,3.5433428 L 36.057351,19.151045 C 44.769741,29.58253 39.419346,42.414092 26.125181,43.508521 C 7.3917365,44.015286 7.4275065,28.119221 12.17284,20.333442 L 23.996861,3.5433428 z "
id="path2071"
sodipodi:nodetypes="ccccc"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
sodipodi:nodetypes="ccccc" />
<path
style="fill:#93beff;fill-opacity:1;stroke:#000000;stroke-width:14.10382843;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 359.0208,369.47132 C 289.64507,437.53055 219.98727,505.41409 150.61154,573.47313 C 187.93874,573.54143 225.35922,573.40503 262.68661,573.47313 C 262.68661,654.06643 262.68661,734.65974 262.68661,815.25304 C 329.00806,815.25304 395.32971,815.25304 461.65134,815.25304 C 461.65134,734.86969 461.65134,654.48632 461.65134,574.10276 C 496.04273,574.16582 530.52013,574.0399 564.91152,574.10276 C 496.30183,505.79126 427.63028,437.78301 359.0208,369.47132 z"
id="rect2634"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/seeding16.png"
inkscape:export-xdpi="1.7060417"
inkscape:export-ydpi="1.7060417" />
style="fill:#93beff;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.7;stroke-miterlimit:4;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:round"
d="M 24.3125 14.9375 C 20.869248 18.315409 17.412003 21.684591 13.96875 25.0625 C 15.821373 25.065889 17.678627 25.059111 19.53125 25.0625 C 19.53125 29.0625 19.53125 33.0625 19.53125 37.0625 C 22.822917 37.0625 26.114582 37.0625 29.40625 37.0625 C 29.40625 33.072917 29.40625 29.083333 29.40625 25.09375 C 31.113161 25.096872 32.824339 25.090627 34.53125 25.09375 C 31.126025 21.703313 27.717725 18.327937 24.3125 14.9375 z "
id="rect2634" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

After

Width:  |  Height:  |  Size: 612 B

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2517"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="traffic.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/traffic16.png"
inkscape:export-xdpi="2.459017"
inkscape:export-ydpi="2.459017">
<defs
id="defs2519">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2525" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="375"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="667"
inkscape:window-height="709"
inkscape:window-x="50"
inkscape:window-y="25" />
<metadata
id="metadata2522">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="opacity:0.8;fill:#93beff;fill-opacity:1;stroke:#000000;stroke-width:14.10382843;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 426.97356,240.8999 C 357.59783,308.95913 287.94003,376.84267 218.5643,444.90171 C 255.8915,444.97001 293.31198,444.83361 330.63937,444.90171 C 330.63937,525.49501 330.63937,606.08832 330.63937,686.68162 C 396.96082,686.68162 463.28247,686.68162 529.6041,686.68162 C 529.6041,606.29827 529.6041,525.9149 529.6041,445.53134 C 563.99549,445.5944 598.47289,445.46848 632.86428,445.53134 C 564.25459,377.21984 495.58304,309.21159 426.97356,240.8999 z"
id="rect2634"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/traffic32.png"
inkscape:export-xdpi="4.9180341"
inkscape:export-ydpi="4.9180341" />
<path
style="opacity:0.8;fill:#b7e399;fill-opacity:1;stroke:#000000;stroke-width:14.10382843;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 298.40213,812.39589 C 229.0264,744.33666 159.3686,676.45312 89.992873,608.39408 C 127.32007,608.32578 164.74055,608.46218 202.06794,608.39408 C 202.06794,527.80078 202.06794,447.20747 202.06794,366.61417 C 268.38939,366.61417 334.71104,366.61417 401.03267,366.61417 C 401.03267,446.99752 401.03267,527.38089 401.03267,607.76445 C 435.42406,607.70139 469.90146,607.82731 504.29285,607.76445 C 435.68316,676.07595 367.01161,744.0842 298.40213,812.39589 z"
id="path2528"
inkscape:export-filename="/home/andrew/Projects/deluge/trunk/deluge/data/pixmaps/traffic32.png"
inkscape:export-xdpi="4.9180341"
inkscape:export-ydpi="4.9180341" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

View File

@ -1,6 +1,6 @@
[Desktop Entry]
Version=1.0
Name=Deluge BitTorrent Client
Name=Deluge
GenericName=Bittorrent Client
Comment=Transfer files using the Bittorrent protocol
Exec=deluge

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

@ -1,54 +0,0 @@
.TH DELUGE 1 "March 2009" "1.1.4"
.SH NAME
deluge - a bittorrent client
.SH SYNOPSIS
.B deluge [options] [torrent]
.SH DESCRIPTION
.br
.P
Deluge utilizes a client/server model, with 'deluged' being the daemon process and 'deluge' being used to launch a user-interface.
.br
.P
By default, Deluge will run in 'Classic' mode where the daemon functionality will be hidden and the GtkUI will automatically launch a 'deluged' process. You can turn this off in the Preferences dialog.
.SH OPTIONS
.TP
.I [torrent]
List of ".torrent" files to add to the download queue.
.TP
.I --version
Show program's version number and exit.
.TP
.I -h, --help
Show this help message and exit.
.TP
.I -c CONFIG, --config=CONFIG
Sets the configuration path.
.TP
.I -u UI, --ui=UI
The UI that you wish to launch, current options include: gtk, web or null
.TP
.I -l LOGFILE, --logfile=LOGFILE
Output to designated logfile instead of stdout
.TP
.I -L LOGLEVEL, --loglevel=LOGLEVEL
Set the log level (default is error): none, info, warning, error, critical, debug
.TP
.I -q --quiet
Sets the log level to 'none', this is the same as `\-L none`
.TP
.I -s DEFAULT_UI, --set-default-ui=DEFAULT_UI
Sets the default UI to be run when no UI is specified
.SH SEE ALSO
.B Homepage:
http://www.deluge-torrent.org/
.SH AUTHOR
This manual page was written by Andrew Resch <andrewresch@gmail.com>.
.br
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation
.br

View File

@ -1,54 +0,0 @@
.TH DELUGED 1 "March 2009" "1.1.4"
.SH NAME
deluged - a bittorrent client daemon
.SH SYNOPSIS
.B deluged [options]
.SH DESCRIPTION
.br
.P
Deluge utilizes a client/server model, with 'deluged' being the daemon process and 'deluge' being used to launch a user-interface.
.br
.P
By default, 'deluged' will run as a daemon, to prevent this you can run deluged with the \-d option. This option is useful for running deluged with the start-stop-daemon.
.SH OPTIONS
.TP
.I --version
Show program's version number and exit.
.TP
.I -h, --help
Show this help message and exit.
.TP
.I -p PORT, --port=PORT
Port daemon will listen on, default is 58846
.TP
.I -d, --do-not-daemonize
Do not daemonize
.TP
.I -c CONFIG, --config=CONFIG
Sets the configuration path.
.TP
.I -l LOGFILE, --logfile=LOGFILE
Output to designated logfile instead of stdout
.TP
.I -P PIDFILE, --pidfile=PIDFILE
Use pidfile to store process id
.TP
.I -L LOGLEVEL, --loglevel=LOGLEVEL
Set the log level (default is error): none, info, warning, error, critical, debug
.TP
.I -q --quiet
Sets the log level to 'none', this is the same as `\-L none`
.SH SEE ALSO
.B Homepage:
http://www.deluge-torrent.org/
.SH AUTHOR
This manual page was written by Andrew Resch <andrew.resch@gmail.com>.
.br
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation
.br

View File

@ -1,179 +0,0 @@
# -*- coding: utf-8 -*-
#
# deluge documentation build configuration file, created by
# sphinx-quickstart on Tue Nov 4 18:24:06 2008.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
#
# All configuration values have a default value; values that are commented out
# serve to show the default value.
import sys, os
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
sys.path.append(os.path.abspath(os.path.dirname(__file__ + "../../")))
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General substitutions.
project = 'deluge'
copyright = '2008, Andrew Resch'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
#
# The short X.Y version.
version = '1.1.0'
# The full version, including alpha/beta/rc tags.
release = '1.1.0'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directories, that shouldn't be searched
# for source files.
#exclude_dirs = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (within the static path) to place at the top of
# the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, the reST sources are included in the HTML build as _sources/<name>.
#html_copy_source = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'delugedoc'
# Options for LaTeX output
# ------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'deluge.tex', 'deluge Documentation',
'Andrew Resch', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

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,5 +0,0 @@
:mod:`deluge.common`
====================
.. automodule:: deluge.common
:members:

View File

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

View File

@ -1,34 +1,42 @@
#
# error.py
#
# Copyright (C) 2008 Andrew Resch <andrewresch@gmail.com>
#
# Copyright (C) 2008 Andrew Resch ('andar') <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.
class DelugeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class NoCoreError(DelugeError):
pass

View File

@ -1,23 +1,4 @@
deluge/plugins/label/label/data/label_pref.glade
deluge/plugins/label/label/data/label_options.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/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
@ -27,18 +8,16 @@ 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_config.py
deluge/plugins/label/label/webui.py
deluge/plugins/label/label/gtk_sidebar.py
deluge/plugins/label/label/gtkui.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/__init__.py
deluge/plugins/label/label/ui.py
deluge/plugins/label/label/webui_pages.py
deluge/plugins/label/label/__init__.py
deluge/plugins/label/label/core.py
deluge/plugins/label/setup.py
@ -52,33 +31,14 @@ deluge/plugins/blocklist/blocklist/text.py
deluge/plugins/blocklist/blocklist/peerguardian.py
deluge/plugins/blocklist/blocklist/__init__.py
deluge/plugins/blocklist/blocklist/core.py
deluge/plugins/coreclient.py
deluge/plugins/__init__.py
deluge/plugins/webuipluginbase.py
deluge/configmanager.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/status_tab.py
deluge/ui/gtkui/statistics_tab.py
deluge/ui/gtkui/addtorrentdialog.py
deluge/ui/gtkui/coreconfig.py
deluge/ui/gtkui/sidebar.py
@ -89,15 +49,12 @@ 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
@ -106,10 +63,8 @@ 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
@ -138,7 +93,7 @@ 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/egg_render.py
deluge/ui/webui/lib/pythonize.py
deluge/ui/webui/lib/static_handler.py
deluge/ui/webui/lib/__init__.py
deluge/ui/webui/lib/web.py
@ -159,10 +114,10 @@ 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/multicall_notepad.py
deluge/ui/webui/tests/test_all.py
deluge/ui/webui/apache.py
deluge/ui/webui/web.py
@ -171,22 +126,27 @@ 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/plugins/blocklist/blocklist/data/blocklist_pref.glade
deluge/ui/gtkui/glade/add_torrent_dialog.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/dgtkpopups.glade
deluge/ui/gtkui/glade/tray_menu.glade
deluge/ui/gtkui/glade/main_window.glade

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