Compare commits
81 Commits
archive/1.
...
deluge-1.1
Author | SHA1 | Date | |
---|---|---|---|
5f2159931e | |||
18bbaf2b36 | |||
107079fbab | |||
57c1950d40 | |||
40e700cf86 | |||
f1f50dc447 | |||
2f3edc0352 | |||
959f6e550f | |||
748a82a23b | |||
009b34bccb | |||
6cd794fa18 | |||
b258a9c340 | |||
d8447aea72 | |||
d5c12a47c2 | |||
0d7cf1af81 | |||
64d94eb95f | |||
28eda6caa0 | |||
150c803d19 | |||
d88fe0e894 | |||
225afdec1f | |||
4175289690 | |||
d669e6e864 | |||
1a70007697 | |||
0208e59ad6 | |||
1bf2fb47b7 | |||
8deee64007 | |||
42cceabd8e | |||
6eb413dd1e | |||
81b895bd1d | |||
2edf1fc692 | |||
8c489e86d2 | |||
530fcf255b | |||
af1b3a6d3a | |||
04d344a133 | |||
7226cbb53d | |||
f168f7e18e | |||
923cfaab5c | |||
b3aa588650 | |||
08b92148ca | |||
914ae20e74 | |||
c562024407 | |||
6aa405187f | |||
ad0b335648 | |||
83690d5aaf | |||
df30d4b5c9 | |||
0296f6c6e9 | |||
7bdabc207d | |||
5e0d3bedef | |||
e23a4c5da7 | |||
d25b41f1de | |||
07126decab | |||
5ee25515c1 | |||
f86b5dd0ad | |||
d8a187a8f6 | |||
1f52a3fc20 | |||
c58e2481b9 | |||
7b99298203 | |||
2ff6b85771 | |||
5c4b64d656 | |||
36539cdd1d | |||
afb12d7403 | |||
f31ac4bdc8 | |||
69a0dbca4d | |||
eced7ab068 | |||
d73a1abbe4 | |||
ac5b5fdefb | |||
1f1a0168e7 | |||
86f9184320 | |||
9b1ea3d8de | |||
e7aad6a345 | |||
aa8d18c081 | |||
6bc4caa4e6 | |||
68df5a389d | |||
21c57e935e | |||
9cd3e7cf56 | |||
489d805cb4 | |||
b974f91da8 | |||
4b1eecf026 | |||
01bda41ba8 | |||
0e60a4903e | |||
926d71c8a1 |
300
ChangeLog
300
ChangeLog
@ -1,4 +1,52 @@
|
||||
Deluge 1.1.0 - "" (In Development)
|
||||
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
|
||||
|
||||
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 'PeerGuardian 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
|
||||
@ -12,6 +60,7 @@ Deluge 1.1.0 - "" (In Development)
|
||||
* 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
|
||||
@ -58,3 +107,252 @@ Deluge 1.1.0 - "" (In Development)
|
||||
* 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 ConnectionManager
|
||||
|
||||
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
|
||||
|
||||
WebUi:
|
||||
* 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:
|
||||
* Fix #560 force an int value for global max connections
|
||||
* Fix #545 use proper values in ratio calculation
|
||||
* Fix UPnP again..
|
||||
|
||||
GtkUI:
|
||||
* Fix #565 wait for the deluged process to start to prevent defunct processes
|
||||
|
||||
OS X:
|
||||
* Fix issues with gettext
|
||||
|
||||
Windows:
|
||||
* Fix starting on non-English versions of Windows
|
||||
|
||||
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.
|
||||
* Fix issue where fastresume files would be rejected when using FAT32. This
|
||||
would cause the torrent to be rechecked on every startup.
|
||||
* Fix ip filtering
|
||||
|
||||
GtkUI:
|
||||
* Re-add the "Max Connections Per Second" option with a default setting of 20
|
||||
|
||||
WebUI:
|
||||
* Fix White template for Opera
|
||||
|
||||
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:
|
||||
* Fix issue where torrents will not be properly added to the session
|
||||
|
||||
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
|
||||
* 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.
|
||||
* Removed the 'Maximum Connections Per Second' setting and replaced it with a
|
||||
default setting of 20. This should alleviate speed issues some are experiencing.
|
||||
* Changed max half-open connections default limit to 8 on XP/2000 and 4 on Vista
|
||||
* Prevent being able to set file priorities for compactly allocated torrents as
|
||||
it is not intended to work.
|
||||
* Fix freezing on start-up issues on systems that do not have a properly
|
||||
configured localhost entry.
|
||||
* Change max connections default setting to 200
|
||||
* Fix issue with invalid bencoding from some trackers
|
||||
* Plenty of libtorrent updates that should improve core stability
|
||||
|
||||
GtkUI:
|
||||
* Improve performance of files tab by only updating when values change
|
||||
|
||||
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:
|
||||
* Add enable "Auto Add" checkbox
|
||||
|
||||
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:
|
||||
* 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:
|
||||
* 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:
|
||||
* Attempt to automatically upgrade a 0.5.x state file to new format
|
||||
* Tracker errors now change the tracker status
|
||||
|
||||
Plugins:
|
||||
* Fix bug in Blocklist that prevented downloading a new file every X days
|
||||
|
||||
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:
|
||||
* 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:
|
||||
* Add 'edit' to edit trackers dialog
|
||||
* Improve performance of initial torrent list load
|
||||
* Fix hiding the bottom pane when disabling all the tabs
|
||||
* Fix not showing new torrents if you don't use the All label first
|
||||
* Fix size units to be more accurate
|
||||
* Fix torrentview sorting to be persistent
|
||||
* Fix not displaying file list when state changes
|
||||
* Expand root folder in files tab by default
|
||||
|
||||
Null:
|
||||
* Fix #415 crash when using 'config-set' with no parameters
|
||||
|
||||
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:
|
||||
* Fix CPU spikes
|
||||
|
||||
GtkUI:
|
||||
* Fix move storage dialog when connected to a remote daemon
|
||||
|
||||
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:
|
||||
* Handle shutting down more cleanly
|
||||
* Add translators to credits
|
||||
|
||||
Plugins:
|
||||
* Improve the Blocklist plugin preferences page.
|
||||
|
||||
Windows:
|
||||
* Fix drag n' drop support
|
||||
|
||||
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:
|
||||
* Add drag n' drop support for adding .torrent files
|
||||
* 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
|
||||
* Fix displaying of torrents when language is not English
|
||||
* 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:
|
||||
* 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:
|
||||
* Default to gtkui when running 'deluge' instead of defaulting to last used.
|
||||
|
||||
GtkUI:
|
||||
* Fix open folder
|
||||
* Fix #349 tab ordering when hiding/showing
|
||||
|
||||
Windows:
|
||||
* Fix torrent file association and adding files from command line
|
||||
|
||||
Plugins:
|
||||
* Blocklist plugin has been rewritten
|
||||
|
||||
Misc:
|
||||
* Some changes for python 2.6 compatibility
|
||||
|
||||
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:
|
||||
* Include missing 'classic' template
|
||||
* Update options tab to include queue settings
|
||||
|
||||
Windows:
|
||||
* Fix displaying of tray icon
|
||||
* Fix scrolling of tray menu
|
||||
* Fix hiding of tray icon when shutting down
|
||||
* Fix tray icon tool tip length to show properly
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,5 +1,5 @@
|
||||
deluge-torrent (0.9.08-1) unstable; urgency=low
|
||||
deluge-torrent (1.1.0-1) unstable; urgency=low
|
||||
|
||||
* R8 release
|
||||
* 1.1.0 final
|
||||
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Tue, 26 Aug 2008 16:31:14 -0800
|
||||
-- Andrew Resch (andar) <andrewresch@gmail.com> Sat, 10 Jan 2008 16:31:14 -0800
|
||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -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 | notification-daemon-xfce, python-dbus, librsvg2-common, python-pyopenssl, python-setuptools, python-pkg-resources
|
||||
Conflicts: deluge-torrent-common
|
||||
Replaces: deluge-torrent-common
|
||||
Description: A Bittorrent client written in Python/PyGTK
|
||||
|
@ -79,7 +79,7 @@ def get_version():
|
||||
:rtype: string
|
||||
|
||||
"""
|
||||
return pkg_resources.require("Deluge")[0].version.split("r")[0]
|
||||
return pkg_resources.require("Deluge")[0].version
|
||||
|
||||
def get_revision():
|
||||
"""
|
||||
|
@ -317,7 +317,36 @@ class Core(
|
||||
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():
|
||||
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
|
||||
|
@ -76,25 +76,29 @@ class OldStateUpgrader:
|
||||
log.debug("Unable to open 0.5 state file: %s", e)
|
||||
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)
|
||||
try:
|
||||
torrent_info = None
|
||||
log.debug("Attempting to create torrent_info from %s", torrent_path)
|
||||
_file = open(torrent_path, "rb")
|
||||
torrent_info = lt.torrent_info(lt.bdecode(_file.read()))
|
||||
_file.close()
|
||||
except (IOError, RuntimeError), e:
|
||||
log.warning("Unable to open %s: %s", filepath, e)
|
||||
if type(state).__name__ == 'list':
|
||||
log.debug("0.5 state file is too old to upgrade:")
|
||||
return
|
||||
else:
|
||||
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)
|
||||
try:
|
||||
torrent_info = None
|
||||
log.debug("Attempting to create torrent_info from %s", torrent_path)
|
||||
_file = open(torrent_path, "rb")
|
||||
torrent_info = lt.torrent_info(lt.bdecode(_file.read()))
|
||||
_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"))
|
||||
import shutil
|
||||
shutil.copyfile(torrent_path, os.path.join(self.config["state_location"], str(torrent_info.info_hash()) + ".torrent"))
|
||||
|
||||
# Set the file prioritiy property if not already there
|
||||
if not hasattr(ti, "priorities"):
|
||||
ti.priorities = [1] * torrent_info.num_files()
|
||||
# Set the file prioritiy property if not already there
|
||||
if not hasattr(ti, "priorities"):
|
||||
ti.priorities = [1] * torrent_info.num_files()
|
||||
|
||||
# Create the new TorrentState object
|
||||
new_torrent = deluge.core.torrentmanager.TorrentState(
|
||||
@ -112,16 +116,16 @@ 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.")
|
||||
state_file = open(
|
||||
os.path.join(self.config["state_location"], "torrents.state"), "wb")
|
||||
cPickle.dump(new_state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
return
|
||||
# Now we need to write out the new state file
|
||||
try:
|
||||
log.debug("Saving torrent state file.")
|
||||
state_file = open(
|
||||
os.path.join(self.config["state_location"], "torrents.state"), "wb")
|
||||
cPickle.dump(new_state, state_file)
|
||||
state_file.close()
|
||||
except IOError, e:
|
||||
log.warning("Unable to save state file: %s", e)
|
||||
return
|
||||
|
||||
# Rename the persistent.state file
|
||||
try:
|
||||
|
@ -68,7 +68,7 @@ DEFAULT_PREFS = {
|
||||
"max_download_speed": -1.0,
|
||||
"max_upload_slots_global": 4,
|
||||
"max_half_open_connections": (lambda: deluge.common.windows_check() and
|
||||
(lambda: deluge.common.vista_check() and 4 or 8)() or -1)(),
|
||||
(lambda: deluge.common.vista_check() and 4 or 8)() or 50)(),
|
||||
"max_connections_per_second": 20,
|
||||
"ignore_limits_on_local_network": True,
|
||||
"max_connections_per_torrent": -1,
|
||||
@ -461,7 +461,7 @@ class PreferencesManager(component.Component):
|
||||
for k, v in value.items():
|
||||
if v["type"]:
|
||||
proxy_settings = lt.proxy_settings()
|
||||
proxy_settings.proxy_type = lt.proxy_type(v["type"])
|
||||
proxy_settings.type = lt.proxy_type(v["type"])
|
||||
proxy_settings.username = v["username"]
|
||||
proxy_settings.password = v["password"]
|
||||
proxy_settings.hostname = v["hostname"]
|
||||
|
@ -82,14 +82,10 @@ class TorrentOptions(dict):
|
||||
return k
|
||||
|
||||
def iteritems(self):
|
||||
return self.items().itermitems()
|
||||
return self.items().iteritems()
|
||||
|
||||
def has_key(self, key):
|
||||
if super(TorrentOptions, self).has_key(key):
|
||||
return True
|
||||
elif self.default_keys.has_key(key):
|
||||
return True
|
||||
return False
|
||||
return super(TorrentOptions, self).has_key(key) or key in self.default_keys
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super(TorrentOptions, self).__setitem__(key, value)
|
||||
@ -97,11 +93,14 @@ class TorrentOptions(dict):
|
||||
def __getitem__(self, key):
|
||||
if super(TorrentOptions, self).has_key(key):
|
||||
return super(TorrentOptions, self).__getitem__(key)
|
||||
else:
|
||||
if self.default_keys[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.
|
||||
@ -520,9 +519,22 @@ class Torrent:
|
||||
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:
|
||||
host = ".".join(parts[-2:])
|
||||
if parts[-2] in ("co", "com"):
|
||||
host = ".".join(parts[-3:])
|
||||
else:
|
||||
host = ".".join(parts[-2:])
|
||||
return host
|
||||
return ""
|
||||
|
||||
|
@ -1,14 +1,5 @@
|
||||
deluge/plugins/label/label/data/label_pref.glade
|
||||
deluge/plugins/label/label/data/label_options.glade
|
||||
deluge/plugins/label/build/lib/label/data/label_pref.glade
|
||||
deluge/plugins/label/build/lib/label/data/label_options.glade
|
||||
deluge/plugins/graph/build/lib/graph/data/config.glade
|
||||
deluge/plugins/blocklist/build/lib/blocklist/data/blocklist_pref.glade
|
||||
deluge/plugins/blocklist/blocklist/data/blocklist_pref.glade
|
||||
deluge/plugins/stats/build/lib/stats/data/config.glade
|
||||
deluge/plugins/stats/build/lib/stats/data/tabs.glade
|
||||
deluge/plugins/stats/stats/data/config.glade
|
||||
deluge/plugins/stats/stats/data/tabs.glade
|
||||
deluge/ui/gtkui/glade/add_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/filtertree_menu.glade
|
||||
deluge/ui/gtkui/glade/torrent_menu.glade
|
||||
@ -18,7 +9,6 @@ deluge/ui/gtkui/glade/edit_trackers.glade
|
||||
deluge/ui/gtkui/glade/queuedtorrents.glade
|
||||
deluge/ui/gtkui/glade/move_storage_dialog.glade
|
||||
deluge/ui/gtkui/glade/connection_manager.glade
|
||||
deluge/ui/gtkui/glade/wizard.glade
|
||||
deluge/ui/gtkui/glade/create_torrent_dialog.glade
|
||||
deluge/ui/gtkui/glade/dgtkpopups.glade
|
||||
deluge/ui/gtkui/glade/tray_menu.glade
|
||||
@ -65,14 +55,6 @@ deluge/plugins/blocklist/blocklist/core.py
|
||||
deluge/plugins/coreclient.py
|
||||
deluge/plugins/__init__.py
|
||||
deluge/plugins/webuipluginbase.py
|
||||
deluge/plugins/stats/setup.py
|
||||
deluge/plugins/stats/stats/webui.py
|
||||
deluge/plugins/stats/stats/gtkui.py
|
||||
deluge/plugins/stats/stats/test.py
|
||||
deluge/plugins/stats/stats/graph.py
|
||||
deluge/plugins/stats/stats/test_total.py
|
||||
deluge/plugins/stats/stats/__init__.py
|
||||
deluge/plugins/stats/stats/core.py
|
||||
deluge/configmanager.py
|
||||
deluge/ui/tracker_icons.py
|
||||
deluge/ui/client.py
|
||||
@ -96,7 +78,7 @@ deluge/ui/console/__init__.py
|
||||
deluge/ui/gtkui/listview.py
|
||||
deluge/ui/gtkui/options_tab.py
|
||||
deluge/ui/gtkui/statusbar.py
|
||||
deluge/ui/gtkui/statistics_tab.py
|
||||
deluge/ui/gtkui/status_tab.py
|
||||
deluge/ui/gtkui/addtorrentdialog.py
|
||||
deluge/ui/gtkui/coreconfig.py
|
||||
deluge/ui/gtkui/sidebar.py
|
||||
@ -193,8 +175,6 @@ 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
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3042
deluge/i18n/be.po
Normal file
3042
deluge/i18n/be.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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
1359
deluge/i18n/de.po
1359
deluge/i18n/de.po
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
1130
deluge/i18n/en_AU.po
1130
deluge/i18n/en_AU.po
File diff suppressed because it is too large
Load Diff
1798
deluge/i18n/en_CA.po
1798
deluge/i18n/en_CA.po
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
1060
deluge/i18n/es.po
1060
deluge/i18n/es.po
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
1104
deluge/i18n/fi.po
1104
deluge/i18n/fi.po
File diff suppressed because it is too large
Load Diff
1674
deluge/i18n/fr.po
1674
deluge/i18n/fr.po
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
1148
deluge/i18n/hu.po
1148
deluge/i18n/hu.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2184
deluge/i18n/is.po
2184
deluge/i18n/is.po
File diff suppressed because it is too large
Load Diff
1133
deluge/i18n/it.po
1133
deluge/i18n/it.po
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
4014
deluge/i18n/kk.po
4014
deluge/i18n/kk.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1523
deluge/i18n/ko.po
1523
deluge/i18n/ko.po
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
1313
deluge/i18n/ms.po
1313
deluge/i18n/ms.po
File diff suppressed because it is too large
Load Diff
1015
deluge/i18n/nb.po
1015
deluge/i18n/nb.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1379
deluge/i18n/nl.po
1379
deluge/i18n/nl.po
File diff suppressed because it is too large
Load Diff
1644
deluge/i18n/pl.po
1644
deluge/i18n/pl.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1411
deluge/i18n/pt.po
1411
deluge/i18n/pt.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1695
deluge/i18n/ro.po
1695
deluge/i18n/ro.po
File diff suppressed because it is too large
Load Diff
1510
deluge/i18n/ru.po
1510
deluge/i18n/ru.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1722
deluge/i18n/sk.po
1722
deluge/i18n/sk.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1498
deluge/i18n/sr.po
1498
deluge/i18n/sr.po
File diff suppressed because it is too large
Load Diff
1290
deluge/i18n/sv.po
1290
deluge/i18n/sv.po
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
1943
deluge/i18n/uk.po
1943
deluge/i18n/uk.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1173
deluge/i18n/zh_CN.po
1173
deluge/i18n/zh_CN.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1373
deluge/i18n/zh_TW.po
1373
deluge/i18n/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@ import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
import deluge.common
|
||||
import deluge.configmanager
|
||||
|
||||
def start_ui():
|
||||
"""Entry point for ui script"""
|
||||
@ -58,10 +59,22 @@ def start_ui():
|
||||
help="Set the log level: none, info, warning, error, critical, debug", action="store", type="str")
|
||||
parser.add_option("-q", "--quiet", dest="quiet",
|
||||
help="Sets the log level to 'none', this is the same as `-L none`", action="store_true", default=False)
|
||||
parser.add_option("-s", "--set-default-ui", dest="default_ui",
|
||||
help="Sets the default UI to be run when no UI is specified", action="store", type="str")
|
||||
|
||||
# Get the options and args from the OptionParser
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.default_ui:
|
||||
if options.config:
|
||||
deluge.configmanager.set_config_dir(options.config)
|
||||
|
||||
config = deluge.configmanager.ConfigManager("ui.conf")
|
||||
config["default_ui"] = options.default_ui
|
||||
config.save()
|
||||
print "The default UI has been changed to", options.default_ui
|
||||
sys.exit(0)
|
||||
|
||||
if options.quiet:
|
||||
options.loglevel = "none"
|
||||
|
||||
@ -174,7 +187,7 @@ def start_daemon():
|
||||
# If the donot daemonize is set, then we just skip the forking
|
||||
if not options.donot:
|
||||
# Windows check, we log to the config folder by default
|
||||
if deluge.common.windows_check():
|
||||
if deluge.common.windows_check() or deluge.common.osx_check():
|
||||
open_logfile()
|
||||
write_pidfile()
|
||||
else:
|
||||
|
@ -125,11 +125,10 @@ def makeinfo(path, piece_length, progress, name = None,
|
||||
try:
|
||||
u = decode_from_filesystem(name)
|
||||
except Exception, e:
|
||||
s = str_exc(e)
|
||||
raise Exception('Could not convert file/directory name %r to '
|
||||
'Unicode (%s). Either the assumed filesystem '
|
||||
'Unicode. Either the assumed filesystem '
|
||||
'encoding "%s" is wrong or the filename contains '
|
||||
'illegal bytes.') % (name, s, get_filesystem_encoding())
|
||||
'illegal bytes.') % (name, get_filesystem_encoding())
|
||||
|
||||
if u.translate(noncharacter_translate) != u:
|
||||
raise Exception('File/directory name "%s" contains reserved '
|
||||
|
@ -37,10 +37,10 @@ import deluge.component as component
|
||||
import deluge.configmanager
|
||||
|
||||
from peerguardian import PGReader, PGException
|
||||
from text import TextReader, GZMuleReader, PGZip
|
||||
from text import TextReader, GZMuleReader, PGZip, PGTextReaderGzip
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
"url": "http://www.deluge-torrent.org/blocklist/pipfilter.dat.gz",
|
||||
"url": "http://deluge-torrent.org/blocklist/nipfilter.dat.gz",
|
||||
"load_on_start": False,
|
||||
"check_after_days": 4,
|
||||
"listtype": "gzmule",
|
||||
@ -56,7 +56,8 @@ FORMATS = {
|
||||
'gzmule': ["Emule IP list (GZip)", GZMuleReader],
|
||||
'spzip': ["SafePeer Text (Zipped)", PGZip],
|
||||
'pgtext': ["PeerGuardian Text (Uncompressed)", TextReader],
|
||||
'p2bgz': ["PeerGuardian P2B (GZip)", PGReader]
|
||||
'p2bgz': ["PeerGuardian P2B (GZip)", PGReader],
|
||||
'pgtextgz': ["PeerGuardian Text (GZip)", PGTextReaderGzip]
|
||||
}
|
||||
|
||||
class Core(CorePluginBase):
|
||||
@ -164,6 +165,7 @@ class Core(CorePluginBase):
|
||||
read_list = FORMATS[self.config["listtype"]][1](bl_file)
|
||||
except Exception, e:
|
||||
log.debug("Unable to read blocklist file: %s", e)
|
||||
self.is_importing = False
|
||||
return
|
||||
|
||||
try:
|
||||
@ -173,6 +175,7 @@ class Core(CorePluginBase):
|
||||
self.core.export_block_ip_range(ips)
|
||||
self.num_blocked += 1
|
||||
ips = read_list.next()
|
||||
read_list.close()
|
||||
except Exception, e:
|
||||
log.debug("Exception during import: %s", e)
|
||||
else:
|
||||
|
@ -138,9 +138,11 @@ class GtkUI(ui.UI):
|
||||
client.blocklist_set_config(None, config)
|
||||
|
||||
def _on_button_check_download_clicked(self, widget):
|
||||
self._on_apply_prefs()
|
||||
client.blocklist_import(None, True, False)
|
||||
|
||||
def _on_button_force_download_clicked(self, widget):
|
||||
self._on_apply_prefs()
|
||||
client.blocklist_import(None, True, True)
|
||||
|
||||
def _on_status_item_clicked(self, widget, event):
|
||||
|
@ -59,6 +59,13 @@ class PGTextReader(TextBase):
|
||||
regexp = ':(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+)\.(\d+)\.(\d+)\.(\d+)\s*$'
|
||||
TextBase.__init__(self, fd, regexp)
|
||||
|
||||
class PGTextReaderGzip(PGTextReader):
|
||||
def __init__(self, filename):
|
||||
log.debug("PGTextReaderGzip loading")
|
||||
try:
|
||||
PGTextReader.__init__(self, gzip.open(filename, "r"))
|
||||
except:
|
||||
log.debug("Wrong file type or corrupted blocklist file.")
|
||||
|
||||
# This reads uncompressed PG text list
|
||||
class TextReader(PGTextReader):
|
||||
|
@ -219,8 +219,12 @@ class Core(CorePluginBase):
|
||||
torrent.set_remove_at_ratio(options['remove_at_ratio'])
|
||||
|
||||
if options["apply_move_completed"]:
|
||||
torrent.set_move_on_completed(options["move_completed"])
|
||||
torrent.set_move_on_completed_path(options["move_completed_path"])
|
||||
torrent.set_options(
|
||||
{
|
||||
"move_completed": options["move_completed"],
|
||||
"move_completed_path": options["move_completed_path"]
|
||||
}
|
||||
)
|
||||
|
||||
def _has_auto_match(self, torrent ,label_options):
|
||||
"match for auto_add fields"
|
||||
@ -297,11 +301,12 @@ class Core(CorePluginBase):
|
||||
|
||||
def export_set_config(self, options):
|
||||
"""global_options:"""
|
||||
for key, value in options.items:
|
||||
if key in CORE_OPTIONS:
|
||||
self.config[key] = value
|
||||
if options:
|
||||
for key, value in options.items:
|
||||
if key in CORE_OPTIONS:
|
||||
self.config[key] = value
|
||||
|
||||
self.config.save()
|
||||
self.config.save()
|
||||
|
||||
def _status_get_label(self, torrent_id):
|
||||
return self.torrent_labels.get(torrent_id) or ""
|
||||
|
@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
mkdir temp
|
||||
export PYTHONPATH=./temp
|
||||
python setup.py develop --install-dir ./temp
|
||||
cp ./temp/Stats.egg-link ~/.config/deluge/plugins
|
||||
rm -fr ./temp
|
@ -1,70 +0,0 @@
|
||||
#
|
||||
# setup.py
|
||||
#
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# 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
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
__plugin_name__ = "Stats"
|
||||
__author__ = "Martijn Voncken"
|
||||
__author_email__ = "mvoncken@gmail.com"
|
||||
__version__ = "0.1"
|
||||
__url__ = "http://deluge-torrent.org"
|
||||
__license__ = "GPLv3"
|
||||
__description__ = ""
|
||||
__long_description__ = """"""
|
||||
__pkg_data__ = {__plugin_name__.lower(): ["template/*", "data/*"]}
|
||||
|
||||
setup(
|
||||
name=__plugin_name__,
|
||||
version=__version__,
|
||||
description=__description__,
|
||||
author=__author__,
|
||||
author_email=__author_email__,
|
||||
url=__url__,
|
||||
license=__license__,
|
||||
long_description=__long_description__,
|
||||
|
||||
packages=[__plugin_name__.lower()],
|
||||
package_data = __pkg_data__,
|
||||
|
||||
entry_points="""
|
||||
[deluge.plugin.core]
|
||||
%s = %s:CorePlugin
|
||||
[deluge.plugin.gtkui]
|
||||
%s = %s:GtkUIPlugin
|
||||
[deluge.plugin.webui]
|
||||
%s = %s:WebUIPlugin
|
||||
""" % ((__plugin_name__, __plugin_name__.lower())*3)
|
||||
)
|
@ -1,65 +0,0 @@
|
||||
#
|
||||
# __init__.py
|
||||
#
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# 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
|
||||
|
||||
from deluge.log import LOG as log
|
||||
|
||||
from deluge.plugins.init import PluginBase
|
||||
|
||||
class CorePlugin(PluginBase):
|
||||
def __init__(self, plugin_api, plugin_name):
|
||||
# Load the Core portion of the plugin
|
||||
try:
|
||||
from core import Core
|
||||
self.plugin = Core(plugin_api, plugin_name)
|
||||
except Exception, e:
|
||||
log.debug("Did not load a Core plugin: %s", e)
|
||||
|
||||
class WebUIPlugin(PluginBase):
|
||||
def __init__(self, plugin_api, plugin_name):
|
||||
try:
|
||||
from webui import WebUI
|
||||
self.plugin = WebUI(plugin_api, plugin_name)
|
||||
except Exception, e:
|
||||
log.debug("Did not load a WebUI plugin: %s", e)
|
||||
|
||||
class GtkUIPlugin(PluginBase):
|
||||
def __init__(self, plugin_api, plugin_name):
|
||||
# Load the GtkUI portion of the plugin
|
||||
try:
|
||||
from gtkui import GtkUI
|
||||
self.plugin = GtkUI(plugin_api, plugin_name)
|
||||
except Exception, e:
|
||||
log.debug("Did not load a GtkUI plugin: %s", e)
|
@ -1,156 +0,0 @@
|
||||
#
|
||||
# core.py
|
||||
#
|
||||
# Copyright (C) 2008 Damien Churchill <damoxc@gmail.com>
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) Marcos Pinto 2007 <markybob@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
|
||||
|
||||
import deluge
|
||||
from deluge.log import LOG as log
|
||||
from deluge.plugins.corepluginbase import CorePluginBase
|
||||
from deluge import component
|
||||
from deluge import configmanager
|
||||
import gobject
|
||||
#from deluge.plugins.coreclient import client #1.1 and later only
|
||||
#client: see http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
"test":"NiNiNi",
|
||||
"update_interval":2000, #2 seconds.
|
||||
"length":150, # 2 seconds * 150 --> 5 minutes.
|
||||
}
|
||||
|
||||
DEFAULT_TOTALS = {
|
||||
"total_upload":0,
|
||||
"total_download":0,
|
||||
"total_payload_upload":0,
|
||||
"total_payload_download":0,
|
||||
"stats":{}
|
||||
}
|
||||
|
||||
class Core(CorePluginBase):
|
||||
totals = {} #class var to catch only updating this once per session in enable.
|
||||
|
||||
def enable(self):
|
||||
self.core = component.get("Core")
|
||||
self.stats ={}
|
||||
|
||||
self.config = configmanager.ConfigManager("stats.conf", DEFAULT_PREFS)
|
||||
self.saved_stats = configmanager.ConfigManager("stats.totals", DEFAULT_TOTALS)
|
||||
if self.totals == {}:
|
||||
self.totals.update(self.saved_stats.config)
|
||||
|
||||
self.stats = self.saved_stats.get("stats") or {}
|
||||
self.add_stats(
|
||||
'upload_rate',
|
||||
'download_rate',
|
||||
'num_connections',
|
||||
'dht_nodes',
|
||||
'dht_cache_nodes',
|
||||
'dht_torrents',
|
||||
)
|
||||
|
||||
self.update_timer = gobject.timeout_add(
|
||||
self.config.get("update_interval"), self.update_stats)
|
||||
self.save_timer = gobject.timeout_add(60 * 1000, self.save_stats)
|
||||
self.length = self.config.get("length")
|
||||
|
||||
def disable(self):
|
||||
self.save_stats()
|
||||
gobject.source_remove(self.update_timer)
|
||||
gobject.source_remove(self.save_timer)
|
||||
|
||||
def add_stats(self, *stats):
|
||||
for stat in stats:
|
||||
if stat not in self.stats:
|
||||
self.stats[stat] = []
|
||||
|
||||
def update_stats(self):
|
||||
try:
|
||||
stats = self.core.export_get_stats()
|
||||
status = self.core.session.status()
|
||||
for stat in dir(status):
|
||||
if not stat.startswith('_') and stat not in stats:
|
||||
stats[stat] = getattr(status, stat, None)
|
||||
|
||||
for stat, stat_list in self.stats.iteritems():
|
||||
if stat in stats:
|
||||
stat_list.insert(0, int(stats[stat]))
|
||||
|
||||
if len(stat_list) > self.length:
|
||||
stat_list.pop()
|
||||
except Exception,e:
|
||||
log.error(e.message)
|
||||
return True
|
||||
|
||||
def save_stats(self):
|
||||
try:
|
||||
self.saved_stats.set("stats", self.stats)
|
||||
self.saved_stats.config.update(self.export_get_totals())
|
||||
self.saved_stats.save()
|
||||
except Exception,e:
|
||||
log.error(e.message)
|
||||
return True
|
||||
|
||||
|
||||
# export:
|
||||
def export_get_stats(self, keys):
|
||||
stats_dict = {}
|
||||
for stat in self.stats:
|
||||
if stat not in keys:
|
||||
continue
|
||||
stats_dict[stat] = self.stats[stat]
|
||||
return stats_dict
|
||||
|
||||
def export_get_totals(self):
|
||||
result = {}
|
||||
session_totals = self.export_get_session_totals()
|
||||
for key in session_totals:
|
||||
result[key] = self.totals[key] + session_totals[key]
|
||||
return result
|
||||
|
||||
def export_get_session_totals(self):
|
||||
status = self.core.session.status()
|
||||
return {
|
||||
"total_upload":status.total_upload,
|
||||
"total_download":status.total_download,
|
||||
"total_payload_upload":status.total_payload_upload,
|
||||
"total_payload_download":status.total_payload_download
|
||||
}
|
||||
|
||||
def export_set_config(self, config):
|
||||
"sets the config dictionary"
|
||||
for key in config.keys():
|
||||
self.config[key] = config[key]
|
||||
self.config.save()
|
||||
|
||||
def export_get_config(self):
|
||||
"returns the config dictionary"
|
||||
return self.config.config
|
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.5 on Fri Aug 8 23:34:44 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<child>
|
||||
<widget class="GtkHBox" id="prefs_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Test config value:</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="txt_test">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.5 on Mon Oct 13 20:17:39 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="graph_label">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-page-setup</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="graph_label_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Graphs</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="graph_tab">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<child>
|
||||
<widget class="GtkNotebook" id="graph_notebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tab_pos">GTK_POS_LEFT</property>
|
||||
<child>
|
||||
<widget class="GtkDrawingArea" id="bandwidth_graph">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="bandwidth_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Bandwidth</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">tab</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkDrawingArea" id="connections_graph">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="connections_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Connections</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">tab</property>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkDrawingArea" id="seeds_graph">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="seeds_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Seeds/Peers</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">tab</property>
|
||||
<property name="position">2</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
@ -1,250 +0,0 @@
|
||||
#
|
||||
# graph.py
|
||||
#
|
||||
# Copyright (C) 2008 Damien Churchill <damoxc@gmail.com>
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) Marcos Pinto 2007 <markybob@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
|
||||
|
||||
"""
|
||||
port of old plugin by markybob.
|
||||
"""
|
||||
import time
|
||||
import cairo
|
||||
from deluge.log import LOG as log
|
||||
from deluge.ui.client import aclient
|
||||
|
||||
black = (0, 0, 0)
|
||||
gray = (0.75, 0.75, 0.75)
|
||||
white = (1.0, 1.0, 1.0)
|
||||
darkred = (0.65, 0, 0)
|
||||
red = (1.0, 0, 0)
|
||||
green = (0, 1.0, 0)
|
||||
blue = (0, 0, 1.0)
|
||||
orange = (1.0, 0.74, 0)
|
||||
|
||||
def default_formatter(value):
|
||||
return str(value)
|
||||
|
||||
def change_opacity(color, opactiy):
|
||||
"""A method to assist in changing the opactiy of a color inorder to draw the
|
||||
fills.
|
||||
"""
|
||||
color = list(color)
|
||||
if len(color) == 4:
|
||||
color[3] = opactiy
|
||||
else:
|
||||
color.append(opactiy)
|
||||
return tuple(color)
|
||||
|
||||
class Graph:
|
||||
def __init__(self):
|
||||
self.width = 100
|
||||
self.height = 100
|
||||
self.length = 150
|
||||
self.stat_info = {}
|
||||
self.line_size = 2
|
||||
self.mean_selected = True
|
||||
self.legend_selected = True
|
||||
self.max_selected = True
|
||||
self.black = (0, 0 , 0,)
|
||||
self.interval = 2000 # 2 secs
|
||||
self.text_bg = (255, 255 , 255, 128) # prototyping
|
||||
self.set_left_axis()
|
||||
|
||||
def set_left_axis(self, **kargs):
|
||||
self.left_axis = kargs
|
||||
|
||||
def add_stat(self, stat, label='', axis='left', line=True, fill=True, color=None):
|
||||
self.stat_info[stat] = {
|
||||
'axis': axis,
|
||||
'label': label,
|
||||
'line': line,
|
||||
'fill': fill,
|
||||
'color': color
|
||||
}
|
||||
|
||||
def async_request(self):
|
||||
aclient.stats_get_stats(self.set_stats, self.stat_info.keys())
|
||||
aclient.stats_get_config(self.set_config)
|
||||
|
||||
def set_stats(self, stats):
|
||||
self.stats = stats
|
||||
|
||||
def set_config(self, config):
|
||||
self.length = config["length"]
|
||||
self.interval = config["update_interval"]
|
||||
|
||||
def draw_to_context(self, context, width, height):
|
||||
self.ctx = context
|
||||
self.width, self.height = width, height
|
||||
self.draw_rect(white, 0, 0, self.width, self.height)
|
||||
self.draw_x_axis()
|
||||
self.draw_left_axis()
|
||||
|
||||
if self.legend_selected:
|
||||
self.draw_legend()
|
||||
return self.ctx
|
||||
|
||||
def draw(self, width, height):
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
|
||||
self.ctx = cairo.Context(self.surface)
|
||||
self.draw_rect(white, 0, 0, self.width, self.height)
|
||||
self.draw_x_axis()
|
||||
self.draw_left_axis()
|
||||
|
||||
if self.legend_selected:
|
||||
self.draw_legend()
|
||||
return self.surface
|
||||
|
||||
def draw_x_axis(self):
|
||||
now = time.time()
|
||||
duration = self.length * (self.interval / 1000.0)
|
||||
start = now - duration
|
||||
ratio = (self.width - 40) / duration
|
||||
seconds_to_minute = 60 - time.localtime(start)[5]
|
||||
|
||||
for i in xrange(0, 5):
|
||||
text = time.strftime('%H:%M', time.localtime(start + seconds_to_minute + (60*i)))
|
||||
x = int(ratio * (seconds_to_minute + (60*i)))
|
||||
self.draw_text(text, x + 46, self.height - 20)
|
||||
x = x + 59.5
|
||||
self.draw_dotted_line(gray, x, 20, x, self.height - 20)
|
||||
|
||||
y = self.height - 22.5
|
||||
self.draw_dotted_line(gray, 60, y, int(self.width), y)
|
||||
|
||||
def draw_left_axis(self):
|
||||
stats = {}
|
||||
max_values = []
|
||||
for stat in self.stat_info:
|
||||
if self.stat_info[stat]['axis'] == 'left':
|
||||
stats[stat] = self.stat_info[stat]
|
||||
stats[stat]['values'] = self.stats[stat]
|
||||
stats[stat]['fill_color'] = change_opacity(stats[stat]['color'], 0.5)
|
||||
stats[stat]['color'] = change_opacity(stats[stat]['color'], 0.8)
|
||||
stats[stat]['max_value'] = max(self.stats[stat])
|
||||
max_values.append(stats[stat]['max_value'])
|
||||
if len(max_values) > 1:
|
||||
max_value = max(*max_values)
|
||||
else:
|
||||
max_value = max_values[0]
|
||||
|
||||
if max_value < self.left_axis['min']:
|
||||
max_value = self.left_axis['min']
|
||||
|
||||
height = self.height - self.line_size - 22
|
||||
#max_value = float(round(max_value, len(str(max_value)) * -1))
|
||||
max_value = float(max_value)
|
||||
ratio = height / max_value
|
||||
|
||||
for i in xrange(1, 6):
|
||||
y = int(ratio * ((max_value / 5) * i)) - 0.5
|
||||
if i < 5:
|
||||
self.draw_dotted_line(gray, 60, y, self.width, y)
|
||||
text = self.left_axis['formatter']((max_value / 5) * (5 - i))
|
||||
self.draw_text(text, 0, y - 6)
|
||||
self.draw_dotted_line(gray, 60.5, 20, 60.5, self.height - 20)
|
||||
|
||||
for stat, info in stats.iteritems():
|
||||
self.draw_value_poly(info['values'], info['color'], max_value)
|
||||
self.draw_value_poly(info['values'], info['fill_color'], max_value, info['fill'])
|
||||
|
||||
def draw_legend(self):
|
||||
pass
|
||||
|
||||
def trace_path(self, values, max_value):
|
||||
height = self.height - 24
|
||||
width = self.width
|
||||
line_width = self.line_size
|
||||
|
||||
self.ctx.set_line_width(line_width)
|
||||
self.ctx.move_to(width, height)
|
||||
|
||||
self.ctx.line_to(width,
|
||||
int(height - ((height - 28) * values[0] / max_value)))
|
||||
|
||||
x = width
|
||||
step = (width - 60) / float(self.length)
|
||||
for i, value in enumerate(values):
|
||||
if i == self.length - 1:
|
||||
x = 62
|
||||
self.ctx.line_to(x,
|
||||
int(height - 1 - ((height - 28) * value / max_value))
|
||||
)
|
||||
x -= step
|
||||
|
||||
self.ctx.line_to(
|
||||
int(width + 62 - (((len(values) - 1) * width) / (self.length - 1))),
|
||||
height)
|
||||
self.ctx.close_path()
|
||||
|
||||
def draw_value_poly(self, values, color, max_value, fill=False):
|
||||
self.trace_path(values, max_value)
|
||||
self.ctx.set_source_rgba(*color)
|
||||
|
||||
if fill:
|
||||
self.ctx.fill()
|
||||
else:
|
||||
self.ctx.stroke()
|
||||
|
||||
def draw_text(self, text, x, y):
|
||||
self.ctx.set_font_size(9)
|
||||
self.ctx.move_to(x, y + 9)
|
||||
self.ctx.set_source_rgba(*self.black)
|
||||
self.ctx.show_text(text)
|
||||
|
||||
def draw_rect(self, color, x, y, height, width):
|
||||
self.ctx.set_source_rgba(*color)
|
||||
self.ctx.rectangle(x, y, height, width)
|
||||
self.ctx.fill()
|
||||
|
||||
def draw_line(self, color, x1, y1, x2, y2):
|
||||
self.ctx.set_source_rgba(*color)
|
||||
self.ctx.set_line_width(1)
|
||||
self.ctx.move_to(x1, y1)
|
||||
self.ctx.line_to(x2, y2)
|
||||
self.ctx.stroke()
|
||||
|
||||
def draw_dotted_line(self, color, x1, y1, x2, y2):
|
||||
self.ctx.set_source_rgba(*color)
|
||||
self.ctx.set_line_width(1)
|
||||
self.ctx.move_to(x1, y1)
|
||||
self.ctx.line_to(x2, y2)
|
||||
#self.ctx.stroke_preserve()
|
||||
#self.ctx.set_source_rgba(*white)
|
||||
#self.ctx.set_dash((1, 1), 4)
|
||||
self.ctx.stroke()
|
||||
#self.ctx.set_dash((1, 1), 0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import test
|
@ -1,115 +0,0 @@
|
||||
#
|
||||
# gtkui.py
|
||||
#
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# 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
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
from gtk.glade import XML
|
||||
|
||||
import graph
|
||||
from deluge import component
|
||||
from deluge.log import LOG as log
|
||||
from deluge.common import fspeed
|
||||
from deluge.ui.client import aclient
|
||||
from deluge.ui.gtkui.torrentdetails import Tab
|
||||
|
||||
class GraphsTab(Tab):
|
||||
def __init__(self, glade):
|
||||
Tab.__init__(self)
|
||||
self._name = 'Graphs'
|
||||
self.glade = glade
|
||||
self.window = self.glade.get_widget('graph_tab')
|
||||
self.notebook = self.glade.get_widget('graph_notebook')
|
||||
self.label = self.glade.get_widget('graph_label')
|
||||
self.bandwidth_graph = self.glade.get_widget('bandwidth_graph')
|
||||
self.bandwidth_graph.connect('expose_event', self.bandwidth_expose)
|
||||
self.window.unparent()
|
||||
self.label.unparent()
|
||||
|
||||
def bandwidth_expose(self, widget, event):
|
||||
self.graph_widget = self.bandwidth_graph
|
||||
self.graph = graph.Graph()
|
||||
self.graph.add_stat('download_rate', label='Download Rate', color=graph.green)
|
||||
self.graph.add_stat('upload_rate', label='Upload Rate', color=graph.blue)
|
||||
self.graph.set_left_axis(formatter=fspeed, min=10240)
|
||||
self.update_timer = gobject.timeout_add(2000, self.update_graph)
|
||||
self.update_graph()
|
||||
|
||||
def update_graph(self):
|
||||
width, height = self.graph_widget.allocation.width, self.graph_widget.allocation.height
|
||||
context = self.graph_widget.window.cairo_create()
|
||||
self.graph.async_request()
|
||||
aclient.force_call(True)
|
||||
self.graph.draw_to_context(context, width, height)
|
||||
return True
|
||||
|
||||
class GtkUI(object):
|
||||
def __init__(self, plugin_api, plugin_name):
|
||||
log.debug("Calling Stats UI init")
|
||||
self.plugin = plugin_api
|
||||
|
||||
def enable(self):
|
||||
self.glade = XML(self.get_resource("config.glade"))
|
||||
self.plugin.add_preferences_page("Stats", self.glade.get_widget("prefs_box"))
|
||||
self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs)
|
||||
self.plugin.register_hook("on_show_prefs", self.on_show_prefs)
|
||||
self.on_show_prefs()
|
||||
|
||||
self.graphs_tab = GraphsTab(XML(self.get_resource("tabs.glade")))
|
||||
self.torrent_details = component.get('TorrentDetails')
|
||||
self.torrent_details.notebook.append_page(self.graphs_tab.window, self.graphs_tab.label)
|
||||
|
||||
def disable(self):
|
||||
self.plugin.remove_preferences_page("Stats")
|
||||
self.plugin.deregister_hook("on_apply_prefs", self.on_apply_prefs)
|
||||
self.plugin.deregister_hook("on_show_prefs", self.on_show_prefs)
|
||||
|
||||
def on_apply_prefs(self):
|
||||
log.debug("applying prefs for Stats")
|
||||
config = {
|
||||
"test":self.glade.get_widget("txt_test").get_text()
|
||||
}
|
||||
aclient.stats_set_config(None, config)
|
||||
|
||||
def on_show_prefs(self):
|
||||
aclient.stats_get_config(self.cb_get_config)
|
||||
|
||||
def cb_get_config(self, config):
|
||||
"callback for on show_prefs"
|
||||
self.glade.get_widget("txt_test").set_text(config["test"])
|
||||
|
||||
def get_resource(self, filename):
|
||||
import pkg_resources, os
|
||||
return pkg_resources.resource_filename("stats", os.path.join("data", filename))
|
@ -1,12 +0,0 @@
|
||||
$:render.header(_("Network Graph"), 'graph')
|
||||
$:render.admin_toolbar('graph')
|
||||
|
||||
<div style="padding-left:20px">
|
||||
|
||||
<img src="$base/graph/network.png?height=300&width=1000"><br \>
|
||||
<img src="$base/graph/connections.png?height=300&width=1000"><br \>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
$:render.footer()
|
@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="2" />
|
||||
</head>
|
||||
<body>
|
||||
<img src="output_async.png" /> <br />
|
||||
<img src="output_dht.png" />
|
||||
</body>
|
||||
</html>
|
@ -1,78 +0,0 @@
|
||||
from deluge.ui.client import sclient, aclient
|
||||
sclient.set_core_uri()
|
||||
import graph
|
||||
import deluge
|
||||
|
||||
def test_sync():
|
||||
if 1:
|
||||
upload = sclient.graph_get_upload()
|
||||
download = sclient.graph_get_download()
|
||||
print upload
|
||||
print download
|
||||
else:
|
||||
upload = [66804, 66915, 66974, 67447, 67540, 67318, 67320, 67249, 66659, 66489, 67027, 66914, 66802, 67303, 67654, 67643, 67763, 67528, 67523, 67431, 67214, 66939, 67316, 67020, 66881, 67103, 67377, 67141, 67366, 67492, 67375, 67203, 67056, 67010, 67029, 66741, 66695, 66868, 66805, 66264, 66249, 66317, 66459, 66306, 66681, 66954, 66662, 66278, 65921, 65695, 65681, 65942, 66000, 66140, 66424, 66480, 66257, 66271, 66145, 65854, 65568, 65268, 65112, 65050, 65027, 64676, 64655, 64178, 64386, 63979, 63271, 62746, 62337, 62297, 62496, 62902, 63801, 64121, 62957, 62921, 63051, 62644, 63240, 64107, 63968, 63987, 63644, 63263, 63153, 62999, 62843, 62777, 63101, 63078, 63178, 63126, 63401, 62630, 62451, 62505, 62254, 61485, 61264, 60937, 60568, 61011, 61109, 60325, 60196, 59640, 59619, 59514, 60813, 60572, 61632, 61689, 63365, 64583, 66396, 67179, 68209, 68295, 67674, 67559, 67195, 66178, 65632, 66124, 66456, 66676, 67183, 67620, 66960, 66347, 65925, 65907, 65896, 66738, 66703, 67060, 67004, 67007, 66329, 65304, 52002, 38969, 25433, 12426, 0, 0]
|
||||
download = [42926, 43853, 43157, 45470, 44254, 46272, 45083, 47344, 46716, 51963, 50112, 52334, 55525, 57545, 53691, 51637, 49574, 49836, 48295, 49843, 52878, 56014, 56966, 56938, 60065, 60461, 56542, 59526, 58678, 54424, 51862, 55109, 52132, 53783, 51687, 56567, 52182, 50758, 46714, 50511, 48161, 50920, 48694, 50528, 55074, 55420, 55882, 59268, 59958, 57938, 57115, 51424, 51180, 53184, 52879, 51177, 54417, 51097, 47901, 49870, 55865, 61118, 61476, 63498, 58878, 49630, 45975, 45632, 45892, 44855, 49495, 48304, 45829, 42152, 39403, 37574, 32384, 34933, 34901, 33492, 31953, 36271, 33826, 34515, 36408, 41106, 43054, 44110, 40810, 41383, 37267, 35881, 38660, 37525, 34857, 36718, 36842, 34281, 39528, 41854, 42952, 40021, 41722, 41045, 42917, 39287, 38672, 32824, 28765, 22686, 18490, 15714, 15268, 14793, 15305, 16354, 16720, 17502, 17857, 16622, 18447, 19929, 31138, 36965, 36158, 32795, 30445, 21997, 18100, 22491, 27227, 29317, 32436, 35700, 39140, 36258, 33697, 24751, 20354, 8211, 3836, 1560, 834, 2034, 1744, 1637, 1637, 1637, 0, 0]
|
||||
|
||||
from graph import NetworkGraph
|
||||
n = NetworkGraph()
|
||||
n.savedUpSpeeds = upload
|
||||
n.savedDownSpeeds = download
|
||||
|
||||
n.draw(800,200)
|
||||
n.surface.write_to_png('output_sync.png')
|
||||
|
||||
def test_async():
|
||||
g = graph.Graph()
|
||||
g.add_stat('download_rate', color=graph.green)
|
||||
g.add_stat('upload_rate', color=graph.blue)
|
||||
g.set_left_axis(formatter=deluge.common.fspeed, min=10240)
|
||||
g.async_request()
|
||||
aclient.force_call(True)
|
||||
surface = g.draw(600, 300)
|
||||
surface.write_to_png('output_async.png')
|
||||
|
||||
def test_dht():
|
||||
"""'boring graph, but testing if it works'"""
|
||||
|
||||
g = graph.Graph()
|
||||
g.add_stat('dht_nodes', color=graph.orange)
|
||||
g.add_stat('dht_cache_nodes', color=graph.blue)
|
||||
g.add_stat('dht_torrents', color=graph.green)
|
||||
g.add_stat('num_connections', color=graph.darkred) #testing : non dht
|
||||
g.set_left_axis(formatter=str, min=10)
|
||||
g.async_request()
|
||||
aclient.force_call(True)
|
||||
surface = g.draw(600, 300)
|
||||
surface.write_to_png('output_dht.png')
|
||||
|
||||
|
||||
def test_write():
|
||||
"""
|
||||
writing to a file-like object; need this for webui.
|
||||
"""
|
||||
class fake_file:
|
||||
def __init__(self):
|
||||
self.data = []
|
||||
def write(self, str):
|
||||
self.data.append(str)
|
||||
|
||||
g = graph.Graph()
|
||||
g.add_stat('download_rate', color=graph.green)
|
||||
g.add_stat('upload_rate', color=graph.blue)
|
||||
g.set_left_axis(formatter=deluge.common.fspeed, min=10240)
|
||||
g.async_request()
|
||||
aclient.force_call(True)
|
||||
surface = g.draw(900, 150)
|
||||
|
||||
file_like = fake_file()
|
||||
surface.write_to_png(file_like)
|
||||
data = "".join(file_like.data)
|
||||
|
||||
f = open("file_like.png","wb")
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
#test_sync()
|
||||
test_async()
|
||||
test_dht()
|
||||
#test_write()
|
@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
while true; do
|
||||
python test.py
|
||||
sleep 2
|
||||
done;
|
@ -1,23 +0,0 @@
|
||||
from deluge.ui.client import sclient, aclient
|
||||
from deluge.common import fsize
|
||||
sclient.set_core_uri()
|
||||
|
||||
def print_totals(totals):
|
||||
for name, value in totals.iteritems():
|
||||
print name , fsize(value)
|
||||
|
||||
print "overhead:"
|
||||
print "up:", fsize(totals["total_upload"] - totals["total_payload_upload"] )
|
||||
print "down:", fsize(totals["total_download"] - totals["total_payload_download"] )
|
||||
|
||||
|
||||
print "==totals=="
|
||||
print_totals(sclient.stats_get_totals())
|
||||
|
||||
print "==session totals=="
|
||||
print_totals(sclient.stats_get_session_totals())
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,127 +0,0 @@
|
||||
#
|
||||
# webui.py
|
||||
#
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may redistribute it and/or modify it under the terms of the
|
||||
# GNU General Public License, as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# deluge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# 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
|
||||
|
||||
import os
|
||||
from deluge.common import fspeed
|
||||
from deluge.log import LOG as log
|
||||
from deluge.ui.client import sclient, aclient
|
||||
from deluge.plugins.webuipluginbase import WebUIPluginBase
|
||||
from deluge import component
|
||||
import graph
|
||||
|
||||
api = component.get("WebPluginApi")
|
||||
forms = api.forms
|
||||
|
||||
#pages:
|
||||
class graph_page:
|
||||
@api.deco.deluge_page
|
||||
def GET(self, args):
|
||||
return api.render.stats.graph()
|
||||
|
||||
class network_png:
|
||||
@api.deco.check_session
|
||||
def GET(self, args):
|
||||
aclient.force_call(True) #bug, invalid data in async queue?
|
||||
self.data = ''
|
||||
vars = api.web.input(width = 600, height = 150)
|
||||
api.web.header("Content-Type", "image/png")
|
||||
g = graph.Graph()
|
||||
g.add_stat('download_rate', color=graph.green)
|
||||
g.add_stat('upload_rate', color=graph.blue)
|
||||
g.set_left_axis(formatter=fspeed, min=10240)
|
||||
g.async_request()
|
||||
aclient.force_call(True)
|
||||
surface = g.draw(int(vars.width), int(vars.height))
|
||||
surface.write_to_png(self)
|
||||
print self.data
|
||||
|
||||
def write(self, str): #file like object for pango; write_to_png
|
||||
self.data += str
|
||||
|
||||
class connections_png:
|
||||
@api.deco.check_session
|
||||
def GET(self, args):
|
||||
"testing, not a final graph"
|
||||
aclient.force_call(True) #bug, invalid data in async queue?
|
||||
self.data = ''
|
||||
vars = api.web.input(width = 600, height = 150)
|
||||
api.web.header("Content-Type", "image/png")
|
||||
g = graph.Graph()
|
||||
g.add_stat('dht_nodes', color=graph.orange)
|
||||
g.add_stat('dht_cache_nodes', color=graph.blue)
|
||||
g.add_stat('dht_torrents', color=graph.green)
|
||||
g.add_stat('num_connections', color=graph.darkred) #testing : non dht
|
||||
g.set_left_axis(formatter=str, min=10)
|
||||
g.async_request()
|
||||
aclient.force_call(True)
|
||||
surface = g.draw(int(vars.width), int(vars.height))
|
||||
surface.write_to_png(self)
|
||||
print self.data
|
||||
|
||||
def write(self, str): #file like object for pango; write_to_png
|
||||
self.data += str
|
||||
|
||||
class WebUI(WebUIPluginBase):
|
||||
#map url's to classes: [(url,class), ..]
|
||||
urls = [
|
||||
('/graph', graph_page),
|
||||
('/graph/network.png', network_png),
|
||||
('/graph/connections.png', connections_png)
|
||||
]
|
||||
|
||||
def enable(self):
|
||||
api.config_page_manager.register('plugins', 'stats' ,ConfigForm)
|
||||
api.menu_manager.register_admin_page("stats", _("Stats"), "/graph") #<--top menu
|
||||
|
||||
def disable(self):
|
||||
api.config_page_manager.deregister('stats')
|
||||
api.menu_manager.deregister_admin_page("stats") #<--top menu
|
||||
|
||||
|
||||
class ConfigForm(forms.Form):
|
||||
#meta:
|
||||
title = _("Graph")
|
||||
|
||||
#load/save:
|
||||
def initial_data(self):
|
||||
return sclient.graph_get_config()
|
||||
|
||||
def save(self, data):
|
||||
cfg = dict(data)
|
||||
sclient.graph_set_config(cfg)
|
||||
|
||||
#django newforms magic: define config fields:
|
||||
test = forms.CharField(label=_("Test config value"))
|
@ -1 +1,24 @@
|
||||
#
|
||||
# __init__.py
|
||||
#
|
||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@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.
|
||||
#
|
||||
UI_PATH = __path__[0]
|
||||
|
@ -1,4 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# colors.py
|
||||
#
|
||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@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 re, sys
|
||||
|
||||
def color(string, fg=None, attrs=[], bg=None, keep_open=False, input=False):
|
||||
|
@ -1,4 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# add.py
|
||||
#
|
||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@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.
|
||||
#
|
||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
||||
from deluge.ui.console import mapping
|
||||
from deluge.ui.console.colors import templates
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user