diff options
355 files changed, 1594 insertions, 1029 deletions
diff --git a/.gitignore b/.gitignore index 2a7eb4d80..cf7a67e64 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist _trial_temp deluge/i18n/*/ *.desktop +.build_data* @@ -32,6 +32,7 @@ * Implemented sequential downloads UI handling. * #378: Allow showing a pieces bar instead of a regular progress bar in a torrent's status tab. + * #2093: Make torrent opening compatible with all unicode paths. ==== Blocklist Plugin ==== * #1382: Implemented whitelist support to both core and GTK UI. @@ -44,6 +45,72 @@ === Deluge 1.3.6 (In Development) === ==== Core ==== * Catch & log KeyError when removing a torrent from the queued torrents set + * Fix moving/renaming torrents issues when using libtorrent 0.16 + * Make sure queue order is preserved when restarting + * #2160: Disable use of python bindings for libtorrent extensions and replace with session flag + * #2163: Fix unable add torrent file with empty (0:) encoding tag + * #2201: Fix error in authmanager if auth file has extra newlines + * #2109: Fix the Proxy settings not being cleared by setting None + * #2110: Fix accepting magnet uris with xt param anywhere within them + * #2204: Fix daemon shutdown hang with large numbers of torrents + +==== Client ==== + * Fix keyerrors after removing torrents from UIs + +==== GtkUI ==== + * Add move completed option to add torrent dialog + * Prevent jitter in torrent view + * Fix torrent creation with non-ascii characters + * Fix #2100 : Add option not to bring main window to front when adding torrents through ipcinterface + * Add Quit Dialog when toggling classic mode in preferences and only show connection manager when not in classic mode. + * #2169: Fix 'Download Location' in the Add Torrent Dialog not set correctly when folder typed into Other->Location field + * #2171: Fix the Add Peer dialog not responding if empty or invalid values entered + * #2104: Fix no title set for the appindicator + * #2086: Fix submenus and icons for appindicator + * #2146: Fix missing translations in View|Tabs submenu + * Fix torrent names on libtorrent 0.16 on windows + * #2147: Fix missing translations for plugin preferences page + * #1474: Fix the on_show_prefs hook not being executed immediatly after enabling a plugin + * #1946: Fix ReactorNotRestartable error when set as startup application + * #2130: Fix same name can be given to different files in Add Torrent dialog + * #2129: Fix empty filename able to be set in AddTorrent dialog + * #2228: Fix Apply-To-All in AddTorrent Dialog copying file renames to other torrents + +==== Console ==== + * LP#1004793: Enable use of connect command in non-interactive mode + * Ensure console commands are executed in order + * #2065: Fix crash with missing closing quote + * #1397: Add support for -s STATE in info command + +==== WebUI ==== + * Add move completed option to add torrent dialog + * #2112: Fix world readable tmp directory in json_api + * #2069: Fix login window layout problem when using larger than default font size + * #1890: Fix columns in files and peers view could use some spacing + * #2103: Fix sorting by name is case-sensitive [sedulous] + * #2120: Fix manually entered values not being saved in spinners + * #2212: Fix unable to scroll in proxy preferences page + * Fix autoconnecting to the default host + * #2046: Fix plugins not enabling properly until after refreshing page + * #2125: Fix plugin methods not being available when enabled until restart + * #2085: Fix not showing torrents in sidebar for categories other than 'All' in classic mode + * #2232: Fix flag icon path in Peers Tab missing deluge.config.base + * Fix submenus closing upon mouse click + +==== Windows OS ==== + * Hide the cmd windows when running deluged.exe or deluge-web.exe + * Add deluged-debug.exe and deluge-web-debug.exe that still show the cmd window + * Add gtk locale files to fix untranslated text + * Fix the Open Folder option not working with non-ascii paths + * Fix the daemon starting with config dir containing spaces + * Fix Windows tray submenu items requiring right-click instead of left-click + * Fix issue with adding some torrents with illegal characters via url in gtk client + +==== OS X ==== + * Fix Open File/Folder option + +==== Execute ==== + * Fix execute plugin not working with unicode torrent names === Deluge 1.3.5 (09 April 2012) === ==== GtkUI ==== @@ -1,5 +1,5 @@ === Core === - * python >= 2.5 + * python >= 2.6 * twisted >= 8.1 * twisted-web >= 8.1 * pyopenssl @@ -11,6 +11,7 @@ * chardet * geoip-database (optional) * setproctitle (optional) + * rencode >= 1.0.2 (optional), a pure python version is included * libtorrent >= 0.16.1, or build the included version diff --git a/deluge/_libtorrent.py b/deluge/_libtorrent.py index ab782d67a..898cfb150 100644 --- a/deluge/_libtorrent.py +++ b/deluge/_libtorrent.py @@ -45,9 +45,9 @@ supports. """ -REQUIRED_VERSION = "0.14.9.0" +REQUIRED_VERSION = "0.16.1.0" -def check_version(LT): +def check_version(lt): from deluge.common import VersionSplit if VersionSplit(lt.version) < VersionSplit(REQUIRED_VERSION): raise ImportError("This version of Deluge requires libtorrent >=%s!" % REQUIRED_VERSION) diff --git a/deluge/common.py b/deluge/common.py index ea615df20..f3236dea5 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -37,17 +37,23 @@ """Common functions for various parts of Deluge to use.""" import os +import sys import time import subprocess import platform import chardet import logging +import pkg_resources +import gettext +import locale try: import json except ImportError: import simplejson as json +from deluge.error import * + log = logging.getLogger(__name__) # Do a little hack here just in case the user has json-py installed since it @@ -65,12 +71,6 @@ if not hasattr(json, "dumps"): json.dump = dump json.load = load -import pkg_resources -import gettext -import locale - -from deluge.error import * - LT_TORRENT_STATE = { "Queued": 0, "Checking": 1, @@ -90,7 +90,6 @@ LT_TORRENT_STATE = { 7: "Checking Resume Data" } - TORRENT_STATE = [ "Allocating", "Checking", @@ -134,17 +133,26 @@ def get_default_config_dir(filename=None): :rtype: string """ + if windows_check(): - if filename: - return os.path.join(os.environ.get("APPDATA"), "deluge", filename) - else: - return os.path.join(os.environ.get("APPDATA"), "deluge") + def save_config_path(resource): + appDataPath = os.environ.get("APPDATA") + if not appDataPath: + import _winreg + hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders") + appDataReg = _winreg.QueryValueEx(hkey, "AppData") + appDataPath = appDataReg[0] + _winreg.CloseKey(hkey) + return os.path.join(appDataPath, resource) else: - import xdg.BaseDirectory - if filename: - return os.path.join(xdg.BaseDirectory.save_config_path("deluge"), filename) - else: - return xdg.BaseDirectory.save_config_path("deluge") + from xdg.BaseDirectory import save_config_path + if not filename: + filename = '' + try: + return os.path.join(save_config_path("deluge"), filename) + except OSError, e: + log.error("Unable to use default config directory, exiting... (%s)", e) + sys.exit(1) def get_default_download_dir(): """ @@ -231,7 +239,7 @@ def open_file(path): """ if windows_check(): - os.startfile("%s" % path) + os.startfile(path.decode("utf8")) elif osx_check(): subprocess.Popen(["open", "%s" % path]) else: @@ -448,7 +456,9 @@ def is_magnet(uri): True """ - if uri[:20] == "magnet:?xt=urn:btih:": + magnet_scheme = 'magnet:?' + xt_param = 'xt=urn:btih:' + if uri.startswith(magnet_scheme) and xt_param in uri: return True return False @@ -516,9 +526,8 @@ def free_space(path): raise InvalidPathError("%s is not a valid path" % path) if windows_check(): - import win32file - sectors, bytes, free, total = map(long, win32file.GetDiskFreeSpace(path)) - return (free * sectors * bytes) + from win32file import GetDiskFreeSpaceEx + return GetDiskFreeSpaceEx(path)[0] else: disk_data = os.statvfs(path.encode("utf8")) block_size = disk_data.f_frsize @@ -542,15 +551,23 @@ def is_ip(ip): import socket #first we test ipv4 try: - if socket.inet_pton(socket.AF_INET, "%s" % (ip)): - return True + if windows_check(): + if socket.inet_aton("%s" % (ip)): + return True + else: + 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)): + if windows_check(): + log.warning("ipv6 check unavailable on windows") return True + else: + if socket.inet_pton(socket.AF_INET6, "%s" % (ip)): + return True except socket.error: return False @@ -608,37 +625,55 @@ def xml_encode(string): def decode_string(s, encoding="utf8"): """ - Decodes a string and re-encodes it in utf8. If it cannot decode using - `:param:encoding` then it will try to detect the string encoding and - decode it. + Decodes a string and return unicode. If it cannot decode using + `:param:encoding` then it will try latin1, and if that fails, + try to detect the string encoding. If that fails, decode with + ignore. :param s: string to decode :type s: string :keyword encoding: the encoding to use in the decoding :type encoding: string + :returns: s converted to unicode + :rtype: unicode """ + if not s: + return u'' + elif isinstance(s, unicode): + return s - try: - s = s.decode(encoding).encode("utf8", "ignore") - except UnicodeDecodeError: - s = s.decode(chardet.detect(s)["encoding"], "ignore").encode("utf8", "ignore") - return s + encodings = [lambda: ("utf8", 'strict'), + lambda: ("iso-8859-1", 'strict'), + lambda: (chardet.detect(s)["encoding"], 'strict'), + lambda: (chardet.detect(s)["encoding"], 'ignore')] -def utf8_encoded(s): + if not encoding is "utf8": + encodings.insert(0, lambda: (encoding, 'strict')) + + for l in encodings: + try: + return s.decode(*l()) + except UnicodeDecodeError: + pass + return u'' + +def utf8_encoded(s, encoding="utf8"): """ Returns a utf8 encoded string of s :param s: (unicode) string to (re-)encode :type s: basestring + :keyword encoding: the encoding to use in the decoding + :type encoding: string :returns: a utf8 encoded string of s :rtype: str """ if isinstance(s, str): - s = decode_string(s) + s = decode_string(s, encoding).encode("utf8") elif isinstance(s, unicode): - s = s.encode("utf8", "ignore") + s = s.encode("utf8") return s class VersionSplit(object): @@ -741,3 +776,39 @@ def setup_translations(setup_pygtk=False): log.exception(e) import __builtin__ __builtin__.__dict__["_"] = lambda x: x + +def unicode_argv(): + """ Gets sys.argv as list of unicode objects on any platform.""" + if windows_check(): + # Versions 2.x of Python don't support Unicode in sys.argv on + # Windows, with the underlying Windows API instead replacing multi-byte + # characters with '?'. + from ctypes import POINTER, byref, cdll, c_int, windll + from ctypes.wintypes import LPCWSTR, LPWSTR + + GetCommandLineW = cdll.kernel32.GetCommandLineW + GetCommandLineW.argtypes = [] + GetCommandLineW.restype = LPCWSTR + + CommandLineToArgvW = windll.shell32.CommandLineToArgvW + CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)] + CommandLineToArgvW.restype = POINTER(LPWSTR) + + cmd = GetCommandLineW() + argc = c_int(0) + argv = CommandLineToArgvW(cmd, byref(argc)) + if argc.value > 0: + # Remove Python executable and commands if present + start = argc.value - len(sys.argv) + return [argv[i] for i in + xrange(start, argc.value)] + else: + # On other platforms, we have to find the likely encoding of the args and decode + # First check if sys.stdout or stdin have encoding set + encoding = getattr(sys.stdout, "encoding") or getattr(sys.stdin, "encoding") + # If that fails, check what the locale is set to + encoding = encoding or locale.getpreferredencoding() + # As a last resort, just default to utf-8 + encoding = encoding or "utf-8" + + return [arg.decode(encoding) for arg in sys.argv] diff --git a/deluge/component.py b/deluge/component.py index 538d2f9f6..6085db277 100644 --- a/deluge/component.py +++ b/deluge/component.py @@ -34,6 +34,7 @@ # import logging +from collections import defaultdict from twisted.internet.defer import maybeDeferred, succeed, DeferredList, fail from twisted.internet.task import LoopingCall @@ -225,6 +226,8 @@ class ComponentRegistry(object): """ def __init__(self): self.components = {} + # Stores all of the components that are dependent on a particular component + self.dependents = defaultdict(list) def register(self, obj): """ @@ -243,6 +246,9 @@ class ComponentRegistry(object): "Component already registered with name %s" % name) self.components[obj._component_name] = obj + if obj._component_depend: + for depend in obj._component_depend: + self.dependents[depend].append(name) def deregister(self, obj): """ @@ -317,11 +323,23 @@ class ComponentRegistry(object): elif isinstance(names, str): names = [names] + def on_dependents_stopped(result, name): + return self.components[name]._component_stop() + + stopped_in_deferred = set() deferreds = [] for name in names: + if name in stopped_in_deferred: + continue if name in self.components: - deferreds.append(self.components[name]._component_stop()) + if name in self.dependents: + # If other components depend on this component, stop them first + d = self.stop(self.dependents[name]).addCallback(on_dependents_stopped, name) + deferreds.append(d) + stopped_in_deferred.update(self.dependents[name]) + else: + deferreds.append(self.components[name]._component_stop()) return DeferredList(deferreds) @@ -360,7 +378,7 @@ class ComponentRegistry(object): :param names: a list of Components to resume :type names: list - :returns: a Deferred object that will fire once all Components have been sucessfully resumed + :returns: a Deferred object that will fire once all Components have been successfully resumed :rtype: twisted.internet.defer.Deferred """ @@ -384,16 +402,14 @@ class ComponentRegistry(object): be called when the program is exiting to ensure all Components have a chance to properly shutdown. - :returns: a Deferred object that will fire once all Components have been sucessfully resumed + :returns: a Deferred object that will fire once all Components have been successfully shut down :rtype: twisted.internet.defer.Deferred """ - deferreds = [] + def on_stopped(result): + return DeferredList(map(lambda c: c._component_shutdown(), self.components.values())) - for component in self.components.values(): - deferreds.append(component._component_shutdown()) - - return DeferredList(deferreds) + return self.stop(self.components.keys()).addCallback(on_stopped) def update(self): """ diff --git a/deluge/core/alertmanager.py b/deluge/core/alertmanager.py index e2ff6c865..a4464eb8c 100644 --- a/deluge/core/alertmanager.py +++ b/deluge/core/alertmanager.py @@ -46,6 +46,7 @@ from twisted.internet import reactor import deluge.component as component from deluge._libtorrent import lt +from deluge.common import decode_string log = logging.getLogger(__name__) @@ -75,7 +76,8 @@ class AlertManager(component.Component): def stop(self): for dc in self.delayed_calls: - dc.cancel() + if dc.active(): + dc.cancel() self.delayed_calls = [] def register_handler(self, alert_type, handler): @@ -121,7 +123,7 @@ class AlertManager(component.Component): while alert is not None: alert_type = type(alert).__name__ # Display the alert message - log.debug("%s: %s", alert_type, alert.message()) + log.debug("%s: %s", alert_type, decode_string(alert.message())) # Call any handlers for this alert type if alert_type in self.handlers: for handler in self.handlers[alert_type]: diff --git a/deluge/core/authmanager.py b/deluge/core/authmanager.py index 771043e8b..f8cffbb7c 100644 --- a/deluge/core/authmanager.py +++ b/deluge/core/authmanager.py @@ -236,10 +236,10 @@ class AuthManager(component.Component): f = open(auth_file, "r").readlines() for line in f: - if line.startswith("#"): - # This is a comment line - continue line = line.strip() + if line.startswith("#") or not line: + # This line is a comment or empty + continue try: lsplit = line.split(":") except Exception, e: diff --git a/deluge/core/core.py b/deluge/core/core.py index e69944790..242359a9d 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -94,6 +94,8 @@ class Core(component.Component): self.settings.user_agent = "Deluge/%(deluge_version)s Libtorrent/%(lt_version)s" % \ { 'deluge_version': deluge.common.get_version(), 'lt_version': self.get_libtorrent_version().rpartition(".")[0] } + # Increase the alert queue size so that alerts don't get lost + self.settings.alert_queue_size = 10000 # Set session settings self.settings.send_redundant_have = True diff --git a/deluge/core/filtermanager.py b/deluge/core/filtermanager.py index 25ae4be1b..53e95030c 100644 --- a/deluge/core/filtermanager.py +++ b/deluge/core/filtermanager.py @@ -153,9 +153,8 @@ class FilterManager(component.Component): #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 isinstance(value, basestring): + filter_dict[key] = [value] if "id"in filter_dict: #optimized filter for id: torrent_ids = list(filter_dict["id"]) diff --git a/deluge/core/rpcserver.py b/deluge/core/rpcserver.py index 3ecbd39e8..649c2ce29 100644 --- a/deluge/core/rpcserver.py +++ b/deluge/core/rpcserver.py @@ -509,7 +509,7 @@ class RPCServer(component.Component): """ log.debug("intevents: %s", self.factory.interested_events) # Find sessions interested in this event - for session_id, interest in self.factory.interested_events.iteritems(): + for session_id, interest in self.factory.interested_events.items(): if event.name in interest: log.debug("Emit Event: %s %s", event.name, event.args) # This session is interested so send a RPC_EVENT diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index cafec162c..c5fd81955 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -37,9 +37,12 @@ import os import time import logging +import re from urllib import unquote from urlparse import urlparse +from twisted.internet.defer import Deferred, DeferredList +from twisted.internet.task import LoopingCall from deluge._libtorrent import lt import deluge.common @@ -116,7 +119,6 @@ class Torrent(object): # We use this to return dicts that only contain changes from the previous # {session_id: status_dict, ...} self.prev_status = {} - from twisted.internet.task import LoopingCall self.prev_status_cleanup_loop = LoopingCall(self.cleanup_prev_status) self.prev_status_cleanup_loop.start(10) @@ -125,14 +127,10 @@ class Torrent(object): # 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 + # Keep a list of Deferreds for file indexes we're waiting for file_rename alerts on # This is so we can send one folder_renamed signal instead of multiple # file_renamed signals. - # [(old_folder, new_folder, [*indexes]), ...] + # [{index: Deferred, ...}, ...] self.waiting_on_folder_rename = [] # We store the filename just in case we need to make a copy of the torrentfile @@ -177,13 +175,7 @@ class Torrent(object): # Tracker list self.trackers = [] # Create a list of trackers - for value in self.handle.trackers(): - if lt.version_minor < 15: - tracker = {} - tracker["url"] = value.url - tracker["tier"] = value.tier - else: - tracker = value + for tracker in self.handle.trackers(): self.trackers.append(tracker) # Various torrent options @@ -240,8 +232,13 @@ class Torrent(object): "max_upload_speed": self.set_max_upload_speed, "prioritize_first_last_pieces": self.set_prioritize_first_last, "sequential_download": self.set_sequential_download - } + + # set_prioritize_first_last is called by set_file_priorities, + # so remove if file_priorities is set in options. + if "file_priorities" in options: + del OPTIONS_FUNCS["prioritize_first_last_pieces"] + for (key, value) in options.items(): if OPTIONS_FUNCS.has_key(key): OPTIONS_FUNCS[key](value) @@ -252,7 +249,7 @@ class Torrent(object): def get_name(self): if self.handle.has_metadata(): - name = self.torrent_info.file_at(0).path.split("/", 1)[0] + name = self.torrent_info.file_at(0).path.replace("\\", "/", 1).split("/", 1)[0] if not name: name = self.torrent_info.name() try: @@ -304,26 +301,44 @@ class Torrent(object): def set_prioritize_first_last(self, prioritize): self.options["prioritize_first_last_pieces"] = prioritize - if self.handle.has_metadata(): - if self.options["compact_allocation"]: - log.debug("Setting first/last priority with compact " - "allocation does not work!") - return - - paths = {} - ti = self.handle.get_torrent_info() - for n in range(ti.num_pieces()): - slices = ti.map_block(n, 0, ti.piece_size(n)) - for slice in slices: - if self.handle.file_priority(slice.file_index): - paths.setdefault(slice.file_index, []).append(n) - - priorities = self.handle.piece_priorities() - for pieces in paths.itervalues(): - two_percent = int(0.02*len(pieces)) or 1 - for piece in pieces[:two_percent]+pieces[-two_percent:]: - priorities[piece] = 7 if prioritize else 1 - self.handle.prioritize_pieces(priorities) + if not prioritize: + # If we are turning off this option, call set_file_priorities to + # reset all the piece priorities + self.set_file_priorities(self.options["file_priorities"]) + return + if not self.handle.has_metadata(): + return + if self.options["compact_allocation"]: + log.debug("Setting first/last priority with compact " + "allocation does not work!") + return + # A list of priorities for each piece in the torrent + priorities = self.handle.piece_priorities() + prioritized_pieces = [] + ti = self.handle.get_torrent_info() + for i in range(ti.num_files()): + f = ti.file_at(i) + two_percent_bytes = int(0.02 * f.size) + # Get the pieces for the byte offsets + first_start = ti.map_file(i, 0, 0).piece + first_end = ti.map_file(i, two_percent_bytes, 0).piece + last_start = ti.map_file(i, f.size - two_percent_bytes, 0).piece + last_end = ti.map_file(i, max(f.size - 1, 0), 0).piece + + first_end += 1 + last_end += 1 + prioritized_pieces.append((first_start, first_end)) + prioritized_pieces.append((last_start, last_end)) + + # Creating two lists with priorites for the first/last pieces + # of this file, and insert the priorities into the list + first_list = [7] * (first_end - first_start) + last_list = [7] * (last_end - last_start) + priorities[first_start:first_end] = first_list + priorities[last_start:last_end] = last_list + # Setting the priorites for all the pieces of this torrent + self.handle.prioritize_pieces(priorities) + return prioritized_pieces, priorities def set_sequential_download(self, set_sequencial): self.options["sequential_download"] = set_sequencial @@ -380,7 +395,8 @@ class Torrent(object): log.warning("File priorities were not set for this torrent") # Set the first/last priorities if needed - self.set_prioritize_first_last(self.options["prioritize_first_last_pieces"]) + if self.options["prioritize_first_last_pieces"]: + self.set_prioritize_first_last(self.options["prioritize_first_last_pieces"]) def set_trackers(self, trackers): """Sets trackers""" @@ -885,31 +901,32 @@ class Torrent(object): def move_storage(self, dest): """Move a torrent's storage location""" - - if deluge.common.windows_check(): - # Attempt to convert utf8 path to unicode - # Note: Inconsistent encoding for 'dest', needs future investigation - try: - dest_u = unicode(dest, "utf-8") - except TypeError: - # String is already unicode - dest_u = dest - else: - dest_u = dest + try: + dest = unicode(dest, "utf-8") + except TypeError: + # String is already unicode + pass - if not os.path.exists(dest_u): + if not os.path.exists(dest): try: # Try to make the destination path if it doesn't exist - os.makedirs(dest_u) + os.makedirs(dest) except IOError, e: log.exception(e) log.error("Could not move storage for torrent %s since %s does " "not exist and could not create the directory.", - self.torrent_id, dest_u) + self.torrent_id, dest) return False + + dest_bytes = dest.encode('utf-8') try: - self.handle.move_storage(dest_u) - except: + # libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise + try: + self.handle.move_storage(dest) + except TypeError: + self.handle.move_storage(dest_bytes) + except Exception, e: + log.error("Error calling libtorrent move_storage: %s" % e) return False return True @@ -918,7 +935,6 @@ class Torrent(object): """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_torrentfile(self): """Writes the torrent file""" @@ -985,12 +1001,26 @@ class Torrent(object): """Renames files in the torrent. 'filenames' should be a list of (index, filename) pairs.""" for index, filename in filenames: + # Make sure filename is a unicode object + try: + filename = unicode(filename, "utf-8") + except TypeError: + pass filename = sanitize_filepath(filename) - self.handle.rename_file(index, filename.encode("utf-8")) + # libtorrent needs unicode object if wstrings are enabled, utf8 bytestring otherwise + try: + self.handle.rename_file(index, filename) + except TypeError: + self.handle.rename_file(index, filename.encode("utf-8")) def rename_folder(self, folder, new_folder): - """Renames a folder within a torrent. This basically does a file rename - on all of the folders children.""" + """ + Renames a folder within a torrent. This basically does a file rename + on all of the folders children. + + :returns: A deferred which fires when the rename is complete + :rtype: twisted.internet.defer.Deferred + """ 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) @@ -998,13 +1028,57 @@ class Torrent(object): new_folder = sanitize_filepath(new_folder, folder=True) - wait_on_folder = (folder, new_folder, []) + def on_file_rename_complete(result, wait_dict, index): + wait_dict.pop(index, None) + + wait_on_folder = {} + self.waiting_on_folder_rename.append(wait_on_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"]) + # Keep track of filerenames we're waiting on + wait_on_folder[f["index"]] = Deferred().addBoth(on_file_rename_complete, wait_on_folder, f["index"]) self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1).encode("utf-8")) - self.waiting_on_folder_rename.append(wait_on_folder) + + def on_folder_rename_complete(result, torrent, folder, new_folder): + component.get("EventManager").emit(TorrentFolderRenamedEvent(torrent.torrent_id, folder, new_folder)) + # Empty folders are removed after libtorrent folder renames + self.remove_empty_folders(folder) + torrent.waiting_on_folder_rename = filter(None, torrent.waiting_on_folder_rename) + component.get("TorrentManager").save_resume_data((self.torrent_id,)) + + d = DeferredList(wait_on_folder.values()) + d.addBoth(on_folder_rename_complete, self, folder, new_folder) + return d + + def remove_empty_folders(self, folder): + """ + Recursively removes folders but only if they are empty. + Cleans up after libtorrent folder renames. + + """ + info = self.get_status(['save_path']) + # Regex removes leading slashes that causes join function to ignore save_path + folder_full_path = os.path.join(info['save_path'], re.sub("^/*", "", folder)) + folder_full_path = os.path.normpath(folder_full_path) + + try: + if not os.listdir(folder_full_path): + os.removedirs(folder_full_path) + log.debug("Removed Empty Folder %s", folder_full_path) + else: + for root, dirs, files in os.walk(folder_full_path, topdown=False): + for name in dirs: + try: + os.removedirs(os.path.join(root, name)) + log.debug("Removed Empty Folder %s", os.path.join(root, name)) + except OSError as (errno, strerror): + from errno import ENOTEMPTY + if errno == ENOTEMPTY: + # Error raised if folder is not empty + log.debug("%s", strerror) + + except OSError as (errno, strerror): + log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno) def cleanup_prev_status(self): """ diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index b3c6d4cba..9a8d8a59c 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -38,13 +38,12 @@ import cPickle import os -import time import shutil import operator import logging -import re from twisted.internet.task import LoopingCall +from twisted.internet.defer import Deferred, DeferredList from deluge._libtorrent import lt @@ -56,7 +55,7 @@ from deluge.core.authmanager import AUTH_LEVEL_ADMIN from deluge.core.torrent import Torrent from deluge.core.torrent import TorrentOptions import deluge.core.oldstateupgrader -from deluge.common import utf8_encoded +from deluge.common import utf8_encoded, decode_string log = logging.getLogger(__name__) @@ -133,7 +132,7 @@ class TorrentManager(component.Component): def __init__(self): component.Component.__init__(self, "TorrentManager", interval=5, - depend=["CorePluginManager"]) + depend=["CorePluginManager", "AlertManager"]) log.debug("TorrentManager init..") # Set the libtorrent session self.session = component.get("Core").session @@ -151,15 +150,11 @@ class TorrentManager(component.Component): self.last_seen_complete_loop = None self.queued_torrents = set() - # 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 = [] + # This is a map of torrent_ids to Deferreds used to track needed resume data. + # The Deferreds will be completed when resume data has been saved. + self.waiting_on_resume_data = {} - # self.num_resume_data used to save resume_data in bulk - self.num_resume_data = 0 - - # Keeps track of resume data that needs to be saved to disk + # Keeps track of resume data self.resume_data = {} # Register set functions @@ -216,11 +211,14 @@ class TorrentManager(component.Component): # Try to load the state from file self.load_state() - # Save the state every 5 minutes + # Save the state periodically self.save_state_timer = LoopingCall(self.save_state) self.save_state_timer.start(200, False) self.save_resume_data_timer = LoopingCall(self.save_resume_data) - self.save_resume_data_timer.start(190) + self.save_resume_data_timer.start(190, False) + # Force update for all resume data a bit less frequently + self.save_all_resume_data_timer = LoopingCall(self.save_resume_data, self.torrents.keys()) + self.save_all_resume_data_timer.start(900, False) if self.last_seen_complete_loop: self.last_seen_complete_loop.start(60) @@ -233,45 +231,21 @@ class TorrentManager(component.Component): if self.save_resume_data_timer.running: self.save_resume_data_timer.stop() + if self.save_all_resume_data_timer.running: + self.save_all_resume_data_timer.stop() + if self.last_seen_complete_loop: self.last_seen_complete_loop.stop() # Save state on shutdown self.save_state() - # Make another list just to make sure all paused torrents will be - # passed to self.save_resume_data(). With - # self.shutdown_torrent_pause_list it is possible to have a case when - # torrent_id is removed from it in self.on_alert_torrent_paused() - # before we call self.save_resume_data() here. - save_resume_data_list = [] + self.session.pause() for key in self.torrents: # Stop the status cleanup LoopingCall here self.torrents[key].prev_status_cleanup_loop.stop() - if not self.torrents[key].handle.is_paused(): - # We set auto_managed false to prevent lt from resuming the torrent - self.torrents[key].handle.auto_managed(False) - self.torrents[key].handle.pause() - self.shutdown_torrent_pause_list.append(key) - save_resume_data_list.append(key) - - self.save_resume_data(save_resume_data_list) - - # We have to wait for all torrents to pause and write their resume data - wait = True - while wait: - 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) - # Wait for all alerts - self.alerts.handle_alerts(True) + return self.save_resume_data(self.torrents.keys()) def update(self): for torrent_id, torrent in self.torrents.items(): @@ -409,7 +383,8 @@ class TorrentManager(component.Component): resume_data = self.legacy_get_resume_data_from_file(state.torrent_id) self.legacy_delete_resume_data(state.torrent_id) - add_torrent_params["resume_data"] = resume_data + if resume_data: + add_torrent_params["resume_data"] = resume_data else: # We have a torrent_info object or magnet uri so we're not loading from state. if torrent_info: @@ -452,9 +427,16 @@ class TorrentManager(component.Component): # before adding to the session. if options["mapped_files"]: for index, fname in options["mapped_files"].items(): + try: + fname = unicode(fname, "utf-8") + except TypeError: + pass fname = deluge.core.torrent.sanitize_filepath(fname) log.debug("renaming file index %s to %s", index, fname) - torrent_info.rename_file(index, utf8_encoded(fname)) + try: + torrent_info.rename_file(index, fname) + except TypeError: + torrent_info.rename_file(index, fname.encode("utf-8")) add_torrent_params["ti"] = torrent_info @@ -589,12 +571,11 @@ class TorrentManager(component.Component): :raises InvalidTorrentError: if the torrent_id is not in the session """ - - if torrent_id not in self.torrents: + try: + torrent_name = self.torrents[torrent_id].get_status(["name"])["name"] + except KeyError: raise InvalidTorrentError("torrent_id not in session") - torrent_name = self.torrents[torrent_id].get_status(["name"])["name"] - # Emit the signal to the clients component.get("EventManager").emit(PreTorrentRemovedEvent(torrent_id)) @@ -606,9 +587,7 @@ class TorrentManager(component.Component): return False # Remove fastresume data if it is exists - resume_data = self.load_resume_data_file() - resume_data.pop(torrent_id, None) - self.save_resume_data_file(resume_data) + self.resume_data.pop(torrent_id, None) # Remove the .torrent file in the state self.torrents[torrent_id].delete_torrentfile() @@ -678,7 +657,7 @@ class TorrentManager(component.Component): # Reorder the state.torrents list to add torrents in the correct queue # order. - state.torrents.sort(key=operator.attrgetter("queue")) + state.torrents.sort(key=operator.attrgetter("queue"), reverse=self.config["queue_new_to_top"]) resume_data = self.load_resume_data_file() @@ -770,17 +749,34 @@ class TorrentManager(component.Component): def save_resume_data(self, torrent_ids=None): """ - Saves resume data for list of torrent_ids or for all torrents if - torrent_ids is None + Saves resume data for list of torrent_ids or for all torrents + needing resume data updated if torrent_ids is None + + :returns: A Deferred whose callback will be invoked when save is complete + :rtype: twisted.internet.defer.Deferred """ if torrent_ids is None: - torrent_ids = self.torrents.keys() + torrent_ids = (t[0] for t in self.torrents.iteritems() if t[1].handle.need_save_resume_data()) + + deferreds = [] + + def on_torrent_resume_save(result, torrent_id): + self.waiting_on_resume_data.pop(torrent_id, None) for torrent_id in torrent_ids: + d = self.waiting_on_resume_data.get(torrent_id) + if not d: + d = Deferred().addBoth(on_torrent_resume_save, torrent_id) + self.waiting_on_resume_data[torrent_id] = d + deferreds.append(d) self.torrents[torrent_id].save_resume_data() - self.num_resume_data = len(torrent_ids) + def on_all_resume_data_finished(result): + if result: + self.save_resume_data_file() + + return DeferredList(deferreds).addBoth(on_all_resume_data_finished) def load_resume_data_file(self): resume_data = {} @@ -800,73 +796,22 @@ class TorrentManager(component.Component): return resume_data - def save_resume_data_file(self, resume_data=None): + def save_resume_data_file(self): """ - Saves the resume data file with the contents of self.resume_data. If - `resume_data` is None, then we grab the resume_data from the file on - disk, else, we update `resume_data` with self.resume_data and save - that to disk. - - :param resume_data: the current resume_data, this will be loaded from disk if not provided - :type resume_data: dict - + Saves the resume data file with the contents of self.resume_data. """ - # Check to see if we're waiting on more resume data - if self.num_resume_data or not self.resume_data: - return - path = os.path.join(get_config_dir(), "state", "torrents.fastresume") - # First step is to load the existing file and update the dictionary - if resume_data is None: - resume_data = self.load_resume_data_file() - - resume_data.update(self.resume_data) - self.resume_data = {} - try: log.debug("Saving fastresume file: %s", path) fastresume_file = open(path, "wb") - fastresume_file.write(lt.bencode(resume_data)) + fastresume_file.write(lt.bencode(self.resume_data)) fastresume_file.flush() os.fsync(fastresume_file.fileno()) fastresume_file.close() except IOError: log.warning("Error trying to save fastresume file") - def remove_empty_folders(self, torrent_id, folder): - """ - Recursively removes folders but only if they are empty. - Cleans up after libtorrent folder renames. - - """ - if torrent_id not in self.torrents: - raise InvalidTorrentError("torrent_id is not in session") - - info = self.torrents[torrent_id].get_status(['save_path']) - # Regex removes leading slashes that causes join function to ignore save_path - folder_full_path = os.path.join(info['save_path'], re.sub("^/*", "", folder)) - folder_full_path = os.path.normpath(folder_full_path) - - try: - if not os.listdir(folder_full_path): - os.removedirs(folder_full_path) - log.debug("Removed Empty Folder %s", folder_full_path) - else: - for root, dirs, files in os.walk(folder_full_path, topdown=False): - for name in dirs: - try: - os.removedirs(os.path.join(root, name)) - log.debug("Removed Empty Folder %s", os.path.join(root, name)) - except OSError as (errno, strerror): - from errno import ENOTEMPTY - if errno == ENOTEMPTY: - # Error raised if folder is not empty - log.debug("%s", strerror) - - except OSError as (errno, strerror): - log.debug("Cannot Remove Folder: %s (ErrNo %s)", strerror, errno) - def get_queue_position(self, torrent_id): """Get queue position of torrent""" return self.torrents[torrent_id].get_queue_position() @@ -981,14 +926,9 @@ class TorrentManager(component.Component): if torrent.state != old_state: component.get("EventManager").emit(TorrentStateChangedEvent(torrent_id, torrent.state)) - # Don't save resume data for each torrent after self.stop() was called. - # We save resume data in bulk in self.stop() in this case. - if self.save_resume_data_timer.running: - # Write the fastresume file - self.save_resume_data((torrent_id, )) - - if torrent_id in self.shutdown_torrent_pause_list: - self.shutdown_torrent_pause_list.remove(torrent_id) + # Write the fastresume file if we are not waiting on a bulk write + if torrent_id not in self.waiting_on_resume_data: + self.save_resume_data((torrent_id,)) def on_alert_torrent_checked(self, alert): log.debug("on_alert_torrent_checked") @@ -1008,15 +948,14 @@ class TorrentManager(component.Component): torrent.update_state() def on_alert_tracker_reply(self, alert): - log.debug("on_alert_tracker_reply: %s", alert.message().decode("utf8")) + log.debug("on_alert_tracker_reply: %s", decode_string(alert.message())) try: torrent = self.torrents[str(alert.handle.info_hash())] except: return # Set the tracker status for the torrent - if alert.message() != "Got peers from DHT": - torrent.set_tracker_status(_("Announce OK")) + torrent.set_tracker_status(_("Announce OK")) # Check to see if we got any peer information from the tracker if alert.handle.status().num_complete == -1 or \ @@ -1040,7 +979,7 @@ class TorrentManager(component.Component): torrent = self.torrents[str(alert.handle.info_hash())] except: return - tracker_status = '%s: %s' % (_("Warning"), str(alert.message())) + tracker_status = '%s: %s' % (_("Warning"), decode_string(alert.message())) # Set the tracker status for the torrent torrent.set_tracker_status(tracker_status) @@ -1050,7 +989,7 @@ class TorrentManager(component.Component): torrent = self.torrents[str(alert.handle.info_hash())] except: return - tracker_status = "%s: %s" % (_("Error"), alert.msg) + tracker_status = "%s: %s" % (_("Error"), decode_string(alert.msg)) torrent.set_tracker_status(tracker_status) def on_alert_storage_moved(self, alert): @@ -1098,32 +1037,21 @@ class TorrentManager(component.Component): def on_alert_save_resume_data(self, alert): log.debug("on_alert_save_resume_data") - try: - torrent_id = str(alert.handle.info_hash()) - torrent = self.torrents[torrent_id] - except: - return + torrent_id = str(alert.handle.info_hash()) - # Libtorrent in add_torrent() expects resume_data to be bencoded - self.resume_data[torrent_id] = lt.bencode(alert.resume_data) - self.num_resume_data -= 1 + if torrent_id in self.torrents: + # Libtorrent in add_torrent() expects resume_data to be bencoded + self.resume_data[torrent_id] = lt.bencode(alert.resume_data) - torrent.waiting_on_resume_data = False - - self.save_resume_data_file() + if torrent_id in self.waiting_on_resume_data: + self.waiting_on_resume_data[torrent_id].callback(None) def on_alert_save_resume_data_failed(self, alert): - log.debug("on_alert_save_resume_data_failed: %s", alert.message()) - try: - torrent = self.torrents[str(alert.handle.info_hash())] - except: - return - - self.num_resume_data -= 1 - torrent.waiting_on_resume_data = False - - self.save_resume_data_file() + log.debug("on_alert_save_resume_data_failed: %s", decode_string(alert.message())) + torrent_id = str(alert.handle.info_hash()) + if torrent_id in self.waiting_on_resume_data: + self.waiting_on_resume_data[torrent_id].errback(Exception(decode_string(alert.message()))) def on_alert_file_renamed(self, alert): log.debug("on_alert_file_renamed") @@ -1134,24 +1062,12 @@ class TorrentManager(component.Component): except: return - # 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("EventManager").emit(TorrentFolderRenamedEvent(torrent_id, wait_on_folder[0], wait_on_folder[1])) - # Empty folders are removed after libtorrent folder renames - self.remove_empty_folders(torrent_id, wait_on_folder[0]) - del torrent.waiting_on_folder_rename[i] - self.save_resume_data((torrent_id,)) - break - # 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: + # We need to see if this file index is in a waiting_on_folder dict + for wait_on_folder in torrent.waiting_on_folder_rename: + if alert.index in wait_on_folder: + wait_on_folder[alert.index].callback(None) + break + else: # This is just a regular file rename so send the signal component.get("EventManager").emit(TorrentFileRenamedEvent(torrent_id, alert.index, alert.name)) self.save_resume_data((torrent_id,)) @@ -1165,7 +1081,7 @@ class TorrentManager(component.Component): torrent.write_torrentfile() def on_alert_file_error(self, alert): - log.debug("on_alert_file_error: %s", alert.message()) + log.debug("on_alert_file_error: %s", decode_string(alert.message())) try: torrent = self.torrents[str(alert.handle.info_hash())] except: @@ -1173,7 +1089,7 @@ class TorrentManager(component.Component): torrent.update_state() def on_alert_file_completed(self, alert): - log.debug("file_completed_alert: %s", alert.message()) + log.debug("file_completed_alert: %s", decode_string(alert.message())) try: torrent_id = str(alert.handle.info_hash()) except: diff --git a/deluge/main.py b/deluge/main.py index a966356de..c68ab3d5e 100644 --- a/deluge/main.py +++ b/deluge/main.py @@ -43,8 +43,10 @@ import os import sys from optparse import OptionParser +from logging import FileHandler, getLogger +from errno import EEXIST -import deluge.log +from deluge.log import setupLogger import deluge.error def version_callback(option, opt_str, value, parser): @@ -86,21 +88,18 @@ def start_ui(): help="Rotate logfiles.", action="store_true", default=False) # Get the options and args from the OptionParser - (options, args) = parser.parse_args() + (options, args) = parser.parse_args(deluge.common.unicode_argv()[1:]) + # Setup the logger if options.quiet: options.loglevel = "none" - if options.loglevel: options.loglevel = options.loglevel.lower() - logfile_mode = 'w' if options.rotate_logs: logfile_mode = 'a' - - # Setup the logger - deluge.log.setupLogger(level=options.loglevel, filename=options.logfile, - filemode=logfile_mode) + setupLogger(level=options.loglevel, filename=options.logfile, filemode=logfile_mode) + log = getLogger(__name__) if options.config: if not os.path.exists(options.config): @@ -110,7 +109,7 @@ def start_ui(): except Exception, e: pass elif not os.path.isdir(options.config): - print "Config option needs to be a directory!" + log.error("Config option needs to be a directory!") sys.exit(1) else: if not os.path.exists(deluge.common.get_default_config_dir()): @@ -129,8 +128,6 @@ def start_ui(): version = deluge.common.get_version() - import logging - log = logging.getLogger(__name__) log.info("Deluge ui %s", version) log.debug("options: %s", options) log.debug("args: %s", args) @@ -188,27 +185,35 @@ this should be an IP address", metavar="IFACE", # Get the options and args from the OptionParser (options, args) = parser.parse_args() + # Setup the logger if options.quiet: options.loglevel = "none" - + if options.logfile: + # Try to create the logfile's directory if it doesn't exist + try: + os.makedirs(os.path.abspath(os.path.dirname(options.logfile))) + except OSError, e: + if e.errno != EEXIST: + print "There was an error creating the log directory, exiting... (%s)" % e + sys.exit(1) logfile_mode = 'w' if options.rotate_logs: logfile_mode = 'a' - - # Setup the logger - deluge.log.setupLogger(level=options.loglevel, filename=options.logfile, - filemode=logfile_mode) + setupLogger(level=options.loglevel, filename=options.logfile, filemode=logfile_mode) + log = getLogger(__name__) import deluge.configmanager if options.config: if not deluge.configmanager.set_config_dir(options.config): - print("There was an error setting the config dir! Exiting..") + log.error("There was an error setting the config directory! Exiting...") sys.exit(1) # Sets the options.logfile to point to the default location def open_logfile(): if not options.logfile: options.logfile = deluge.configmanager.get_config_dir("deluged.log") + file_handler = FileHandler(options.logfile) + log.addHandler(file_handler) # Writes out a pidfile if necessary def write_pidfile(): @@ -242,37 +247,32 @@ this should be an IP address", metavar="IFACE", open_logfile() - # Setup the logger - try: - # Try to make the logfile's directory if it doesn't exist - os.makedirs(os.path.abspath(os.path.dirname(options.logfile))) - except: - pass - - import logging - log = logging.getLogger(__name__) + def run_daemon(options, args): + try: + from deluge.core.daemon import Daemon + Daemon(options, args) + except deluge.error.DaemonRunningError, e: + log.error(e) + log.error("You cannot run multiple daemons with the same config directory set.") + log.error("If you believe this is an error, you can force a start by deleting %s.", deluge.configmanager.get_config_dir("deluged.pid")) + sys.exit(1) + except Exception, e: + log.exception(e) + sys.exit(1) if options.profile: - import hotshot - hsp = hotshot.Profile(deluge.configmanager.get_config_dir("deluged.profile")) - hsp.start() - try: - from deluge.core.daemon import Daemon - Daemon(options, args) - except deluge.error.DaemonRunningError, e: - log.error(e) - log.error("You cannot run multiple daemons with the same config directory set.") - log.error("If you believe this is an error, you can force a start by deleting %s.", deluge.configmanager.get_config_dir("deluged.pid")) - sys.exit(1) - except Exception, e: - log.exception(e) - sys.exit(1) - finally: - if options.profile: - hsp.stop() - hsp.close() - import hotshot.stats - stats = hotshot.stats.load(deluge.configmanager.get_config_dir("deluged.profile")) - stats.strip_dirs() - stats.sort_stats("time", "calls") - stats.print_stats(400) + import cProfile + profiler = cProfile.Profile() + profile_output = deluge.configmanager.get_config_dir("deluged.profile") + + # Twisted catches signals to terminate + def save_profile_stats(): + profiler.dump_stats(profile_output) + print "Profile stats saved to %s" % profile_output + + from twisted.internet import reactor + reactor.addSystemEventTrigger("before", "shutdown", save_profile_stats) + print "Running with profiler..." + profiler.runcall(run_daemon, options, args) + else: + run_daemon(options, args) diff --git a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py index 6803755d2..b369fc124 100644 --- a/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py +++ b/deluge/plugins/AutoAdd/deluge/plugins/autoadd/gtkui.py @@ -403,12 +403,11 @@ class GtkUI(GtkPluginBase): sw.add(self.treeView) sw.show_all() component.get("Preferences").add_page( - "AutoAdd", self.glade.get_widget("prefs_box") + _("AutoAdd"), self.glade.get_widget("prefs_box") ) - self.on_show_prefs() def disable(self): - component.get("Preferences").remove_page("AutoAdd") + component.get("Preferences").remove_page(_("AutoAdd")) component.get("PluginManager").deregister_hook( "on_apply_prefs", self.on_apply_prefs ) diff --git a/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py b/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py index 6f0469200..8ee08ee92 100644 --- a/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py +++ b/deluge/plugins/Extractor/deluge/plugins/extractor/gtkui.py @@ -54,13 +54,13 @@ class GtkUI(GtkPluginBase): def enable(self): self.glade = gtk.glade.XML(get_resource("extractor_prefs.glade")) - component.get("Preferences").add_page("Extractor", self.glade.get_widget("extractor_prefs_box")) + component.get("Preferences").add_page(_("Extractor"), self.glade.get_widget("extractor_prefs_box")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) self.on_show_prefs() def disable(self): - component.get("Preferences").remove_page("Extractor") + component.get("Preferences").remove_page(_("Extractor")) component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs) del self.glade diff --git a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py index 2400c7966..44558fda4 100644 --- a/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py +++ b/deluge/plugins/Notifications/deluge/plugins/notifications/gtkui.py @@ -242,7 +242,7 @@ class GtkUiNotifications(CustomNotifications): log.debug("Handler for TorrentFinishedEvent GTKUI called. " "Got Torrent Status") title = _("Finished Torrent") - message = _("The torrent \"%(name)s\" including %(num_files)i " + message = _("The torrent \"%(name)s\" including %(num_files)i file(s) " "has finished downloading.") % torrent_status return title, message @@ -287,7 +287,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications): if parent: parent.remove(self.prefs) index = prefs.notebook.append_page(self.prefs) - prefs.liststore.append([index, "Notifications"]) + prefs.liststore.append([index, _("Notifications")]) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) @@ -320,7 +320,7 @@ class GtkUI(GtkPluginBase, GtkUiNotifications): def disable(self): GtkUiNotifications.disable(self) - component.get("Preferences").remove_page("Notifications") + component.get("Preferences").remove_page(_("Notifications")) component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", diff --git a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py index 580eba2d8..5d16e660a 100644 --- a/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py +++ b/deluge/plugins/Scheduler/deluge/plugins/scheduler/gtkui.py @@ -170,7 +170,7 @@ class GtkUI(GtkPluginBase): client.register_event_handler("SchedulerEvent", self.on_scheduler_event) def disable(self): - component.get("Preferences").remove_page("Scheduler") + component.get("Preferences").remove_page(_("Scheduler")) # Remove status item component.get("StatusBar").remove_item(self.status_item) del self.status_item @@ -294,4 +294,4 @@ class GtkUI(GtkPluginBase): vbox.pack_start(frame, False, False) vbox.show_all() - component.get("Preferences").add_page("Scheduler", vbox) + component.get("Preferences").add_page(_("Scheduler"), vbox) diff --git a/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py b/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py index 978ac5fe4..c13f0b755 100644 --- a/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py +++ b/deluge/plugins/WebUi/deluge/plugins/webui/gtkui.py @@ -53,14 +53,14 @@ class GtkUI(GtkPluginBase): def enable(self): self.glade = gtk.glade.XML(get_resource("config.glade")) - component.get("Preferences").add_page("WebUi", self.glade.get_widget("prefs_box")) + component.get("Preferences").add_page(_("WebUi"), self.glade.get_widget("prefs_box")) component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs) client.webui.get_config().addCallback(self.cb_get_config) client.webui.got_deluge_web().addCallback(self.cb_chk_deluge_web) def disable(self): - component.get("Preferences").remove_page("WebUi") + component.get("Preferences").remove_page(_("WebUi")) component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs) component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs) diff --git a/deluge/rencode.py b/deluge/rencode.py index a0a6eec35..7c0f7d8b1 100644 --- a/deluge/rencode.py +++ b/deluge/rencode.py @@ -19,7 +19,7 @@ rencode module versions, so you should check that you are using the same rencode version throughout your project. """ -__version__ = '1.0.1' +__version__ = '1.0.2' __all__ = ['dumps', 'loads'] # Original bencode module by Petru Paler, et al. @@ -107,6 +107,9 @@ STR_FIXED_COUNT = 64 LIST_FIXED_START = STR_FIXED_START+STR_FIXED_COUNT LIST_FIXED_COUNT = 64 +# Whether strings should be decoded when loading +_decode_utf8 = False + def decode_int(x, f): f += 1 newf = x.index(CHR_TERM, f) @@ -159,12 +162,8 @@ def decode_string(x, f): raise ValueError colon += 1 s = x[colon:colon+n] - try: - t = s.decode("utf8") - if len(t) != len(s): - s = t - except UnicodeDecodeError: - pass + if _decode_utf8: + s = s.decode('utf8') return (s, colon+n) def decode_list(x, f): @@ -218,12 +217,8 @@ def make_fixed_length_string_decoders(): def make_decoder(slen): def f(x, f): s = x[f+1:f+1+slen] - try: - t = s.decode("utf8") - if len(t) != len(s): - s = t - except UnicodeDecodeError: - pass + if _decode_utf8: + s = s.decode("utf8") return (s, f+1+slen) return f for i in range(STR_FIXED_COUNT): @@ -279,7 +274,9 @@ def encode_dict(x,r): r.append(CHR_TERM) -def loads(x): +def loads(x, decode_utf8=False): + global _decode_utf8 + _decode_utf8 = decode_utf8 try: r, l = decode_func[x[0]](x, 0) except (IndexError, KeyError): diff --git a/deluge/tests/dir_with_6_files.torrent b/deluge/tests/dir_with_6_files.torrent Binary files differnew file mode 100644 index 000000000..2c6b5fb02 --- /dev/null +++ b/deluge/tests/dir_with_6_files.torrent diff --git a/deluge/tests/test_component.py b/deluge/tests/test_component.py index ab5e4d534..6f13eeca2 100644 --- a/deluge/tests/test_component.py +++ b/deluge/tests/test_component.py @@ -3,8 +3,8 @@ from twisted.internet import threads import deluge.component as component class testcomponent(component.Component): - def __init__(self, name): - component.Component.__init__(self, name) + def __init__(self, name, depend=None): + component.Component.__init__(self, name, depend=depend) self.start_count = 0 self.stop_count = 0 @@ -51,6 +51,7 @@ class testcomponent_shutdown(component.Component): class ComponentTestClass(unittest.TestCase): def tearDown(self): + component.stop() component._ComponentRegistry.components = {} def test_start_component(self): @@ -63,16 +64,22 @@ class ComponentTestClass(unittest.TestCase): d.addCallback(on_start, c) return d - def test_start_depends(self): + def test_start_stop_depends(self): + def on_stop(result, c1, c2): + self.assertEquals(c1._component_state, "Stopped") + self.assertEquals(c2._component_state, "Stopped") + self.assertEquals(c1.stop_count, 1) + self.assertEquals(c2.stop_count, 1) + def on_start(result, c1, c2): self.assertEquals(c1._component_state, "Started") self.assertEquals(c2._component_state, "Started") self.assertEquals(c1.start_count, 1) self.assertEquals(c2.start_count, 1) + return component.stop(["test_start_depends_c1"]).addCallback(on_stop, c1, c2) c1 = testcomponent("test_start_depends_c1") - c2 = testcomponent("test_start_depends_c2") - c2._component_depend = ["test_start_depends_c1"] + c2 = testcomponent("test_start_depends_c2", depend=["test_start_depends_c1"]) d = component.start(["test_start_depends_c2"]) d.addCallback(on_start, c1, c2) @@ -80,15 +87,12 @@ class ComponentTestClass(unittest.TestCase): def start_with_depends(self): c1 = testcomponent_delaystart("test_start_all_c1") - c2 = testcomponent("test_start_all_c2") - c3 = testcomponent_delaystart("test_start_all_c3") - c4 = testcomponent("test_start_all_c4") + c2 = testcomponent("test_start_all_c2", depend=["test_start_all_c4"]) + c3 = testcomponent_delaystart("test_start_all_c3", + depend=["test_start_all_c5", "test_start_all_c1"]) + c4 = testcomponent("test_start_all_c4", depend=["test_start_all_c3"]) c5 = testcomponent("test_start_all_c5") - c3._component_depend = ["test_start_all_c5", "test_start_all_c1"] - c4._component_depend = ["test_start_all_c3"] - c2._component_depend = ["test_start_all_c4"] - d = component.start() return (d, c1, c2, c3, c4, c5) @@ -130,15 +134,15 @@ class ComponentTestClass(unittest.TestCase): return d def test_stop_all(self): - def on_stop(*args): - for c in args[1:]: + def on_stop(result, *args): + for c in args: self.assertEquals(c._component_state, "Stopped") self.assertEquals(c.stop_count, 1) - def on_start(*args): - for c in args[1:]: + def on_start(result, *args): + for c in args: self.assertEquals(c._component_state, "Started") - return component.stop().addCallback(on_stop, *args[1:]) + return component.stop().addCallback(on_stop, *args) ret = self.start_with_depends() ret[0].addCallback(on_start, *ret[1:]) diff --git a/deluge/tests/test_torrent.py b/deluge/tests/test_torrent.py new file mode 100644 index 000000000..f55b4d4e2 --- /dev/null +++ b/deluge/tests/test_torrent.py @@ -0,0 +1,127 @@ +from twisted.trial import unittest +import os + +import deluge.core.torrent +import test_torrent +import common +from deluge.core.rpcserver import RPCServer +from deluge.core.core import Core + +deluge.core.torrent.component = test_torrent + +from deluge._libtorrent import lt + +import deluge.component as component +from deluge.core.torrent import Torrent + +config_setup = False +core = None +rpcserver = None + +# This is called by torrent.py when calling component.get("...") +def get(key): + if key is "Core": + return core + elif key is "RPCServer": + return rpcserver + else: + return None + +class TorrentTestCase(unittest.TestCase): + + def setup_config(self): + global config_setup + config_setup = True + config_dir = common.set_tmp_config_dir() + core_config = deluge.config.Config("core.conf", defaults=deluge.core.preferencesmanager.DEFAULT_PREFS, config_dir=config_dir) + core_config.save() + + def setUp(self): + self.setup_config() + global rpcserver + global core + rpcserver = RPCServer(listen=False) + core = Core() + self.session = lt.session() + self.torrent = None + return component.start() + + def tearDown(self): + if self.torrent: + self.torrent.prev_status_cleanup_loop.stop() + + def on_shutdown(result): + component._ComponentRegistry.components = {} + return component.shutdown().addCallback(on_shutdown) + + def print_priority_list(self, priorities): + tmp = '' + for i, p in enumerate(priorities): + if i % 100 == 0: + print tmp + tmp = '' + tmp += "%s" % p + print tmp + + def get_torrent_atp(self, filename): + filename = os.path.join(os.path.dirname(__file__), filename) + e = lt.bdecode(open(filename, 'rb').read()) + info = lt.torrent_info(e) + atp = {"ti": info} + atp["save_path"] = os.getcwd() + atp["storage_mode"] = lt.storage_mode_t.storage_mode_sparse + atp["add_paused"] = False + atp["auto_managed"] = True + atp["duplicate_is_error"] = True + return atp + + def test_set_prioritize_first_last(self): + piece_indexes = [(0,1), (0,1), (0,1), (0,1), (0,2), (50,52), + (51,53), (110,112), (111,114), (200,203), + (202,203), (212,213), (212,218), (457,463)] + self.run_test_set_prioritize_first_last("dir_with_6_files.torrent", piece_indexes) + + def run_test_set_prioritize_first_last(self, torrent_file, prioritized_piece_indexes): + atp = self.get_torrent_atp(torrent_file) + handle = self.session.add_torrent(atp) + + self.torrent = Torrent(handle, {}) + priorities_original = handle.piece_priorities() + prioritized_pieces, new_priorites = self.torrent.set_prioritize_first_last(True) + priorities = handle.piece_priorities() + non_prioritized_pieces = list(range(len(priorities))) + + # The prioritized indexes are the same as we expect + self.assertEquals(prioritized_pieces, prioritized_piece_indexes) + + # Test the priority of the prioritized pieces + for first, last in prioritized_pieces: + for i in range(first, last): + if i in non_prioritized_pieces: + non_prioritized_pieces.remove(i) + self.assertEquals(priorities[i], 7) + + # Test the priority of all the non-prioritized pieces + for i in non_prioritized_pieces: + self.assertEquals(priorities[i], 1) + + # The length of the list of new priorites is the same as the original + self.assertEquals(len(priorities_original), len(new_priorites)) + + #self.print_priority_list(priorities) + + def test_set_prioritize_first_last_false(self): + atp = self.get_torrent_atp("dir_with_6_files.torrent") + handle = self.session.add_torrent(atp) + self.torrent = Torrent(handle, {}) + # First set some pieces prioritized + self.torrent.set_prioritize_first_last(True) + # Reset pirorities + self.torrent.set_prioritize_first_last(False) + priorities = handle.piece_priorities() + + # Test the priority of the prioritized pieces + for i in priorities: + self.assertEquals(priorities[i], 1) + + #self.print_priority_list(priorities) diff --git a/tests/test_transfer.py b/deluge/tests/test_transfer.py index cd9a271d5..cd9a271d5 100644 --- a/tests/test_transfer.py +++ b/deluge/tests/test_transfer.py diff --git a/deluge/tests/test_ui_common.py b/deluge/tests/test_ui_common.py new file mode 100644 index 000000000..14d58e7b4 --- /dev/null +++ b/deluge/tests/test_ui_common.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from twisted.trial import unittest +import os +from deluge.ui.common import TorrentInfo + +class UICommonTestCase(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + def test_utf8_encoded_paths(self): + filename = os.path.join(os.path.dirname(__file__), "test.torrent") + ti = TorrentInfo(filename) + self.assertTrue(ti.files_tree.has_key("azcvsupdater_2.6.2.jar")) + + def test_utf8_encoded_paths2(self): + filename = os.path.join(os.path.dirname(__file__), "unicode_filenames.torrent") + ti = TorrentInfo(filename) + + files = ti.files_tree["unicode_filenames"] + self.assertTrue(files.has_key("\xe3\x83\x86\xe3\x82\xaf\xe3\x82\xb9\xe3\x83\xbb\xe3\x83" + "\x86\xe3\x82\xaf\xe3\x82\xb5\xe3\x83\xb3.mkv")) + self.assertTrue(files.has_key("\xd0\x9c\xd0\xb8\xd1\x85\xd0\xb0\xd0\xb8\xd0\xbb \xd0\x93" + "\xd0\xbe\xd1\x80\xd0\xb1\xd0\xb0\xd1\x87\xd1\x91\xd0\xb2.mkv")) + self.assertTrue(files.has_key("Alisher ibn G'iyosiddin Navoiy.mkv")) + self.assertTrue(files.has_key("Ascii title.mkv")) + self.assertTrue(files.has_key("\xe0\xa6\xb8\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x81\xe0\xa6" + "\xae\xe0\xa6\xbe\xe0\xa6\xb0 \xe0\xa6\xb0\xe0\xa6\xbe\xe0\xa7\x9f.mkv")) diff --git a/deluge/tests/unicode_filenames.torrent b/deluge/tests/unicode_filenames.torrent Binary files differnew file mode 100644 index 000000000..e34f055df --- /dev/null +++ b/deluge/tests/unicode_filenames.torrent diff --git a/deluge/transfer.py b/deluge/transfer.py index c89f89e4f..a09ad98a5 100644 --- a/deluge/transfer.py +++ b/deluge/transfer.py @@ -140,7 +140,7 @@ class DelugeTransferProtocol(Protocol): """ try: - self.message_received(rencode.loads(zlib.decompress(data))) + self.message_received(rencode.loads(zlib.decompress(data), decode_utf8=True)) except Exception, e: log.warn("Failed to decompress (%d bytes) and load serialized data "\ "with rencode: %s" % (len(data), str(e))) diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 3feba4c57..342480e20 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -37,17 +37,14 @@ import logging from twisted.internet.protocol import ClientFactory from twisted.internet import reactor, ssl, defer +import sys +import subprocess import deluge.common from deluge import error from deluge.event import known_events from deluge.transfer import DelugeTransferProtocol -if deluge.common.windows_check(): - import win32api -else: - import subprocess - RPC_RESPONSE = 1 RPC_ERROR = 2 RPC_EVENT = 3 @@ -628,13 +625,10 @@ class Client(object): :raises OSError: received from subprocess.call() """ + # subprocess.popen does not work with unicode args (with non-ascii characters) on windows + config = config.encode(sys.getfilesystemencoding()) try: - if deluge.common.windows_check(): - win32api.WinExec("deluged --port=%s --config=\"%s\"" % (port, config)) - elif deluge.common.osx_check(): - subprocess.call(["nohup", "deluged", "--port=%s" % port, "--config=%s" % config]) - else: - subprocess.call(["deluged", "--port=%s" % port, "--config=%s" % config]) + subprocess.Popen(["deluged", "--port=%s" % port, "--config=%s" % config]) except OSError, e: from errno import ENOENT if e.errno == ENOENT: diff --git a/deluge/ui/common.py b/deluge/ui/common.py index 3b754cef7..795fdcda8 100644 --- a/deluge/ui/common.py +++ b/deluge/ui/common.py @@ -51,7 +51,7 @@ except ImportError: from sha import sha from deluge import bencode -from deluge.common import decode_string, path_join +from deluge.common import utf8_encoded, path_join import deluge.configmanager log = logging.getLogger(__name__) @@ -88,9 +88,9 @@ class TorrentInfo(object): # Check if 'name.utf-8' is in the torrent and if not try to decode the string # using the encoding found. if "name.utf-8" in self.__m_metadata["info"]: - self.__m_name = decode_string(self.__m_metadata["info"]["name.utf-8"]) + self.__m_name = utf8_encoded(self.__m_metadata["info"]["name.utf-8"]) else: - self.__m_name = decode_string(self.__m_metadata["info"]["name"], self.encoding) + self.__m_name = utf8_encoded(self.__m_metadata["info"]["name"], self.encoding) # Get list of files from torrent info paths = {} @@ -104,10 +104,13 @@ class TorrentInfo(object): if "path.utf-8" in f: path = os.path.join(prefix, *f["path.utf-8"]) else: - path = decode_string(os.path.join(prefix, decode_string(os.path.join(*f["path"]), self.encoding)), self.encoding) + path = utf8_encoded(os.path.join(prefix, utf8_encoded(os.path.join(*f["path"]), self.encoding)), self.encoding) f["index"] = index + if "sha1" in f and len(f["sha1"]) == 20: + f["sha1"] = f["sha1"].encode('hex') + if "ed2k" in f and len(f["ed2k"]) == 16: + f["ed2k"] = f["ed2k"].encode('hex') paths[path] = f - dirname = os.path.dirname(path) while dirname: dirinfo = dirs.setdefault(dirname, {}) @@ -160,7 +163,7 @@ class TorrentInfo(object): if "path.utf-8" in f: path = os.path.join(prefix, *f["path.utf-8"]) else: - path = decode_string(os.path.join(prefix, decode_string(os.path.join(*f["path"]), self.encoding)), self.encoding) + path = utf8_encoded(os.path.join(prefix, utf8_encoded(os.path.join(*f["path"]), self.encoding)), self.encoding) self.__m_files.append({ 'path': path, 'size': f["length"], diff --git a/deluge/ui/console/commands/manage.py b/deluge/ui/console/commands/manage.py index ab781b768..ef66829d4 100644 --- a/deluge/ui/console/commands/manage.py +++ b/deluge/ui/console/commands/manage.py @@ -133,7 +133,22 @@ class Command(BaseCommand): deferred.callback(True) self.console.write("Setting %s to %s for torrents %s.." % (key, val, torrent_ids)) - client.core.set_torrent_options(torrent_ids, {key: val}).addCallback(on_set_config) + + + for tid in torrent_ids: + if key == "move_on_completed_path": + client.core.set_torrent_move_completed_path(tid, val).addCallback(on_set_config) + elif key == "move_on_completed": + client.core.set_torrent_move_completed(tid, val).addCallback(on_set_config) + elif key == "is_auto_managed": + client.core.set_torrent_auto_managed(tid, val).addCallback(on_set_config) + elif key == "remove_at_ratio": + client.core.set_torrent_remove_at_ratio(tid, val).addCallback(on_set_config) + elif key == "prioritize_first_last": + client.core.set_torrent_prioritize_first_last(tid, val).addCallback(on_set_config) + else: + client.core.set_torrent_options(torrent_ids, {key: val}).addCallback(on_set_config) + break return deferred def complete(self, line): diff --git a/deluge/ui/console/modes/torrent_actions.py b/deluge/ui/console/modes/torrent_actions.py index 2988245e1..fb6a9f4cd 100644 --- a/deluge/ui/console/modes/torrent_actions.py +++ b/deluge/ui/console/modes/torrent_actions.py @@ -250,6 +250,8 @@ def torrent_action(idx, data, mode, ids): for tid in ids: if "move_on_completed_path" in options: client.core.set_torrent_move_completed_path(tid, options["move_on_completed_path"]) + if "move_on_completed" in options: + client.core.set_torrent_move_completed(tid, options["move_on_completed"]) if "is_auto_managed" in options: client.core.set_torrent_auto_managed(tid, options["is_auto_managed"]) if "remove_at_ratio" in options: diff --git a/deluge/ui/console/modes/torrentdetail.py b/deluge/ui/console/modes/torrentdetail.py index 13ec757b9..4252c4e17 100644 --- a/deluge/ui/console/modes/torrentdetail.py +++ b/deluge/ui/console/modes/torrentdetail.py @@ -310,6 +310,8 @@ class TorrentDetail(BaseMode, component.Component): color_partially_selected = "magenta" color_highlighted = "white" for fl in files: + #from sys import stderr + #print >> stderr, fl[6] # kick out if we're going to draw too low on the screen if (off >= self.rows-1): self.more_to_draw = True @@ -317,18 +319,34 @@ class TorrentDetail(BaseMode, component.Component): self.file_limit = idx - if idx >= self.file_off: - # set fg/bg colors based on if we are selected/marked or not - # default values - fg = "white" - bg = "black" + # default color values + fg = "white" + bg = "black" + attr = "" + + if fl[6] == -2: priority = -1 #Mixed + elif fl[6] == 0: + priority = 0 #Do Not Download + fg = "red" + elif fl[6] == 1: + priority = 1 #Normal + elif fl[6] <= 6: + priority = 2 #High + fg = "yellow" + elif fl[6] == 7: + priority = 3 #Highest + fg = "green" + + if idx >= self.file_off: + # set fg/bg colors based on whether the file is selected/marked or not if fl[1] in self.marked: bg = color_selected if fl[3]: if self.marked[fl[1]] < self.__get_contained_files_count(file_list=fl[3]): bg = color_partially_selected + attr = "bold" if idx == self.current_file_idx: self.current_file = fl @@ -339,9 +357,14 @@ class TorrentDetail(BaseMode, component.Component): if self.marked[fl[1]] < self.__get_contained_files_count(file_list = fl[3]): fg = color_partially_selected else: - fg = "black" + if fg == "white": + fg = "black" + attr = "bold" - color_string = "{!%s,%s!}"%(fg,bg) + if attr: + color_string = "{!%s,%s,%s!}"%(fg, bg, attr) + else: + color_string = "{!%s,%s!}"%(fg, bg) #actually draw the dir/file string if fl[3] and fl[4]: # this is an expanded directory diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py index 84ea16e57..13ac640d6 100644 --- a/deluge/ui/gtkui/addtorrentdialog.py +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -180,7 +180,11 @@ class AddTorrentDialog(component.Component): self.builder.get_object("button_move_completed_location").hide() self.builder.get_object("entry_move_completed_path").show() - self.dialog.set_transient_for(component.get("MainWindow").window) + if component.get("MainWindow").is_on_active_workspace(): + self.dialog.set_transient_for(component.get("MainWindow").window) + else: + self.dialog.set_transient_for(None) + self.dialog.present() if focus: self.dialog.window.focus() @@ -213,9 +217,6 @@ class AddTorrentDialog(component.Component): new_row = None for filename in filenames: - # Convert the path to unicode - filename = unicode(filename) - # Get the torrent data from the torrent file try: info = deluge.ui.common.TorrentInfo(filename) @@ -693,8 +694,7 @@ class AddTorrentDialog(component.Component): # Create a tmp file path import tempfile - import os.path - tmp_file = os.path.join(tempfile.gettempdir(), url.split("/")[-1]) + (tmp_handle, tmp_file) = tempfile.mkstemp() def on_part(data, current_length, total_length): if total_length: @@ -825,14 +825,15 @@ class AddTorrentDialog(component.Component): self.save_torrent_options(row) - # The options we want all the torrents to have - options = self.options[model.get_value(row, 0)] + # The options, except file renames, we want all the torrents to have + options = self.options[model.get_value(row, 0)].copy() + options.pop("mapped_files", None) # Set all the torrent options row = model.get_iter_first() while row != None: torrent_id = model.get_value(row, 0) - self.options[torrent_id] = options + self.options[torrent_id].update(options) row = model.iter_next(row) def _on_button_revert_clicked(self, widget): @@ -863,7 +864,7 @@ class AddTorrentDialog(component.Component): def _on_filename_edited(self, renderer, path, new_text): index = self.files_treestore[path][3] - new_text = new_text.strip(os.path.sep) + new_text = new_text.strip(os.path.sep).strip() # Return if the text hasn't changed if new_text == self.files_treestore[path][1]: @@ -881,9 +882,15 @@ class AddTorrentDialog(component.Component): if index > -1: # We're renaming a file! Yay! That's easy! + if not new_text: + return parent = self.files_treestore.iter_parent(itr) file_path = os.path.join(self.get_file_path(parent), new_text) - + # Don't rename if filename exists + if parent: + for row in self.files_treestore[parent].iterchildren(): + if new_text == row[1]: + return if os.path.sep in new_text: # There are folders in this path, so we need to create them # and then move the file iter to top diff --git a/deluge/ui/gtkui/common.py b/deluge/ui/gtkui/common.py index 4b56048e5..088223803 100644 --- a/deluge/ui/gtkui/common.py +++ b/deluge/ui/gtkui/common.py @@ -111,7 +111,7 @@ def build_menu_radio_list(value_list, callback, pref_value=None, if show_notset: menuitem = gtk.RadioMenuItem(group, notset_label) - menuitem.set_name(notset_label) + menuitem.set_name("unlimited") if pref_value < notset_lessthan and pref_value != None: menuitem.set_active(True) if show_activated and pref_value == 1: @@ -124,7 +124,7 @@ def build_menu_radio_list(value_list, callback, pref_value=None, menuitem = gtk.SeparatorMenuItem() menu.append(menuitem) menuitem = gtk.MenuItem(_("Other...")) - menuitem.set_name(_("Other...")) + menuitem.set_name("other") menuitem.connect("activate", callback) menu.append(menuitem) diff --git a/deluge/ui/gtkui/createtorrentdialog.py b/deluge/ui/gtkui/createtorrentdialog.py index acfc06097..435cba0a6 100644 --- a/deluge/ui/gtkui/createtorrentdialog.py +++ b/deluge/ui/gtkui/createtorrentdialog.py @@ -174,7 +174,7 @@ class CreateTorrentDialog: chooser.destroy() return - path = result.decode('utf-8').encode(sys.getfilesystemencoding()) + path = result.decode('utf-8') self.files_treestore.clear() self.files_treestore.append(None, [result, gtk.STOCK_FILE, deluge.common.get_path_size(path)]) @@ -202,7 +202,7 @@ class CreateTorrentDialog: chooser.destroy() return - path = result.decode('utf-8').encode(sys.getfilesystemencoding()) + path = result.decode('utf-8') self.files_treestore.clear() self.files_treestore.append(None, [result, gtk.STOCK_OPEN, deluge.common.get_path_size(path)]) diff --git a/deluge/ui/gtkui/glade/preferences_dialog.ui b/deluge/ui/gtkui/glade/preferences_dialog.ui index e9f526d38..09a6ea5de 100644 --- a/deluge/ui/gtkui/glade/preferences_dialog.ui +++ b/deluge/ui/gtkui/glade/preferences_dialog.ui @@ -2466,6 +2466,19 @@ used sparingly.</property> </packing> </child> <child> + <object class="GtkCheckButton" id="chk_focus_main_window_on_add"> + <property name="label" translatable="yes">Focus window when adding torrent</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> <object class="GtkCheckButton" id="piecesbar_toggle"> <property name="visible">True</property> <property name="can_focus">True</property> @@ -2491,7 +2504,7 @@ status tab (<b>EXPERIMENTAL!!!</b>)</property> <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child> diff --git a/deluge/ui/gtkui/glade/tray_menu.ui b/deluge/ui/gtkui/glade/tray_menu.ui index c92797cd2..b621e5fd4 100644 --- a/deluge/ui/gtkui/glade/tray_menu.ui +++ b/deluge/ui/gtkui/glade/tray_menu.ui @@ -61,6 +61,7 @@ <property name="use_underline">True</property> <property name="image">menu-item-image1</property> <property name="use_stock">False</property> + <property name="always_show_image">True</property> <signal name="activate" handler="on_menuitem_add_torrent_activate" swapped="no"/> </object> </child> @@ -109,6 +110,7 @@ <property name="use_underline">True</property> <property name="image">download-limit-image</property> <property name="use_stock">False</property> + <property name="always_show_image">True</property> </object> </child> <child> @@ -120,6 +122,7 @@ <property name="use_underline">True</property> <property name="image">upload-limit-image</property> <property name="use_stock">False</property> + <property name="always_show_image">True</property> </object> </child> <child> diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 53072e2ac..685ed45a5 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -149,6 +149,7 @@ DEFAULT_PREFS = { "pieces_color_waiting": [4874, 56494, 0], "pieces_color_downloading": [65535, 55255, 0], "pieces_color_completed": [4883, 26985, 56540], + "focus_main_window_on_add": True, } class GtkUI(object): @@ -245,9 +246,8 @@ class GtkUI(object): component.stop() # Process any pending gtk events since the mainloop has been quit - if not deluge.common.windows_check(): - while gtk.events_pending() and reactor.running: - reactor.doIteration(0) + while gtk.events_pending(): + gtk.main_iteration(0) # Shutdown all components component.shutdown() diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py index cb7259cc5..f8eab61da 100644 --- a/deluge/ui/gtkui/ipcinterface.py +++ b/deluge/ui/gtkui/ipcinterface.py @@ -40,6 +40,8 @@ import base64 import logging from urllib import url2pathname from urlparse import urlparse +from glob import glob +from tempfile import mkstemp try: import rencode @@ -59,8 +61,10 @@ log = logging.getLogger(__name__) class IPCProtocolServer(Protocol): def dataReceived(self, data): - data = rencode.loads(data) - component.get("MainWindow").present() + config = ConfigManager("gtkui.conf") + data = rencode.loads(data, decode_utf8=True) + if not data or config["focus_main_window_on_add"]: + component.get("MainWindow").present() process_args(data) class IPCProtocolClient(Protocol): @@ -75,23 +79,20 @@ class IPCProtocolClient(Protocol): class IPCClientFactory(ClientFactory): protocol = IPCProtocolClient - def __init__(self, args, connect_failed): + def __init__(self): self.stop = False - self.args = args - self.connect_failed = connect_failed def clientConnectionFailed(self, connector, reason): - log.info("Connection to running instance failed. Starting new one..") + log.warning("Connection to running instance failed.") reactor.stop() class IPCInterface(component.Component): def __init__(self, args): component.Component.__init__(self, "IPCInterface") - if not os.path.exists(deluge.configmanager.get_config_dir("ipc")): - os.makedirs(deluge.configmanager.get_config_dir("ipc")) - - socket = os.path.join(deluge.configmanager.get_config_dir("ipc"), "deluge-gtk") - + ipc_dir = deluge.configmanager.get_config_dir("ipc") + if not os.path.exists(ipc_dir): + os.makedirs(ipc_dir) + socket = os.path.join(ipc_dir, "deluge-gtk") if deluge.common.windows_check(): # If we're on windows we need to check the global mutex to see if deluge is # already running. @@ -120,6 +121,10 @@ class IPCInterface(component.Component): reactor.run() sys.exit(0) else: + # Find and remove any restart tempfiles + old_tempfile = glob(os.path.join(ipc_dir, 'tmp*deluge')) + for f in old_tempfile: + os.remove(f) lockfile = socket + ".lock" log.debug("Checking if lockfile exists: %s", lockfile) if os.path.lexists(lockfile): @@ -138,45 +143,28 @@ class IPCInterface(component.Component): self.factory.protocol = IPCProtocolServer reactor.listenUNIX(socket, self.factory, wantPID=True) except twisted.internet.error.CannotListenError, e: - log.info("Deluge is already running! Sending arguments to running instance..") - self.factory = IPCClientFactory(args, self.connect_failed) + log.info("Deluge is already running! Sending arguments to running instance...") + self.factory = IPCClientFactory() + self.factory.args = args reactor.connectUNIX(socket, self.factory, checkPID=True) reactor.run() if self.factory.stop: + log.info("Success sending arguments to running Deluge.") import gtk gtk.gdk.notify_startup_complete() sys.exit(0) else: - self.connect_failed(args) + if old_tempfile: + log.error("Deluge restart failed: %s", e) + sys.exit(1) + else: + log.warning('Restarting Deluge... (%s)', e) + # Create a tempfile to keep track of restart + mkstemp('deluge', dir=ipc_dir) + os.execv(sys.argv[0], sys.argv) else: process_args(args) - def connect_failed(self, args): - # This gets called when we're unable to do a connectUNIX to the ipc - # socket. We'll delete the lock and socket files and start up Deluge. - - socket = os.path.join(deluge.configmanager.get_config_dir("ipc"), "deluge-gtk") - if os.path.exists(socket): - try: - os.remove(socket) - except Exception, e: - log.error("Unable to remove socket file: %s", e) - - lock = socket + ".lock" - if os.path.lexists(lock): - try: - os.remove(lock) - except Exception, e: - log.error("Unable to remove lock file: %s", e) - try: - self.factory = Factory() - self.factory.protocol = IPCProtocolServer - reactor.listenUNIX(socket, self.factory, wantPID=True) - except Exception, e: - log.error("Unable to start IPC listening socket: %s", e) - finally: - process_args(args) - def shutdown(self): if deluge.common.windows_check(): import win32api diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py index d491441d0..4d07a5750 100644 --- a/deluge/ui/gtkui/mainwindow.py +++ b/deluge/ui/gtkui/mainwindow.py @@ -42,6 +42,11 @@ import gtk import logging import urllib +try: + import wnck +except ImportError: + wnck = None + from deluge.ui.client import client import deluge.component as component from deluge.configmanager import ConfigManager @@ -76,6 +81,8 @@ class _GtkBuilderSignalsHolder(object): class MainWindow(component.Component): def __init__(self): + if wnck: + self.screen = wnck.screen_get_default() component.Component.__init__(self, "MainWindow", interval=2) self.config = ConfigManager("gtkui.conf") self.gtk_builder_signals_holder = _GtkBuilderSignalsHolder() @@ -167,7 +174,6 @@ class MainWindow(component.Component): component.resume("TorrentDetails") except: pass - self.window.show() @@ -324,3 +330,11 @@ class MainWindow(component.Component): def on_torrentfinished_event(self, torrent_id): from deluge.ui.gtkui.notification import Notification Notification().notify(torrent_id) + + def is_on_active_workspace(self): + # Returns True if mainwindow is on active workspace or wnck module not available + if not wnck: + return True + for win in self.screen.get_windows(): + if win.get_xid() == self.window.window.xid: + return win.is_on_workspace(win.get_screen().get_active_workspace()) diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py index b5169977d..a5bfcc819 100644 --- a/deluge/ui/gtkui/pluginmanager.py +++ b/deluge/ui/gtkui/pluginmanager.py @@ -93,6 +93,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase, def _on_plugin_enabled_event(self, name): self.enable_plugin(name) + self.run_on_show_prefs() def _on_plugin_disabled_event(self, name): self.disable_plugin(name) diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index 34f8da6f0..2755a330c 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -121,7 +121,8 @@ class Preferences(component.Component): self.accounts_frame = self.builder.get_object("AccountsFrame") # Setup plugin tab listview - self.plugin_liststore = gtk.ListStore(str, bool) + # The third entry is for holding translated plugin names + self.plugin_liststore = gtk.ListStore(str, bool, str) self.plugin_liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) self.plugin_listview = self.builder.get_object("plugin_listview") self.plugin_listview.set_model(self.plugin_liststore) @@ -131,7 +132,7 @@ class Preferences(component.Component): self.plugin_listview.append_column( gtk.TreeViewColumn(_("Enabled"), render, active=1)) self.plugin_listview.append_column( - gtk.TreeViewColumn(_("Plugin"), gtk.CellRendererText(), text=0)) + gtk.TreeViewColumn(_("Plugin"), gtk.CellRendererText(), text=2)) # Connect to the 'changed' event of TreeViewSelection to get selection # changes. @@ -552,6 +553,8 @@ class Preferences(component.Component): self.gtkui_config["classic_mode"]) self.builder.get_object("chk_show_rate_in_title").set_active( self.gtkui_config["show_rate_in_title"]) + self.builder.get_object("chk_focus_main_window_on_add").set_active( + self.gtkui_config["focus_main_window_on_add"]) self.builder.get_object("piecesbar_toggle").set_active( self.gtkui_config["show_piecesbar"] ) @@ -583,6 +586,7 @@ class Preferences(component.Component): row = self.plugin_liststore.append() self.plugin_liststore.set_value(row, 0, plugin) self.plugin_liststore.set_value(row, 1, enabled) + self.plugin_liststore.set_value(row, 2, _(plugin)) # Now show the dialog self.pref_dialog.show() @@ -739,6 +743,8 @@ class Preferences(component.Component): new_gtkui_config["show_rate_in_title"] = \ self.builder.get_object("chk_show_rate_in_title").get_active() + new_gtkui_config["focus_main_window_on_add"] = \ + self.builder.get_object("chk_focus_main_window_on_add").get_active() ## Other tab ## new_gtkui_config["show_new_releases"] = \ diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py index 3b63934c5..7eeaaa78b 100644 --- a/deluge/ui/gtkui/queuedtorrents.py +++ b/deluge/ui/gtkui/queuedtorrents.py @@ -173,7 +173,7 @@ class QueuedTorrents(component.Component): def on_button_add_clicked(self, widget): # Add all the torrents in the liststore def add_torrent(model, path, iter, data): - torrent_path = model.get_value(iter, 1) + torrent_path = model.get_value(iter, 1).decode('utf-8') process_args([torrent_path]) self.liststore.foreach(add_torrent, None) diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index c433b2834..f4219900c 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -392,9 +392,9 @@ class StatusBar(component.Component): def _on_set_download_speed(self, widget): log.debug("_on_set_download_speed") - if widget.get_name() == _("Unlimited"): + if widget.get_name() == "unlimited": value = -1 - elif widget.get_name() == _("Other..."): + elif widget.get_name() == "other": value = common.show_other_dialog( _("Set Maximum Download Speed"), _("KiB/s"), None, "downloading.svg", self.max_download_speed) if value == None: @@ -420,9 +420,9 @@ class StatusBar(component.Component): def _on_set_upload_speed(self, widget): log.debug("_on_set_upload_speed") - if widget.get_name() == _("Unlimited"): + if widget.get_name() == "unlimited": value = -1 - elif widget.get_name() == _("Other..."): + elif widget.get_name() == "other": value = common.show_other_dialog( _("Set Maximum Upload Speed"), _("KiB/s"), None, "seeding.svg", self.max_upload_speed) if value == None: @@ -447,9 +447,9 @@ class StatusBar(component.Component): def _on_set_connection_limit(self, widget): log.debug("_on_set_connection_limit") - if widget.get_name() == _("Unlimited"): + if widget.get_name() == "unlimited": value = -1 - elif widget.get_name() == _("Other..."): + elif widget.get_name() == "other": value = common.show_other_dialog( _("Set Maximum Connections"), "", gtk.STOCK_NETWORK, None, self.max_connections) if value == None: diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py index c54b0943a..553ebb354 100644 --- a/deluge/ui/gtkui/systemtray.py +++ b/deluge/ui/gtkui/systemtray.py @@ -138,10 +138,9 @@ class SystemTray(component.Component): self.tray.connect("activate", self.on_tray_clicked) self.tray.connect("popup-menu", self.on_tray_popup) - # For some reason these icons do not display in appindicator - self.builder.get_object("download-limit-image").set_from_file( + self.builder.get_object("download-limit-image").set_from_file( deluge.common.get_pixmap("downloading16.png")) - self.builder.get_object("upload-limit-image").set_from_file( + self.builder.get_object("upload-limit-image").set_from_file( deluge.common.get_pixmap("seeding16.png")) client.register_event_handler("ConfigValueChangedEvent", self.config_value_changed) @@ -157,21 +156,14 @@ class SystemTray(component.Component): if self.config["enable_system_tray"]: if self.config["classic_mode"]: - self.hide_widget_list.remove("menuitem_quitdaemon") - self.hide_widget_list.remove("separatormenuitem4") + try: + self.hide_widget_list.remove("menuitem_quitdaemon") + self.hide_widget_list.remove("separatormenuitem4") + except ValueError: + pass self.builder.get_object("menuitem_quitdaemon").hide() self.builder.get_object("separatormenuitem4").hide() - # These do not work with appindicator currently and can crash Deluge. - # Related to Launchpad bug #608219 - if appindicator and self.config["enable_appindicator"]: - self.hide_widget_list.remove("menuitem_download_limit") - self.hide_widget_list.remove("menuitem_upload_limit") - self.hide_widget_list.remove("separatormenuitem3") - self.builder.get_object("menuitem_download_limit").hide() - self.builder.get_object("menuitem_upload_limit").hide() - self.builder.get_object("separatormenuitem3").hide() - # Show widgets in the hide list because we've connected to a host for widget in self.hide_widget_list: self.builder.get_object(widget).show() @@ -266,16 +258,15 @@ class SystemTray(component.Component): def build_tray_bwsetsubmenu(self): # Create the Download speed list sub-menu submenu_bwdownset = common.build_menu_radio_list( - self.config["tray_download_speed_list"], self.tray_setbwdown, + self.config["tray_download_speed_list"], self.on_tray_setbwdown, self.max_download_speed, _("KiB/s"), show_notset=True, show_other=True) # Create the Upload speed list sub-menu submenu_bwupset = common.build_menu_radio_list( - self.config["tray_upload_speed_list"], self.tray_setbwup, + self.config["tray_upload_speed_list"], self.on_tray_setbwup, self.max_upload_speed, _("KiB/s"), show_notset=True, show_other=True) - # Add the sub-menus to the tray menu self.builder.get_object("menuitem_download_limit").set_submenu( submenu_bwdownset) @@ -286,10 +277,6 @@ class SystemTray(component.Component): submenu_bwdownset.show_all() submenu_bwupset.show_all() - # Re-set the menu to partly work around Launchpad bug #608219 - if appindicator and self.config["enable_appindicator"]: - self.indicator.set_menu(self.tray_menu) - def disable(self,invert_app_ind_conf=False): """Disables the system tray icon or appindicator.""" try: @@ -360,6 +347,7 @@ class SystemTray(component.Component): popup_function = gtk.status_icon_position_menu if deluge.common.windows_check(): popup_function = None + button = 0 self.tray_menu.popup(None, None, popup_function, button, activate_time, status_icon) @@ -399,10 +387,22 @@ class SystemTray(component.Component): self.window.quit(shutdown=True) - def tray_setbwdown(self, widget, data=None): + def on_tray_setbwdown(self, widget, data=None): + if isinstance(widget, gtk.RadioMenuItem): + #ignore previous radiomenuitem value + if not widget.get_active(): + return self.setbwlimit(widget, _("Set Maximum Download Speed"), "max_download_speed", "tray_download_speed_list", self.max_download_speed, "downloading.svg") + def on_tray_setbwup(self, widget, data=None): + if isinstance(widget, gtk.RadioMenuItem): + #ignore previous radiomenuitem value + if not widget.get_active(): + return + self.setbwlimit(widget, _("Set Maximum Upload Speed"), "max_upload_speed", + "tray_upload_speed_list", self.max_upload_speed, "seeding.svg") + def _on_window_hide(self, widget, data=None): """_on_window_hide - update the menuitem's status""" log.debug("_on_window_hide") @@ -413,26 +413,21 @@ class SystemTray(component.Component): log.debug("_on_window_show") self.builder.get_object("menuitem_show_deluge").set_active(True) - def tray_setbwup(self, widget, data=None): - self.setbwlimit(widget, _("Set Maximum Upload Speed"), "max_upload_speed", - "tray_upload_speed_list", self.max_upload_speed, "seeding.svg") - def setbwlimit(self, widget, string, core_key, ui_key, default, image): """Sets the bandwidth limit based on the user selection.""" - value = widget.get_children()[0].get_text().rstrip(" " + _("KiB/s")) - if value == _("Unlimited"): + value = widget.get_children()[0].get_text().split(" ")[0] + log.debug('setbwlimit: %s', value) + if widget.get_name() == "unlimited": value = -1 - - if value == _("Other..."): + if widget.get_name() == "other": value = common.show_other_dialog(string, _("KiB/s"), None, image, default) if value == None: return - + elif value == 0: + value = -1 # Set the config in the core client.core.set_config({core_key: value}) - self.build_tray_bwsetsubmenu() - def unlock_tray(self, is_showing_dlg=[False]): try: from hashlib import sha1 as sha_hash @@ -450,13 +445,13 @@ class SystemTray(component.Component): entered_pass.set_width_chars(25) entered_pass.set_visibility(False) - tray_lock = gtk.Dialog(title="", parent=self.window.window, + self.tray_lock = gtk.Dialog(title="", parent=self.window.window, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) - tray_lock.set_default_response(gtk.RESPONSE_OK) - tray_lock.set_has_separator(False) + self.tray_lock.set_default_response(gtk.RESPONSE_OK) + self.tray_lock.set_has_separator(False) - tray_lock.set_border_width(5) + self.tray_lock.set_border_width(5) hbox = gtk.HBox(spacing=5) @@ -481,15 +476,15 @@ class SystemTray(component.Component): vbox.pack_start(entered_pass) - tray_lock.vbox.pack_start(hbox) + self.tray_lock.vbox.pack_start(hbox) def on_response(dialog, response_id): if response_id == gtk.RESPONSE_OK: if self.config["tray_password"] == sha_hash(entered_pass.get_text()).hexdigest(): self.window.present() - tray_lock.destroy() + self.tray_lock.destroy() is_showing_dlg[0] = False - tray_lock.connect("response", on_response) - tray_lock.show_all() + self.tray_lock.connect("response", on_response) + self.tray_lock.show_all() diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py index 36fc92270..6c11af8f6 100644 --- a/deluge/ui/gtkui/torrentdetails.py +++ b/deluge/ui/gtkui/torrentdetails.py @@ -113,6 +113,15 @@ class TorrentDetails(component.Component): ("Options", True) ] + self.translate_tabs = { + "All" : _("_All"), + "Status" : _("_Status"), + "Details" : _("_Details"), + "Files" : _("_Files"), + "Peers" : _("_Peers"), + "Options" : _("_Options") + } + # Get the state from saved file state = self.load_state() @@ -242,8 +251,8 @@ class TorrentDetails(component.Component): def hide_tab(self, tab_name): """Hides tab by name""" - self.notebook.remove_page(self.tabs[tab_name].position) self.tabs[tab_name].is_visible = False + self.notebook.remove_page(self.tabs[tab_name].position) self.regenerate_positions() self.generate_menu() @@ -275,7 +284,8 @@ class TorrentDetails(component.Component): """Generates the checklist menu for all the tabs and attaches it""" menu = gtk.Menu() # Create 'All' menuitem and a separator - menuitem = gtk.CheckMenuItem("All") + menuitem = gtk.CheckMenuItem(self.translate_tabs["All"], True) + menuitem.set_name("All") all_tabs = True for key in self.tabs: @@ -297,7 +307,8 @@ class TorrentDetails(component.Component): menuitem_list.sort() for pos, name in menuitem_list: - menuitem = gtk.CheckMenuItem(name) + menuitem = gtk.CheckMenuItem(self.translate_tabs[name], True) + menuitem.set_name(name) menuitem.set_active(self.tabs[name].is_visible) menuitem.connect("toggled", self._on_menuitem_toggled) menu.append(menuitem) @@ -386,7 +397,7 @@ class TorrentDetails(component.Component): def _on_menuitem_toggled(self, widget): # Get the tab name - name = widget.get_child().get_text() + name = widget.get_name() if name == "All": if widget.get_active(): self.show_all_tabs() diff --git a/deluge/ui/sessionproxy.py b/deluge/ui/sessionproxy.py index d861afdc6..b7acd890f 100644 --- a/deluge/ui/sessionproxy.py +++ b/deluge/ui/sessionproxy.py @@ -67,11 +67,11 @@ class SessionProxy(component.Component): # Holds the time of the last key update.. {torrent_id: {key1, time, ...}, ...} self.cache_times = {} + def start(self): client.register_event_handler("TorrentStateChangedEvent", self.on_torrent_state_changed) client.register_event_handler("TorrentRemovedEvent", self.on_torrent_removed) client.register_event_handler("TorrentAddedEvent", self.on_torrent_added) - def start(self): def on_get_session_state(torrent_ids): for torrent_id in torrent_ids: # Let's at least store the torrent ids with empty statuses diff --git a/deluge/ui/ui.py b/deluge/ui/ui.py index 792f416c2..46a597a5f 100644 --- a/deluge/ui/ui.py +++ b/deluge/ui/ui.py @@ -107,7 +107,9 @@ class _UI(object): return self.__args def start(self): - (self.__options, self.__args) = self.__parser.parse_args() + # Make sure all arguments are unicode + argv = deluge.common.unicode_argv()[1:] + (self.__options, self.__args) = self.__parser.parse_args(argv) if self.__options.quiet: self.__options.loglevel = "none" diff --git a/deluge/ui/web/TODO b/deluge/ui/web/TODO deleted file mode 100644 index 6861a65f1..000000000 --- a/deluge/ui/web/TODO +++ /dev/null @@ -1,4 +0,0 @@ -* Add Window torrent options - - Add an options manager -* Preferences window options - - Add an options manager diff --git a/deluge/ui/web/auth.py b/deluge/ui/web/auth.py index 5cd345e2c..e26eab486 100644 --- a/deluge/ui/web/auth.py +++ b/deluge/ui/web/auth.py @@ -322,4 +322,5 @@ class Auth(JSONComponent): if self.check_password(password): return self._create_session(__request__) else: + log.error('Login failed (ClientIP %s)', __request__.getClientIP()) return False diff --git a/deluge/ui/web/build b/deluge/ui/web/build index 0c196770e..ad8944285 100755 --- a/deluge/ui/web/build +++ b/deluge/ui/web/build @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh BASE_DIR="${PWD}/`dirname ${0}`" BASE_DIR=`readlink -f "$BASE_DIR"` @@ -32,7 +32,7 @@ check_file() FILE=$1 LAST_BUILD=`grep $FILE $BUILD_DATA` - if [ $? == 1 ]; then return 1; fi; + if [ $? = 1 ]; then return 1; fi; CURRENT=`grep $FILE $BUILD_DATA.tmp` diff --git a/deluge/ui/web/css/deluge.css b/deluge/ui/web/css/deluge.css index 4701d7e66..ab02a4536 100644 --- a/deluge/ui/web/css/deluge.css +++ b/deluge/ui/web/css/deluge.css @@ -244,10 +244,57 @@ dl.singleline dd { } /* Files TreeGrid */ +.x-treegrid-root-table { + border-right: 1px solid; +} + +.x-treegrid-root-node { + overflow: auto; +} + +.x-treegrid-hd-hidden { + visibility: hidden; + border: 0; + width: 0; +} + .x-treegrid-col { - overflow: hidden; + border-bottom: 1px solid; + height: 20px; + overflow: hidden; + vertical-align: top; + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + white-space: nowrap; +} + +.x-treegrid-text { + padding-left: 4px; + -moz-user-select: none; + -khtml-user-select: none; +} + +.x-treegrid-resizer { + border-left:1px solid; + border-right:1px solid; + position:absolute; + left:0; + top:0; +} + +.x-treegrid-header-inner { + overflow: hidden; } +.x-treegrid-root-table, +.x-treegrid-col { + border-color: #ededed; +} + +.x-treegrid-resizer { + border-left-color:#555; + border-right-color:#555; +} /* Options Tab Styles */ .x-deluge-options-label { diff --git a/deluge/ui/web/gen_gettext.py b/deluge/ui/web/gen_gettext.py index 05025aec5..b2518d74b 100644..100755 --- a/deluge/ui/web/gen_gettext.py +++ b/deluge/ui/web/gen_gettext.py @@ -2,15 +2,14 @@ """ Script to go through the javascript files and dynamically generate gettext.js """ - import os import re -import glob -import cStringIO as StringIO +output_file = "gettext.js" string_re = re.compile('_\\(\'(.*?)\'\\)') strings = {} + gettext_tpl = """## -*- coding: utf-8 -*- /* * Script: gettext.js @@ -59,10 +58,10 @@ for root, dnames, files in os.walk('js/deluge-all'): keys = strings.keys() keys.sort() -fp = StringIO.StringIO() +fp = open(output_file, 'w') fp.write(gettext_tpl) for key in keys: fp.write('// %s\n' % ', '.join(map(lambda x: '%s:%s' % x, strings[key]))) fp.write("GetText.add('%(key)s', '${escape(_(\"%(key)s\"))}')\n\n" % locals()) -fp.seek(0) -print fp.read() +fp.close() + diff --git a/deluge/ui/web/gettext.js b/deluge/ui/web/gettext.js index 7bed3e588..acef95a7b 100644 --- a/deluge/ui/web/gettext.js +++ b/deluge/ui/web/gettext.js @@ -26,739 +26,819 @@ function _(string) { return GetText.get(string); } -// Deluge.Torrents.js:117 +// TorrentGrid.js:109 GetText.add('#', '${escape(_("#"))}') -// Deluge.Menus.js:167 +// DetailsTab.js:50 +GetText.add('# of files', '${escape(_("# of files"))}') + +// Menus.js:166 GetText.add('0', '${escape(_("0"))}') -// Deluge.Menus.js:169 +// Menus.js:168 GetText.add('1', '${escape(_("1"))}') -// Deluge.Menus.js:115, Deluge.Menus.js:133 +// Menus.js:111, Menus.js:130 GetText.add('10 KiB/s', '${escape(_("10 KiB/s"))}') -// Deluge.Menus.js:151 +// Menus.js:149 GetText.add('100', '${escape(_("100"))}') -// Deluge.Menus.js:171 +// Menus.js:170 GetText.add('2', '${escape(_("2"))}') -// Deluge.Menus.js:153 +// Menus.js:151 GetText.add('200', '${escape(_("200"))}') -// Deluge.Menus.js:173 +// Menus.js:172 GetText.add('3', '${escape(_("3"))}') -// Deluge.Menus.js:117, Deluge.Menus.js:135 +// Menus.js:113, Menus.js:132 GetText.add('30 KiB/s', '${escape(_("30 KiB/s"))}') -// Deluge.Menus.js:155 +// Menus.js:153 GetText.add('300', '${escape(_("300"))}') -// Deluge.Menus.js:121, Deluge.Menus.js:139 +// Menus.js:117, Menus.js:136 GetText.add('300 KiB/s', '${escape(_("300 KiB/s"))}') -// Deluge.Menus.js:175 +// Menus.js:174 GetText.add('5', '${escape(_("5"))}') -// Deluge.Menus.js:113, Deluge.Menus.js:131 +// Menus.js:109, Menus.js:128 GetText.add('5 KiB/s', '${escape(_("5 KiB/s"))}') -// Deluge.Menus.js:149 +// Menus.js:147 GetText.add('50', '${escape(_("50"))}') -// Deluge.Menus.js:157 +// Menus.js:155 GetText.add('500', '${escape(_("500"))}') -// Deluge.Menus.js:119, Deluge.Menus.js:137 +// Menus.js:115, Menus.js:134 GetText.add('80 KiB/s', '${escape(_("80 KiB/s"))}') -// Deluge.Preferences.Queue.js:70 +// QueuePage.js:69 GetText.add('Active Torrents', '${escape(_("Active Torrents"))}') -// Deluge.ConnectionManager.js:64, Deluge.ConnectionManager.js:222, Deluge.Add.Url.js:55, Deluge.Toolbar.js:51, Deluge.Add.js:384, Deluge.EditTrackers.js:58, Deluge.EditTrackers.js:237, Deluge.Add.File.js:55 +// EditTrackersWindow.js:112, ConnectionManager.js:100, AddConnectionWindow.js:56, Toolbar.js:58, AddTrackerWindow.js:57, UrlWindow.js:50, FileWindow.js:53, AddWindow.js:52 GetText.add('Add', '${escape(_("Add"))}') -// Deluge.ConnectionManager.js:52 +// AddConnectionWindow.js:40 GetText.add('Add Connection', '${escape(_("Add Connection"))}') -// Deluge.Add.js:184 +// OptionsTab.js:144 GetText.add('Add In Paused State', '${escape(_("Add In Paused State"))}') -// Deluge.Add.js:366 +// AddWindow.js:37 GetText.add('Add Torrents', '${escape(_("Add Torrents"))}') -// Deluge.EditTrackers.js:39 +// AddTrackerWindow.js:40 GetText.add('Add Tracker', '${escape(_("Add Tracker"))}') -// Deluge.Add.File.js:47 +// FileWindow.js:40 GetText.add('Add from File', '${escape(_("Add from File"))}') -// Deluge.Add.Url.js:47 +// UrlWindow.js:36 GetText.add('Add from Url', '${escape(_("Add from Url"))}') -// Deluge.Preferences.Downloads.js:142 +// DownloadsPage.js:146 GetText.add('Add torrents in Paused state', '${escape(_("Add torrents in Paused state"))}') -// Deluge.Torrents.js:184 +// TorrentGrid.js:180 GetText.add('Added', '${escape(_("Added"))}') -// Deluge.Sidebar.js:198 +// FilterPanel.js:124 GetText.add('All', '${escape(_("All"))}') -// Deluge.Add.js:114, Deluge.Preferences.Downloads.js:97 +// OptionsTab.js:77, DownloadsPage.js:100 GetText.add('Allocation', '${escape(_("Allocation"))}') -// Deluge.Preferences.Daemon.js:81 +// DaemonPage.js:77 GetText.add('Allow Remote Connections', '${escape(_("Allow Remote Connections"))}') -// Deluge.Details.Options.js:347, Deluge.Preferences.js:91 +// InterfacePage.js:78 +GetText.add('Allow the use of multiple filters at once', '${escape(_("Allow the use of multiple filters at once"))}') + +// OptionsTab.js:347, PreferencesWindow.js:107 GetText.add('Apply', '${escape(_("Apply"))}') -// Deluge.Menus.js:182, Deluge.Details.Options.js:215 +// Menus.js:181, OptionsTab.js:215 GetText.add('Auto Managed', '${escape(_("Auto Managed"))}') -// Deluge.Preferences.Downloads.js:88 +// DownloadsPage.js:91 GetText.add('Autoadd .torrent files from', '${escape(_("Autoadd .torrent files from"))}') -// Deluge.Torrents.js:178 +// TorrentGrid.js:173 GetText.add('Avail', '${escape(_("Avail"))}') -// Deluge.Add.js:144, Deluge.Details.Options.js:88, Deluge.Preferences.Bandwidth.js:39 +// FileBrowser.js:47 +GetText.add('Back', '${escape(_("Back"))}') + +// OptionsTab.js:88, OptionsTab.js:107, BandwidthPage.js:42 GetText.add('Bandwidth', '${escape(_("Bandwidth"))}') -// Deluge.Preferences.Other.js:63 +// OtherPage.js:66 GetText.add('Be alerted about new releases', '${escape(_("Be alerted about new releases"))}') -// Deluge.Menus.js:210 +// Menus.js:210 GetText.add('Bottom', '${escape(_("Bottom"))}') -// Deluge.Preferences.Plugins.js:74, Deluge.Add.File.js:70 +// MoveStorage.js:73, FileWindow.js:70, InstallPluginWindow.js:69 GetText.add('Browse', '${escape(_("Browse"))}') -// Deluge.Preferences.Cache.js:39 +// CachePage.js:41 GetText.add('Cache', '${escape(_("Cache"))}') -// Deluge.Preferences.Cache.js:71 +// CachePage.js:69 GetText.add('Cache Expiry (seconds)', '${escape(_("Cache Expiry (seconds)"))}') -// Deluge.Preferences.Cache.js:59 +// CachePage.js:63 GetText.add('Cache Size (16 KiB Blocks)', '${escape(_("Cache Size (16 KiB Blocks)"))}') -// Deluge.Add.js:383, Deluge.MoveStorage.js:56, Deluge.EditTrackers.js:57, Deluge.EditTrackers.js:116, Deluge.EditTrackers.js:178, Deluge.Remove.js:53 +// EditTrackersWindow.js:56, OtherLimitWindow.js:72, RemoveWindow.js:55, MoveStorage.js:55, EditTrackerWindow.js:56, AddTrackerWindow.js:56, AddWindow.js:51 GetText.add('Cancel', '${escape(_("Cancel"))}') -// Deluge.Preferences.js:55 +// PreferencesWindow.js:85 GetText.add('Categories', '${escape(_("Categories"))}') -// Deluge.Preferences.Interface.js:180 +// InterfacePage.js:173 GetText.add('Certificate', '${escape(_("Certificate"))}') -// Deluge.Preferences.Interface.js:118 +// InterfacePage.js:117 GetText.add('Change', '${escape(_("Change"))}') -// Deluge.Preferences.Interface.js:227 +// InterfacePage.js:224 GetText.add('Change Successful', '${escape(_("Change Successful"))}') -// Deluge.ConnectionManager.js:63, Deluge.ConnectionManager.js:171, Deluge.Preferences.js:90 +// ConnectionManager.js:54, AddConnectionWindow.js:55, PreferencesWindow.js:106 GetText.add('Close', '${escape(_("Close"))}') -// Deluge.Add.js:137 +// DetailsTab.js:51 +GetText.add('Comment', '${escape(_("Comment"))}') + +// OptionsTab.js:100 GetText.add('Compact', '${escape(_("Compact"))}') -// Deluge.Preferences.Interface.js:106 +// InterfacePage.js:105 GetText.add('Confirm Password', '${escape(_("Confirm Password"))}') -// Deluge.ConnectionManager.js:172, Deluge.ConnectionManager.js:284 +// ConnectionManager.js:55, ConnectionManager.js:184 GetText.add('Connect', '${escape(_("Connect"))}') -// Deluge.ConnectionManager.js:277, Deluge.ConnectionManager.js:322 +// ConnectionManager.js:177, ConnectionManager.js:225 GetText.add('Connected', '${escape(_("Connected"))}') -// Deluge.Menus.js:145 +// Menus.js:142 GetText.add('Connection Limit', '${escape(_("Connection Limit"))}') -// Deluge.ConnectionManager.js:159, Deluge.Toolbar.js:99 +// ConnectionManager.js:43, Toolbar.js:100 GetText.add('Connection Manager', '${escape(_("Connection Manager"))}') -// Deluge.Statusbar.js:25, Deluge.Preferences.Daemon.js:72 +// UI.js:151 +GetText.add('Connection restored', '${escape(_("Connection restored"))}') + +// Statusbar.js:57, DaemonPage.js:68 GetText.add('Connections', '${escape(_("Connections"))}') -// Deluge.Add.Url.js:73 +// UrlWindow.js:68 GetText.add('Cookies', '${escape(_("Cookies"))}') -// Deluge.Preferences.Downloads.js:80 +// DownloadsPage.js:83 GetText.add('Copy of .torrent files to', '${escape(_("Copy of .torrent files to"))}') -// Deluge.Toolbar.js:44 +// Toolbar.js:52 GetText.add('Create', '${escape(_("Create"))}') -// Deluge.Menus.js:109 +// Menus.js:104 GetText.add('D/L Speed Limit', '${escape(_("D/L Speed Limit"))}') -// Deluge.Preferences.Network.js:229, Deluge.Preferences.Proxy.js:202 +// NetworkPage.js:225, ProxyPage.js:70 GetText.add('DHT', '${escape(_("DHT"))}') -// Deluge.Statusbar.js:52 +// Statusbar.js:210 GetText.add('DHT Nodes', '${escape(_("DHT Nodes"))}') -// Deluge.Preferences.Daemon.js:39 +// DaemonPage.js:41 GetText.add('Daemon', '${escape(_("Daemon"))}') -// Deluge.Preferences.Daemon.js:58 +// DaemonPage.js:57 GetText.add('Daemon port', '${escape(_("Daemon port"))}') -// Deluge.Details.Details.js:36 +// Toolbar.js:45 +GetText.add('Deluge', '${escape(_("Deluge"))}') + +// DetailsTab.js:36 GetText.add('Details', '${escape(_("Details"))}') -// Deluge.Preferences.Encryption.js:66, Deluge.Preferences.Encryption.js:82 +// EncryptionPage.js:65, EncryptionPage.js:82 GetText.add('Disabled', '${escape(_("Disabled"))}') -// Deluge.ConnectionManager.js:279 +// ConnectionManager.js:179 GetText.add('Disconnect', '${escape(_("Disconnect"))}') -// Deluge.Menus.js:410, Deluge.js:107 +// Menus.js:257, Deluge.js:156 GetText.add('Do Not Download', '${escape(_("Do Not Download"))}') -// Deluge.Preferences.Queue.js:117 +// QueuePage.js:107 GetText.add('Do not count slow torrents', '${escape(_("Do not count slow torrents"))}') -// Deluge.Toolbar.js:86, Deluge.Menus.js:204, Deluge.EditTrackers.js:231 +// EditTrackersWindow.js:107, Menus.js:204, Toolbar.js:89 GetText.add('Down', '${escape(_("Down"))}') -// Deluge.Torrents.js:154 +// TorrentGrid.js:241 +GetText.add('Down Limit', '${escape(_("Down Limit"))}') + +// TorrentGrid.js:148 GetText.add('Down Speed', '${escape(_("Down Speed"))}') -// Deluge.Add.js:94 +// FilesTab.js:63 +GetText.add('Download', '${escape(_("Download"))}') + +// OptionsTab.js:55 GetText.add('Download Location', '${escape(_("Download Location"))}') -// Deluge.Statusbar.js:32 +// Statusbar.js:104 GetText.add('Download Speed', '${escape(_("Download Speed"))}') -// Deluge.Preferences.Downloads.js:66 +// DownloadsPage.js:69 GetText.add('Download to', '${escape(_("Download to"))}') -// Deluge.Preferences.Downloads.js:39 +// TorrentGrid.js:227 +GetText.add('Downloaded', '${escape(_("Downloaded"))}') + +// DownloadsPage.js:42 GetText.add('Downloads', '${escape(_("Downloads"))}') -// Deluge.Torrents.js:166 +// TorrentGrid.js:160 GetText.add('ETA', '${escape(_("ETA"))}') -// Deluge.EditTrackers.js:243 +// EditTrackersWindow.js:117 GetText.add('Edit', '${escape(_("Edit"))}') -// Deluge.EditTrackers.js:98 +// EditTrackerWindow.js:40 GetText.add('Edit Tracker', '${escape(_("Edit Tracker"))}') -// Deluge.Menus.js:224, Deluge.Details.Options.js:329, Deluge.EditTrackers.js:160 +// EditTrackersWindow.js:40, Menus.js:224, OptionsTab.js:332 GetText.add('Edit Trackers', '${escape(_("Edit Trackers"))}') -// Deluge.Preferences.Encryption.js:98 +// EncryptionPage.js:99 GetText.add('Either', '${escape(_("Either"))}') -// Deluge.Preferences.Plugins.js:157, Deluge.Preferences.Encryption.js:65, Deluge.Preferences.Encryption.js:81 +// EncryptionPage.js:64, EncryptionPage.js:81, PluginsPage.js:81 GetText.add('Enabled', '${escape(_("Enabled"))}') -// Deluge.Preferences.Encryption.js:110 +// EncryptionPage.js:112 GetText.add('Encrypt entire stream', '${escape(_("Encrypt entire stream"))}') -// Deluge.Preferences.Encryption.js:39 +// EncryptionPage.js:41 GetText.add('Encryption', '${escape(_("Encryption"))}') -// Deluge.ConnectionManager.js:128, Deluge.ConnectionManager.js:391, Deluge.ConnectionManager.js:447, Deluge.Add.js:541 +// ConnectionManager.js:308, ConnectionManager.js:364, AddConnectionWindow.js:103, AddWindow.js:209 GetText.add('Error', '${escape(_("Error"))}') -// Deluge.Menus.js:406 +// Menus.js:253 GetText.add('Expand All', '${escape(_("Expand All"))}') -// Deluge.Add.js:431, Deluge.Add.File.js:67 +// FileWindow.js:67, AddWindow.js:98 GetText.add('File', '${escape(_("File"))}') -// Deluge.Add.js:63, Deluge.Details.Files.js:53 +// FileBrowser.js:36 +GetText.add('File Browser', '${escape(_("File Browser"))}') + +// OptionsPanel.js:143 +GetText.add('File prioritization is unavailable when using Compact allocation. Would you like to switch to Full allocation?', '${escape(_("File prioritization is unavailable when using Compact allocation. Would you like to switch to Full allocation?"))}') + +// FilesTab.js:40, FilesTab.js:50 GetText.add('Filename', '${escape(_("Filename"))}') -// Deluge.Add.js:54, Deluge.Details.Files.js:47 +// FilesTab.js:35, FilesTab.js:41 GetText.add('Files', '${escape(_("Files"))}') -// Deluge.Sidebar.js:75 +// Sidebar.js:55 GetText.add('Filters', '${escape(_("Filters"))}') -// Deluge.Preferences.Plugins.js:191 +// PluginsPage.js:118 GetText.add('Find More', '${escape(_("Find More"))}') -// Deluge.Preferences.Downloads.js:54 +// DownloadsPage.js:57 GetText.add('Folders', '${escape(_("Folders"))}') -// Deluge.Menus.js:236 +// Menus.js:236 GetText.add('Force Recheck', '${escape(_("Force Recheck"))}') -// Deluge.Preferences.Encryption.js:64, Deluge.Preferences.Encryption.js:80 +// EncryptionPage.js:63, EncryptionPage.js:80 GetText.add('Forced', '${escape(_("Forced"))}') -// Deluge.Statusbar.js:58 +// FileBrowser.js:50 +GetText.add('Forward', '${escape(_("Forward"))}') + +// Statusbar.js:216 GetText.add('Freespace in download location', '${escape(_("Freespace in download location"))}') -// Deluge.Add.js:130 +// OptionsTab.js:93 GetText.add('Full', '${escape(_("Full"))}') -// Deluge.Preferences.Encryption.js:97 +// EncryptionPage.js:98 GetText.add('Full Stream', '${escape(_("Full Stream"))}') -// Deluge.Preferences.Queue.js:53, Deluge.Add.js:177, Deluge.Details.Options.js:281 +// OptionsTab.js:293, OptionsTab.js:137, QueuePage.js:52 GetText.add('General', '${escape(_("General"))}') -// Deluge.Preferences.Other.js:94 +// OtherPage.js:97 GetText.add('GeoIP Database', '${escape(_("GeoIP Database"))}') -// Deluge.Preferences.Bandwidth.js:53 +// BandwidthPage.js:56 GetText.add('Global Bandwidth Usage', '${escape(_("Global Bandwidth Usage"))}') -// Deluge.Preferences.Proxy.js:61 +// ProxyField.js:59 GetText.add('HTTP', '${escape(_("HTTP"))}') -// Deluge.Preferences.Proxy.js:62 +// ProxyField.js:60 GetText.add('HTTP with Auth', '${escape(_("HTTP with Auth"))}') -// Deluge.Preferences.Encryption.js:96 +// EncryptionPage.js:97 GetText.add('Handshake', '${escape(_("Handshake"))}') -// Deluge.Toolbar.js:107 +// DetailsTab.js:47 +GetText.add('Hash', '${escape(_("Hash"))}') + +// Toolbar.js:107 GetText.add('Help', '${escape(_("Help"))}') -// Deluge.Menus.js:420, Deluge.js:109 +// Menus.js:267, Deluge.js:158 GetText.add('High Priority', '${escape(_("High Priority"))}') -// Deluge.Menus.js:425, Deluge.js:110 +// Menus.js:272, Deluge.js:159 GetText.add('Highest Priority', '${escape(_("Highest Priority"))}') -// Deluge.ConnectionManager.js:77, Deluge.ConnectionManager.js:193, Deluge.Preferences.Proxy.js:73 +// FileBrowser.js:56 +GetText.add('Home', '${escape(_("Home"))}') + +// ConnectionManager.js:74, AddConnectionWindow.js:66, ProxyField.js:71 GetText.add('Host', '${escape(_("Host"))}') -// Deluge.Preferences.Bandwidth.js:145 +// BandwidthPage.js:122 GetText.add('Ignore limits on local network', '${escape(_("Ignore limits on local network"))}') -// Deluge.Preferences.Encryption.js:58 +// EncryptionPage.js:57 GetText.add('Inbound', '${escape(_("Inbound"))}') -// Deluge.Preferences.Network.js:53 +// NetworkPage.js:51 GetText.add('Incoming Ports', '${escape(_("Incoming Ports"))}') -// Deluge.Preferences.Plugins.js:203 +// PluginsPage.js:135 GetText.add('Info', '${escape(_("Info"))}') -// Deluge.Add.js:444 +// AddWindow.js:107 GetText.add('Infohash', '${escape(_("Infohash"))}') -// Deluge.Preferences.Plugins.js:59, Deluge.Preferences.Plugins.js:186 +// InstallPluginWindow.js:54, PluginsPage.js:113 GetText.add('Install', '${escape(_("Install"))}') -// Deluge.Preferences.Plugins.js:55 +// InstallPluginWindow.js:40 GetText.add('Install Plugin', '${escape(_("Install Plugin"))}') -// Deluge.Preferences.Interface.js:39, Deluge.Preferences.Interface.js:54 +// InterfacePage.js:41, InterfacePage.js:53 GetText.add('Interface', '${escape(_("Interface"))}') -// Deluge.Preferences.Interface.js:202 +// InterfacePage.js:199 GetText.add('Invalid Password', '${escape(_("Invalid Password"))}') -// Deluge.Details.Options.js:114, Deluge.Details.Options.js:141 +// OptionsTab.js:114, OptionsTab.js:141 GetText.add('KiB/s', '${escape(_("KiB/s"))}') -// Deluge.Preferences.Network.js:223 +// Statusbar.js:144, Statusbar.js:192 +GetText.add('Kib/s', '${escape(_("Kib/s"))}') + +// NetworkPage.js:219 GetText.add('LSD', '${escape(_("LSD"))}') -// Deluge.Preferences.Encryption.js:90 +// TorrentGrid.js:187 +GetText.add('Last Seen Complete', '${escape(_("Last Seen Complete"))}') + +// EncryptionPage.js:91 GetText.add('Level', '${escape(_("Level"))}') -// Deluge.Details.Status.js:57, Deluge.Details.Details.js:43 +// StatusTab.js:61 GetText.add('Loading', '${escape(_("Loading"))}') -// Deluge.MoveStorage.js:68, Deluge.Preferences.Other.js:101 +// MoveStorage.js:67, OtherPage.js:104 GetText.add('Location', '${escape(_("Location"))}') -// Deluge.Login.js:52, Deluge.Login.js:63 +// LoginWindow.js:45, LoginWindow.js:54 GetText.add('Login', '${escape(_("Login"))}') -// Deluge.Login.js:139 +// LoginWindow.js:130 GetText.add('Login Failed', '${escape(_("Login Failed"))}') -// Deluge.Toolbar.js:115 +// Toolbar.js:114 GetText.add('Logout', '${escape(_("Logout"))}') -// Deluge.Add.js:164, Deluge.Details.Options.js:150 +// OptionsTab.js:150, OptionsTab.js:126 GetText.add('Max Connections', '${escape(_("Max Connections"))}') -// Deluge.Add.js:152 +// OptionsTab.js:116 GetText.add('Max Down Speed', '${escape(_("Max Down Speed"))}') -// Deluge.Details.Options.js:97 +// OptionsTab.js:97 GetText.add('Max Download Speed', '${escape(_("Max Download Speed"))}') -// Deluge.Add.js:158 +// OptionsTab.js:121 GetText.add('Max Up Speed', '${escape(_("Max Up Speed"))}') -// Deluge.Add.js:170, Deluge.Details.Options.js:173 +// OptionsTab.js:173, OptionsTab.js:131 GetText.add('Max Upload Slots', '${escape(_("Max Upload Slots"))}') -// Deluge.Details.Options.js:123 +// OptionsTab.js:123 GetText.add('Max Upload Speed', '${escape(_("Max Upload Speed"))}') -// Deluge.Preferences.Bandwidth.js:121 +// BandwidthPage.js:103 GetText.add('Maximum Connection Attempts per Second', '${escape(_("Maximum Connection Attempts per Second"))}') -// Deluge.Preferences.Bandwidth.js:61, Deluge.Preferences.Bandwidth.js:166 +// BandwidthPage.js:68, BandwidthPage.js:147 GetText.add('Maximum Connections', '${escape(_("Maximum Connections"))}') -// Deluge.Preferences.Bandwidth.js:85, Deluge.Preferences.Bandwidth.js:190 +// BandwidthPage.js:82, BandwidthPage.js:161 GetText.add('Maximum Download Speed (KiB/s)', '${escape(_("Maximum Download Speed (KiB/s)"))}') -// Deluge.Preferences.Bandwidth.js:109 +// BandwidthPage.js:96 GetText.add('Maximum Half-Open Connections', '${escape(_("Maximum Half-Open Connections"))}') -// Deluge.Preferences.Bandwidth.js:73, Deluge.Preferences.Bandwidth.js:178 +// BandwidthPage.js:75, BandwidthPage.js:154 GetText.add('Maximum Upload Slots', '${escape(_("Maximum Upload Slots"))}') -// Deluge.Preferences.Bandwidth.js:97, Deluge.Preferences.Bandwidth.js:202 +// BandwidthPage.js:89, BandwidthPage.js:168 GetText.add('Maximum Upload Speed (KiB/s)', '${escape(_("Maximum Upload Speed (KiB/s)"))}') -// Deluge.MoveStorage.js:57 +// MoveStorage.js:56 GetText.add('Move', '${escape(_("Move"))}') -// Deluge.Details.Options.js:262 +// OptionsTab.js:262 GetText.add('Move Completed', '${escape(_("Move Completed"))}') -// Deluge.Menus.js:242, Deluge.MoveStorage.js:39 +// Menus.js:242, MoveStorage.js:38 GetText.add('Move Storage', '${escape(_("Move Storage"))}') -// Deluge.Preferences.Downloads.js:72 +// DownloadsPage.js:75 GetText.add('Move completed to', '${escape(_("Move completed to"))}') -// Deluge.Preferences.Network.js:209 +// NetworkPage.js:205 GetText.add('NAT-PMP', '${escape(_("NAT-PMP"))}') -// Deluge.Torrents.js:124 +// TorrentGrid.js:116, DetailsTab.js:46 GetText.add('Name', '${escape(_("Name"))}') -// Deluge.Preferences.Network.js:40 +// NetworkPage.js:42 GetText.add('Network', '${escape(_("Network"))}') -// Deluge.Preferences.Network.js:192 +// NetworkPage.js:188 GetText.add('Network Extras', '${escape(_("Network Extras"))}') -// Deluge.Preferences.Network.js:161 +// NetworkPage.js:157 GetText.add('Network Interface', '${escape(_("Network Interface"))}') -// Deluge.Preferences.Interface.js:102 +// InterfacePage.js:101 GetText.add('New Password', '${escape(_("New Password"))}') -// Deluge.Preferences.Proxy.js:57 +// ProxyField.js:55 GetText.add('None', '${escape(_("None"))}') -// Deluge.Menus.js:415, Deluge.js:108 +// Menus.js:262, Deluge.js:157 GetText.add('Normal Priority', '${escape(_("Normal Priority"))}') -// Deluge.Statusbar.js:7 +// Statusbar.js:39 GetText.add('Not Connected', '${escape(_("Not Connected"))}') -// Deluge.Add.js:542 +// AddWindow.js:210 GetText.add('Not a valid torrent', '${escape(_("Not a valid torrent"))}') -// Deluge.Preferences.Notification.js:1 -GetText.add('Notification', '${escape(_("Notification"))}') - -// Deluge.ConnectionManager.js:280, Deluge.ConnectionManager.js:288 +// ConnectionManager.js:180, ConnectionManager.js:188 GetText.add('Offline', '${escape(_("Offline"))}') -// Deluge.EditTrackers.js:179, Deluge.Preferences.js:92 +// EditTrackersWindow.js:57, OtherLimitWindow.js:73, PreferencesWindow.js:108 GetText.add('Ok', '${escape(_("Ok"))}') -// Deluge.Preferences.Interface.js:98 +// InterfacePage.js:97 GetText.add('Old Password', '${escape(_("Old Password"))}') -// Deluge.Add.js:85, Deluge.Menus.js:105, Deluge.Details.Options.js:50, Deluge.Preferences.Downloads.js:125 +// Menus.js:99, OptionsTab.js:49, OptionsTab.js:40, DownloadsPage.js:129 GetText.add('Options', '${escape(_("Options"))}') -// Deluge.Menus.js:301, Deluge.Menus.js:348, Deluge.Menus.js:395, Deluge.Preferences.Daemon.js:88, Deluge.Preferences.Other.js:39 +// Statusbar.js:90, Statusbar.js:138, Statusbar.js:186, OtherPage.js:42, DaemonPage.js:84 GetText.add('Other', '${escape(_("Other"))}') -// Deluge.Preferences.Encryption.js:74 +// EncryptionPage.js:74 GetText.add('Outbound', '${escape(_("Outbound"))}') -// Deluge.Preferences.Network.js:108 +// NetworkPage.js:104 GetText.add('Outgoing Ports', '${escape(_("Outgoing Ports"))}') -// Deluge.ConnectionManager.js:109, Deluge.Preferences.Interface.js:85, Deluge.Preferences.Interface.js:217, Deluge.Preferences.Proxy.js:100, Deluge.Login.js:75 +// TorrentGrid.js:207 +GetText.add('Owner', '${escape(_("Owner"))}') + +// AddConnectionWindow.js:88, LoginWindow.js:70, ProxyField.js:95, InterfacePage.js:84, InterfacePage.js:214 GetText.add('Password', '${escape(_("Password"))}') -// Deluge.Toolbar.js:65, Deluge.Menus.js:93 +// DetailsTab.js:48 +GetText.add('Path', '${escape(_("Path"))}') + +// Menus.js:88, Toolbar.js:70 GetText.add('Pause', '${escape(_("Pause"))}') -// Deluge.Preferences.Proxy.js:184 +// ProxyPage.js:52 GetText.add('Peer', '${escape(_("Peer"))}') -// Deluge.Preferences.Network.js:216 +// NetworkPage.js:212 GetText.add('Peer Exchange', '${escape(_("Peer Exchange"))}') -// Deluge.Preferences.Network.js:185 +// NetworkPage.js:181 GetText.add('Peer TOS Byte', '${escape(_("Peer TOS Byte"))}') -// Deluge.Details.Peers.js:64, Deluge.Torrents.js:148 +// TorrentGrid.js:141, TorrentGrid.js:255, PeersTab.js:61 GetText.add('Peers', '${escape(_("Peers"))}') -// Deluge.Preferences.Bandwidth.js:158 +// BandwidthPage.js:135 GetText.add('Per Torrent Bandwidth Usage', '${escape(_("Per Torrent Bandwidth Usage"))}') -// Deluge.Preferences.Daemon.js:97 +// DaemonPage.js:93 GetText.add('Periodically check the website for new releases', '${escape(_("Periodically check the website for new releases"))}') -// Deluge.Preferences.Plugins.js:164 +// PluginsPage.js:92 GetText.add('Plugin', '${escape(_("Plugin"))}') -// Deluge.Preferences.Plugins.js:71 +// InstallPluginWindow.js:66 GetText.add('Plugin Egg', '${escape(_("Plugin Egg"))}') -// Deluge.Preferences.Plugins.js:113 +// PluginsPage.js:41 GetText.add('Plugins', '${escape(_("Plugins"))}') -// Deluge.ConnectionManager.js:85, Deluge.Preferences.Interface.js:151, Deluge.Preferences.Proxy.js:80, Deluge.Preferences.Daemon.js:53 +// AddConnectionWindow.js:72, ProxyField.js:78, DaemonPage.js:52, InterfacePage.js:147 GetText.add('Port', '${escape(_("Port"))}') -// Deluge.Toolbar.js:92, Deluge.Preferences.js:50 +// QueuePage.js:114 +GetText.add('Prefer Seeding over Downloading', '${escape(_("Prefer Seeding over Downloading"))}') + +// Toolbar.js:94, PreferencesWindow.js:47 GetText.add('Preferences', '${escape(_("Preferences"))}') -// Deluge.Details.Options.js:296 +// OptionsTab.js:308 GetText.add('Prioritize First/Last', '${escape(_("Prioritize First/Last"))}') -// Deluge.Add.js:190 +// OptionsTab.js:150 GetText.add('Prioritize First/Last Pieces', '${escape(_("Prioritize First/Last Pieces"))}') -// Deluge.Preferences.Downloads.js:136 +// DownloadsPage.js:140 GetText.add('Prioritize first and last pieces of torrent', '${escape(_("Prioritize first and last pieces of torrent"))}') -// Deluge.Details.Files.js:67 +// FilesTab.js:60 GetText.add('Priority', '${escape(_("Priority"))}') -// Deluge.Details.Options.js:288 +// OptionsTab.js:300 GetText.add('Private', '${escape(_("Private"))}') -// Deluge.Preferences.Interface.js:173 +// InterfacePage.js:166 GetText.add('Private Key', '${escape(_("Private Key"))}') -// Deluge.Details.Files.js:62, Deluge.Torrents.js:136 +// TorrentGrid.js:128, FilesTab.js:52 GetText.add('Progress', '${escape(_("Progress"))}') -// Deluge.Statusbar.js:46 +// Statusbar.js:200 GetText.add('Protocol Traffic Download/Upload', '${escape(_("Protocol Traffic Download/Upload"))}') -// Deluge.Preferences.Proxy.js:175 +// ProxyPage.js:42 GetText.add('Proxy', '${escape(_("Proxy"))}') -// Deluge.Preferences.Queue.js:39, Deluge.Menus.js:187, Deluge.Details.Options.js:196 +// TorrentGrid.js:213 +GetText.add('Public', '${escape(_("Public"))}') + +// Menus.js:186, OptionsTab.js:196, QueuePage.js:41 GetText.add('Queue', '${escape(_("Queue"))}') -// Deluge.Preferences.Queue.js:63 +// QueuePage.js:62 GetText.add('Queue new torrents to top', '${escape(_("Queue new torrents to top"))}') -// Deluge.Preferences.Bandwidth.js:152 +// BandwidthPage.js:129 GetText.add('Rate limit IP overhead', '${escape(_("Rate limit IP overhead"))}') -// Deluge.Torrents.js:172 +// TorrentGrid.js:166 GetText.add('Ratio', '${escape(_("Ratio"))}') -// Deluge.ConnectionManager.js:229, Deluge.Toolbar.js:58, Deluge.Add.js:450, Deluge.EditTrackers.js:249 +// EditTrackersWindow.js:122, ConnectionManager.js:107, Toolbar.js:64, AddWindow.js:112 GetText.add('Remove', '${escape(_("Remove"))}') -// Deluge.Menus.js:230, Deluge.Remove.js:38, Deluge.Remove.js:55 +// Menus.js:230, RemoveWindow.js:39, RemoveWindow.js:57 GetText.add('Remove Torrent', '${escape(_("Remove Torrent"))}') -// Deluge.Remove.js:54 +// RemoveWindow.js:56 GetText.add('Remove With Data', '${escape(_("Remove With Data"))}') -// Deluge.Details.Options.js:253 +// OptionsTab.js:253 GetText.add('Remove at ratio', '${escape(_("Remove at ratio"))}') -// Deluge.Preferences.Queue.js:209 +// QueuePage.js:198 GetText.add('Remove torrent when share ratio is reached', '${escape(_("Remove torrent when share ratio is reached"))}') -// Deluge.Toolbar.js:72, Deluge.Menus.js:99 +// Menus.js:94, Toolbar.js:76 GetText.add('Resume', '${escape(_("Resume"))}') -// Deluge.EditTrackers.js:117 +// EditTrackerWindow.js:57 GetText.add('Save', '${escape(_("Save"))}') -// Deluge.Preferences.Queue.js:154 +// TorrentGrid.js:200 +GetText.add('Save Path', '${escape(_("Save Path"))}') + +// QueuePage.js:149 GetText.add('Seed Time (m)', '${escape(_("Seed Time (m)"))}') -// Deluge.Torrents.js:142 +// TorrentGrid.js:134, TorrentGrid.js:255 GetText.add('Seeders', '${escape(_("Seeders"))}') -// Deluge.Preferences.Queue.js:123 +// QueuePage.js:120 GetText.add('Seeding', '${escape(_("Seeding"))}') -// Deluge.Add.File.js:66 +// FileWindow.js:66 GetText.add('Select a torrent', '${escape(_("Select a torrent"))}') -// Deluge.Preferences.Plugins.js:70 +// InstallPluginWindow.js:65 GetText.add('Select an egg', '${escape(_("Select an egg"))}') -// Deluge.Preferences.Interface.js:130 +// InterfacePage.js:129 GetText.add('Server', '${escape(_("Server"))}') -// Deluge.Preferences.Interface.js:141 +// InterfacePage.js:140 GetText.add('Session Timeout', '${escape(_("Session Timeout"))}') -// Deluge.Preferences.Cache.js:53, Deluge.Preferences.Encryption.js:53 +// Statusbar.js:96 +GetText.add('Set Maximum Connections', '${escape(_("Set Maximum Connections"))}') + +// Statusbar.js:143 +GetText.add('Set Maximum Download Speed', '${escape(_("Set Maximum Download Speed"))}') + +// Statusbar.js:191 +GetText.add('Set Maximum Upload Speed', '${escape(_("Set Maximum Upload Speed"))}') + +// EncryptionPage.js:51, CachePage.js:52 GetText.add('Settings', '${escape(_("Settings"))}') -// Deluge.Preferences.Queue.js:130 +// QueuePage.js:127 GetText.add('Share Ratio Limit', '${escape(_("Share Ratio Limit"))}') -// Deluge.Preferences.Queue.js:142 +// QueuePage.js:138 GetText.add('Share Time Ratio', '${escape(_("Share Time Ratio"))}') -// Deluge.Preferences.Interface.js:72 +// TorrentGrid.js:220 +GetText.add('Shared', '${escape(_("Shared"))}') + +// InterfacePage.js:71 GetText.add('Show filters with zero torrents', '${escape(_("Show filters with zero torrents"))}') -// Deluge.Preferences.Interface.js:65 +// InterfacePage.js:64 GetText.add('Show session speed in titlebar', '${escape(_("Show session speed in titlebar"))}') -// Deluge.Preferences.Interface.js:79 -GetText.add('Show trackers with zero torrents', '${escape(_("Show trackers with zero torrents"))}') - -// Deluge.Add.js:67, Deluge.Details.Files.js:57, Deluge.Torrents.js:130 +// TorrentGrid.js:122, FilesTab.js:44, FilesTab.js:54 GetText.add('Size', '${escape(_("Size"))}') -// Deluge.Preferences.Proxy.js:58 +// ProxyField.js:56 GetText.add('Socksv4', '${escape(_("Socksv4"))}') -// Deluge.Preferences.Proxy.js:59 +// ProxyField.js:57 GetText.add('Socksv5', '${escape(_("Socksv5"))}') -// Deluge.Preferences.Proxy.js:60 +// ProxyField.js:58 GetText.add('Socksv5 with Auth', '${escape(_("Socksv5 with Auth"))}') -// Deluge.ConnectionManager.js:291 +// ConnectionManager.js:191 GetText.add('Start Daemon', '${escape(_("Start Daemon"))}') -// Deluge.Sidebar.js:37 +// Sidebar.js:34 GetText.add('State', '${escape(_("State"))}') -// Deluge.ConnectionManager.js:186, Deluge.Details.Status.js:35 +// ConnectionManager.js:68, StatusTab.js:39, DetailsTab.js:52 GetText.add('Status', '${escape(_("Status"))}') -// Deluge.ConnectionManager.js:237, Deluge.ConnectionManager.js:297, Deluge.ConnectionManager.js:415 +// ConnectionManager.js:115, ConnectionManager.js:197, ConnectionManager.js:328 GetText.add('Stop Daemon', '${escape(_("Stop Daemon"))}') -// Deluge.Details.Options.js:225 +// OptionsTab.js:225 GetText.add('Stop seed at ratio', '${escape(_("Stop seed at ratio"))}') -// Deluge.Preferences.Queue.js:183 +// QueuePage.js:175 GetText.add('Stop seeding when share ratio reaches:', '${escape(_("Stop seeding when share ratio reaches:"))}') -// Deluge.Preferences.Other.js:69 +// OtherPage.js:72 GetText.add('System Information', '${escape(_("System Information"))}') -// Deluge.Preferences.Network.js:177 +// NetworkPage.js:173 GetText.add('TOS', '${escape(_("TOS"))}') -// Deluge.EditTrackers.js:198 +// EditTrackersWindow.js:76 GetText.add('Tier', '${escape(_("Tier"))}') -// Deluge.Menus.js:192 +// Menus.js:192 GetText.add('Top', '${escape(_("Top"))}') -// Deluge.Preferences.Queue.js:77 +// QueuePage.js:76 GetText.add('Total Active', '${escape(_("Total Active"))}') -// Deluge.Preferences.Queue.js:89 +// QueuePage.js:85 GetText.add('Total Active Downloading', '${escape(_("Total Active Downloading"))}') -// Deluge.Preferences.Queue.js:101 +// QueuePage.js:94 GetText.add('Total Active Seeding', '${escape(_("Total Active Seeding"))}') -// Deluge.Preferences.Proxy.js:196, Deluge.Torrents.js:190, Deluge.EditTrackers.js:126, Deluge.EditTrackers.js:205 +// DetailsTab.js:49 +GetText.add('Total Size', '${escape(_("Total Size"))}') + +// EditTrackersWindow.js:80, TorrentGrid.js:193, EditTrackerWindow.js:66, DetailsTab.js:53, ProxyPage.js:64 GetText.add('Tracker', '${escape(_("Tracker"))}') -// Deluge.Sidebar.js:38 +// Sidebar.js:35 GetText.add('Tracker Host', '${escape(_("Tracker Host"))}') -// Deluge.EditTrackers.js:67 +// AddTrackerWindow.js:66 GetText.add('Trackers', '${escape(_("Trackers"))}') -// Deluge.Preferences.Proxy.js:50 +// ProxyField.js:48 GetText.add('Type', '${escape(_("Type"))}') -// Deluge.Menus.js:127 +// Menus.js:123 GetText.add('U/L Speed Limit', '${escape(_("U/L Speed Limit"))}') -// Deluge.Preferences.Network.js:203 +// NetworkPage.js:199 GetText.add('UPnP', '${escape(_("UPnP"))}') -// Deluge.Menus.js:123, Deluge.Menus.js:141, Deluge.Menus.js:159, Deluge.Menus.js:177, Deluge.Menus.js:295, Deluge.Menus.js:342, Deluge.Menus.js:389 +// OptionsPanel.js:142 +GetText.add('Unable to set file priority!', '${escape(_("Unable to set file priority!"))}') + +// Statusbar.js:85, Statusbar.js:133, Statusbar.js:181, Menus.js:119, Menus.js:138, Menus.js:157, Menus.js:176 GetText.add('Unlimited', '${escape(_("Unlimited"))}') -// Deluge.Toolbar.js:79, Deluge.Menus.js:198, Deluge.EditTrackers.js:225 +// EditTrackersWindow.js:102, Menus.js:198, Toolbar.js:83, FileBrowser.js:53 GetText.add('Up', '${escape(_("Up"))}') -// Deluge.Torrents.js:160 +// TorrentGrid.js:248 +GetText.add('Up Limit', '${escape(_("Up Limit"))}') + +// TorrentGrid.js:154 GetText.add('Up Speed', '${escape(_("Up Speed"))}') -// Deluge.Menus.js:218 +// Menus.js:218 GetText.add('Update Tracker', '${escape(_("Update Tracker"))}') -// Deluge.Preferences.Other.js:53 +// OtherPage.js:56 GetText.add('Updates', '${escape(_("Updates"))}') -// Deluge.Menus.js:163 +// Menus.js:161 GetText.add('Upload Slot Limit', '${escape(_("Upload Slot Limit"))}') -// Deluge.Statusbar.js:39 +// Statusbar.js:152 GetText.add('Upload Speed', '${escape(_("Upload Speed"))}') -// Deluge.Preferences.Plugins.js:83 +// TorrentGrid.js:234 +GetText.add('Uploaded', '${escape(_("Uploaded"))}') + +// InstallPluginWindow.js:78 GetText.add('Uploading your plugin...', '${escape(_("Uploading your plugin..."))}') -// Deluge.Add.File.js:81 +// FileWindow.js:82 GetText.add('Uploading your torrent...', '${escape(_("Uploading your torrent..."))}') -// Deluge.Add.Url.js:65, Deluge.Add.js:437 +// UrlWindow.js:60, AddWindow.js:102 GetText.add('Url', '${escape(_("Url"))}') -// Deluge.Preferences.Downloads.js:117 +// DownloadsPage.js:121 GetText.add('Use Compact', '${escape(_("Use Compact"))}') -// Deluge.Preferences.Downloads.js:114 +// DownloadsPage.js:118 GetText.add('Use Full', '${escape(_("Use Full"))}') -// Deluge.Preferences.Network.js:62, Deluge.Preferences.Network.js:117 +// NetworkPage.js:60, NetworkPage.js:113 GetText.add('Use Random Ports', '${escape(_("Use Random Ports"))}') -// Deluge.Preferences.Interface.js:165 +// InterfacePage.js:158 GetText.add('Use SSL (paths relative to Deluge config folder)', '${escape(_("Use SSL (paths relative to Deluge config folder)"))}') -// Deluge.ConnectionManager.js:101, Deluge.Preferences.Proxy.js:93 +// AddConnectionWindow.js:83, ProxyField.js:88 GetText.add('Username', '${escape(_("Username"))}') -// Deluge.ConnectionManager.js:199 +// ConnectionManager.js:80 GetText.add('Version', '${escape(_("Version"))}') -// Deluge.Preferences.Proxy.js:190 +// ProxyPage.js:58 GetText.add('Web Seed', '${escape(_("Web Seed"))}') -// Deluge.Preferences.Other.js:87 +// OtherPage.js:90 GetText.add('Yes, please send anonymous statistics', '${escape(_("Yes, please send anonymous statistics"))}') -// Deluge.Login.js:140 +// LoginWindow.js:131 GetText.add('You entered an incorrect password', '${escape(_("You entered an incorrect password"))}') -// Deluge.Preferences.Interface.js:218 +// InterfacePage.js:215 GetText.add('Your old password was incorrect!', '${escape(_("Your old password was incorrect!"))}') -// Deluge.Preferences.Interface.js:228 +// InterfacePage.js:225 GetText.add('Your password was successfully changed!', '${escape(_("Your password was successfully changed!"))}') -// Deluge.Preferences.Interface.js:203 +// InterfacePage.js:200 GetText.add('Your passwords don\'t match!', '${escape(_("Your passwords don\'t match!"))}') - diff --git a/deluge/ui/web/icons/readme.txt b/deluge/ui/web/icons/readme.txt deleted file mode 100644 index 66049b810..000000000 --- a/deluge/ui/web/icons/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -images from the fruge icon set. -See LICENSE for a list of icons not taken from fruge. diff --git a/deluge/ui/web/images/debugerror.png b/deluge/ui/web/images/debugerror.png Binary files differdeleted file mode 100644 index fedb1a724..000000000 --- a/deluge/ui/web/images/debugerror.png +++ /dev/null diff --git a/deluge/ui/web/images/deluge-icon.png b/deluge/ui/web/images/deluge-icon.png Binary files differdeleted file mode 100644 index e39cd0c7e..000000000 --- a/deluge/ui/web/images/deluge-icon.png +++ /dev/null diff --git a/deluge/ui/web/images/deluge16.png b/deluge/ui/web/images/deluge16.png Binary files differdeleted file mode 100644 index e39cd0c7e..000000000 --- a/deluge/ui/web/images/deluge16.png +++ /dev/null diff --git a/deluge/ui/web/images/deluge32.png b/deluge/ui/web/images/deluge32.png Binary files differdeleted file mode 100644 index 2d272f2ea..000000000 --- a/deluge/ui/web/images/deluge32.png +++ /dev/null diff --git a/deluge/ui/web/images/deluge_icon.gif b/deluge/ui/web/images/deluge_icon.gif Binary files differdeleted file mode 100644 index f00149312..000000000 --- a/deluge/ui/web/images/deluge_icon.gif +++ /dev/null diff --git a/deluge/ui/web/js/deluge-all-debug.js b/deluge/ui/web/js/deluge-all-debug.js index 390f3f970..9a18fedf6 100644 --- a/deluge/ui/web/js/deluge-all-debug.js +++ b/deluge/ui/web/js/deluge-all-debug.js @@ -1,6 +1,6 @@ /*! * Deluge.data.SortTypes.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -39,7 +39,7 @@ Ext.namespace('Deluge.data'); * * @class Deluge.data.SortTypes * @singleton - */ + */ Deluge.data.SortTypes = { asIPAddress: function(value) { var d = value.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/); @@ -48,6 +48,10 @@ Deluge.data.SortTypes = { asQueuePosition: function(value) { return (value > -1) ? value : Number.MAX_VALUE; + }, + + asName: function(value) { + return String(value).toLowerCase(); } } /*! @@ -121,7 +125,7 @@ Deluge.data.Peer = Ext.data.Record.create([ ]); /*! * Deluge.data.TorrentRecord.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -168,7 +172,8 @@ Deluge.data.Torrent = Ext.data.Record.create([{ type: 'int' }, { name: 'name', - type: 'string' + type: 'string', + sortType: Deluge.data.SortTypes.asName }, { name: 'total_size', type: 'int' @@ -349,7 +354,7 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, { title: _('Details'), fields: {}, - + autoScroll: true, queuedItems: {}, oldData: {}, @@ -428,7 +433,7 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, { }); /*! * Deluge.details.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -457,12 +462,11 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, { * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ - + Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { title: _('Files'), - autoScroll: true, rootVisible: false, columns: [{ @@ -502,7 +506,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { } }) }], - + selModel: new Ext.tree.MultiSelectionModel(), initComponent: function() { @@ -558,7 +562,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { this.clear(); this.torrentId = torrentId; } - + deluge.client.web.get_torrent_files(torrentId, { success: this.onRequestComplete, scope: this, @@ -591,7 +595,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { folderSort: true }); }, - + onContextMenu: function(node, e) { e.stopEvent(); var selModel = this.getSelectionModel(); @@ -601,7 +605,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { } deluge.menus.filePriorities.showAt(e.getPoint()); }, - + onItemClick: function(baseItem, e) { switch (baseItem.id) { case 'expandAll': @@ -628,7 +632,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { return; } }); - + var priorities = new Array(Ext.keys(indexes).length); for (var index in indexes) { priorities[index] = indexes[index]; @@ -645,7 +649,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { break; } }, - + onRequestComplete: function(files, options) { if (!this.getRootNode().hasChildNodes()) { this.createFileTree(files); @@ -1127,7 +1131,7 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { if (!value.replace(' ', '').replace(' ', '')){ return ''; } - return String.format('<img src="flag/{0}" />', value); + return String.format('<img src="{0}flag/{1}" />', deluge.config.base, value); } function peerAddressRenderer(value, p, record) { var seed = (record.data['seed'] == 1024) ? 'x-deluge-seed' : 'x-deluge-peer'; @@ -1544,6 +1548,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, { }, { text: _('Infohash'), iconCls: 'icon-add-magnet', + hidden: true, disabled: true }, '->', { text: _('Remove'), @@ -1783,7 +1788,7 @@ Deluge.add.FileWindow = Ext.extend(Deluge.add.Window, { }); /*! * Deluge.add.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -1823,7 +1828,7 @@ Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { layout: 'fit', title: _('Files'), - autoScroll: true, + autoScroll: false, animate: false, border: false, disabled: true, @@ -2099,7 +2104,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, { }); /*! * Deluge.add.OptionsPanel.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -2166,7 +2171,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { width: 400, labelSeparator: '' })); - + var panel = this.add({ border: false, layout: 'column', @@ -2177,7 +2182,6 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { border: false, autoHeight: true, defaultType: 'radio', - width: 100 }); this.optionsManager.bind('compact_allocation', fieldset.add({ @@ -2185,6 +2189,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { columns: 1, vertical: true, labelSeparator: '', + width: 80, items: [{ name: 'compact_allocation', value: false, @@ -2206,35 +2211,32 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { title: _('Bandwidth'), border: false, autoHeight: true, - labelWidth: 100, + bodyStyle: 'margin-left: 7px', + labelWidth: 105, width: 200, defaultType: 'spinnerfield' }); this.optionsManager.bind('max_download_speed', fieldset.add({ fieldLabel: _('Max Down Speed'), - labelStyle: 'margin-left: 10px', name: 'max_download_speed', width: 60 })); this.optionsManager.bind('max_upload_speed', fieldset.add({ fieldLabel: _('Max Up Speed'), - labelStyle: 'margin-left: 10px', name: 'max_upload_speed', width: 60 })); this.optionsManager.bind('max_connections', fieldset.add({ fieldLabel: _('Max Connections'), - labelStyle: 'margin-left: 10px', name: 'max_connections', width: 60 })); this.optionsManager.bind('max_upload_slots', fieldset.add({ fieldLabel: _('Max Upload Slots'), - labelStyle: 'margin-left: 10px', name: 'max_upload_slots', width: 60 })); - + fieldset = panel.add({ title: _('General'), border: false, @@ -2364,7 +2366,7 @@ Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, { var cookies = this.cookieField.getValue(); var torrentId = this.createTorrentId(); - if (url.substring(0,20) == 'magnet:?xt=urn:btih:') { + if (url.indexOf('magnet:?') == 0 && url.indexOf('xt=urn:btih') > -1) { deluge.client.web.get_magnet_info(url, { success: this.onGotInfo, scope: this, @@ -4392,7 +4394,7 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { }); /*! * Deluge.preferences.ProxyPage.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -4432,11 +4434,12 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { config = Ext.apply({ border: false, title: _('Proxy'), - layout: 'form' + layout: 'form', + autoScroll: true }, config); Deluge.preferences.Proxy.superclass.constructor.call(this, config); }, - + initComponent: function() { Deluge.preferences.Proxy.superclass.initComponent.call(this); this.peer = this.add(new Deluge.preferences.ProxyField({ @@ -4444,28 +4447,28 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { name: 'peer' })); this.peer.on('change', this.onProxyChange, this); - + this.web_seed = this.add(new Deluge.preferences.ProxyField({ title: _('Web Seed'), name: 'web_seed' })); this.web_seed.on('change', this.onProxyChange, this); - + this.tracker = this.add(new Deluge.preferences.ProxyField({ title: _('Tracker'), name: 'tracker' })); this.tracker.on('change', this.onProxyChange, this); - + this.dht = this.add(new Deluge.preferences.ProxyField({ title: _('DHT'), name: 'dht' })); this.dht.on('change', this.onProxyChange, this); - + deluge.preferences.getOptionsManager().bind('proxies', this); }, - + getValue: function() { return { 'dht': this.dht.getValue(), @@ -4474,18 +4477,18 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { 'web_seed': this.web_seed.getValue() } }, - + setValue: function(value) { for (var proxy in value) { this[proxy].setValue(value[proxy]); } }, - + onProxyChange: function(field, newValue, oldValue) { var newValues = this.getValue(); var oldValues = Ext.apply({}, newValues); oldValues[field.getName()] = oldValue; - + this.fireEvent('change', this, newValues, oldValues); } }); @@ -5343,20 +5346,20 @@ Ext.namespace('Ext.ux.util'); Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { _components: [], - + _methods: [], - + _requests: {}, - + _url: null, - + _optionKeys: ['scope', 'success', 'failure'], - + constructor: function(config) { Ext.ux.util.RpcClient.superclass.constructor.call(this, config); this._url = config.url || null; this._id = 0; - + this.addEvents( // raw events /** @@ -5365,16 +5368,13 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { * @param {Ext.ux.util.RpcClient} this */ 'connected', - + 'error' ); this.reloadMethods(); }, - + reloadMethods: function() { - Ext.each(this._components, function(component) { - delete this[component]; - }, this); this._execute('system.listMethods', { success: this._setMethods, scope: this @@ -5385,14 +5385,14 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { options = options || {}; options.params = options.params || []; options.id = this._id; - + var request = Ext.encode({ method: method, params: options.params, id: options.id }); this._id++; - + return Ext.Ajax.request({ url: this._url, method: 'POST', @@ -5403,7 +5403,7 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { options: options }); }, - + _onFailure: function(response, requestOptions) { var options = requestOptions.options; errorObj = { @@ -5414,23 +5414,23 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { code: 255 } } - + this.fireEvent('error', errorObj, response, requestOptions) - + if (Ext.type(options.failure) != 'function') return; if (options.scope) { options.failure.call(options.scope, errorObj, response, requestOptions); } else { options.failure(errorObj, response, requestOptions); - } + } }, - + _onSuccess: function(response, requestOptions) { var responseObj = Ext.decode(response.responseText); var options = requestOptions.options; if (responseObj.error) { this.fireEvent('error', responseObj, response, requestOptions); - + if (Ext.type(options.failure) != 'function') return; if (options.scope) { options.failure.call(options.scope, responseObj, response, requestOptions); @@ -5446,21 +5446,21 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { } } }, - + _parseArgs: function(args) { var params = []; Ext.each(args, function(arg) { params.push(arg); }); - + var options = params[params.length - 1]; if (Ext.type(options) == 'object') { var keys = Ext.keys(options), isOption = false; - + Ext.each(this._optionKeys, function(key) { if (keys.indexOf(key) > -1) isOption = true; }); - + if (isOption) { params.remove(options) } else { @@ -5475,11 +5475,11 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { _setMethods: function(methods) { var components = {}, self = this; - + Ext.each(methods, function(method) { var parts = method.split('.'); var component = components[parts[0]] || {}; - + var fn = function() { var options = self._parseArgs(arguments); return self._execute(method, options); @@ -5487,11 +5487,15 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { component[parts[1]] = fn; components[parts[0]] = component; }); - + for (var name in components) { self[name] = components[name]; } - + Ext.each(this._components, function(component) { + if (!component in components) { + delete this[component]; + } + }, this); this._components = Ext.keys(components); this.fireEvent('connected', this); } @@ -6479,13 +6483,15 @@ Deluge.EventsManager = Ext.extend(Ext.util.Observable, { }, onGetEventsSuccess: function(events) { - if (!events) return; - Ext.each(events, function(event) { - var name = event[0], args = event[1]; - args.splice(0, 0, name); - this.fireEvent.apply(this, args); - }, this); - if (this.running) this.getEvents(); + if (!this.running) return; + if (events) { + Ext.each(events, function(event) { + var name = event[0], args = event[1]; + args.splice(0, 0, name); + this.fireEvent.apply(this, args); + }, this); + } + this.getEvents(); }, // private @@ -7039,7 +7045,7 @@ Ext.each(Deluge.Keys.Grid, function(key) { }); /*! * Deluge.LoginWindow.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -7070,7 +7076,7 @@ Ext.each(Deluge.Keys.Grid, function(key) { */ Deluge.LoginWindow = Ext.extend(Ext.Window, { - + firstShow: true, bodyStyle: 'padding: 10px 5px;', buttonAlign: 'center', @@ -7084,36 +7090,39 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, { title: _('Login'), width: 300, height: 120, - + initComponent: function() { Deluge.LoginWindow.superclass.initComponent.call(this); this.on('show', this.onShow, this); - + this.addButton({ text: _('Login'), handler: this.onLogin, scope: this }); - + this.form = this.add({ xtype: 'form', baseCls: 'x-plain', - labelWidth: 55, - width: 300, - defaults: {width: 200}, + labelWidth: 120, + labelAlign: 'right', + defaults: {width: 110}, defaultType: 'textfield' }); this.passwordField = this.form.add({ xtype: 'textfield', fieldLabel: _('Password'), + grow: true, + growMin: '110', + growMax: '145', id: '_password', name: 'password', inputType: 'password' }); this.passwordField.on('specialkey', this.onSpecialKey, this); }, - + logout: function() { deluge.events.fire('logout'); deluge.client.auth.delete_session({ @@ -7123,17 +7132,17 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, { scope: this }); }, - + show: function(skipCheck) { if (this.firstShow) { deluge.client.on('error', this.onClientError, this); this.firstShow = false; } - + if (skipCheck) { return Deluge.LoginWindow.superclass.show.call(this); } - + deluge.client.auth.check_session({ success: function(result) { if (result) { @@ -7148,11 +7157,11 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, { scope: this }); }, - + onSpecialKey: function(field, e) { if (e.getKey() == 13) this.onLogin(); }, - + onLogin: function() { var passwordField = this.passwordField; deluge.client.auth.login(passwordField.getValue(), { @@ -7178,16 +7187,16 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, { scope: this }); }, - + onClientError: function(errorObj, response, requestOptions) { if (errorObj.error.code == 1) { deluge.events.fire('logout'); this.show(true); } }, - + onShow: function() { - this.passwordField.focus(true, 100); + this.passwordField.focus(true, 300); } }); /*! @@ -7290,10 +7299,12 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, '-', { text: _('Options'), iconCls: 'icon-options', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('D/L Speed Limit'), iconCls: 'x-deluge-downloading', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('5 KiB/s') @@ -7312,6 +7323,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('U/L Speed Limit'), iconCls: 'x-deluge-seeding', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('5 KiB/s') @@ -7330,6 +7342,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('Connection Limit'), iconCls: 'x-deluge-connections', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('50') @@ -7348,6 +7361,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('Upload Slot Limit'), iconCls: 'icon-upload-slots', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('0') @@ -7372,6 +7386,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, '-', { text: _('Queue'), iconCls: 'icon-queue', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ torrentAction: 'top', @@ -7956,6 +7971,7 @@ Deluge.Plugin = Ext.extend(Ext.util.Observable, { * then executes the plugins setup method, onEnabled. */ enable: function() { + deluge.client.reloadMethods(); this.fireEvent("enable", this); if (this.onEnable) this.onEnable(); }, @@ -9046,7 +9062,7 @@ Deluge.Toolbar = Ext.extend(Ext.Toolbar, { idProperty: 'id', fields: [ {name: 'queue', sortType: Deluge.data.SortTypes.asQueuePosition}, - {name: 'name'}, + {name: 'name', sortType: Deluge.data.SortTypes.asName}, {name: 'total_size', type: 'int'}, {name: 'state'}, {name: 'progress', type: 'float'}, @@ -9055,7 +9071,7 @@ Deluge.Toolbar = Ext.extend(Ext.Toolbar, { {name: 'num_peers', type: 'int'}, {name: 'total_peers', type: 'int'}, {name: 'download_payload_rate', type: 'int'}, - {name: 'upload_payload_speed', type: 'int'}, + {name: 'upload_payload_rate', type: 'int'}, {name: 'eta', type: 'int', sortType: etaSorter}, {name: 'ratio', type: 'float'}, {name: 'distributed_copies', type: 'float'}, @@ -9495,7 +9511,7 @@ deluge.ui = { }, onPluginDisabled: function(pluginName) { - deluge.plugins[pluginName].disable(); + if (deluge.plugins[pluginName]) deluge.plugins[pluginName].disable(); }, onPluginLoaded: function(options) { diff --git a/deluge/ui/web/js/deluge-all.js b/deluge/ui/web/js/deluge-all.js index 7348b402f..c06a1865c 100644 --- a/deluge/ui/web/js/deluge-all.js +++ b/deluge/ui/web/js/deluge-all.js @@ -1,6 +1,6 @@ /* * Deluge.data.SortTypes.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.data");Deluge.data.SortTypes={asIPAddress:function(a){var b=a.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/);return((((((+b[1])*256)+(+b[2]))*256)+(+b[3]))*256)+(+b[4])},asQueuePosition:function(a){return(a>-1)?a:Number.MAX_VALUE}} +Ext.namespace("Deluge.data");Deluge.data.SortTypes={asIPAddress:function(a){var b=a.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/);return((((((+b[1])*256)+(+b[2]))*256)+(+b[3]))*256)+(+b[4])},asQueuePosition:function(a){return(a>-1)?a:Number.MAX_VALUE},asName:function(a){return String(a).toLowerCase()}} /* * Deluge.data.PeerRecord.js * @@ -64,7 +64,7 @@ Ext.namespace("Deluge.data");Deluge.data.SortTypes={asIPAddress:function(a){var ;Ext.namespace("Deluge.data");Deluge.data.Peer=Ext.data.Record.create([{name:"country",type:"string"},{name:"ip",type:"string",sortType:Deluge.data.SortTypes.asIPAddress},{name:"client",type:"string"},{name:"progress",type:"float"},{name:"down_speed",type:"int"},{name:"up_speed",type:"int"},{name:"seed",type:"int"}]); /* * Deluge.data.TorrentRecord.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -93,7 +93,7 @@ Ext.namespace("Deluge.data");Deluge.data.SortTypes={asIPAddress:function(a){var * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.data");Deluge.data.Torrent=Ext.data.Record.create([{name:"queue",type:"int"},{name:"name",type:"string"},{name:"total_size",type:"int"},{name:"state",type:"string"},{name:"progress",type:"int"},{name:"num_seeds",type:"int"},{name:"total_seeds",type:"int"},{name:"num_peers",type:"int"},{name:"total_peers",type:"int"},{name:"download_payload_rate",type:"int"},{name:"upload_payload_rate",type:"int"},{name:"eta",type:"int"},{name:"ratio",type:"float"},{name:"distributed_copies",type:"float"},{name:"time_added",type:"int"},{name:"tracker_host",type:"string"}]); +Ext.namespace("Deluge.data");Deluge.data.Torrent=Ext.data.Record.create([{name:"queue",type:"int"},{name:"name",type:"string",sortType:Deluge.data.SortTypes.asName},{name:"total_size",type:"int"},{name:"state",type:"string"},{name:"progress",type:"int"},{name:"num_seeds",type:"int"},{name:"total_seeds",type:"int"},{name:"num_peers",type:"int"},{name:"total_peers",type:"int"},{name:"download_payload_rate",type:"int"},{name:"upload_payload_rate",type:"int"},{name:"eta",type:"int"},{name:"ratio",type:"float"},{name:"distributed_copies",type:"float"},{name:"time_added",type:"int"},{name:"tracker_host",type:"string"}]); /* * Deluge.details.DetailsPanel.js * @@ -125,10 +125,10 @@ Ext.namespace("Deluge.data");Deluge.data.Torrent=Ext.data.Record.create([{name:" * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.details");Deluge.details.DetailsPanel=Ext.extend(Ext.TabPanel,{id:"torrentDetails",activeTab:0,initComponent:function(){Deluge.details.DetailsPanel.superclass.initComponent.call(this);this.add(new Deluge.details.StatusTab());this.add(new Deluge.details.DetailsTab());this.add(new Deluge.details.FilesTab());this.add(new Deluge.details.PeersTab());this.add(new Deluge.details.OptionsTab())},clear:function(){this.items.each(function(a){if(a.clear){a.clear.defer(100,a);a.disable()}})},update:function(a){var b=deluge.torrents.getSelected();if(!b){this.clear();return}this.items.each(function(c){if(c.disabled){c.enable()}});a=a||this.getActiveTab();if(a.update){a.update(b.id)}},onRender:function(b,a){Deluge.details.DetailsPanel.superclass.onRender.call(this,b,a);deluge.events.on("disconnect",this.clear,this);deluge.torrents.on("rowclick",this.onTorrentsClick,this);this.on("tabchange",this.onTabChange,this);deluge.torrents.getSelectionModel().on("selectionchange",function(c){if(!c.hasSelection()){this.clear()}},this)},onTabChange:function(a,b){this.update(b)},onTorrentsClick:function(a,c,b){this.update()}});Deluge.details.DetailsTab=Ext.extend(Ext.Panel,{title:_("Details"),fields:{},queuedItems:{},oldData:{},initComponent:function(){Deluge.details.DetailsTab.superclass.initComponent.call(this);this.addItem("torrent_name",_("Name"));this.addItem("hash",_("Hash"));this.addItem("path",_("Path"));this.addItem("size",_("Total Size"));this.addItem("files",_("# of files"));this.addItem("comment",_("Comment"));this.addItem("status",_("Status"));this.addItem("tracker",_("Tracker"))},onRender:function(b,a){Deluge.details.DetailsTab.superclass.onRender.call(this,b,a);this.body.setStyle("padding","10px");this.dl=Ext.DomHelper.append(this.body,{tag:"dl"},true);for(var c in this.queuedItems){this.doAddItem(c,this.queuedItems[c])}},addItem:function(b,a){if(!this.rendered){this.queuedItems[b]=a}else{this.doAddItem(b,a)}},doAddItem:function(b,a){Ext.DomHelper.append(this.dl,{tag:"dt",cls:b,html:a+":"});this.fields[b]=Ext.DomHelper.append(this.dl,{tag:"dd",cls:b,html:""},true)},clear:function(){if(!this.fields){return}for(var a in this.fields){this.fields[a].dom.innerHTML=""}this.oldData={}},update:function(a){deluge.client.web.get_torrent_status(a,Deluge.Keys.Details,{success:this.onRequestComplete,scope:this,torrentId:a})},onRequestComplete:function(e,c,a,b){var d={torrent_name:e.name,hash:b.options.torrentId,path:e.save_path,size:fsize(e.total_size),files:e.num_files,status:e.message,tracker:e.tracker,comment:e.comment};for(var f in this.fields){if(!Ext.isDefined(d[f])){continue}if(d[f]==this.oldData[f]){continue}this.fields[f].dom.innerHTML=Ext.escapeHTML(d[f])}this.oldData=d}}); +Ext.namespace("Deluge.details");Deluge.details.DetailsPanel=Ext.extend(Ext.TabPanel,{id:"torrentDetails",activeTab:0,initComponent:function(){Deluge.details.DetailsPanel.superclass.initComponent.call(this);this.add(new Deluge.details.StatusTab());this.add(new Deluge.details.DetailsTab());this.add(new Deluge.details.FilesTab());this.add(new Deluge.details.PeersTab());this.add(new Deluge.details.OptionsTab())},clear:function(){this.items.each(function(a){if(a.clear){a.clear.defer(100,a);a.disable()}})},update:function(a){var b=deluge.torrents.getSelected();if(!b){this.clear();return}this.items.each(function(c){if(c.disabled){c.enable()}});a=a||this.getActiveTab();if(a.update){a.update(b.id)}},onRender:function(b,a){Deluge.details.DetailsPanel.superclass.onRender.call(this,b,a);deluge.events.on("disconnect",this.clear,this);deluge.torrents.on("rowclick",this.onTorrentsClick,this);this.on("tabchange",this.onTabChange,this);deluge.torrents.getSelectionModel().on("selectionchange",function(c){if(!c.hasSelection()){this.clear()}},this)},onTabChange:function(a,b){this.update(b)},onTorrentsClick:function(a,c,b){this.update()}});Deluge.details.DetailsTab=Ext.extend(Ext.Panel,{title:_("Details"),fields:{},autoScroll:true,queuedItems:{},oldData:{},initComponent:function(){Deluge.details.DetailsTab.superclass.initComponent.call(this);this.addItem("torrent_name",_("Name"));this.addItem("hash",_("Hash"));this.addItem("path",_("Path"));this.addItem("size",_("Total Size"));this.addItem("files",_("# of files"));this.addItem("comment",_("Comment"));this.addItem("status",_("Status"));this.addItem("tracker",_("Tracker"))},onRender:function(b,a){Deluge.details.DetailsTab.superclass.onRender.call(this,b,a);this.body.setStyle("padding","10px");this.dl=Ext.DomHelper.append(this.body,{tag:"dl"},true);for(var c in this.queuedItems){this.doAddItem(c,this.queuedItems[c])}},addItem:function(b,a){if(!this.rendered){this.queuedItems[b]=a}else{this.doAddItem(b,a)}},doAddItem:function(b,a){Ext.DomHelper.append(this.dl,{tag:"dt",cls:b,html:a+":"});this.fields[b]=Ext.DomHelper.append(this.dl,{tag:"dd",cls:b,html:""},true)},clear:function(){if(!this.fields){return}for(var a in this.fields){this.fields[a].dom.innerHTML=""}this.oldData={}},update:function(a){deluge.client.web.get_torrent_status(a,Deluge.Keys.Details,{success:this.onRequestComplete,scope:this,torrentId:a})},onRequestComplete:function(e,c,a,b){var d={torrent_name:e.name,hash:b.options.torrentId,path:e.save_path,size:fsize(e.total_size),files:e.num_files,status:e.message,tracker:e.tracker,comment:e.comment};for(var f in this.fields){if(!Ext.isDefined(d[f])){continue}if(d[f]==this.oldData[f]){continue}this.fields[f].dom.innerHTML=Ext.escapeHTML(d[f])}this.oldData=d}}); /* * Deluge.details.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -157,7 +157,7 @@ Ext.namespace("Deluge.details");Deluge.details.DetailsPanel=Ext.extend(Ext.TabPa * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Deluge.details.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{title:_("Files"),autoScroll:true,rootVisible:false,columns:[{header:_("Filename"),width:330,dataIndex:"filename"},{header:_("Size"),width:150,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{xtype:"tgrendercolumn",header:_("Progress"),width:150,dataIndex:"progress",renderer:function(a){var b=a*100;return Deluge.progressBar(b,this.col.width,b.toFixed(2)+"%",0)}},{header:_("Priority"),width:150,dataIndex:"priority",tpl:new Ext.XTemplate('<tpl if="!isNaN(priority)"><div class="{priority:this.getClass}">{priority:this.getName}</div></tpl>',{getClass:function(a){return FILE_PRIORITY_CSS[a]},getName:function(a){return _(FILE_PRIORITY[a])}})}],selModel:new Ext.tree.MultiSelectionModel(),initComponent:function(){Deluge.details.FilesTab.superclass.initComponent.call(this);this.setRootNode(new Ext.tree.TreeNode({text:"Files"}))},clear:function(){var a=this.getRootNode();if(!a.hasChildNodes()){return}a.cascade(function(c){var b=c.parentNode;if(!b){return}if(!b.ownerTree){return}b.removeChild(c)})},createFileTree:function(c){function b(g,d){for(var e in g.contents){var f=g.contents[e];if(f.type=="dir"){b(f,d.appendChild(new Ext.tree.TreeNode({text:e,filename:e,size:f.size,progress:f.progress,priority:f.priority})))}else{d.appendChild(new Ext.tree.TreeNode({text:e,filename:e,fileIndex:f.index,size:f.size,progress:f.progress,priority:f.priority,leaf:true,iconCls:"x-deluge-file",uiProvider:Ext.ux.tree.TreeGridNodeUI}))}}}var a=this.getRootNode();b(c,a);a.firstChild.expand()},update:function(a){if(this.torrentId!=a){this.clear();this.torrentId=a}deluge.client.web.get_torrent_files(a,{success:this.onRequestComplete,scope:this,torrentId:a})},updateFileTree:function(b){function a(g,c){for(var d in g.contents){var f=g.contents[d];var e=c.findChild("filename",d);e.attributes.size=f.size;e.attributes.progress=f.progress;e.attributes.priority=f.priority;e.ui.updateColumns();if(f.type=="dir"){a(f,e)}}}a(b,this.getRootNode())},onRender:function(b,a){Deluge.details.FilesTab.superclass.onRender.call(this,b,a);deluge.menus.filePriorities.on("itemclick",this.onItemClick,this);this.on("contextmenu",this.onContextMenu,this);this.sorter=new Ext.tree.TreeSorter(this,{folderSort:true})},onContextMenu:function(b,c){c.stopEvent();var a=this.getSelectionModel();if(a.getSelectedNodes().length<2){a.clearSelections();b.select()}deluge.menus.filePriorities.showAt(c.getPoint())},onItemClick:function(h,g){switch(h.id){case"expandAll":this.expandAll();break;default:var f={};function a(e){if(Ext.isEmpty(e.attributes.fileIndex)){return}f[e.attributes.fileIndex]=e.attributes.priority}this.getRootNode().cascade(a);var b=this.getSelectionModel().getSelectedNodes();Ext.each(b,function(i){if(!i.isLeaf()){function e(j){if(Ext.isEmpty(j.attributes.fileIndex)){return}f[j.attributes.fileIndex]=h.filePriority}i.cascade(e)}else{if(!Ext.isEmpty(i.attributes.fileIndex)){f[i.attributes.fileIndex]=h.filePriority;return}}});var d=new Array(Ext.keys(f).length);for(var c in f){d[c]=f[c]}deluge.client.core.set_torrent_file_priorities(this.torrentId,d,{success:function(){Ext.each(b,function(e){e.setColumnValue(3,h.filePriority)})},scope:this});break}},onRequestComplete:function(b,a){if(!this.getRootNode().hasChildNodes()){this.createFileTree(b)}else{this.updateFileTree(b)}}}); +Deluge.details.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{title:_("Files"),rootVisible:false,columns:[{header:_("Filename"),width:330,dataIndex:"filename"},{header:_("Size"),width:150,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{xtype:"tgrendercolumn",header:_("Progress"),width:150,dataIndex:"progress",renderer:function(a){var b=a*100;return Deluge.progressBar(b,this.col.width,b.toFixed(2)+"%",0)}},{header:_("Priority"),width:150,dataIndex:"priority",tpl:new Ext.XTemplate('<tpl if="!isNaN(priority)"><div class="{priority:this.getClass}">{priority:this.getName}</div></tpl>',{getClass:function(a){return FILE_PRIORITY_CSS[a]},getName:function(a){return _(FILE_PRIORITY[a])}})}],selModel:new Ext.tree.MultiSelectionModel(),initComponent:function(){Deluge.details.FilesTab.superclass.initComponent.call(this);this.setRootNode(new Ext.tree.TreeNode({text:"Files"}))},clear:function(){var a=this.getRootNode();if(!a.hasChildNodes()){return}a.cascade(function(c){var b=c.parentNode;if(!b){return}if(!b.ownerTree){return}b.removeChild(c)})},createFileTree:function(c){function b(g,d){for(var e in g.contents){var f=g.contents[e];if(f.type=="dir"){b(f,d.appendChild(new Ext.tree.TreeNode({text:e,filename:e,size:f.size,progress:f.progress,priority:f.priority})))}else{d.appendChild(new Ext.tree.TreeNode({text:e,filename:e,fileIndex:f.index,size:f.size,progress:f.progress,priority:f.priority,leaf:true,iconCls:"x-deluge-file",uiProvider:Ext.ux.tree.TreeGridNodeUI}))}}}var a=this.getRootNode();b(c,a);a.firstChild.expand()},update:function(a){if(this.torrentId!=a){this.clear();this.torrentId=a}deluge.client.web.get_torrent_files(a,{success:this.onRequestComplete,scope:this,torrentId:a})},updateFileTree:function(b){function a(g,c){for(var d in g.contents){var f=g.contents[d];var e=c.findChild("filename",d);e.attributes.size=f.size;e.attributes.progress=f.progress;e.attributes.priority=f.priority;e.ui.updateColumns();if(f.type=="dir"){a(f,e)}}}a(b,this.getRootNode())},onRender:function(b,a){Deluge.details.FilesTab.superclass.onRender.call(this,b,a);deluge.menus.filePriorities.on("itemclick",this.onItemClick,this);this.on("contextmenu",this.onContextMenu,this);this.sorter=new Ext.tree.TreeSorter(this,{folderSort:true})},onContextMenu:function(b,c){c.stopEvent();var a=this.getSelectionModel();if(a.getSelectedNodes().length<2){a.clearSelections();b.select()}deluge.menus.filePriorities.showAt(c.getPoint())},onItemClick:function(h,g){switch(h.id){case"expandAll":this.expandAll();break;default:var f={};function a(e){if(Ext.isEmpty(e.attributes.fileIndex)){return}f[e.attributes.fileIndex]=e.attributes.priority}this.getRootNode().cascade(a);var b=this.getSelectionModel().getSelectedNodes();Ext.each(b,function(i){if(!i.isLeaf()){function e(j){if(Ext.isEmpty(j.attributes.fileIndex)){return}f[j.attributes.fileIndex]=h.filePriority}i.cascade(e)}else{if(!Ext.isEmpty(i.attributes.fileIndex)){f[i.attributes.fileIndex]=h.filePriority;return}}});var d=new Array(Ext.keys(f).length);for(var c in f){d[c]=f[c]}deluge.client.core.set_torrent_file_priorities(this.torrentId,d,{success:function(){Ext.each(b,function(e){e.setColumnValue(3,h.filePriority)})},scope:this});break}},onRequestComplete:function(b,a){if(!this.getRootNode().hasChildNodes()){this.createFileTree(b)}else{this.updateFileTree(b)}}}); /* * Deluge.details.OptionsTab.js * @@ -221,7 +221,7 @@ Deluge.details.OptionsTab=Ext.extend(Ext.form.FormPanel,{constructor:function(a) * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -(function(){function a(d){if(!d.replace(" ","").replace(" ","")){return""}return String.format('<img src="flag/{0}" />',d)}function b(g,h,e){var d=(e.data.seed==1024)?"x-deluge-seed":"x-deluge-peer";if(peer_ip.length>2){var f=peer_ip.pop();var i=peer_ip.join(":");g="["+i+"]:"+f}return String.format('<div class="{0}">{1}</div>',d,g)}function c(e){var d=(e*100).toFixed(0);return Deluge.progressBar(d,this.width-8,d+"%")}Deluge.details.PeersTab=Ext.extend(Ext.grid.GridPanel,{peers:{},constructor:function(d){d=Ext.apply({title:_("Peers"),cls:"x-deluge-peers",store:new Ext.data.Store({reader:new Ext.data.JsonReader({idProperty:"ip",root:"peers"},Deluge.data.Peer)}),columns:[{header:" ",width:30,sortable:true,renderer:a,dataIndex:"country"},{header:"Address",width:125,sortable:true,renderer:b,dataIndex:"ip"},{header:"Client",width:125,sortable:true,renderer:fplain,dataIndex:"client"},{header:"Progress",width:150,sortable:true,renderer:c,dataIndex:"progress"},{header:"Down Speed",width:100,sortable:true,renderer:fspeed,dataIndex:"down_speed"},{header:"Up Speed",width:100,sortable:true,renderer:fspeed,dataIndex:"up_speed"}],stripeRows:true,deferredRender:false,autoScroll:true},d);Deluge.details.PeersTab.superclass.constructor.call(this,d)},clear:function(){this.getStore().removeAll();this.peers={}},update:function(d){deluge.client.web.get_torrent_status(d,Deluge.Keys.Peers,{success:this.onRequestComplete,scope:this})},onRequestComplete:function(h,g){if(!h){return}var f=this.getStore();var e=[];var i={};Ext.each(h.peers,function(m){if(this.peers[m.ip]){var j=f.getById(m.ip);j.beginEdit();for(var l in m){if(j.get(l)!=m[l]){j.set(l,m[l])}}j.endEdit()}else{this.peers[m.ip]=1;e.push(new Deluge.data.Peer(m,m.ip))}i[m.ip]=1},this);f.add(e);f.each(function(j){if(!i[j.id]){f.remove(j);delete this.peers[j.id]}},this);f.commitChanges();var d=f.getSortState();if(!d){return}f.sort(d.field,d.direction)}})})(); +(function(){function a(d){if(!d.replace(" ","").replace(" ","")){return""}return String.format('<img src="{0}flag/{1}" />',deluge.config.base,d)}function b(g,h,e){var d=(e.data.seed==1024)?"x-deluge-seed":"x-deluge-peer";if(peer_ip.length>2){var f=peer_ip.pop();var i=peer_ip.join(":");g="["+i+"]:"+f}return String.format('<div class="{0}">{1}</div>',d,g)}function c(e){var d=(e*100).toFixed(0);return Deluge.progressBar(d,this.width-8,d+"%")}Deluge.details.PeersTab=Ext.extend(Ext.grid.GridPanel,{peers:{},constructor:function(d){d=Ext.apply({title:_("Peers"),cls:"x-deluge-peers",store:new Ext.data.Store({reader:new Ext.data.JsonReader({idProperty:"ip",root:"peers"},Deluge.data.Peer)}),columns:[{header:" ",width:30,sortable:true,renderer:a,dataIndex:"country"},{header:"Address",width:125,sortable:true,renderer:b,dataIndex:"ip"},{header:"Client",width:125,sortable:true,renderer:fplain,dataIndex:"client"},{header:"Progress",width:150,sortable:true,renderer:c,dataIndex:"progress"},{header:"Down Speed",width:100,sortable:true,renderer:fspeed,dataIndex:"down_speed"},{header:"Up Speed",width:100,sortable:true,renderer:fspeed,dataIndex:"up_speed"}],stripeRows:true,deferredRender:false,autoScroll:true},d);Deluge.details.PeersTab.superclass.constructor.call(this,d)},clear:function(){this.getStore().removeAll();this.peers={}},update:function(d){deluge.client.web.get_torrent_status(d,Deluge.Keys.Peers,{success:this.onRequestComplete,scope:this})},onRequestComplete:function(h,g){if(!h){return}var f=this.getStore();var e=[];var i={};Ext.each(h.peers,function(m){if(this.peers[m.ip]){var j=f.getById(m.ip);j.beginEdit();for(var l in m){if(j.get(l)!=m[l]){j.set(l,m[l])}}j.endEdit()}else{this.peers[m.ip]=1;e.push(new Deluge.data.Peer(m,m.ip))}i[m.ip]=1},this);f.add(e);f.each(function(j){if(!i[j.id]){f.remove(j);delete this.peers[j.id]}},this);f.commitChanges();var d=f.getSortState();if(!d){return}f.sort(d.field,d.direction)}})})(); /* * Deluge.details.StatusTab.js * @@ -317,7 +317,7 @@ Ext.ns("Deluge.add");Deluge.add.Window=Ext.extend(Ext.Window,{initComponent:func * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.add");Deluge.add.AddWindow=Ext.extend(Deluge.add.Window,{title:_("Add Torrents"),layout:"border",width:470,height:450,bodyStyle:"padding: 10px 5px;",buttonAlign:"right",closeAction:"hide",closable:true,plain:true,iconCls:"x-deluge-add-window-icon",initComponent:function(){Deluge.add.AddWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("Add"),this.onAddClick,this);function a(c,d,b){if(b.data.info_hash){return String.format('<div class="x-deluge-add-torrent-name">{0}</div>',c)}else{return String.format('<div class="x-deluge-add-torrent-name-loading">{0}</div>',c)}}this.list=new Ext.list.ListView({store:new Ext.data.SimpleStore({fields:[{name:"info_hash",mapping:1},{name:"text",mapping:2}],id:0}),columns:[{id:"torrent",width:150,sortable:true,renderer:a,dataIndex:"text"}],stripeRows:true,singleSelect:true,listeners:{selectionchange:{fn:this.onSelect,scope:this}},hideHeaders:true,autoExpandColumn:"torrent",height:"100%",autoScroll:true});this.add({region:"center",items:[this.list],margins:"5 5 5 5",bbar:new Ext.Toolbar({items:[{iconCls:"x-deluge-add-file",text:_("File"),handler:this.onFile,scope:this},{text:_("Url"),iconCls:"icon-add-url",handler:this.onUrl,scope:this},{text:_("Infohash"),iconCls:"icon-add-magnet",disabled:true},"->",{text:_("Remove"),iconCls:"icon-remove",handler:this.onRemove,scope:this}]})});this.optionsPanel=this.add(new Deluge.add.OptionsPanel());this.on("hide",this.onHide,this);this.on("show",this.onShow,this)},clear:function(){this.list.getStore().removeAll();this.optionsPanel.clear()},onAddClick:function(){var a=[];if(!this.list){return}this.list.getStore().each(function(b){var c=b.get("info_hash");a.push({path:this.optionsPanel.getFilename(c),options:this.optionsPanel.getOptions(c)})},this);deluge.client.web.add_torrents(a,{success:function(b){}});this.clear();this.hide()},onCancelClick:function(){this.clear();this.hide()},onFile:function(){if(!this.file){this.file=new Deluge.add.FileWindow()}this.file.show()},onHide:function(){this.optionsPanel.setActiveTab(0);this.optionsPanel.files.setDisabled(true);this.optionsPanel.form.setDisabled(true)},onRemove:function(){if(!this.list.getSelectionCount()){return}var a=this.list.getSelectedRecords()[0];this.list.getStore().remove(a);this.optionsPanel.clear();if(this.torrents&&this.torrents[a.id]){delete this.torrents[a.id]}},onSelect:function(c,b){if(b.length){var a=this.list.getRecord(b[0]);this.optionsPanel.setTorrent(a.get("info_hash"))}else{this.optionsPanel.files.setDisabled(true);this.optionsPanel.form.setDisabled(true)}},onShow:function(){if(!this.url){this.url=new Deluge.add.UrlWindow();this.url.on("beforeadd",this.onTorrentBeforeAdd,this);this.url.on("add",this.onTorrentAdd,this)}if(!this.file){this.file=new Deluge.add.FileWindow();this.file.on("beforeadd",this.onTorrentBeforeAdd,this);this.file.on("add",this.onTorrentAdd,this)}this.optionsPanel.form.getDefaults()},onTorrentBeforeAdd:function(b,c){var a=this.list.getStore();a.loadData([[b,null,c]],true)},onTorrentAdd:function(a,c){var b=this.list.getStore().getById(a);if(!c){Ext.MessageBox.show({title:_("Error"),msg:_("Not a valid torrent"),buttons:Ext.MessageBox.OK,modal:false,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});this.list.getStore().remove(b)}else{b.set("info_hash",c.info_hash);b.set("text",c.name);this.list.getStore().commitChanges();this.optionsPanel.addTorrent(c);this.list.select(b)}},onUrl:function(a,b){this.url.show()}}); +Ext.namespace("Deluge.add");Deluge.add.AddWindow=Ext.extend(Deluge.add.Window,{title:_("Add Torrents"),layout:"border",width:470,height:450,bodyStyle:"padding: 10px 5px;",buttonAlign:"right",closeAction:"hide",closable:true,plain:true,iconCls:"x-deluge-add-window-icon",initComponent:function(){Deluge.add.AddWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("Add"),this.onAddClick,this);function a(c,d,b){if(b.data.info_hash){return String.format('<div class="x-deluge-add-torrent-name">{0}</div>',c)}else{return String.format('<div class="x-deluge-add-torrent-name-loading">{0}</div>',c)}}this.list=new Ext.list.ListView({store:new Ext.data.SimpleStore({fields:[{name:"info_hash",mapping:1},{name:"text",mapping:2}],id:0}),columns:[{id:"torrent",width:150,sortable:true,renderer:a,dataIndex:"text"}],stripeRows:true,singleSelect:true,listeners:{selectionchange:{fn:this.onSelect,scope:this}},hideHeaders:true,autoExpandColumn:"torrent",height:"100%",autoScroll:true});this.add({region:"center",items:[this.list],margins:"5 5 5 5",bbar:new Ext.Toolbar({items:[{iconCls:"x-deluge-add-file",text:_("File"),handler:this.onFile,scope:this},{text:_("Url"),iconCls:"icon-add-url",handler:this.onUrl,scope:this},{text:_("Infohash"),iconCls:"icon-add-magnet",hidden:true,disabled:true},"->",{text:_("Remove"),iconCls:"icon-remove",handler:this.onRemove,scope:this}]})});this.optionsPanel=this.add(new Deluge.add.OptionsPanel());this.on("hide",this.onHide,this);this.on("show",this.onShow,this)},clear:function(){this.list.getStore().removeAll();this.optionsPanel.clear()},onAddClick:function(){var a=[];if(!this.list){return}this.list.getStore().each(function(b){var c=b.get("info_hash");a.push({path:this.optionsPanel.getFilename(c),options:this.optionsPanel.getOptions(c)})},this);deluge.client.web.add_torrents(a,{success:function(b){}});this.clear();this.hide()},onCancelClick:function(){this.clear();this.hide()},onFile:function(){if(!this.file){this.file=new Deluge.add.FileWindow()}this.file.show()},onHide:function(){this.optionsPanel.setActiveTab(0);this.optionsPanel.files.setDisabled(true);this.optionsPanel.form.setDisabled(true)},onRemove:function(){if(!this.list.getSelectionCount()){return}var a=this.list.getSelectedRecords()[0];this.list.getStore().remove(a);this.optionsPanel.clear();if(this.torrents&&this.torrents[a.id]){delete this.torrents[a.id]}},onSelect:function(c,b){if(b.length){var a=this.list.getRecord(b[0]);this.optionsPanel.setTorrent(a.get("info_hash"))}else{this.optionsPanel.files.setDisabled(true);this.optionsPanel.form.setDisabled(true)}},onShow:function(){if(!this.url){this.url=new Deluge.add.UrlWindow();this.url.on("beforeadd",this.onTorrentBeforeAdd,this);this.url.on("add",this.onTorrentAdd,this)}if(!this.file){this.file=new Deluge.add.FileWindow();this.file.on("beforeadd",this.onTorrentBeforeAdd,this);this.file.on("add",this.onTorrentAdd,this)}this.optionsPanel.form.getDefaults()},onTorrentBeforeAdd:function(b,c){var a=this.list.getStore();a.loadData([[b,null,c]],true)},onTorrentAdd:function(a,c){var b=this.list.getStore().getById(a);if(!c){Ext.MessageBox.show({title:_("Error"),msg:_("Not a valid torrent"),buttons:Ext.MessageBox.OK,modal:false,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});this.list.getStore().remove(b)}else{b.set("info_hash",c.info_hash);b.set("text",c.name);this.list.getStore().commitChanges();this.optionsPanel.addTorrent(c);this.list.select(b)}},onUrl:function(a,b){this.url.show()}}); /* * Deluge.add.File.js * @@ -352,7 +352,7 @@ Ext.namespace("Deluge.add");Deluge.add.AddWindow=Ext.extend(Deluge.add.Window,{t Ext.ns("Deluge.add");Deluge.add.FileWindow=Ext.extend(Deluge.add.Window,{title:_("Add from File"),layout:"fit",width:350,height:115,modal:true,plain:true,buttonAlign:"center",closeAction:"hide",bodyStyle:"padding: 10px 5px;",iconCls:"x-deluge-add-file",initComponent:function(){Deluge.add.FileWindow.superclass.initComponent.call(this);this.addButton(_("Add"),this.onAddClick,this);this.form=this.add({xtype:"form",baseCls:"x-plain",labelWidth:35,autoHeight:true,fileUpload:true,items:[{xtype:"fileuploadfield",id:"torrentFile",width:280,height:24,emptyText:_("Select a torrent"),fieldLabel:_("File"),name:"file",buttonCfg:{text:_("Browse")+"..."}}]})},onAddClick:function(c,b){if(this.form.getForm().isValid()){this.torrentId=this.createTorrentId();this.form.getForm().submit({url:deluge.config.base+"upload",waitMsg:_("Uploading your torrent..."),failure:this.onUploadFailure,success:this.onUploadSuccess,scope:this});var a=this.form.getForm().findField("torrentFile").value;a=a.split("\\").slice(-1)[0];this.fireEvent("beforeadd",this.torrentId,a)}},onGotInfo:function(d,c,a,b){d.filename=b.options.filename;this.fireEvent("add",this.torrentId,d)},onUploadFailure:function(a,b){this.hide()},onUploadSuccess:function(c,b){this.hide();if(b.result.success){var a=b.result.files[0];this.form.getForm().findField("torrentFile").setValue("");deluge.client.web.get_torrent_info(a,{success:this.onGotInfo,scope:this,filename:a})}}}); /* * Deluge.add.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -381,7 +381,7 @@ Ext.ns("Deluge.add");Deluge.add.FileWindow=Ext.extend(Deluge.add.Window,{title:_ * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.ns("Deluge.add");Deluge.add.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{layout:"fit",title:_("Files"),autoScroll:true,animate:false,border:false,disabled:true,rootVisible:false,columns:[{header:_("Filename"),width:295,dataIndex:"filename"},{header:_("Size"),width:60,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{header:_("Download"),width:65,dataIndex:"download",tpl:new Ext.XTemplate("{download:this.format}",{format:function(a){return'<div rel="chkbox" class="x-grid3-check-col'+(a?"-on":"")+'"> </div>'}})}],initComponent:function(){Deluge.add.FilesTab.superclass.initComponent.call(this);this.on("click",this.onNodeClick,this)},clearFiles:function(){var a=this.getRootNode();if(!a.hasChildNodes()){return}a.cascade(function(b){if(!b.parentNode||!b.getOwnerTree()){return}b.remove()})},setDownload:function(b,c,d){b.attributes.download=c;b.ui.updateColumns();if(b.isLeaf()){if(!d){return this.fireEvent("fileschecked",[b],c,!c)}}else{var a=[b];b.cascade(function(e){e.attributes.download=c;e.ui.updateColumns();a.push(e)},this);if(!d){return this.fireEvent("fileschecked",a,c,!c)}}},onNodeClick:function(b,c){var a=new Ext.Element(c.target);if(a.getAttribute("rel")=="chkbox"){this.setDownload(b,!b.attributes.download)}}}); +Ext.ns("Deluge.add");Deluge.add.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{layout:"fit",title:_("Files"),autoScroll:false,animate:false,border:false,disabled:true,rootVisible:false,columns:[{header:_("Filename"),width:295,dataIndex:"filename"},{header:_("Size"),width:60,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{header:_("Download"),width:65,dataIndex:"download",tpl:new Ext.XTemplate("{download:this.format}",{format:function(a){return'<div rel="chkbox" class="x-grid3-check-col'+(a?"-on":"")+'"> </div>'}})}],initComponent:function(){Deluge.add.FilesTab.superclass.initComponent.call(this);this.on("click",this.onNodeClick,this)},clearFiles:function(){var a=this.getRootNode();if(!a.hasChildNodes()){return}a.cascade(function(b){if(!b.parentNode||!b.getOwnerTree()){return}b.remove()})},setDownload:function(b,c,d){b.attributes.download=c;b.ui.updateColumns();if(b.isLeaf()){if(!d){return this.fireEvent("fileschecked",[b],c,!c)}}else{var a=[b];b.cascade(function(e){e.attributes.download=c;e.ui.updateColumns();a.push(e)},this);if(!d){return this.fireEvent("fileschecked",a,c,!c)}}},onNodeClick:function(b,c){var a=new Ext.Element(c.target);if(a.getAttribute("rel")=="chkbox"){this.setDownload(b,!b.attributes.download)}}}); /* * Deluge.add.Infohash.js * @@ -448,7 +448,7 @@ Ext.namespace("Ext.deluge.add"); Ext.ns("Deluge.add");Deluge.add.OptionsPanel=Ext.extend(Ext.TabPanel,{torrents:{},region:"south",margins:"5 5 5 5",activeTab:0,height:220,initComponent:function(){Deluge.add.OptionsPanel.superclass.initComponent.call(this);this.files=this.add(new Deluge.add.FilesTab());this.form=this.add(new Deluge.add.OptionsTab());this.files.on("fileschecked",this.onFilesChecked,this)},addTorrent:function(c){this.torrents[c.info_hash]=c;var b={};this.walkFileTree(c.files_tree,function(e,g,h,f){if(g!="file"){return}b[h.index]=h.download},this);var a=[];Ext.each(Ext.keys(b),function(e){a[e]=b[e]});var d=this.form.optionsManager.changeId(c.info_hash,true);this.form.optionsManager.setDefault("file_priorities",a);this.form.optionsManager.changeId(d,true)},clear:function(){this.files.clearFiles();this.form.optionsManager.resetAll()},getFilename:function(a){return this.torrents[a]["filename"]},getOptions:function(a){var c=this.form.optionsManager.changeId(a,true);var b=this.form.optionsManager.get();this.form.optionsManager.changeId(c,true);Ext.each(b.file_priorities,function(e,d){b.file_priorities[d]=(e)?1:0});return b},setTorrent:function(b){if(!b){return}this.torrentId=b;this.form.optionsManager.changeId(b);this.files.clearFiles();var a=this.files.getRootNode();var c=this.form.optionsManager.get("file_priorities");this.form.setDisabled(false);if(this.torrents[b]["files_tree"]){this.walkFileTree(this.torrents[b]["files_tree"],function(e,f,h,d){var g=new Ext.tree.TreeNode({download:(h.index)?c[h.index]:true,filename:e,fileindex:h.index,leaf:f!="dir",size:h.length});d.appendChild(g);if(f=="dir"){return g}},this,a);a.firstChild.expand();this.files.setDisabled(false);this.files.show()}else{this.form.show();this.files.setDisabled(true)}},walkFileTree:function(g,h,e,a){for(var b in g.contents){var f=g.contents[b];var d=f.type;if(e){var c=h.apply(e,[b,d,f,a])}else{var c=h(b,d,f,a)}if(d=="dir"){this.walkFileTree(f,h,e,c)}}},onFilesChecked:function(a,c,b){if(this.form.optionsManager.get("compact_allocation")){Ext.Msg.show({title:_("Unable to set file priority!"),msg:_("File prioritization is unavailable when using Compact allocation. Would you like to switch to Full allocation?"),buttons:Ext.Msg.YESNO,fn:function(d){if(d=="yes"){this.form.optionsManager.update("compact_allocation",false);Ext.each(a,function(f){if(f.attributes.fileindex<0){return}var e=this.form.optionsManager.get("file_priorities");e[f.attributes.fileindex]=c;this.form.optionsManager.update("file_priorities",e)},this)}else{this.files.setDownload(a[0],b,true)}},scope:this,icon:Ext.MessageBox.QUESTION})}else{Ext.each(a,function(e){if(e.attributes.fileindex<0){return}var d=this.form.optionsManager.get("file_priorities");d[e.attributes.fileindex]=c;this.form.optionsManager.update("file_priorities",d)},this)}}}); /* * Deluge.add.OptionsPanel.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -477,7 +477,7 @@ Ext.ns("Deluge.add");Deluge.add.OptionsPanel=Ext.extend(Ext.TabPanel,{torrents:{ * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.ns("Deluge.add");Deluge.add.OptionsTab=Ext.extend(Ext.form.FormPanel,{title:_("Options"),height:170,border:false,bodyStyle:"padding: 5px",disabled:true,labelWidth:1,initComponent:function(){Deluge.add.OptionsTab.superclass.initComponent.call(this);this.optionsManager=new Deluge.MultiOptionsManager();var a=this.add({xtype:"fieldset",title:_("Download Location"),border:false,autoHeight:true,defaultType:"textfield",labelWidth:1,fieldLabel:"",style:"padding-bottom: 5px; margin-bottom: 0px;"});this.optionsManager.bind("download_location",a.add({fieldLabel:"",name:"download_location",width:400,labelSeparator:""}));var b=this.add({border:false,layout:"column",defaultType:"fieldset"});a=b.add({title:_("Allocation"),border:false,autoHeight:true,defaultType:"radio",width:100});this.optionsManager.bind("compact_allocation",a.add({xtype:"radiogroup",columns:1,vertical:true,labelSeparator:"",items:[{name:"compact_allocation",value:false,inputValue:false,boxLabel:_("Full"),fieldLabel:"",labelSeparator:""},{name:"compact_allocation",value:true,inputValue:true,boxLabel:_("Compact"),fieldLabel:"",labelSeparator:""}]}));a=b.add({title:_("Bandwidth"),border:false,autoHeight:true,labelWidth:100,width:200,defaultType:"spinnerfield"});this.optionsManager.bind("max_download_speed",a.add({fieldLabel:_("Max Down Speed"),labelStyle:"margin-left: 10px",name:"max_download_speed",width:60}));this.optionsManager.bind("max_upload_speed",a.add({fieldLabel:_("Max Up Speed"),labelStyle:"margin-left: 10px",name:"max_upload_speed",width:60}));this.optionsManager.bind("max_connections",a.add({fieldLabel:_("Max Connections"),labelStyle:"margin-left: 10px",name:"max_connections",width:60}));this.optionsManager.bind("max_upload_slots",a.add({fieldLabel:_("Max Upload Slots"),labelStyle:"margin-left: 10px",name:"max_upload_slots",width:60}));a=b.add({title:_("General"),border:false,autoHeight:true,defaultType:"checkbox"});this.optionsManager.bind("add_paused",a.add({name:"add_paused",boxLabel:_("Add In Paused State"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("prioritize_first_last_pieces",a.add({name:"prioritize_first_last_pieces",boxLabel:_("Prioritize First/Last Pieces"),fieldLabel:"",labelSeparator:""}))},getDefaults:function(){var a=["add_paused","compact_allocation","download_location","max_connections_per_torrent","max_download_speed_per_torrent","max_upload_slots_per_torrent","max_upload_speed_per_torrent","prioritize_first_last_pieces"];deluge.client.core.get_config_values(a,{success:function(c){var b={file_priorities:[],add_paused:c.add_paused,compact_allocation:c.compact_allocation,download_location:c.download_location,max_connections:c.max_connections_per_torrent,max_download_speed:c.max_download_speed_per_torrent,max_upload_slots:c.max_upload_slots_per_torrent,max_upload_speed:c.max_upload_speed_per_torrent,prioritize_first_last_pieces:c.prioritize_first_last_pieces};this.optionsManager.options=b;this.optionsManager.resetAll()},scope:this})}}); +Ext.ns("Deluge.add");Deluge.add.OptionsTab=Ext.extend(Ext.form.FormPanel,{title:_("Options"),height:170,border:false,bodyStyle:"padding: 5px",disabled:true,labelWidth:1,initComponent:function(){Deluge.add.OptionsTab.superclass.initComponent.call(this);this.optionsManager=new Deluge.MultiOptionsManager();var a=this.add({xtype:"fieldset",title:_("Download Location"),border:false,autoHeight:true,defaultType:"textfield",labelWidth:1,fieldLabel:"",style:"padding-bottom: 5px; margin-bottom: 0px;"});this.optionsManager.bind("download_location",a.add({fieldLabel:"",name:"download_location",width:400,labelSeparator:""}));var b=this.add({border:false,layout:"column",defaultType:"fieldset"});a=b.add({title:_("Allocation"),border:false,autoHeight:true,defaultType:"radio",});this.optionsManager.bind("compact_allocation",a.add({xtype:"radiogroup",columns:1,vertical:true,labelSeparator:"",width:80,items:[{name:"compact_allocation",value:false,inputValue:false,boxLabel:_("Full"),fieldLabel:"",labelSeparator:""},{name:"compact_allocation",value:true,inputValue:true,boxLabel:_("Compact"),fieldLabel:"",labelSeparator:""}]}));a=b.add({title:_("Bandwidth"),border:false,autoHeight:true,bodyStyle:"margin-left: 7px",labelWidth:105,width:200,defaultType:"spinnerfield"});this.optionsManager.bind("max_download_speed",a.add({fieldLabel:_("Max Down Speed"),name:"max_download_speed",width:60}));this.optionsManager.bind("max_upload_speed",a.add({fieldLabel:_("Max Up Speed"),name:"max_upload_speed",width:60}));this.optionsManager.bind("max_connections",a.add({fieldLabel:_("Max Connections"),name:"max_connections",width:60}));this.optionsManager.bind("max_upload_slots",a.add({fieldLabel:_("Max Upload Slots"),name:"max_upload_slots",width:60}));a=b.add({title:_("General"),border:false,autoHeight:true,defaultType:"checkbox"});this.optionsManager.bind("add_paused",a.add({name:"add_paused",boxLabel:_("Add In Paused State"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("prioritize_first_last_pieces",a.add({name:"prioritize_first_last_pieces",boxLabel:_("Prioritize First/Last Pieces"),fieldLabel:"",labelSeparator:""}))},getDefaults:function(){var a=["add_paused","compact_allocation","download_location","max_connections_per_torrent","max_download_speed_per_torrent","max_upload_slots_per_torrent","max_upload_speed_per_torrent","prioritize_first_last_pieces"];deluge.client.core.get_config_values(a,{success:function(c){var b={file_priorities:[],add_paused:c.add_paused,compact_allocation:c.compact_allocation,download_location:c.download_location,max_connections:c.max_connections_per_torrent,max_download_speed:c.max_download_speed_per_torrent,max_upload_slots:c.max_upload_slots_per_torrent,max_upload_speed:c.max_upload_speed_per_torrent,prioritize_first_last_pieces:c.prioritize_first_last_pieces};this.optionsManager.options=b;this.optionsManager.resetAll()},scope:this})}}); /* * Deluge.add.UrlWindow.js * @@ -509,7 +509,7 @@ Ext.ns("Deluge.add");Deluge.add.OptionsTab=Ext.extend(Ext.form.FormPanel,{title: * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.add");Deluge.add.UrlWindow=Ext.extend(Deluge.add.Window,{title:_("Add from Url"),modal:true,plain:true,layout:"fit",width:350,height:155,buttonAlign:"center",closeAction:"hide",bodyStyle:"padding: 10px 5px;",iconCls:"x-deluge-add-url-window-icon",initComponent:function(){Deluge.add.UrlWindow.superclass.initComponent.call(this);this.addButton(_("Add"),this.onAddClick,this);var a=this.add({xtype:"form",defaultType:"textfield",baseCls:"x-plain",labelWidth:55});this.urlField=a.add({fieldLabel:_("Url"),id:"url",name:"url",width:"97%"});this.urlField.on("specialkey",this.onAdd,this);this.cookieField=a.add({fieldLabel:_("Cookies"),id:"cookies",name:"cookies",width:"97%"});this.cookieField.on("specialkey",this.onAdd,this)},onAddClick:function(f,d){if((f.id=="url"||f.id=="cookies")&&d.getKey()!=d.ENTER){return}var f=this.urlField;var b=f.getValue();var c=this.cookieField.getValue();var a=this.createTorrentId();if(b.substring(0,20)=="magnet:?xt=urn:btih:"){deluge.client.web.get_magnet_info(b,{success:this.onGotInfo,scope:this,filename:b,torrentId:a})}else{deluge.client.web.download_torrent_from_url(b,c,{success:this.onDownload,scope:this,torrentId:a})}this.hide();this.urlField.setValue("");this.fireEvent("beforeadd",a,b)},onDownload:function(a,c,d,b){deluge.client.web.get_torrent_info(a,{success:this.onGotInfo,scope:this,filename:a,torrentId:b.options.torrentId})},onGotInfo:function(d,c,a,b){d.filename=b.options.filename;this.fireEvent("add",b.options.torrentId,d)}}); +Ext.namespace("Deluge.add");Deluge.add.UrlWindow=Ext.extend(Deluge.add.Window,{title:_("Add from Url"),modal:true,plain:true,layout:"fit",width:350,height:155,buttonAlign:"center",closeAction:"hide",bodyStyle:"padding: 10px 5px;",iconCls:"x-deluge-add-url-window-icon",initComponent:function(){Deluge.add.UrlWindow.superclass.initComponent.call(this);this.addButton(_("Add"),this.onAddClick,this);var a=this.add({xtype:"form",defaultType:"textfield",baseCls:"x-plain",labelWidth:55});this.urlField=a.add({fieldLabel:_("Url"),id:"url",name:"url",width:"97%"});this.urlField.on("specialkey",this.onAdd,this);this.cookieField=a.add({fieldLabel:_("Cookies"),id:"cookies",name:"cookies",width:"97%"});this.cookieField.on("specialkey",this.onAdd,this)},onAddClick:function(f,d){if((f.id=="url"||f.id=="cookies")&&d.getKey()!=d.ENTER){return}var f=this.urlField;var b=f.getValue();var c=this.cookieField.getValue();var a=this.createTorrentId();if(b.indexOf("magnet:?")==0&&b.indexOf("xt=urn:btih")>-1){deluge.client.web.get_magnet_info(b,{success:this.onGotInfo,scope:this,filename:b,torrentId:a})}else{deluge.client.web.download_torrent_from_url(b,c,{success:this.onDownload,scope:this,torrentId:a})}this.hide();this.urlField.setValue("");this.fireEvent("beforeadd",a,b)},onDownload:function(a,c,d,b){deluge.client.web.get_torrent_info(a,{success:this.onGotInfo,scope:this,filename:a,torrentId:b.options.torrentId})},onGotInfo:function(d,c,a,b){d.filename=b.options.filename;this.fireEvent("add",b.options.torrentId,d)}}); /* * Deluge.preferences.BandwidthPage.js * @@ -896,7 +896,7 @@ Ext.namespace("Deluge.preferences");PreferencesRecord=Ext.data.Record.create([{n Ext.ns("Deluge.preferences");Deluge.preferences.ProxyField=Ext.extend(Ext.form.FieldSet,{border:false,autoHeight:true,labelWidth:70,initComponent:function(){Deluge.preferences.ProxyField.superclass.initComponent.call(this);this.proxyType=this.add({xtype:"combo",fieldLabel:_("Type"),name:"proxytype",mode:"local",width:150,store:new Ext.data.ArrayStore({fields:["id","text"],data:[[0,_("None")],[1,_("Socksv4")],[2,_("Socksv5")],[3,_("Socksv5 with Auth")],[4,_("HTTP")],[5,_("HTTP with Auth")]]}),editable:false,triggerAction:"all",valueField:"id",displayField:"text"});this.hostname=this.add({xtype:"textfield",name:"hostname",fieldLabel:_("Host"),width:220});this.port=this.add({xtype:"spinnerfield",name:"port",fieldLabel:_("Port"),width:80,decimalPrecision:0,minValue:-1,maxValue:99999});this.username=this.add({xtype:"textfield",name:"username",fieldLabel:_("Username"),width:220});this.password=this.add({xtype:"textfield",name:"password",fieldLabel:_("Password"),inputType:"password",width:220});this.proxyType.on("change",this.onFieldChange,this);this.proxyType.on("select",this.onTypeSelect,this);this.setting=false},getName:function(){return this.initialConfig.name},getValue:function(){return{type:this.proxyType.getValue(),hostname:this.hostname.getValue(),port:Number(this.port.getValue()),username:this.username.getValue(),password:this.password.getValue()}},setValue:function(c){this.setting=true;this.proxyType.setValue(c.type);var b=this.proxyType.getStore().find("id",c.type);var a=this.proxyType.getStore().getAt(b);this.hostname.setValue(c.hostname);this.port.setValue(c.port);this.username.setValue(c.username);this.password.setValue(c.password);this.onTypeSelect(this.type,a,b);this.setting=false},onFieldChange:function(e,d,c){if(this.setting){return}var b=this.getValue();var a=Ext.apply({},b);a[e.getName()]=c;this.fireEvent("change",this,b,a)},onTypeSelect:function(d,a,b){var c=a.get("id");if(c>0){this.hostname.show();this.port.show()}else{this.hostname.hide();this.port.hide()}if(c==3||c==5){this.username.show();this.password.show()}else{this.username.hide();this.password.hide()}}}); /* * Deluge.preferences.ProxyPage.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -925,7 +925,7 @@ Ext.ns("Deluge.preferences");Deluge.preferences.ProxyField=Ext.extend(Ext.form.F * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Deluge.preferences");Deluge.preferences.Proxy=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({border:false,title:_("Proxy"),layout:"form"},a);Deluge.preferences.Proxy.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Proxy.superclass.initComponent.call(this);this.peer=this.add(new Deluge.preferences.ProxyField({title:_("Peer"),name:"peer"}));this.peer.on("change",this.onProxyChange,this);this.web_seed=this.add(new Deluge.preferences.ProxyField({title:_("Web Seed"),name:"web_seed"}));this.web_seed.on("change",this.onProxyChange,this);this.tracker=this.add(new Deluge.preferences.ProxyField({title:_("Tracker"),name:"tracker"}));this.tracker.on("change",this.onProxyChange,this);this.dht=this.add(new Deluge.preferences.ProxyField({title:_("DHT"),name:"dht"}));this.dht.on("change",this.onProxyChange,this);deluge.preferences.getOptionsManager().bind("proxies",this)},getValue:function(){return{dht:this.dht.getValue(),peer:this.peer.getValue(),tracker:this.tracker.getValue(),web_seed:this.web_seed.getValue()}},setValue:function(b){for(var a in b){this[a].setValue(b[a])}},onProxyChange:function(e,d,c){var b=this.getValue();var a=Ext.apply({},b);a[e.getName()]=c;this.fireEvent("change",this,b,a)}}); +Ext.namespace("Deluge.preferences");Deluge.preferences.Proxy=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({border:false,title:_("Proxy"),layout:"form",autoScroll:true},a);Deluge.preferences.Proxy.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Proxy.superclass.initComponent.call(this);this.peer=this.add(new Deluge.preferences.ProxyField({title:_("Peer"),name:"peer"}));this.peer.on("change",this.onProxyChange,this);this.web_seed=this.add(new Deluge.preferences.ProxyField({title:_("Web Seed"),name:"web_seed"}));this.web_seed.on("change",this.onProxyChange,this);this.tracker=this.add(new Deluge.preferences.ProxyField({title:_("Tracker"),name:"tracker"}));this.tracker.on("change",this.onProxyChange,this);this.dht=this.add(new Deluge.preferences.ProxyField({title:_("DHT"),name:"dht"}));this.dht.on("change",this.onProxyChange,this);deluge.preferences.getOptionsManager().bind("proxies",this)},getValue:function(){return{dht:this.dht.getValue(),peer:this.peer.getValue(),tracker:this.tracker.getValue(),web_seed:this.web_seed.getValue()}},setValue:function(b){for(var a in b){this[a].setValue(b[a])}},onProxyChange:function(e,d,c){var b=this.getValue();var a=Ext.apply({},b);a[e.getName()]=c;this.fireEvent("change",this,b,a)}}); /* * Deluge.preferences.QueuePage.js * @@ -1117,7 +1117,7 @@ Ext.ns("Deluge");Deluge.AddTrackerWindow=Ext.extend(Ext.Window,{title:_("Add Tra * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.namespace("Ext.ux.util");Ext.ux.util.RpcClient=Ext.extend(Ext.util.Observable,{_components:[],_methods:[],_requests:{},_url:null,_optionKeys:["scope","success","failure"],constructor:function(a){Ext.ux.util.RpcClient.superclass.constructor.call(this,a);this._url=a.url||null;this._id=0;this.addEvents("connected","error");this.reloadMethods()},reloadMethods:function(){Ext.each(this._components,function(a){delete this[a]},this);this._execute("system.listMethods",{success:this._setMethods,scope:this})},_execute:function(c,a){a=a||{};a.params=a.params||[];a.id=this._id;var b=Ext.encode({method:c,params:a.params,id:a.id});this._id++;return Ext.Ajax.request({url:this._url,method:"POST",success:this._onSuccess,failure:this._onFailure,scope:this,jsonData:b,options:a})},_onFailure:function(b,a){var c=a.options;errorObj={id:c.id,result:null,error:{msg:"HTTP: "+b.status+" "+b.statusText,code:255}};this.fireEvent("error",errorObj,b,a);if(Ext.type(c.failure)!="function"){return}if(c.scope){c.failure.call(c.scope,errorObj,b,a)}else{c.failure(errorObj,b,a)}},_onSuccess:function(c,a){var b=Ext.decode(c.responseText);var d=a.options;if(b.error){this.fireEvent("error",b,c,a);if(Ext.type(d.failure)!="function"){return}if(d.scope){d.failure.call(d.scope,b,c,a)}else{d.failure(b,c,a)}}else{if(Ext.type(d.success)!="function"){return}if(d.scope){d.success.call(d.scope,b.result,b,c,a)}else{d.success(b.result,b,c,a)}}},_parseArgs:function(c){var e=[];Ext.each(c,function(f){e.push(f)});var b=e[e.length-1];if(Ext.type(b)=="object"){var d=Ext.keys(b),a=false;Ext.each(this._optionKeys,function(f){if(d.indexOf(f)>-1){a=true}});if(a){e.remove(b)}else{b={}}}else{b={}}b.params=e;return b},_setMethods:function(b){var d={},a=this;Ext.each(b,function(h){var g=h.split(".");var e=d[g[0]]||{};var f=function(){var i=a._parseArgs(arguments);return a._execute(h,i)};e[g[1]]=f;d[g[0]]=e});for(var c in d){a[c]=d[c]}this._components=Ext.keys(d);this.fireEvent("connected",this)}}); +Ext.namespace("Ext.ux.util");Ext.ux.util.RpcClient=Ext.extend(Ext.util.Observable,{_components:[],_methods:[],_requests:{},_url:null,_optionKeys:["scope","success","failure"],constructor:function(a){Ext.ux.util.RpcClient.superclass.constructor.call(this,a);this._url=a.url||null;this._id=0;this.addEvents("connected","error");this.reloadMethods()},reloadMethods:function(){this._execute("system.listMethods",{success:this._setMethods,scope:this})},_execute:function(c,a){a=a||{};a.params=a.params||[];a.id=this._id;var b=Ext.encode({method:c,params:a.params,id:a.id});this._id++;return Ext.Ajax.request({url:this._url,method:"POST",success:this._onSuccess,failure:this._onFailure,scope:this,jsonData:b,options:a})},_onFailure:function(b,a){var c=a.options;errorObj={id:c.id,result:null,error:{msg:"HTTP: "+b.status+" "+b.statusText,code:255}};this.fireEvent("error",errorObj,b,a);if(Ext.type(c.failure)!="function"){return}if(c.scope){c.failure.call(c.scope,errorObj,b,a)}else{c.failure(errorObj,b,a)}},_onSuccess:function(c,a){var b=Ext.decode(c.responseText);var d=a.options;if(b.error){this.fireEvent("error",b,c,a);if(Ext.type(d.failure)!="function"){return}if(d.scope){d.failure.call(d.scope,b,c,a)}else{d.failure(b,c,a)}}else{if(Ext.type(d.success)!="function"){return}if(d.scope){d.success.call(d.scope,b.result,b,c,a)}else{d.success(b.result,b,c,a)}}},_parseArgs:function(c){var e=[];Ext.each(c,function(f){e.push(f)});var b=e[e.length-1];if(Ext.type(b)=="object"){var d=Ext.keys(b),a=false;Ext.each(this._optionKeys,function(f){if(d.indexOf(f)>-1){a=true}});if(a){e.remove(b)}else{b={}}}else{b={}}b.params=e;return b},_setMethods:function(b){var d={},a=this;Ext.each(b,function(h){var g=h.split(".");var e=d[g[0]]||{};var f=function(){var i=a._parseArgs(arguments);return a._execute(h,i)};e[g[1]]=f;d[g[0]]=e});for(var c in d){a[c]=d[c]}Ext.each(this._components,function(e){if(!e in d){delete this[e]}},this);this._components=Ext.keys(d);this.fireEvent("connected",this)}}); /* * Deluge.ConnectionManager.js * @@ -1277,7 +1277,7 @@ Ext.ns("Deluge");Deluge.EditTrackersWindow=Ext.extend(Ext.Window,{title:_("Edit * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Deluge.EventsManager=Ext.extend(Ext.util.Observable,{constructor:function(){this.toRegister=[];this.on("login",this.onLogin,this);Deluge.EventsManager.superclass.constructor.call(this)},addListener:function(a,c,b,d){this.addEvents(a);if(/[A-Z]/.test(a.substring(0,1))){if(!deluge.client){this.toRegister.push(a)}else{deluge.client.web.register_event_listener(a)}}Deluge.EventsManager.superclass.addListener.call(this,a,c,b,d)},getEvents:function(){deluge.client.web.get_events({success:this.onGetEventsSuccess,failure:this.onGetEventsFailure,scope:this})},start:function(){Ext.each(this.toRegister,function(a){deluge.client.web.register_event_listener(a)});this.running=true;this.errorCount=0;this.getEvents()},stop:function(){this.running=false},onLogin:function(){this.start()},onGetEventsSuccess:function(a){if(!a){return}Ext.each(a,function(d){var c=d[0],b=d[1];b.splice(0,0,c);this.fireEvent.apply(this,b)},this);if(this.running){this.getEvents()}},onGetEventsFailure:function(a,b){if(!this.running){return}if(!b.isTimeout&&this.errorCount++>=3){this.stop();return}this.getEvents()}});Deluge.EventsManager.prototype.on=Deluge.EventsManager.prototype.addListener;Deluge.EventsManager.prototype.fire=Deluge.EventsManager.prototype.fireEvent;deluge.events=new Deluge.EventsManager(); +Deluge.EventsManager=Ext.extend(Ext.util.Observable,{constructor:function(){this.toRegister=[];this.on("login",this.onLogin,this);Deluge.EventsManager.superclass.constructor.call(this)},addListener:function(a,c,b,d){this.addEvents(a);if(/[A-Z]/.test(a.substring(0,1))){if(!deluge.client){this.toRegister.push(a)}else{deluge.client.web.register_event_listener(a)}}Deluge.EventsManager.superclass.addListener.call(this,a,c,b,d)},getEvents:function(){deluge.client.web.get_events({success:this.onGetEventsSuccess,failure:this.onGetEventsFailure,scope:this})},start:function(){Ext.each(this.toRegister,function(a){deluge.client.web.register_event_listener(a)});this.running=true;this.errorCount=0;this.getEvents()},stop:function(){this.running=false},onLogin:function(){this.start()},onGetEventsSuccess:function(a){if(!this.running){return}if(a){Ext.each(a,function(d){var c=d[0],b=d[1];b.splice(0,0,c);this.fireEvent.apply(this,b)},this)}this.getEvents()},onGetEventsFailure:function(a,b){if(!this.running){return}if(!b.isTimeout&&this.errorCount++>=3){this.stop();return}this.getEvents()}});Deluge.EventsManager.prototype.on=Deluge.EventsManager.prototype.addListener;Deluge.EventsManager.prototype.fire=Deluge.EventsManager.prototype.fireEvent;deluge.events=new Deluge.EventsManager(); /* * Deluge.FileBrowser.js * @@ -1408,7 +1408,7 @@ Ext.ns("Deluge");Deluge.FilterPanel=Ext.extend(Ext.Panel,{autoScroll:true,border Deluge.Keys={Grid:["queue","name","total_size","state","progress","num_seeds","total_seeds","num_peers","total_peers","download_payload_rate","upload_payload_rate","eta","ratio","distributed_copies","is_auto_managed","time_added","tracker_host","save_path","last_seen_complete","total_done","total_uploaded","max_download_speed","max_upload_speed","seeds_peers_ratio"],Status:["total_done","total_payload_download","total_uploaded","total_payload_upload","next_announce","tracker_status","num_pieces","piece_length","is_auto_managed","active_time","seeding_time","seed_rank","last_seen_complete","owner","public","shared"],Files:["files","file_progress","file_priorities"],Peers:["peers"],Details:["name","save_path","total_size","num_files","message","tracker","comment"],Options:["max_download_speed","max_upload_speed","max_connections","max_upload_slots","is_auto_managed","stop_at_ratio","stop_ratio","remove_at_ratio","private","prioritize_first_last","move_completed","move_completed_path"]};Ext.each(Deluge.Keys.Grid,function(a){Deluge.Keys.Status.push(a)}); /* * Deluge.LoginWindow.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -1437,7 +1437,7 @@ Deluge.Keys={Grid:["queue","name","total_size","state","progress","num_seeds","t * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Deluge.LoginWindow=Ext.extend(Ext.Window,{firstShow:true,bodyStyle:"padding: 10px 5px;",buttonAlign:"center",closable:false,closeAction:"hide",iconCls:"x-deluge-login-window-icon",layout:"fit",modal:true,plain:true,resizable:false,title:_("Login"),width:300,height:120,initComponent:function(){Deluge.LoginWindow.superclass.initComponent.call(this);this.on("show",this.onShow,this);this.addButton({text:_("Login"),handler:this.onLogin,scope:this});this.form=this.add({xtype:"form",baseCls:"x-plain",labelWidth:55,width:300,defaults:{width:200},defaultType:"textfield"});this.passwordField=this.form.add({xtype:"textfield",fieldLabel:_("Password"),id:"_password",name:"password",inputType:"password"});this.passwordField.on("specialkey",this.onSpecialKey,this)},logout:function(){deluge.events.fire("logout");deluge.client.auth.delete_session({success:function(a){this.show(true)},scope:this})},show:function(a){if(this.firstShow){deluge.client.on("error",this.onClientError,this);this.firstShow=false}if(a){return Deluge.LoginWindow.superclass.show.call(this)}deluge.client.auth.check_session({success:function(b){if(b){deluge.events.fire("login")}else{this.show(true)}},failure:function(b){this.show(true)},scope:this})},onSpecialKey:function(b,a){if(a.getKey()==13){this.onLogin()}},onLogin:function(){var a=this.passwordField;deluge.client.auth.login(a.getValue(),{success:function(b){if(b){deluge.events.fire("login");this.hide();a.setRawValue("")}else{Ext.MessageBox.show({title:_("Login Failed"),msg:_("You entered an incorrect password"),buttons:Ext.MessageBox.OK,modal:false,fn:function(){a.focus(true,10)},icon:Ext.MessageBox.WARNING,iconCls:"x-deluge-icon-warning"})}},scope:this})},onClientError:function(c,b,a){if(c.error.code==1){deluge.events.fire("logout");this.show(true)}},onShow:function(){this.passwordField.focus(true,100)}}); +Deluge.LoginWindow=Ext.extend(Ext.Window,{firstShow:true,bodyStyle:"padding: 10px 5px;",buttonAlign:"center",closable:false,closeAction:"hide",iconCls:"x-deluge-login-window-icon",layout:"fit",modal:true,plain:true,resizable:false,title:_("Login"),width:300,height:120,initComponent:function(){Deluge.LoginWindow.superclass.initComponent.call(this);this.on("show",this.onShow,this);this.addButton({text:_("Login"),handler:this.onLogin,scope:this});this.form=this.add({xtype:"form",baseCls:"x-plain",labelWidth:120,labelAlign:"right",defaults:{width:110},defaultType:"textfield"});this.passwordField=this.form.add({xtype:"textfield",fieldLabel:_("Password"),grow:true,growMin:"110",growMax:"145",id:"_password",name:"password",inputType:"password"});this.passwordField.on("specialkey",this.onSpecialKey,this)},logout:function(){deluge.events.fire("logout");deluge.client.auth.delete_session({success:function(a){this.show(true)},scope:this})},show:function(a){if(this.firstShow){deluge.client.on("error",this.onClientError,this);this.firstShow=false}if(a){return Deluge.LoginWindow.superclass.show.call(this)}deluge.client.auth.check_session({success:function(b){if(b){deluge.events.fire("login")}else{this.show(true)}},failure:function(b){this.show(true)},scope:this})},onSpecialKey:function(b,a){if(a.getKey()==13){this.onLogin()}},onLogin:function(){var a=this.passwordField;deluge.client.auth.login(a.getValue(),{success:function(b){if(b){deluge.events.fire("login");this.hide();a.setRawValue("")}else{Ext.MessageBox.show({title:_("Login Failed"),msg:_("You entered an incorrect password"),buttons:Ext.MessageBox.OK,modal:false,fn:function(){a.focus(true,10)},icon:Ext.MessageBox.WARNING,iconCls:"x-deluge-icon-warning"})}},scope:this})},onClientError:function(c,b,a){if(c.error.code==1){deluge.events.fire("logout");this.show(true)}},onShow:function(){this.passwordField.focus(true,300)}}); /* * Deluge.Menus.js * @@ -1469,7 +1469,7 @@ Deluge.LoginWindow=Ext.extend(Ext.Window,{firstShow:true,bodyStyle:"padding: 10p * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -deluge.menus={onTorrentAction:function(b,d){var a=deluge.torrents.getSelectedIds();var c=b.initialConfig.torrentAction;switch(c){case"pause":case"resume":deluge.client.core[c+"_torrent"](a,{success:function(){deluge.ui.update()}});break;case"top":case"up":case"down":case"bottom":deluge.client.core["queue_"+c](a,{success:function(){deluge.ui.update()}});break;case"edit_trackers":deluge.editTrackers.show();break;case"update":deluge.client.core.force_reannounce(a,{success:function(){deluge.ui.update()}});break;case"remove":deluge.removeWindow.show(a);break;case"recheck":deluge.client.core.force_recheck(a,{success:function(){deluge.ui.update()}});break;case"move":deluge.moveStorage.show(a);break}}};deluge.menus.torrent=new Ext.menu.Menu({id:"torrentMenu",items:[{torrentAction:"pause",text:_("Pause"),iconCls:"icon-pause",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"resume",text:_("Resume"),iconCls:"icon-resume",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{text:_("Options"),iconCls:"icon-options",menu:new Ext.menu.Menu({items:[{text:_("D/L Speed Limit"),iconCls:"x-deluge-downloading",menu:new Ext.menu.Menu({items:[{text:_("5 KiB/s")},{text:_("10 KiB/s")},{text:_("30 KiB/s")},{text:_("80 KiB/s")},{text:_("300 KiB/s")},{text:_("Unlimited")}]})},{text:_("U/L Speed Limit"),iconCls:"x-deluge-seeding",menu:new Ext.menu.Menu({items:[{text:_("5 KiB/s")},{text:_("10 KiB/s")},{text:_("30 KiB/s")},{text:_("80 KiB/s")},{text:_("300 KiB/s")},{text:_("Unlimited")}]})},{text:_("Connection Limit"),iconCls:"x-deluge-connections",menu:new Ext.menu.Menu({items:[{text:_("50")},{text:_("100")},{text:_("200")},{text:_("300")},{text:_("500")},{text:_("Unlimited")}]})},{text:_("Upload Slot Limit"),iconCls:"icon-upload-slots",menu:new Ext.menu.Menu({items:[{text:_("0")},{text:_("1")},{text:_("2")},{text:_("3")},{text:_("5")},{text:_("Unlimited")}]})},{id:"auto_managed",text:_("Auto Managed"),checked:false}]})},"-",{text:_("Queue"),iconCls:"icon-queue",menu:new Ext.menu.Menu({items:[{torrentAction:"top",text:_("Top"),iconCls:"icon-top",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"up",text:_("Up"),iconCls:"icon-up",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"down",text:_("Down"),iconCls:"icon-down",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"bottom",text:_("Bottom"),iconCls:"icon-bottom",handler:deluge.menus.onTorrentAction,scope:deluge.menus}]})},"-",{torrentAction:"update",text:_("Update Tracker"),iconCls:"icon-update-tracker",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"edit_trackers",text:_("Edit Trackers"),iconCls:"icon-edit-trackers",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{torrentAction:"remove",text:_("Remove Torrent"),iconCls:"icon-remove",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{torrentAction:"recheck",text:_("Force Recheck"),iconCls:"icon-recheck",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"move",text:_("Move Storage"),iconCls:"icon-move",handler:deluge.menus.onTorrentAction,scope:deluge.menus}]});deluge.menus.filePriorities=new Ext.menu.Menu({id:"filePrioritiesMenu",items:[{id:"expandAll",text:_("Expand All"),iconCls:"icon-expand-all"},"-",{id:"no_download",text:_("Do Not Download"),iconCls:"icon-do-not-download",filePriority:FILE_PRIORITY["Do Not Download"]},{id:"normal",text:_("Normal Priority"),iconCls:"icon-normal",filePriority:FILE_PRIORITY["Normal Priority"]},{id:"high",text:_("High Priority"),iconCls:"icon-high",filePriority:FILE_PRIORITY["High Priority"]},{id:"highest",text:_("Highest Priority"),iconCls:"icon-highest",filePriority:FILE_PRIORITY["Highest Priority"]}]}); +deluge.menus={onTorrentAction:function(b,d){var a=deluge.torrents.getSelectedIds();var c=b.initialConfig.torrentAction;switch(c){case"pause":case"resume":deluge.client.core[c+"_torrent"](a,{success:function(){deluge.ui.update()}});break;case"top":case"up":case"down":case"bottom":deluge.client.core["queue_"+c](a,{success:function(){deluge.ui.update()}});break;case"edit_trackers":deluge.editTrackers.show();break;case"update":deluge.client.core.force_reannounce(a,{success:function(){deluge.ui.update()}});break;case"remove":deluge.removeWindow.show(a);break;case"recheck":deluge.client.core.force_recheck(a,{success:function(){deluge.ui.update()}});break;case"move":deluge.moveStorage.show(a);break}}};deluge.menus.torrent=new Ext.menu.Menu({id:"torrentMenu",items:[{torrentAction:"pause",text:_("Pause"),iconCls:"icon-pause",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"resume",text:_("Resume"),iconCls:"icon-resume",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{text:_("Options"),iconCls:"icon-options",hideOnClick:false,menu:new Ext.menu.Menu({items:[{text:_("D/L Speed Limit"),iconCls:"x-deluge-downloading",hideOnClick:false,menu:new Ext.menu.Menu({items:[{text:_("5 KiB/s")},{text:_("10 KiB/s")},{text:_("30 KiB/s")},{text:_("80 KiB/s")},{text:_("300 KiB/s")},{text:_("Unlimited")}]})},{text:_("U/L Speed Limit"),iconCls:"x-deluge-seeding",hideOnClick:false,menu:new Ext.menu.Menu({items:[{text:_("5 KiB/s")},{text:_("10 KiB/s")},{text:_("30 KiB/s")},{text:_("80 KiB/s")},{text:_("300 KiB/s")},{text:_("Unlimited")}]})},{text:_("Connection Limit"),iconCls:"x-deluge-connections",hideOnClick:false,menu:new Ext.menu.Menu({items:[{text:_("50")},{text:_("100")},{text:_("200")},{text:_("300")},{text:_("500")},{text:_("Unlimited")}]})},{text:_("Upload Slot Limit"),iconCls:"icon-upload-slots",hideOnClick:false,menu:new Ext.menu.Menu({items:[{text:_("0")},{text:_("1")},{text:_("2")},{text:_("3")},{text:_("5")},{text:_("Unlimited")}]})},{id:"auto_managed",text:_("Auto Managed"),checked:false}]})},"-",{text:_("Queue"),iconCls:"icon-queue",hideOnClick:false,menu:new Ext.menu.Menu({items:[{torrentAction:"top",text:_("Top"),iconCls:"icon-top",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"up",text:_("Up"),iconCls:"icon-up",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"down",text:_("Down"),iconCls:"icon-down",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"bottom",text:_("Bottom"),iconCls:"icon-bottom",handler:deluge.menus.onTorrentAction,scope:deluge.menus}]})},"-",{torrentAction:"update",text:_("Update Tracker"),iconCls:"icon-update-tracker",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"edit_trackers",text:_("Edit Trackers"),iconCls:"icon-edit-trackers",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{torrentAction:"remove",text:_("Remove Torrent"),iconCls:"icon-remove",handler:deluge.menus.onTorrentAction,scope:deluge.menus},"-",{torrentAction:"recheck",text:_("Force Recheck"),iconCls:"icon-recheck",handler:deluge.menus.onTorrentAction,scope:deluge.menus},{torrentAction:"move",text:_("Move Storage"),iconCls:"icon-move",handler:deluge.menus.onTorrentAction,scope:deluge.menus}]});deluge.menus.filePriorities=new Ext.menu.Menu({id:"filePrioritiesMenu",items:[{id:"expandAll",text:_("Expand All"),iconCls:"icon-expand-all"},"-",{id:"no_download",text:_("Do Not Download"),iconCls:"icon-do-not-download",filePriority:FILE_PRIORITY["Do Not Download"]},{id:"normal",text:_("Normal Priority"),iconCls:"icon-normal",filePriority:FILE_PRIORITY["Normal Priority"]},{id:"high",text:_("High Priority"),iconCls:"icon-high",filePriority:FILE_PRIORITY["High Priority"]},{id:"highest",text:_("Highest Priority"),iconCls:"icon-highest",filePriority:FILE_PRIORITY["Highest Priority"]}]}); /* * Deluge.MoveStorage.js * @@ -1597,7 +1597,7 @@ Ext.ns("Deluge");Deluge.OtherLimitWindow=Ext.extend(Ext.Window,{layout:"fit",wid * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.ns("Deluge");Deluge.Plugin=Ext.extend(Ext.util.Observable,{name:null,constructor:function(a){this.isDelugePlugin=true;this.addEvents({enabled:true,disabled:true});Deluge.Plugin.superclass.constructor.call(this,a)},disable:function(){this.fireEvent("disabled",this);if(this.onDisable){this.onDisable()}},enable:function(){this.fireEvent("enable",this);if(this.onEnable){this.onEnable()}},registerTorrentStatus:function(b,f,a){a=a||{};var e=a.colCfg||{},d=a.storeCfg||{};d=Ext.apply(d,{name:b});deluge.torrents.meta.fields.push(d);deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);e=Ext.apply(e,{header:f,dataIndex:b});var c=deluge.torrents.columns.slice(0);c.push(e);deluge.torrents.colModel.setConfig(c);deluge.torrents.columns=c;Deluge.Keys.Grid.push(b);deluge.torrents.getView().refresh(true)},deregisterTorrentStatus:function(b){var a=[];Ext.each(deluge.torrents.meta.fields,function(e){if(e.name!=b){a.push(e)}});deluge.torrents.meta.fields=a;deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);var d=[];Ext.each(deluge.torrents.columns,function(e){if(e.dataIndex!=b){d.push(e)}});deluge.torrents.colModel.setConfig(d);deluge.torrents.columns=d;var c=[];Ext.each(Deluge.Keys.Grid,function(e){if(e==b){c.push(e)}});Deluge.Keys.Grid=c;deluge.torrents.getView().refresh(true)}});Ext.ns("Deluge.plugins"); +Ext.ns("Deluge");Deluge.Plugin=Ext.extend(Ext.util.Observable,{name:null,constructor:function(a){this.isDelugePlugin=true;this.addEvents({enabled:true,disabled:true});Deluge.Plugin.superclass.constructor.call(this,a)},disable:function(){this.fireEvent("disabled",this);if(this.onDisable){this.onDisable()}},enable:function(){deluge.client.reloadMethods();this.fireEvent("enable",this);if(this.onEnable){this.onEnable()}},registerTorrentStatus:function(b,f,a){a=a||{};var e=a.colCfg||{},d=a.storeCfg||{};d=Ext.apply(d,{name:b});deluge.torrents.meta.fields.push(d);deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);e=Ext.apply(e,{header:f,dataIndex:b});var c=deluge.torrents.columns.slice(0);c.push(e);deluge.torrents.colModel.setConfig(c);deluge.torrents.columns=c;Deluge.Keys.Grid.push(b);deluge.torrents.getView().refresh(true)},deregisterTorrentStatus:function(b){var a=[];Ext.each(deluge.torrents.meta.fields,function(e){if(e.name!=b){a.push(e)}});deluge.torrents.meta.fields=a;deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);var d=[];Ext.each(deluge.torrents.columns,function(e){if(e.dataIndex!=b){d.push(e)}});deluge.torrents.colModel.setConfig(d);deluge.torrents.columns=d;var c=[];Ext.each(Deluge.Keys.Grid,function(e){if(e==b){c.push(e)}});Deluge.Keys.Grid=c;deluge.torrents.getView().refresh(true)}});Ext.ns("Deluge.plugins"); /* * Deluge.RemoveWindow.js * @@ -1757,7 +1757,7 @@ Deluge.Toolbar=Ext.extend(Ext.Toolbar,{constructor:function(a){a=Ext.apply({item * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -(function(){function c(l){return(l==-1)?"":l+1}function f(m,n,l){return String.format('<div class="torrent-name x-deluge-{0}">{1}</div>',l.data.state.toLowerCase(),m)}function g(l){if(!l){return}return fspeed(l)}function i(l){if(l==-1){return""}return fspeed(l*1024)}function k(q,s,o){q=new Number(q);var l=q;var t=o.data.state+" "+q.toFixed(2)+"%";if(this.style){var n=this.style}else{var n=s.style}var m=new Number(n.match(/\w+:\s*(\d+)\w+/)[1]);return Deluge.progressBar(q,m-8,t)}function a(m,n,l){if(l.data.total_seeds>-1){return String.format("{0} ({1})",m,l.data.total_seeds)}else{return m}}function e(m,n,l){if(l.data.total_peers>-1){return String.format("{0} ({1})",m,l.data.total_peers)}else{return m}}function b(m,n,l){return(m<0)?"∞":parseFloat(new Number(m).toFixed(3))}function d(m,n,l){return String.format('<div style="background: url('+deluge.config.base+'tracker/{0}) no-repeat; padding-left: 20px;">{0}</div>',m)}function h(l){return l*-1}function j(l){return l>0?fdate(l):"Never"}Deluge.TorrentGrid=Ext.extend(Ext.grid.GridPanel,{torrents:{},columns:[{id:"queue",header:_("#"),width:30,sortable:true,renderer:c,dataIndex:"queue"},{id:"name",header:_("Name"),width:150,sortable:true,renderer:f,dataIndex:"name"},{header:_("Size"),width:75,sortable:true,renderer:fsize,dataIndex:"total_size"},{header:_("Progress"),width:150,sortable:true,renderer:k,dataIndex:"progress"},{header:_("Seeders"),hidden:true,width:60,sortable:true,renderer:a,dataIndex:"num_seeds"},{header:_("Peers"),hidden:true,width:60,sortable:true,renderer:e,dataIndex:"num_peers"},{header:_("Down Speed"),width:80,sortable:true,renderer:g,dataIndex:"download_payload_rate"},{header:_("Up Speed"),width:80,sortable:true,renderer:g,dataIndex:"upload_payload_rate"},{header:_("ETA"),width:60,sortable:true,renderer:ftime,dataIndex:"eta"},{header:_("Ratio"),hidden:true,width:60,sortable:true,renderer:b,dataIndex:"ratio"},{header:_("Avail"),hidden:true,width:60,sortable:true,renderer:b,dataIndex:"distributed_copies"},{header:_("Added"),hidden:true,width:80,sortable:true,renderer:fdate,dataIndex:"time_added"},{header:_("Last Seen Complete"),width:80,sortable:true,renderer:j,dataIndex:"last_seen_complete"},{header:_("Tracker"),hidden:true,width:120,sortable:true,renderer:d,dataIndex:"tracker_host"},{header:_("Save Path"),hidden:true,width:120,sortable:true,renderer:fplain,dataIndex:"save_path"},{header:_("Owner"),width:80,sortable:true,renderer:fplain,dataIndex:"owner"},{header:_("Public"),hidden:true,width:80,sortable:true,renderer:fplain,dataIndex:"public"},{header:_("Shared"),hidden:true,width:80,sortable:true,renderer:fplain,dataIndex:"shared"},{header:_("Downloaded"),hidden:true,width:75,sortable:true,renderer:fsize,dataIndex:"total_done"},{header:_("Uploaded"),hidden:true,width:75,sortable:true,renderer:fsize,dataIndex:"total_uploaded"},{header:_("Down Limit"),hidden:true,width:75,sortable:true,renderer:i,dataIndex:"max_download_speed"},{header:_("Up Limit"),hidden:true,width:75,sortable:true,renderer:i,dataIndex:"max_upload_speed"},{header:_("Seeders")+"/"+_("Peers"),hidden:true,width:75,sortable:true,renderer:b,dataIndex:"seeds_peers_ratio"}],meta:{root:"torrents",idProperty:"id",fields:[{name:"queue",sortType:Deluge.data.SortTypes.asQueuePosition},{name:"name"},{name:"total_size",type:"int"},{name:"state"},{name:"progress",type:"float"},{name:"num_seeds",type:"int"},{name:"total_seeds",type:"int"},{name:"num_peers",type:"int"},{name:"total_peers",type:"int"},{name:"download_payload_rate",type:"int"},{name:"upload_payload_speed",type:"int"},{name:"eta",type:"int",sortType:h},{name:"ratio",type:"float"},{name:"distributed_copies",type:"float"},{name:"time_added",type:"int"},{name:"tracker_host"},{name:"save_path"},{name:"total_done",type:"int"},{name:"total_uploaded",type:"int"},{name:"max_download_speed",type:"int"},{name:"max_upload_speed",type:"int"},{name:"seeds_peers_ratio",type:"float"}]},keys:[{key:"a",ctrl:true,stopEvent:true,handler:function(){deluge.torrents.getSelectionModel().selectAll()}},{key:[46],stopEvent:true,handler:function(){ids=deluge.torrents.getSelectedIds();deluge.removeWindow.show(ids)}}],constructor:function(l){l=Ext.apply({id:"torrentGrid",store:new Ext.data.JsonStore(this.meta),columns:this.columns,keys:this.keys,region:"center",cls:"deluge-torrents",stripeRows:true,autoExpandColumn:"name",autoExpandMin:150,deferredRender:false,autoScroll:true,margins:"5 5 0 0",stateful:true,view:new Ext.ux.grid.BufferView({rowHeight:26,scrollDelay:false})},l);Deluge.TorrentGrid.superclass.constructor.call(this,l)},initComponent:function(){Deluge.TorrentGrid.superclass.initComponent.call(this);deluge.events.on("torrentRemoved",this.onTorrentRemoved,this);deluge.events.on("disconnect",this.onDisconnect,this);this.on("rowcontextmenu",function(l,o,n){n.stopEvent();var m=l.getSelectionModel();if(!m.hasSelection()){m.selectRow(o)}deluge.menus.torrent.showAt(n.getPoint())})},getTorrent:function(l){return this.getStore().getAt(l)},getSelected:function(){return this.getSelectionModel().getSelected()},getSelections:function(){return this.getSelectionModel().getSelections()},getSelectedId:function(){return this.getSelectionModel().getSelected().id},getSelectedIds:function(){var l=[];Ext.each(this.getSelectionModel().getSelections(),function(m){l.push(m.id)});return l},update:function(o,m){var q=this.getStore();if(m){q.removeAll();this.torrents={}}var p=[];for(var r in o){var u=o[r];if(this.torrents[r]){var n=q.getById(r);n.beginEdit();for(var l in u){if(n.get(l)!=u[l]){n.set(l,u[l])}}n.endEdit()}else{var n=new Deluge.data.Torrent(u);n.id=r;this.torrents[r]=1;p.push(n)}}q.add(p);q.each(function(t){if(!o[t.id]){q.remove(t);delete this.torrents[t.id]}},this);q.commitChanges();var s=q.getSortState();if(!s){return}q.sort(s.field,s.direction)},onDisconnect:function(){this.getStore().removeAll();this.torrents={}},onTorrentRemoved:function(m){var l=this.getSelectionModel();Ext.each(m,function(o){var n=this.getStore().getById(o);if(l.isSelected(n)){l.deselectRow(this.getStore().indexOf(n))}this.getStore().remove(n);delete this.torrents[o]},this)}});deluge.torrents=new Deluge.TorrentGrid()})(); +(function(){function c(l){return(l==-1)?"":l+1}function f(m,n,l){return String.format('<div class="torrent-name x-deluge-{0}">{1}</div>',l.data.state.toLowerCase(),m)}function g(l){if(!l){return}return fspeed(l)}function i(l){if(l==-1){return""}return fspeed(l*1024)}function k(q,s,o){q=new Number(q);var l=q;var t=o.data.state+" "+q.toFixed(2)+"%";if(this.style){var n=this.style}else{var n=s.style}var m=new Number(n.match(/\w+:\s*(\d+)\w+/)[1]);return Deluge.progressBar(q,m-8,t)}function a(m,n,l){if(l.data.total_seeds>-1){return String.format("{0} ({1})",m,l.data.total_seeds)}else{return m}}function e(m,n,l){if(l.data.total_peers>-1){return String.format("{0} ({1})",m,l.data.total_peers)}else{return m}}function b(m,n,l){return(m<0)?"∞":parseFloat(new Number(m).toFixed(3))}function d(m,n,l){return String.format('<div style="background: url('+deluge.config.base+'tracker/{0}) no-repeat; padding-left: 20px;">{0}</div>',m)}function h(l){return l*-1}function j(l){return l>0?fdate(l):"Never"}Deluge.TorrentGrid=Ext.extend(Ext.grid.GridPanel,{torrents:{},columns:[{id:"queue",header:_("#"),width:30,sortable:true,renderer:c,dataIndex:"queue"},{id:"name",header:_("Name"),width:150,sortable:true,renderer:f,dataIndex:"name"},{header:_("Size"),width:75,sortable:true,renderer:fsize,dataIndex:"total_size"},{header:_("Progress"),width:150,sortable:true,renderer:k,dataIndex:"progress"},{header:_("Seeders"),hidden:true,width:60,sortable:true,renderer:a,dataIndex:"num_seeds"},{header:_("Peers"),hidden:true,width:60,sortable:true,renderer:e,dataIndex:"num_peers"},{header:_("Down Speed"),width:80,sortable:true,renderer:g,dataIndex:"download_payload_rate"},{header:_("Up Speed"),width:80,sortable:true,renderer:g,dataIndex:"upload_payload_rate"},{header:_("ETA"),width:60,sortable:true,renderer:ftime,dataIndex:"eta"},{header:_("Ratio"),hidden:true,width:60,sortable:true,renderer:b,dataIndex:"ratio"},{header:_("Avail"),hidden:true,width:60,sortable:true,renderer:b,dataIndex:"distributed_copies"},{header:_("Added"),hidden:true,width:80,sortable:true,renderer:fdate,dataIndex:"time_added"},{header:_("Last Seen Complete"),width:80,sortable:true,renderer:j,dataIndex:"last_seen_complete"},{header:_("Tracker"),hidden:true,width:120,sortable:true,renderer:d,dataIndex:"tracker_host"},{header:_("Save Path"),hidden:true,width:120,sortable:true,renderer:fplain,dataIndex:"save_path"},{header:_("Owner"),width:80,sortable:true,renderer:fplain,dataIndex:"owner"},{header:_("Public"),hidden:true,width:80,sortable:true,renderer:fplain,dataIndex:"public"},{header:_("Shared"),hidden:true,width:80,sortable:true,renderer:fplain,dataIndex:"shared"},{header:_("Downloaded"),hidden:true,width:75,sortable:true,renderer:fsize,dataIndex:"total_done"},{header:_("Uploaded"),hidden:true,width:75,sortable:true,renderer:fsize,dataIndex:"total_uploaded"},{header:_("Down Limit"),hidden:true,width:75,sortable:true,renderer:i,dataIndex:"max_download_speed"},{header:_("Up Limit"),hidden:true,width:75,sortable:true,renderer:i,dataIndex:"max_upload_speed"},{header:_("Seeders")+"/"+_("Peers"),hidden:true,width:75,sortable:true,renderer:b,dataIndex:"seeds_peers_ratio"}],meta:{root:"torrents",idProperty:"id",fields:[{name:"queue",sortType:Deluge.data.SortTypes.asQueuePosition},{name:"name",sortType:Deluge.data.SortTypes.asName},{name:"total_size",type:"int"},{name:"state"},{name:"progress",type:"float"},{name:"num_seeds",type:"int"},{name:"total_seeds",type:"int"},{name:"num_peers",type:"int"},{name:"total_peers",type:"int"},{name:"download_payload_rate",type:"int"},{name:"upload_payload_rate",type:"int"},{name:"eta",type:"int",sortType:h},{name:"ratio",type:"float"},{name:"distributed_copies",type:"float"},{name:"time_added",type:"int"},{name:"tracker_host"},{name:"save_path"},{name:"total_done",type:"int"},{name:"total_uploaded",type:"int"},{name:"max_download_speed",type:"int"},{name:"max_upload_speed",type:"int"},{name:"seeds_peers_ratio",type:"float"}]},keys:[{key:"a",ctrl:true,stopEvent:true,handler:function(){deluge.torrents.getSelectionModel().selectAll()}},{key:[46],stopEvent:true,handler:function(){ids=deluge.torrents.getSelectedIds();deluge.removeWindow.show(ids)}}],constructor:function(l){l=Ext.apply({id:"torrentGrid",store:new Ext.data.JsonStore(this.meta),columns:this.columns,keys:this.keys,region:"center",cls:"deluge-torrents",stripeRows:true,autoExpandColumn:"name",autoExpandMin:150,deferredRender:false,autoScroll:true,margins:"5 5 0 0",stateful:true,view:new Ext.ux.grid.BufferView({rowHeight:26,scrollDelay:false})},l);Deluge.TorrentGrid.superclass.constructor.call(this,l)},initComponent:function(){Deluge.TorrentGrid.superclass.initComponent.call(this);deluge.events.on("torrentRemoved",this.onTorrentRemoved,this);deluge.events.on("disconnect",this.onDisconnect,this);this.on("rowcontextmenu",function(l,o,n){n.stopEvent();var m=l.getSelectionModel();if(!m.hasSelection()){m.selectRow(o)}deluge.menus.torrent.showAt(n.getPoint())})},getTorrent:function(l){return this.getStore().getAt(l)},getSelected:function(){return this.getSelectionModel().getSelected()},getSelections:function(){return this.getSelectionModel().getSelections()},getSelectedId:function(){return this.getSelectionModel().getSelected().id},getSelectedIds:function(){var l=[];Ext.each(this.getSelectionModel().getSelections(),function(m){l.push(m.id)});return l},update:function(o,m){var q=this.getStore();if(m){q.removeAll();this.torrents={}}var p=[];for(var r in o){var u=o[r];if(this.torrents[r]){var n=q.getById(r);n.beginEdit();for(var l in u){if(n.get(l)!=u[l]){n.set(l,u[l])}}n.endEdit()}else{var n=new Deluge.data.Torrent(u);n.id=r;this.torrents[r]=1;p.push(n)}}q.add(p);q.each(function(t){if(!o[t.id]){q.remove(t);delete this.torrents[t.id]}},this);q.commitChanges();var s=q.getSortState();if(!s){return}q.sort(s.field,s.direction)},onDisconnect:function(){this.getStore().removeAll();this.torrents={}},onTorrentRemoved:function(m){var l=this.getSelectionModel();Ext.each(m,function(o){var n=this.getStore().getById(o);if(l.isSelected(n)){l.deselectRow(this.getStore().indexOf(n))}this.getStore().remove(n);delete this.torrents[o]},this)}});deluge.torrents=new Deluge.TorrentGrid()})(); /* * Deluge.UI.js * @@ -1789,4 +1789,4 @@ Deluge.Toolbar=Ext.extend(Ext.Toolbar,{constructor:function(a){a=Ext.apply({item * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -deluge.ui={errorCount:0,filters:null,initialize:function(){deluge.add=new Deluge.add.AddWindow();deluge.details=new Deluge.details.DetailsPanel();deluge.connectionManager=new Deluge.ConnectionManager();deluge.editTrackers=new Deluge.EditTrackersWindow();deluge.login=new Deluge.LoginWindow();deluge.preferences=new Deluge.preferences.PreferencesWindow();deluge.sidebar=new Deluge.Sidebar();deluge.statusbar=new Deluge.Statusbar();deluge.toolbar=new Deluge.Toolbar();this.detailsPanel=new Ext.Panel({id:"detailsPanel",cls:"detailsPanel",region:"south",split:true,height:215,minSize:100,collapsible:true,margins:"0 5 5 5",cmargins:"0 5 5 5",layout:"fit",items:[deluge.details],});this.MainPanel=new Ext.Panel({id:"mainPanel",iconCls:"x-deluge-main-panel",layout:"border",border:false,tbar:deluge.toolbar,items:[deluge.sidebar,this.detailsPanel,deluge.torrents],bbar:deluge.statusbar});this.Viewport=new Ext.Viewport({layout:"fit",items:[this.MainPanel]});deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this);deluge.events.on("PluginDisabledEvent",this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this);deluge.client=new Ext.ux.util.RpcClient({url:deluge.config.base+"json"});for(var a in Deluge.pluginStore){a=Deluge.createPlugin(a);a.enable();deluge.plugins[a.name]=a}Ext.QuickTips.init();deluge.client.on("connected",function(b){deluge.login.show()},this,{single:true});this.update=this.update.createDelegate(this);this.checkConnection=this.checkConnection.createDelegate(this);this.originalTitle=document.title},checkConnection:function(){deluge.client.web.connected({success:this.onConnectionSuccess,failure:this.onConnectionError,scope:this})},update:function(){var a=deluge.sidebar.getFilterStates();this.oldFilters=this.filters;this.filters=a;deluge.client.web.update_ui(Deluge.Keys.Grid,a,{success:this.onUpdate,failure:this.onUpdateError,scope:this});deluge.details.update()},onConnectionError:function(a){},onConnectionSuccess:function(a){deluge.statusbar.setStatus({iconCls:"x-deluge-statusbar icon-ok",text:_("Connection restored")});clearInterval(this.checking);if(!a){deluge.connectionManager.show()}},onUpdateError:function(a){if(this.errorCount==2){Ext.MessageBox.show({title:"Lost Connection",msg:"The connection to the webserver has been lost!",buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.ERROR});deluge.events.fire("disconnect");deluge.statusbar.setStatus({text:"Lost connection to webserver"});this.checking=setInterval(this.checkConnection,2000)}this.errorCount++},onUpdate:function(a){if(!a.connected){deluge.connectionManager.disconnect(true);return}if(deluge.config.show_session_speed){document.title="D: "+fsize_short(a.stats.download_rate,true)+" U: "+fsize_short(a.stats.upload_rate,true)+" - "+this.originalTitle}if(Ext.areObjectsEqual(this.filters,this.oldFilters)){deluge.torrents.update(a.torrents)}else{deluge.torrents.update(a.torrents,true)}deluge.statusbar.update(a.stats);deluge.sidebar.update(a.filters);this.errorCount=0},onConnect:function(){if(!this.running){this.running=setInterval(this.update,2000);this.update()}deluge.client.web.get_plugins({success:this.onGotPlugins,scope:this})},onDisconnect:function(){this.stop()},onGotPlugins:function(a){Ext.each(a.enabled_plugins,function(b){if(deluge.plugins[b]){return}deluge.client.web.get_plugin_resources(b,{success:this.onGotPluginResources,scope:this})},this)},onPluginEnabled:function(a){if(deluge.plugins[a]){deluge.plugins[a].enable()}else{deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})}},onGotPluginResources:function(b){var a=(Deluge.debug)?b.debug_scripts:b.scripts;Ext.each(a,function(c){Ext.ux.JSLoader({url:deluge.config.base+c,onLoad:this.onPluginLoaded,pluginName:b.name})},this)},onPluginDisabled:function(a){deluge.plugins[a].disable()},onPluginLoaded:function(a){if(!Deluge.hasPlugin(a.pluginName)){return}plugin=Deluge.createPlugin(a.pluginName);plugin.enable();deluge.plugins[plugin.name]=plugin},stop:function(){if(this.running){clearInterval(this.running);this.running=false;deluge.torrents.getStore().removeAll()}}};Ext.onReady(function(a){deluge.ui.initialize()});
\ No newline at end of file +deluge.ui={errorCount:0,filters:null,initialize:function(){deluge.add=new Deluge.add.AddWindow();deluge.details=new Deluge.details.DetailsPanel();deluge.connectionManager=new Deluge.ConnectionManager();deluge.editTrackers=new Deluge.EditTrackersWindow();deluge.login=new Deluge.LoginWindow();deluge.preferences=new Deluge.preferences.PreferencesWindow();deluge.sidebar=new Deluge.Sidebar();deluge.statusbar=new Deluge.Statusbar();deluge.toolbar=new Deluge.Toolbar();this.detailsPanel=new Ext.Panel({id:"detailsPanel",cls:"detailsPanel",region:"south",split:true,height:215,minSize:100,collapsible:true,margins:"0 5 5 5",cmargins:"0 5 5 5",layout:"fit",items:[deluge.details],});this.MainPanel=new Ext.Panel({id:"mainPanel",iconCls:"x-deluge-main-panel",layout:"border",border:false,tbar:deluge.toolbar,items:[deluge.sidebar,this.detailsPanel,deluge.torrents],bbar:deluge.statusbar});this.Viewport=new Ext.Viewport({layout:"fit",items:[this.MainPanel]});deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this);deluge.events.on("PluginDisabledEvent",this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this);deluge.client=new Ext.ux.util.RpcClient({url:deluge.config.base+"json"});for(var a in Deluge.pluginStore){a=Deluge.createPlugin(a);a.enable();deluge.plugins[a.name]=a}Ext.QuickTips.init();deluge.client.on("connected",function(b){deluge.login.show()},this,{single:true});this.update=this.update.createDelegate(this);this.checkConnection=this.checkConnection.createDelegate(this);this.originalTitle=document.title},checkConnection:function(){deluge.client.web.connected({success:this.onConnectionSuccess,failure:this.onConnectionError,scope:this})},update:function(){var a=deluge.sidebar.getFilterStates();this.oldFilters=this.filters;this.filters=a;deluge.client.web.update_ui(Deluge.Keys.Grid,a,{success:this.onUpdate,failure:this.onUpdateError,scope:this});deluge.details.update()},onConnectionError:function(a){},onConnectionSuccess:function(a){deluge.statusbar.setStatus({iconCls:"x-deluge-statusbar icon-ok",text:_("Connection restored")});clearInterval(this.checking);if(!a){deluge.connectionManager.show()}},onUpdateError:function(a){if(this.errorCount==2){Ext.MessageBox.show({title:"Lost Connection",msg:"The connection to the webserver has been lost!",buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.ERROR});deluge.events.fire("disconnect");deluge.statusbar.setStatus({text:"Lost connection to webserver"});this.checking=setInterval(this.checkConnection,2000)}this.errorCount++},onUpdate:function(a){if(!a.connected){deluge.connectionManager.disconnect(true);return}if(deluge.config.show_session_speed){document.title="D: "+fsize_short(a.stats.download_rate,true)+" U: "+fsize_short(a.stats.upload_rate,true)+" - "+this.originalTitle}if(Ext.areObjectsEqual(this.filters,this.oldFilters)){deluge.torrents.update(a.torrents)}else{deluge.torrents.update(a.torrents,true)}deluge.statusbar.update(a.stats);deluge.sidebar.update(a.filters);this.errorCount=0},onConnect:function(){if(!this.running){this.running=setInterval(this.update,2000);this.update()}deluge.client.web.get_plugins({success:this.onGotPlugins,scope:this})},onDisconnect:function(){this.stop()},onGotPlugins:function(a){Ext.each(a.enabled_plugins,function(b){if(deluge.plugins[b]){return}deluge.client.web.get_plugin_resources(b,{success:this.onGotPluginResources,scope:this})},this)},onPluginEnabled:function(a){if(deluge.plugins[a]){deluge.plugins[a].enable()}else{deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})}},onGotPluginResources:function(b){var a=(Deluge.debug)?b.debug_scripts:b.scripts;Ext.each(a,function(c){Ext.ux.JSLoader({url:deluge.config.base+c,onLoad:this.onPluginLoaded,pluginName:b.name})},this)},onPluginDisabled:function(a){if(deluge.plugins[a]){deluge.plugins[a].disable()}},onPluginLoaded:function(a){if(!Deluge.hasPlugin(a.pluginName)){return}plugin=Deluge.createPlugin(a.pluginName);plugin.enable();deluge.plugins[plugin.name]=plugin},stop:function(){if(this.running){clearInterval(this.running);this.running=false;deluge.torrents.getStore().removeAll()}}};Ext.onReady(function(a){deluge.ui.initialize()});
\ No newline at end of file diff --git a/deluge/ui/web/js/deluge-all/Client.js b/deluge/ui/web/js/deluge-all/Client.js index 658cf7127..979099bea 100644 --- a/deluge/ui/web/js/deluge-all/Client.js +++ b/deluge/ui/web/js/deluge-all/Client.js @@ -40,20 +40,20 @@ Ext.namespace('Ext.ux.util'); Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { _components: [], - + _methods: [], - + _requests: {}, - + _url: null, - + _optionKeys: ['scope', 'success', 'failure'], - + constructor: function(config) { Ext.ux.util.RpcClient.superclass.constructor.call(this, config); this._url = config.url || null; this._id = 0; - + this.addEvents( // raw events /** @@ -62,16 +62,13 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { * @param {Ext.ux.util.RpcClient} this */ 'connected', - + 'error' ); this.reloadMethods(); }, - + reloadMethods: function() { - Ext.each(this._components, function(component) { - delete this[component]; - }, this); this._execute('system.listMethods', { success: this._setMethods, scope: this @@ -82,14 +79,14 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { options = options || {}; options.params = options.params || []; options.id = this._id; - + var request = Ext.encode({ method: method, params: options.params, id: options.id }); this._id++; - + return Ext.Ajax.request({ url: this._url, method: 'POST', @@ -100,7 +97,7 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { options: options }); }, - + _onFailure: function(response, requestOptions) { var options = requestOptions.options; errorObj = { @@ -111,23 +108,23 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { code: 255 } } - + this.fireEvent('error', errorObj, response, requestOptions) - + if (Ext.type(options.failure) != 'function') return; if (options.scope) { options.failure.call(options.scope, errorObj, response, requestOptions); } else { options.failure(errorObj, response, requestOptions); - } + } }, - + _onSuccess: function(response, requestOptions) { var responseObj = Ext.decode(response.responseText); var options = requestOptions.options; if (responseObj.error) { this.fireEvent('error', responseObj, response, requestOptions); - + if (Ext.type(options.failure) != 'function') return; if (options.scope) { options.failure.call(options.scope, responseObj, response, requestOptions); @@ -143,21 +140,21 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { } } }, - + _parseArgs: function(args) { var params = []; Ext.each(args, function(arg) { params.push(arg); }); - + var options = params[params.length - 1]; if (Ext.type(options) == 'object') { var keys = Ext.keys(options), isOption = false; - + Ext.each(this._optionKeys, function(key) { if (keys.indexOf(key) > -1) isOption = true; }); - + if (isOption) { params.remove(options) } else { @@ -172,11 +169,11 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { _setMethods: function(methods) { var components = {}, self = this; - + Ext.each(methods, function(method) { var parts = method.split('.'); var component = components[parts[0]] || {}; - + var fn = function() { var options = self._parseArgs(arguments); return self._execute(method, options); @@ -184,11 +181,15 @@ Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { component[parts[1]] = fn; components[parts[0]] = component; }); - + for (var name in components) { self[name] = components[name]; } - + Ext.each(this._components, function(component) { + if (!component in components) { + delete this[component]; + } + }, this); this._components = Ext.keys(components); this.fireEvent('connected', this); } diff --git a/deluge/ui/web/js/deluge-all/EventsManager.js b/deluge/ui/web/js/deluge-all/EventsManager.js index 9a799d53d..0204b3e7b 100644 --- a/deluge/ui/web/js/deluge-all/EventsManager.js +++ b/deluge/ui/web/js/deluge-all/EventsManager.js @@ -91,13 +91,15 @@ Deluge.EventsManager = Ext.extend(Ext.util.Observable, { }, onGetEventsSuccess: function(events) { - if (!events) return; - Ext.each(events, function(event) { - var name = event[0], args = event[1]; - args.splice(0, 0, name); - this.fireEvent.apply(this, args); - }, this); - if (this.running) this.getEvents(); + if (!this.running) return; + if (events) { + Ext.each(events, function(event) { + var name = event[0], args = event[1]; + args.splice(0, 0, name); + this.fireEvent.apply(this, args); + }, this); + } + this.getEvents(); }, // private diff --git a/deluge/ui/web/js/deluge-all/LoginWindow.js b/deluge/ui/web/js/deluge-all/LoginWindow.js index de77fd78f..2946a0155 100644 --- a/deluge/ui/web/js/deluge-all/LoginWindow.js +++ b/deluge/ui/web/js/deluge-all/LoginWindow.js @@ -59,15 +59,18 @@ Deluge.LoginWindow = Ext.extend(Ext.Window, { this.form = this.add({ xtype: 'form', baseCls: 'x-plain', - labelWidth: 55, - width: 300, - defaults: {width: 200}, + labelWidth: 120, + labelAlign: 'right', + defaults: {width: 110}, defaultType: 'textfield' }); this.passwordField = this.form.add({ xtype: 'textfield', fieldLabel: _('Password'), + grow: true, + growMin: '110', + growMax: '145', id: '_password', name: 'password', inputType: 'password' diff --git a/deluge/ui/web/js/deluge-all/Menus.js b/deluge/ui/web/js/deluge-all/Menus.js index c8430b615..87fab1777 100644 --- a/deluge/ui/web/js/deluge-all/Menus.js +++ b/deluge/ui/web/js/deluge-all/Menus.js @@ -98,10 +98,12 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, '-', { text: _('Options'), iconCls: 'icon-options', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('D/L Speed Limit'), iconCls: 'x-deluge-downloading', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('5 KiB/s') @@ -120,6 +122,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('U/L Speed Limit'), iconCls: 'x-deluge-seeding', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('5 KiB/s') @@ -138,6 +141,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('Connection Limit'), iconCls: 'x-deluge-connections', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('50') @@ -156,6 +160,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, { text: _('Upload Slot Limit'), iconCls: 'icon-upload-slots', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ text: _('0') @@ -180,6 +185,7 @@ deluge.menus.torrent = new Ext.menu.Menu({ }, '-', { text: _('Queue'), iconCls: 'icon-queue', + hideOnClick: false, menu: new Ext.menu.Menu({ items: [{ torrentAction: 'top', diff --git a/deluge/ui/web/js/deluge-all/Plugin.js b/deluge/ui/web/js/deluge-all/Plugin.js index 2453abe05..a3d544e85 100644 --- a/deluge/ui/web/js/deluge-all/Plugin.js +++ b/deluge/ui/web/js/deluge-all/Plugin.js @@ -76,6 +76,7 @@ Deluge.Plugin = Ext.extend(Ext.util.Observable, { * then executes the plugins setup method, onEnabled. */ enable: function() { + deluge.client.reloadMethods(); this.fireEvent("enable", this); if (this.onEnable) this.onEnable(); }, diff --git a/deluge/ui/web/js/deluge-all/TorrentGrid.js b/deluge/ui/web/js/deluge-all/TorrentGrid.js index 4c41b06bc..50be33b03 100644 --- a/deluge/ui/web/js/deluge-all/TorrentGrid.js +++ b/deluge/ui/web/js/deluge-all/TorrentGrid.js @@ -265,7 +265,7 @@ idProperty: 'id', fields: [ {name: 'queue', sortType: Deluge.data.SortTypes.asQueuePosition}, - {name: 'name'}, + {name: 'name', sortType: Deluge.data.SortTypes.asName}, {name: 'total_size', type: 'int'}, {name: 'state'}, {name: 'progress', type: 'float'}, diff --git a/deluge/ui/web/js/deluge-all/UI.js b/deluge/ui/web/js/deluge-all/UI.js index b4305c06f..08774afc2 100644 --- a/deluge/ui/web/js/deluge-all/UI.js +++ b/deluge/ui/web/js/deluge-all/UI.js @@ -256,7 +256,7 @@ deluge.ui = { }, onPluginDisabled: function(pluginName) { - deluge.plugins[pluginName].disable(); + if (deluge.plugins[pluginName]) deluge.plugins[pluginName].disable(); }, onPluginLoaded: function(options) { diff --git a/deluge/ui/web/js/deluge-all/add/FilesTab.js b/deluge/ui/web/js/deluge-all/add/FilesTab.js index 3e624823d..709105b1b 100644 --- a/deluge/ui/web/js/deluge-all/add/FilesTab.js +++ b/deluge/ui/web/js/deluge-all/add/FilesTab.js @@ -1,6 +1,6 @@ /*! * Deluge.add.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -40,7 +40,7 @@ Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { layout: 'fit', title: _('Files'), - autoScroll: true, + autoScroll: false, animate: false, border: false, disabled: true, diff --git a/deluge/ui/web/js/deluge-all/add/OptionsPanel.js b/deluge/ui/web/js/deluge-all/add/OptionsPanel.js index 629c46d85..466b0a0f0 100644 --- a/deluge/ui/web/js/deluge-all/add/OptionsPanel.js +++ b/deluge/ui/web/js/deluge-all/add/OptionsPanel.js @@ -39,7 +39,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, { region: 'south', margins: '5 5 5 5', activeTab: 0, - height: 220, + height: 265, initComponent: function() { Deluge.add.OptionsPanel.superclass.initComponent.call(this); diff --git a/deluge/ui/web/js/deluge-all/add/OptionsTab.js b/deluge/ui/web/js/deluge-all/add/OptionsTab.js index c65dc6f40..04ee39fac 100644 --- a/deluge/ui/web/js/deluge-all/add/OptionsTab.js +++ b/deluge/ui/web/js/deluge-all/add/OptionsTab.js @@ -1,6 +1,6 @@ /*! * Deluge.add.OptionsPanel.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -60,14 +60,30 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { fieldLabel: '', style: 'padding-bottom: 5px; margin-bottom: 0px;' }); - this.optionsManager.bind('download_location', fieldset.add({ fieldLabel: '', name: 'download_location', width: 400, labelSeparator: '' })); - + var fieldset = this.add({ + xtype: 'fieldset', + title: _('Move Completed Location'), + border: false, + autoHeight: true, + defaultType: 'togglefield', + labelWidth: 1, + fieldLabel: '', + style: 'padding-bottom: 5px; margin-bottom: 0px;' + }); + var field = fieldset.add({ + fieldLabel: '', + name: 'move_completed_path', + width: 425 + }); + this.optionsManager.bind('move_completed', field.toggle) + this.optionsManager.bind('move_completed_path', field.input) + var panel = this.add({ border: false, layout: 'column', @@ -77,8 +93,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { title: _('Allocation'), border: false, autoHeight: true, - defaultType: 'radio', - width: 100 + defaultType: 'radio' }); this.optionsManager.bind('compact_allocation', fieldset.add({ @@ -86,6 +101,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { columns: 1, vertical: true, labelSeparator: '', + width: 80, items: [{ name: 'compact_allocation', value: false, @@ -107,35 +123,32 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { title: _('Bandwidth'), border: false, autoHeight: true, - labelWidth: 100, + bodyStyle: 'margin-left: 7px', + labelWidth: 105, width: 200, defaultType: 'spinnerfield' }); this.optionsManager.bind('max_download_speed', fieldset.add({ fieldLabel: _('Max Down Speed'), - labelStyle: 'margin-left: 10px', name: 'max_download_speed', width: 60 })); this.optionsManager.bind('max_upload_speed', fieldset.add({ fieldLabel: _('Max Up Speed'), - labelStyle: 'margin-left: 10px', name: 'max_upload_speed', width: 60 })); this.optionsManager.bind('max_connections', fieldset.add({ fieldLabel: _('Max Connections'), - labelStyle: 'margin-left: 10px', name: 'max_connections', width: 60 })); this.optionsManager.bind('max_upload_slots', fieldset.add({ fieldLabel: _('Max Upload Slots'), - labelStyle: 'margin-left: 10px', name: 'max_upload_slots', width: 60 })); - + fieldset = panel.add({ title: _('General'), border: false, @@ -159,6 +172,7 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { getDefaults: function() { var keys = ['add_paused','compact_allocation','download_location', 'max_connections_per_torrent','max_download_speed_per_torrent', + 'move_completed', 'move_completed_path', 'max_upload_slots_per_torrent','max_upload_speed_per_torrent', 'prioritize_first_last_pieces']; @@ -169,6 +183,8 @@ Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { 'add_paused': config.add_paused, 'compact_allocation': config.compact_allocation, 'download_location': config.download_location, + 'move_completed': config.move_completed, + 'move_completed_path': config.move_completed_path, 'max_connections': config.max_connections_per_torrent, 'max_download_speed': config.max_download_speed_per_torrent, 'max_upload_slots': config.max_upload_slots_per_torrent, diff --git a/deluge/ui/web/js/deluge-all/add/UrlWindow.js b/deluge/ui/web/js/deluge-all/add/UrlWindow.js index 3aba36c1f..8a8a1c1de 100644 --- a/deluge/ui/web/js/deluge-all/add/UrlWindow.js +++ b/deluge/ui/web/js/deluge-all/add/UrlWindow.js @@ -81,7 +81,7 @@ Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, { var cookies = this.cookieField.getValue(); var torrentId = this.createTorrentId(); - if (url.substring(0,20) == 'magnet:?xt=urn:btih:') { + if (url.indexOf('magnet:?') == 0 && url.indexOf('xt=urn:btih') > -1) { deluge.client.web.get_magnet_info(url, { success: this.onGotInfo, scope: this, diff --git a/deluge/ui/web/js/deluge-all/data/SortTypes.js b/deluge/ui/web/js/deluge-all/data/SortTypes.js index e404ba348..3a6de182f 100644 --- a/deluge/ui/web/js/deluge-all/data/SortTypes.js +++ b/deluge/ui/web/js/deluge-all/data/SortTypes.js @@ -1,6 +1,6 @@ /*! * Deluge.data.SortTypes.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -39,7 +39,7 @@ Ext.namespace('Deluge.data'); * * @class Deluge.data.SortTypes * @singleton - */ + */ Deluge.data.SortTypes = { asIPAddress: function(value) { var d = value.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/); @@ -48,5 +48,9 @@ Deluge.data.SortTypes = { asQueuePosition: function(value) { return (value > -1) ? value : Number.MAX_VALUE; + }, + + asName: function(value) { + return String(value).toLowerCase(); } } diff --git a/deluge/ui/web/js/deluge-all/data/TorrentRecord.js b/deluge/ui/web/js/deluge-all/data/TorrentRecord.js index d13806c14..f92cfc641 100644 --- a/deluge/ui/web/js/deluge-all/data/TorrentRecord.js +++ b/deluge/ui/web/js/deluge-all/data/TorrentRecord.js @@ -1,6 +1,6 @@ /*! * Deluge.data.TorrentRecord.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -47,7 +47,8 @@ Deluge.data.Torrent = Ext.data.Record.create([{ type: 'int' }, { name: 'name', - type: 'string' + type: 'string', + sortType: Deluge.data.SortTypes.asName }, { name: 'total_size', type: 'int' diff --git a/deluge/ui/web/js/deluge-all/details/DetailsTab.js b/deluge/ui/web/js/deluge-all/details/DetailsTab.js index ca41478d4..82d54f3bc 100644 --- a/deluge/ui/web/js/deluge-all/details/DetailsTab.js +++ b/deluge/ui/web/js/deluge-all/details/DetailsTab.js @@ -36,7 +36,7 @@ Deluge.details.DetailsTab = Ext.extend(Ext.Panel, { title: _('Details'), fields: {}, - + autoScroll: true, queuedItems: {}, oldData: {}, diff --git a/deluge/ui/web/js/deluge-all/details/FilesTab.js b/deluge/ui/web/js/deluge-all/details/FilesTab.js index 061ed7950..31ab79f55 100644 --- a/deluge/ui/web/js/deluge-all/details/FilesTab.js +++ b/deluge/ui/web/js/deluge-all/details/FilesTab.js @@ -1,6 +1,6 @@ /*! * Deluge.details.FilesTab.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -29,12 +29,11 @@ * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ - + Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { title: _('Files'), - autoScroll: true, rootVisible: false, columns: [{ @@ -74,7 +73,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { } }) }], - + selModel: new Ext.tree.MultiSelectionModel(), initComponent: function() { @@ -130,7 +129,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { this.clear(); this.torrentId = torrentId; } - + deluge.client.web.get_torrent_files(torrentId, { success: this.onRequestComplete, scope: this, @@ -163,7 +162,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { folderSort: true }); }, - + onContextMenu: function(node, e) { e.stopEvent(); var selModel = this.getSelectionModel(); @@ -173,7 +172,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { } deluge.menus.filePriorities.showAt(e.getPoint()); }, - + onItemClick: function(baseItem, e) { switch (baseItem.id) { case 'expandAll': @@ -200,7 +199,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { return; } }); - + var priorities = new Array(Ext.keys(indexes).length); for (var index in indexes) { priorities[index] = indexes[index]; @@ -217,7 +216,7 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { break; } }, - + onRequestComplete: function(files, options) { if (!this.getRootNode().hasChildNodes()) { this.createFileTree(files); diff --git a/deluge/ui/web/js/deluge-all/details/PeersTab.js b/deluge/ui/web/js/deluge-all/details/PeersTab.js index bb45d6655..490c49ff4 100644 --- a/deluge/ui/web/js/deluge-all/details/PeersTab.js +++ b/deluge/ui/web/js/deluge-all/details/PeersTab.js @@ -35,7 +35,7 @@ if (!value.replace(' ', '').replace(' ', '')){ return ''; } - return String.format('<img src="flag/{0}" />', value); + return String.format('<img src="{0}flag/{1}" />', deluge.config.base, value); } function peerAddressRenderer(value, p, record) { var seed = (record.data['seed'] == 1024) ? 'x-deluge-seed' : 'x-deluge-peer'; diff --git a/deluge/ui/web/js/deluge-all/preferences/ProxyField.js b/deluge/ui/web/js/deluge-all/preferences/ProxyField.js index 811372128..fe969b9ba 100644 --- a/deluge/ui/web/js/deluge-all/preferences/ProxyField.js +++ b/deluge/ui/web/js/deluge-all/preferences/ProxyField.js @@ -1,6 +1,6 @@ /*! * Deluge.preferences.ProxyField.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -58,19 +58,23 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { [3, _('Socksv5 with Auth')], [4, _('HTTP')], [5, _('HTTP with Auth')] - ] - }), + ] + }), editable: false, triggerAction: 'all', valueField: 'id', displayField: 'text' }); + this.proxyType.on('change', this.onFieldChange, this); + this.proxyType.on('select', this.onTypeSelect, this); + this.hostname = this.add({ xtype: 'textfield', name: 'hostname', fieldLabel: _('Host'), width: 220 }); + this.hostname.on('change', this.onFieldChange, this); this.port = this.add({ xtype: 'spinnerfield', @@ -81,6 +85,7 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { minValue: -1, maxValue: 99999 }); + this.port.on('change', this.onFieldChange, this); this.username = this.add({ xtype: 'textfield', @@ -88,6 +93,7 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { fieldLabel: _('Username'), width: 220 }); + this.username.on('change', this.onFieldChange, this); this.password = this.add({ xtype: 'textfield', @@ -96,9 +102,8 @@ Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { inputType: 'password', width: 220 }); + this.password.on('change', this.onFieldChange, this); - this.proxyType.on('change', this.onFieldChange, this); - this.proxyType.on('select', this.onTypeSelect, this); this.setting = false; }, diff --git a/deluge/ui/web/js/deluge-all/preferences/ProxyPage.js b/deluge/ui/web/js/deluge-all/preferences/ProxyPage.js index db4740fb6..0cb61a439 100644 --- a/deluge/ui/web/js/deluge-all/preferences/ProxyPage.js +++ b/deluge/ui/web/js/deluge-all/preferences/ProxyPage.js @@ -1,6 +1,6 @@ /*! * Deluge.preferences.ProxyPage.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -40,11 +40,12 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { config = Ext.apply({ border: false, title: _('Proxy'), - layout: 'form' + layout: 'form', + autoScroll: true }, config); Deluge.preferences.Proxy.superclass.constructor.call(this, config); }, - + initComponent: function() { Deluge.preferences.Proxy.superclass.initComponent.call(this); this.peer = this.add(new Deluge.preferences.ProxyField({ @@ -52,28 +53,28 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { name: 'peer' })); this.peer.on('change', this.onProxyChange, this); - + this.web_seed = this.add(new Deluge.preferences.ProxyField({ title: _('Web Seed'), name: 'web_seed' })); this.web_seed.on('change', this.onProxyChange, this); - + this.tracker = this.add(new Deluge.preferences.ProxyField({ title: _('Tracker'), name: 'tracker' })); this.tracker.on('change', this.onProxyChange, this); - + this.dht = this.add(new Deluge.preferences.ProxyField({ title: _('DHT'), name: 'dht' })); this.dht.on('change', this.onProxyChange, this); - + deluge.preferences.getOptionsManager().bind('proxies', this); }, - + getValue: function() { return { 'dht': this.dht.getValue(), @@ -82,18 +83,18 @@ Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { 'web_seed': this.web_seed.getValue() } }, - + setValue: function(value) { for (var proxy in value) { this[proxy].setValue(value[proxy]); } }, - + onProxyChange: function(field, newValue, oldValue) { var newValues = this.getValue(); var oldValues = Ext.apply({}, newValues); oldValues[field.getName()] = oldValue; - + this.fireEvent('change', this, newValues, oldValues); } }); diff --git a/deluge/ui/web/js/ext-extensions-debug.js b/deluge/ui/web/js/ext-extensions-debug.js index ae3841c1a..365e7618d 100644 --- a/deluge/ui/web/js/ext-extensions-debug.js +++ b/deluge/ui/web/js/ext-extensions-debug.js @@ -1543,7 +1543,7 @@ Ext.override(Ext.ux.form.SpinnerField, { }); /*! * Ext.ux.form.SpinnerGroup.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -1581,6 +1581,7 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, { // private defaultType: 'spinnerfield', + anchor: '98%', // private groupCls: 'x-form-spinner-group', @@ -1697,6 +1698,7 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, { this.items.each(function(field) { field.on('spin', this.onFieldChange, this); + field.on('change', this.onFieldChange, this); }, this); if (this.lazyValueSet) { diff --git a/deluge/ui/web/js/ext-extensions.js b/deluge/ui/web/js/ext-extensions.js index e77e6e257..be6f182cb 100644 --- a/deluge/ui/web/js/ext-extensions.js +++ b/deluge/ui/web/js/ext-extensions.js @@ -191,7 +191,7 @@ Ext.ns("Ext.ux.form");Ext.ux.form.SpinnerField=Ext.extend(Ext.form.NumberField,{ Ext.override(Ext.ux.form.SpinnerField,{onBlur:Ext.form.Field.prototype.onBlur}); /* * Ext.ux.form.SpinnerGroup.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -220,7 +220,7 @@ Ext.override(Ext.ux.form.SpinnerField,{onBlur:Ext.form.Field.prototype.onBlur}); * this exception statement from your version. If you delete this exception * statement from all source files in the program, then also delete it here. */ -Ext.ns("Ext.ux.form");Ext.ux.form.SpinnerGroup=Ext.extend(Ext.form.CheckboxGroup,{defaultType:"spinnerfield",groupCls:"x-form-spinner-group",colCfg:{},onRender:function(h,f){if(!this.el){var o={cls:this.groupCls,layout:"column",border:false,renderTo:h};var a=Ext.apply({defaultType:this.defaultType,layout:"form",border:false,labelWidth:60,defaults:{hideLabel:true,anchor:"60%"}},this.colCfg);if(this.items[0].items){Ext.apply(o,{layoutConfig:{columns:this.items.length},defaults:this.defaults,items:this.items});for(var e=0,k=this.items.length;e<k;e++){Ext.applyIf(this.items[e],a)}}else{var d,m=[];if(typeof this.columns=="string"){this.columns=this.items.length}if(!Ext.isArray(this.columns)){var j=[];for(var e=0;e<this.columns;e++){j.push((100/this.columns)*0.01)}this.columns=j}d=this.columns.length;for(var e=0;e<d;e++){var b=Ext.apply({items:[]},a);b[this.columns[e]<=1?"columnWidth":"width"]=this.columns[e];if(this.defaults){b.defaults=Ext.apply(b.defaults||{},this.defaults)}m.push(b)}if(this.vertical){var q=Math.ceil(this.items.length/d),n=0;for(var e=0,k=this.items.length;e<k;e++){if(e>0&&e%q==0){n++}if(this.items[e].fieldLabel){this.items[e].hideLabel=false}m[n].items.push(this.items[e])}}else{for(var e=0,k=this.items.length;e<k;e++){var p=e%d;if(this.items[e].fieldLabel){this.items[e].hideLabel=false}m[p].items.push(this.items[e])}}Ext.apply(o,{layoutConfig:{columns:d},items:m})}this.panel=new Ext.Panel(o);this.el=this.panel.getEl();if(this.forId&&this.itemCls){var c=this.el.up(this.itemCls).child("label",true);if(c){c.setAttribute("htmlFor",this.forId)}}var g=this.panel.findBy(function(l){return l.isFormField},this);this.items=new Ext.util.MixedCollection();this.items.addAll(g);this.items.each(function(l){l.on("spin",this.onFieldChange,this)},this);if(this.lazyValueSet){this.setValue(this.value);delete this.value;delete this.lazyValueSet}if(this.lazyRawValueSet){this.setRawValue(this.rawValue);delete this.rawValue;delete this.lazyRawValueSet}}Ext.ux.form.SpinnerGroup.superclass.onRender.call(this,h,f)},onFieldChange:function(a){this.fireEvent("change",this,this.getValue())},initValue:Ext.emptyFn,getValue:function(){var a=[this.items.getCount()];this.items.each(function(c,b){a[b]=Number(c.getValue())});return a},getRawValue:function(){var a=[this.items.getCount()];this.items.each(function(c,b){a[b]=Number(c.getRawValue())});return a},setValue:function(a){if(!this.rendered){this.value=a;this.lazyValueSet=true}else{this.items.each(function(c,b){c.setValue(a[b])})}},setRawValue:function(a){if(!this.rendered){this.rawValue=a;this.lazyRawValueSet=true}else{this.items.each(function(c,b){c.setRawValue(a[b])})}}});Ext.reg("spinnergroup",Ext.ux.form.SpinnerGroup); +Ext.ns("Ext.ux.form");Ext.ux.form.SpinnerGroup=Ext.extend(Ext.form.CheckboxGroup,{defaultType:"spinnerfield",anchor:"98%",groupCls:"x-form-spinner-group",colCfg:{},onRender:function(h,f){if(!this.el){var o={cls:this.groupCls,layout:"column",border:false,renderTo:h};var a=Ext.apply({defaultType:this.defaultType,layout:"form",border:false,labelWidth:60,defaults:{hideLabel:true,anchor:"60%"}},this.colCfg);if(this.items[0].items){Ext.apply(o,{layoutConfig:{columns:this.items.length},defaults:this.defaults,items:this.items});for(var e=0,k=this.items.length;e<k;e++){Ext.applyIf(this.items[e],a)}}else{var d,m=[];if(typeof this.columns=="string"){this.columns=this.items.length}if(!Ext.isArray(this.columns)){var j=[];for(var e=0;e<this.columns;e++){j.push((100/this.columns)*0.01)}this.columns=j}d=this.columns.length;for(var e=0;e<d;e++){var b=Ext.apply({items:[]},a);b[this.columns[e]<=1?"columnWidth":"width"]=this.columns[e];if(this.defaults){b.defaults=Ext.apply(b.defaults||{},this.defaults)}m.push(b)}if(this.vertical){var q=Math.ceil(this.items.length/d),n=0;for(var e=0,k=this.items.length;e<k;e++){if(e>0&&e%q==0){n++}if(this.items[e].fieldLabel){this.items[e].hideLabel=false}m[n].items.push(this.items[e])}}else{for(var e=0,k=this.items.length;e<k;e++){var p=e%d;if(this.items[e].fieldLabel){this.items[e].hideLabel=false}m[p].items.push(this.items[e])}}Ext.apply(o,{layoutConfig:{columns:d},items:m})}this.panel=new Ext.Panel(o);this.el=this.panel.getEl();if(this.forId&&this.itemCls){var c=this.el.up(this.itemCls).child("label",true);if(c){c.setAttribute("htmlFor",this.forId)}}var g=this.panel.findBy(function(l){return l.isFormField},this);this.items=new Ext.util.MixedCollection();this.items.addAll(g);this.items.each(function(l){l.on("spin",this.onFieldChange,this);l.on("change",this.onFieldChange,this)},this);if(this.lazyValueSet){this.setValue(this.value);delete this.value;delete this.lazyValueSet}if(this.lazyRawValueSet){this.setRawValue(this.rawValue);delete this.rawValue;delete this.lazyRawValueSet}}Ext.ux.form.SpinnerGroup.superclass.onRender.call(this,h,f)},onFieldChange:function(a){this.fireEvent("change",this,this.getValue())},initValue:Ext.emptyFn,getValue:function(){var a=[this.items.getCount()];this.items.each(function(c,b){a[b]=Number(c.getValue())});return a},getRawValue:function(){var a=[this.items.getCount()];this.items.each(function(c,b){a[b]=Number(c.getRawValue())});return a},setValue:function(a){if(!this.rendered){this.value=a;this.lazyValueSet=true}else{this.items.each(function(c,b){c.setValue(a[b])})}},setRawValue:function(a){if(!this.rendered){this.rawValue=a;this.lazyRawValueSet=true}else{this.items.each(function(c,b){c.setRawValue(a[b])})}}});Ext.reg("spinnergroup",Ext.ux.form.SpinnerGroup); /* * Ext.ux.form.ToggleField.js * diff --git a/deluge/ui/web/js/ext-extensions/form/SpinnerGroup.js b/deluge/ui/web/js/ext-extensions/form/SpinnerGroup.js index 7e042fb5a..4ad3a7bf1 100644 --- a/deluge/ui/web/js/ext-extensions/form/SpinnerGroup.js +++ b/deluge/ui/web/js/ext-extensions/form/SpinnerGroup.js @@ -1,6 +1,6 @@ /*! * Ext.ux.form.SpinnerGroup.js - * + * * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * * This program is free software; you can redistribute it and/or modify @@ -38,6 +38,7 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, { // private defaultType: 'spinnerfield', + anchor: '98%', // private groupCls: 'x-form-spinner-group', @@ -154,6 +155,7 @@ Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, { this.items.each(function(field) { field.on('spin', this.onFieldChange, this); + field.on('change', this.onFieldChange, this); }, this); if (this.lazyValueSet) { diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py index 8b0fc9473..4febab156 100644 --- a/deluge/ui/web/json_api.py +++ b/deluge/ui/web/json_api.py @@ -115,49 +115,47 @@ class JSON(resource.Resource, component.Component): self._remote_methods = [] self._local_methods = {} if client.is_classicmode(): - def on_got_methods(methods): - """ - Handles receiving the method names - """ - self._remote_methods = methods - - client.daemon.get_method_list().addCallback(on_got_methods) + self.get_remote_methods() else: client.disconnect_callback = self._on_client_disconnect + def on_get_methods(self, methods): + """ + Handles receiving the method names. + """ + self._remote_methods = methods + + def get_remote_methods(self, result=None): + """ + Updates remote methods from the daemon. + """ + return client.daemon.get_method_list().addCallback(self.on_get_methods) + def connect(self, host="localhost", port=58846, username="", password=""): """ Connects the client to a daemon """ - d = Deferred() - _d = client.connect(host, port, username, password) - - def on_get_methods(methods): - """ - Handles receiving the method names - """ - self._remote_methods = methods - methods = list(self._remote_methods) - methods.extend(self._local_methods) - d.callback(methods) + d = client.connect(host, port, username, password) def on_client_connected(connection_id): """ Handles the client successfully connecting to the daemon and invokes retrieving the method names. """ - d = client.daemon.get_method_list() - d.addCallback(on_get_methods) + d = self.get_remote_methods() component.get("Web.PluginManager").start() component.get("Web").start() - _d.addCallback(on_client_connected) - return d + return d + + return d.addCallback(on_client_connected) def disable(self): if not client.is_classicmode(): client.disconnect() def enable(self): + client.register_event_handler("PluginEnabledEvent", self.get_remote_methods) + client.register_event_handler("PluginDisabledEvent", self.get_remote_methods) if component.get("DelugeWeb").config["default_daemon"]: # Sort out getting the default daemon here default = component.get("DelugeWeb").config["default_daemon"] @@ -722,24 +720,29 @@ class WebApi(JSONComponent): :rtype: dictionary """ - try: - s = uri.split("&")[0][20:] - if len(s) == 32: - info_hash = base64.b32decode(s).encode("hex") - elif len(s) == 40: - info_hash = s - else: - return False + magnet_scheme = 'magnet:?' + xt_param = 'xt=urn:btih:' + dn_param = 'dn=' + if uri.startswith(magnet_scheme): name = None - for i in uri.split("&")[1:]: - if i[:3] == "dn=": - name = unquote_plus(i.split("=")[1]) - if not name: - name = info_hash - return {"name":name, "info_hash":info_hash, "files_tree":''} - except Exception, e: - log.exception(e) - return False + info_hash = None + for param in uri[len(magnet_scheme):].split('&'): + if param.startswith(xt_param): + xt_hash = param[len(xt_param):] + if len(xt_hash) == 32: + info_hash = base64.b32decode(xt_hash).encode("hex") + elif len(xt_hash) == 40: + info_hash = xt_hash + else: + break + elif param.startswith(dn_param): + name = unquote_plus(param[len(dn_param):]) + + if info_hash: + if not name: + name = info_hash + return {"name":name, "info_hash":info_hash, "files_tree":''} + return False @export def add_torrents(self, torrents): @@ -754,7 +757,7 @@ class WebApi(JSONComponent): >>> json_api.web.add_torrents([{ "path": "/tmp/deluge-web/some-torrent-file.torrent", - "options": {"download_path": "/home/deluge/"} + "options": {"download_location": "/home/deluge/"} }]) """ diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/bg-center.gif b/deluge/ui/web/themes/images/vista/basic-dialog/bg-center.gif Binary files differdeleted file mode 100644 index 7bf4a4b41..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/bg-center.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/bg-left.gif b/deluge/ui/web/themes/images/vista/basic-dialog/bg-left.gif Binary files differdeleted file mode 100644 index 94b1dafc7..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/bg-left.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/bg-right.gif b/deluge/ui/web/themes/images/vista/basic-dialog/bg-right.gif Binary files differdeleted file mode 100644 index 6dadaf683..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/bg-right.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/close.gif b/deluge/ui/web/themes/images/vista/basic-dialog/close.gif Binary files differdeleted file mode 100644 index 4278db983..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/collapse.gif b/deluge/ui/web/themes/images/vista/basic-dialog/collapse.gif Binary files differdeleted file mode 100644 index b07e297e5..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/dlg-bg.gif b/deluge/ui/web/themes/images/vista/basic-dialog/dlg-bg.gif Binary files differdeleted file mode 100644 index 1a466633d..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/dlg-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/e-handle.gif b/deluge/ui/web/themes/images/vista/basic-dialog/e-handle.gif Binary files differdeleted file mode 100644 index 48877e748..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/e-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/expand.gif b/deluge/ui/web/themes/images/vista/basic-dialog/expand.gif Binary files differdeleted file mode 100644 index 5b4b0d1e9..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/hd-sprite.gif b/deluge/ui/web/themes/images/vista/basic-dialog/hd-sprite.gif Binary files differdeleted file mode 100644 index 3c2dd632d..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/hd-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/s-handle.gif b/deluge/ui/web/themes/images/vista/basic-dialog/s-handle.gif Binary files differdeleted file mode 100644 index c13c9cdc0..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/s-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/se-handle.gif b/deluge/ui/web/themes/images/vista/basic-dialog/se-handle.gif Binary files differdeleted file mode 100644 index c4e38a2f4..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/se-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/basic-dialog/w-handle.gif b/deluge/ui/web/themes/images/vista/basic-dialog/w-handle.gif Binary files differdeleted file mode 100644 index d59eafc20..000000000 --- a/deluge/ui/web/themes/images/vista/basic-dialog/w-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/gradient-bg.gif b/deluge/ui/web/themes/images/vista/gradient-bg.gif Binary files differdeleted file mode 100644 index 8134e4994..000000000 --- a/deluge/ui/web/themes/images/vista/gradient-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/grid/grid-split.gif b/deluge/ui/web/themes/images/vista/grid/grid-split.gif Binary files differdeleted file mode 100644 index c76a16e95..000000000 --- a/deluge/ui/web/themes/images/vista/grid/grid-split.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/grid/grid-vista-hd.gif b/deluge/ui/web/themes/images/vista/grid/grid-vista-hd.gif Binary files differdeleted file mode 100644 index d0972638e..000000000 --- a/deluge/ui/web/themes/images/vista/grid/grid-vista-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/collapse.gif b/deluge/ui/web/themes/images/vista/layout/collapse.gif Binary files differdeleted file mode 100644 index cbd6e081c..000000000 --- a/deluge/ui/web/themes/images/vista/layout/collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/expand.gif b/deluge/ui/web/themes/images/vista/layout/expand.gif Binary files differdeleted file mode 100644 index 8103c0dd7..000000000 --- a/deluge/ui/web/themes/images/vista/layout/expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/gradient-bg.gif b/deluge/ui/web/themes/images/vista/layout/gradient-bg.gif Binary files differdeleted file mode 100644 index d311e7de6..000000000 --- a/deluge/ui/web/themes/images/vista/layout/gradient-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/ns-collapse.gif b/deluge/ui/web/themes/images/vista/layout/ns-collapse.gif Binary files differdeleted file mode 100644 index f2ad235da..000000000 --- a/deluge/ui/web/themes/images/vista/layout/ns-collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/ns-expand.gif b/deluge/ui/web/themes/images/vista/layout/ns-expand.gif Binary files differdeleted file mode 100644 index 0817ec66f..000000000 --- a/deluge/ui/web/themes/images/vista/layout/ns-expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/panel-close.gif b/deluge/ui/web/themes/images/vista/layout/panel-close.gif Binary files differdeleted file mode 100644 index 4e96481a1..000000000 --- a/deluge/ui/web/themes/images/vista/layout/panel-close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/panel-title-bg.gif b/deluge/ui/web/themes/images/vista/layout/panel-title-bg.gif Binary files differdeleted file mode 100644 index 681f517a3..000000000 --- a/deluge/ui/web/themes/images/vista/layout/panel-title-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/panel-title-light-bg.gif b/deluge/ui/web/themes/images/vista/layout/panel-title-light-bg.gif Binary files differdeleted file mode 100644 index 23d8288b0..000000000 --- a/deluge/ui/web/themes/images/vista/layout/panel-title-light-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/stick.gif b/deluge/ui/web/themes/images/vista/layout/stick.gif Binary files differdeleted file mode 100644 index 7db68eec9..000000000 --- a/deluge/ui/web/themes/images/vista/layout/stick.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/tab-close-on.gif b/deluge/ui/web/themes/images/vista/layout/tab-close-on.gif Binary files differdeleted file mode 100644 index 556e905b1..000000000 --- a/deluge/ui/web/themes/images/vista/layout/tab-close-on.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/layout/tab-close.gif b/deluge/ui/web/themes/images/vista/layout/tab-close.gif Binary files differdeleted file mode 100644 index 0a6f01987..000000000 --- a/deluge/ui/web/themes/images/vista/layout/tab-close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/qtip/bg.gif b/deluge/ui/web/themes/images/vista/qtip/bg.gif Binary files differdeleted file mode 100644 index 5c0e8c92a..000000000 --- a/deluge/ui/web/themes/images/vista/qtip/bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/qtip/tip-sprite.gif b/deluge/ui/web/themes/images/vista/qtip/tip-sprite.gif Binary files differdeleted file mode 100644 index a1862865d..000000000 --- a/deluge/ui/web/themes/images/vista/qtip/tip-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/s.gif b/deluge/ui/web/themes/images/vista/s.gif Binary files differdeleted file mode 100644 index 1d11fa9ad..000000000 --- a/deluge/ui/web/themes/images/vista/s.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/e-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/e-handle-dark.gif Binary files differdeleted file mode 100644 index eac9662ea..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/e-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/e-handle.gif b/deluge/ui/web/themes/images/vista/sizer/e-handle.gif Binary files differdeleted file mode 100644 index f2c9f5382..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/e-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/ne-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/ne-handle-dark.gif Binary files differdeleted file mode 100644 index c9c041c45..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/ne-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/ne-handle.gif b/deluge/ui/web/themes/images/vista/sizer/ne-handle.gif Binary files differdeleted file mode 100644 index 942ae8253..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/ne-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/nw-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/nw-handle-dark.gif Binary files differdeleted file mode 100644 index 23fced98b..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/nw-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/nw-handle.gif b/deluge/ui/web/themes/images/vista/sizer/nw-handle.gif Binary files differdeleted file mode 100644 index d39b0c38d..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/nw-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/s-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/s-handle-dark.gif Binary files differdeleted file mode 100644 index ddc2e18ce..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/s-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/s-handle.gif b/deluge/ui/web/themes/images/vista/sizer/s-handle.gif Binary files differdeleted file mode 100644 index 827c3330a..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/s-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/se-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/se-handle-dark.gif Binary files differdeleted file mode 100644 index 1a678e67f..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/se-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/se-handle.gif b/deluge/ui/web/themes/images/vista/sizer/se-handle.gif Binary files differdeleted file mode 100644 index 69b5a9ed5..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/se-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/sw-handle-dark.gif b/deluge/ui/web/themes/images/vista/sizer/sw-handle-dark.gif Binary files differdeleted file mode 100644 index 937102c6b..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/sw-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/sizer/sw-handle.gif b/deluge/ui/web/themes/images/vista/sizer/sw-handle.gif Binary files differdeleted file mode 100644 index b9e2f563a..000000000 --- a/deluge/ui/web/themes/images/vista/sizer/sw-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-left-bg.gif b/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-left-bg.gif Binary files differdeleted file mode 100644 index 667beeb32..000000000 --- a/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-left-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-right-bg.gif b/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-right-bg.gif Binary files differdeleted file mode 100644 index 6c4e0a45f..000000000 --- a/deluge/ui/web/themes/images/vista/tabs/tab-btm-inactive-right-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/tabs/tab-btm-left-bg.gif b/deluge/ui/web/themes/images/vista/tabs/tab-btm-left-bg.gif Binary files differdeleted file mode 100644 index 1d81e54e1..000000000 --- a/deluge/ui/web/themes/images/vista/tabs/tab-btm-left-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/tabs/tab-btm-right-bg.gif b/deluge/ui/web/themes/images/vista/tabs/tab-btm-right-bg.gif Binary files differdeleted file mode 100644 index 47d005002..000000000 --- a/deluge/ui/web/themes/images/vista/tabs/tab-btm-right-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/tabs/tab-sprite.gif b/deluge/ui/web/themes/images/vista/tabs/tab-sprite.gif Binary files differdeleted file mode 100644 index a16eedb82..000000000 --- a/deluge/ui/web/themes/images/vista/tabs/tab-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/toolbar/gray-bg.gif b/deluge/ui/web/themes/images/vista/toolbar/gray-bg.gif Binary files differdeleted file mode 100644 index 9af15c262..000000000 --- a/deluge/ui/web/themes/images/vista/toolbar/gray-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/vista/toolbar/tb-btn-sprite.gif b/deluge/ui/web/themes/images/vista/toolbar/tb-btn-sprite.gif Binary files differdeleted file mode 100644 index f21b0d612..000000000 --- a/deluge/ui/web/themes/images/vista/toolbar/tb-btn-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/README.txt b/deluge/ui/web/themes/images/yourtheme/README.txt deleted file mode 100644 index acc508732..000000000 --- a/deluge/ui/web/themes/images/yourtheme/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -2010-03-16 jwr: -The image directory, "yourtheme", is an exact copy of the "default" image directory. Remember to update your file paths in "css/yourtheme.css" if you make changes or add your own custom images for your custom theme.
\ No newline at end of file diff --git a/deluge/ui/web/themes/images/yourtheme/box/corners-blue.gif b/deluge/ui/web/themes/images/yourtheme/box/corners-blue.gif Binary files differdeleted file mode 100644 index fa419b50a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/corners-blue.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/corners.gif b/deluge/ui/web/themes/images/yourtheme/box/corners.gif Binary files differdeleted file mode 100644 index 8aa8cae5c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/corners.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/l-blue.gif b/deluge/ui/web/themes/images/yourtheme/box/l-blue.gif Binary files differdeleted file mode 100644 index 5ed7f0043..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/l-blue.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/l.gif b/deluge/ui/web/themes/images/yourtheme/box/l.gif Binary files differdeleted file mode 100644 index 0160f97fe..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/l.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/r-blue.gif b/deluge/ui/web/themes/images/yourtheme/box/r-blue.gif Binary files differdeleted file mode 100644 index 3ea5cae3b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/r-blue.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/r.gif b/deluge/ui/web/themes/images/yourtheme/box/r.gif Binary files differdeleted file mode 100644 index 34237f629..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/r.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/tb-blue.gif b/deluge/ui/web/themes/images/yourtheme/box/tb-blue.gif Binary files differdeleted file mode 100644 index 562fecca8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/tb-blue.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/box/tb.gif b/deluge/ui/web/themes/images/yourtheme/box/tb.gif Binary files differdeleted file mode 100644 index 435889bff..000000000 --- a/deluge/ui/web/themes/images/yourtheme/box/tb.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/arrow.gif b/deluge/ui/web/themes/images/yourtheme/button/arrow.gif Binary files differdeleted file mode 100644 index 3ab4f71ac..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/arrow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/btn.gif b/deluge/ui/web/themes/images/yourtheme/button/btn.gif Binary files differdeleted file mode 100644 index 06b404dd7..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/btn.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/group-cs.gif b/deluge/ui/web/themes/images/yourtheme/button/group-cs.gif Binary files differdeleted file mode 100644 index 3d1dca8f0..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/group-cs.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/group-lr.gif b/deluge/ui/web/themes/images/yourtheme/button/group-lr.gif Binary files differdeleted file mode 100644 index 7c549f96d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/group-lr.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/group-tb.gif b/deluge/ui/web/themes/images/yourtheme/button/group-tb.gif Binary files differdeleted file mode 100644 index adeb0a4cf..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/group-tb.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b-noline.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b-noline.gif Binary files differdeleted file mode 100644 index a4220ee90..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b-noline.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b.gif Binary files differdeleted file mode 100644 index 84b647030..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-b.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-bo.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow-bo.gif Binary files differdeleted file mode 100644 index 548700bf4..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-bo.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-noline.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow-noline.gif Binary files differdeleted file mode 100644 index 0953eab5c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-noline.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-o.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow-o.gif Binary files differdeleted file mode 100644 index 89c70f36f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow-o.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/button/s-arrow.gif b/deluge/ui/web/themes/images/yourtheme/button/s-arrow.gif Binary files differdeleted file mode 100644 index 894077478..000000000 --- a/deluge/ui/web/themes/images/yourtheme/button/s-arrow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/dd/drop-add.gif b/deluge/ui/web/themes/images/yourtheme/dd/drop-add.gif Binary files differdeleted file mode 100644 index b22cd1448..000000000 --- a/deluge/ui/web/themes/images/yourtheme/dd/drop-add.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/dd/drop-no.gif b/deluge/ui/web/themes/images/yourtheme/dd/drop-no.gif Binary files differdeleted file mode 100644 index 08d083355..000000000 --- a/deluge/ui/web/themes/images/yourtheme/dd/drop-no.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/dd/drop-yes.gif b/deluge/ui/web/themes/images/yourtheme/dd/drop-yes.gif Binary files differdeleted file mode 100644 index 8aacb307e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/dd/drop-yes.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/editor/tb-sprite.gif b/deluge/ui/web/themes/images/yourtheme/editor/tb-sprite.gif Binary files differdeleted file mode 100644 index fb7057761..000000000 --- a/deluge/ui/web/themes/images/yourtheme/editor/tb-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/checkbox.gif b/deluge/ui/web/themes/images/yourtheme/form/checkbox.gif Binary files differdeleted file mode 100644 index 835b346cc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/checkbox.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.gif b/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.gif Binary files differdeleted file mode 100644 index da78d45b3..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.psd b/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.psd Binary files differdeleted file mode 100644 index f637fa5d1..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/clear-trigger.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/date-trigger.gif b/deluge/ui/web/themes/images/yourtheme/form/date-trigger.gif Binary files differdeleted file mode 100644 index 25ef7b3ae..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/date-trigger.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/date-trigger.psd b/deluge/ui/web/themes/images/yourtheme/form/date-trigger.psd Binary files differdeleted file mode 100644 index 74883b21c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/date-trigger.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/error-tip-corners.gif b/deluge/ui/web/themes/images/yourtheme/form/error-tip-corners.gif Binary files differdeleted file mode 100644 index 6ea4c3838..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/error-tip-corners.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/exclamation.gif b/deluge/ui/web/themes/images/yourtheme/form/exclamation.gif Binary files differdeleted file mode 100644 index ea31a3060..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/exclamation.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/radio.gif b/deluge/ui/web/themes/images/yourtheme/form/radio.gif Binary files differdeleted file mode 100644 index 36bb91d0c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/radio.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/search-trigger.gif b/deluge/ui/web/themes/images/yourtheme/form/search-trigger.gif Binary files differdeleted file mode 100644 index db8802beb..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/search-trigger.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/search-trigger.psd b/deluge/ui/web/themes/images/yourtheme/form/search-trigger.psd Binary files differdeleted file mode 100644 index b11f27300..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/search-trigger.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/text-bg.gif b/deluge/ui/web/themes/images/yourtheme/form/text-bg.gif Binary files differdeleted file mode 100644 index 4179607cc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/text-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/trigger-square.gif b/deluge/ui/web/themes/images/yourtheme/form/trigger-square.gif Binary files differdeleted file mode 100644 index 3004ec589..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/trigger-square.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/trigger-square.psd b/deluge/ui/web/themes/images/yourtheme/form/trigger-square.psd Binary files differdeleted file mode 100644 index e922ee65d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/trigger-square.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/trigger-tpl.gif b/deluge/ui/web/themes/images/yourtheme/form/trigger-tpl.gif Binary files differdeleted file mode 100644 index e3701a383..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/trigger-tpl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/trigger.gif b/deluge/ui/web/themes/images/yourtheme/form/trigger.gif Binary files differdeleted file mode 100644 index f6cba375a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/trigger.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/form/trigger.psd b/deluge/ui/web/themes/images/yourtheme/form/trigger.psd Binary files differdeleted file mode 100644 index 344c76824..000000000 --- a/deluge/ui/web/themes/images/yourtheme/form/trigger.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/gradient-bg.gif b/deluge/ui/web/themes/images/yourtheme/gradient-bg.gif Binary files differdeleted file mode 100644 index 8134e4994..000000000 --- a/deluge/ui/web/themes/images/yourtheme/gradient-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/arrow-left-white.gif b/deluge/ui/web/themes/images/yourtheme/grid/arrow-left-white.gif Binary files differdeleted file mode 100644 index 63088f56e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/arrow-left-white.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/arrow-right-white.gif b/deluge/ui/web/themes/images/yourtheme/grid/arrow-right-white.gif Binary files differdeleted file mode 100644 index e9e067890..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/arrow-right-white.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/col-move-bottom.gif b/deluge/ui/web/themes/images/yourtheme/grid/col-move-bottom.gif Binary files differdeleted file mode 100644 index cc1e473ec..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/col-move-bottom.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/col-move-top.gif b/deluge/ui/web/themes/images/yourtheme/grid/col-move-top.gif Binary files differdeleted file mode 100644 index 58ff32cc8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/col-move-top.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/columns.gif b/deluge/ui/web/themes/images/yourtheme/grid/columns.gif Binary files differdeleted file mode 100644 index 2d3a82393..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/columns.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/dirty.gif b/deluge/ui/web/themes/images/yourtheme/grid/dirty.gif Binary files differdeleted file mode 100644 index 4f217a479..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/dirty.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/done.gif b/deluge/ui/web/themes/images/yourtheme/grid/done.gif Binary files differdeleted file mode 100644 index a937cb22c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/done.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/drop-no.gif b/deluge/ui/web/themes/images/yourtheme/grid/drop-no.gif Binary files differdeleted file mode 100644 index 31a332bf7..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/drop-no.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/drop-yes.gif b/deluge/ui/web/themes/images/yourtheme/grid/drop-yes.gif Binary files differdeleted file mode 100644 index 926010e17..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/drop-yes.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/footer-bg.gif b/deluge/ui/web/themes/images/yourtheme/grid/footer-bg.gif Binary files differdeleted file mode 100644 index 126120f71..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/footer-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-hd.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-hd.gif Binary files differdeleted file mode 100644 index 862094e68..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-split.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-split.gif Binary files differdeleted file mode 100644 index 5286f58f6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-blue-split.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-hrow.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-hrow.gif Binary files differdeleted file mode 100644 index 637410420..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-hrow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-loading.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-loading.gif Binary files differdeleted file mode 100644 index d112c5401..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-loading.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-split.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-split.gif Binary files differdeleted file mode 100644 index c76a16e95..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-split.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid-vista-hd.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid-vista-hd.gif Binary files differdeleted file mode 100644 index d0972638e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid-vista-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hd-btn.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid3-hd-btn.gif Binary files differdeleted file mode 100644 index 21126075e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hd-btn.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow-over.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow-over.gif Binary files differdeleted file mode 100644 index f9c07af13..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow-over.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow.gif Binary files differdeleted file mode 100644 index 8d459a304..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid3-hrow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-bg.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-bg.gif Binary files differdeleted file mode 100644 index 0b4d6ca3b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-sel-bg.gif b/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-sel-bg.gif Binary files differdeleted file mode 100644 index 1dfe9a69e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/grid3-special-col-sel-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/group-by.gif b/deluge/ui/web/themes/images/yourtheme/grid/group-by.gif Binary files differdeleted file mode 100644 index d6075bba2..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/group-by.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/group-collapse.gif b/deluge/ui/web/themes/images/yourtheme/grid/group-collapse.gif Binary files differdeleted file mode 100644 index 495bb051d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/group-collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/group-expand-sprite.gif b/deluge/ui/web/themes/images/yourtheme/grid/group-expand-sprite.gif Binary files differdeleted file mode 100644 index 9c1653b48..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/group-expand-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/group-expand.gif b/deluge/ui/web/themes/images/yourtheme/grid/group-expand.gif Binary files differdeleted file mode 100644 index a33ac30bd..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/group-expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hd-pop.gif b/deluge/ui/web/themes/images/yourtheme/grid/hd-pop.gif Binary files differdeleted file mode 100644 index eb8ba7967..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hd-pop.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-asc.gif b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-asc.gif Binary files differdeleted file mode 100644 index 8917e0eee..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-asc.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-desc.gif b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-desc.gif Binary files differdeleted file mode 100644 index f26b7c2fc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-desc.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.gif b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.gif Binary files differdeleted file mode 100644 index 159612610..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.png b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.png Binary files differdeleted file mode 100644 index 8b81e7ff2..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-lock.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.gif b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.gif Binary files differdeleted file mode 100644 index af59cf92a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.png b/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.png Binary files differdeleted file mode 100644 index 9dd5df34b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/hmenu-unlock.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/invalid_line.gif b/deluge/ui/web/themes/images/yourtheme/grid/invalid_line.gif Binary files differdeleted file mode 100644 index fb7e0f34d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/invalid_line.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/loading.gif b/deluge/ui/web/themes/images/yourtheme/grid/loading.gif Binary files differdeleted file mode 100644 index e846e1d6c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/loading.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/mso-hd.gif b/deluge/ui/web/themes/images/yourtheme/grid/mso-hd.gif Binary files differdeleted file mode 100644 index 669f3cf08..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/mso-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/nowait.gif b/deluge/ui/web/themes/images/yourtheme/grid/nowait.gif Binary files differdeleted file mode 100644 index 4c5862cd5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/nowait.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-first-disabled.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-first-disabled.gif Binary files differdeleted file mode 100644 index 1e02c419f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-first-disabled.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-first.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-first.gif Binary files differdeleted file mode 100644 index d84f41a91..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-first.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-last-disabled.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-last-disabled.gif Binary files differdeleted file mode 100644 index 869706777..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-last-disabled.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-last.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-last.gif Binary files differdeleted file mode 100644 index 3df5c2ba5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-last.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-next-disabled.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-next-disabled.gif Binary files differdeleted file mode 100644 index 90a7756f6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-next-disabled.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-next.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-next.gif Binary files differdeleted file mode 100644 index 960163530..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-next.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-prev-disabled.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-prev-disabled.gif Binary files differdeleted file mode 100644 index 37154d624..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-prev-disabled.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/page-prev.gif b/deluge/ui/web/themes/images/yourtheme/grid/page-prev.gif Binary files differdeleted file mode 100644 index eb70cf8f6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/page-prev.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/pick-button.gif b/deluge/ui/web/themes/images/yourtheme/grid/pick-button.gif Binary files differdeleted file mode 100644 index 6957924a8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/pick-button.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/refresh.gif b/deluge/ui/web/themes/images/yourtheme/grid/refresh.gif Binary files differdeleted file mode 100644 index 110f6844b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/refresh.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/row-check-sprite.gif b/deluge/ui/web/themes/images/yourtheme/grid/row-check-sprite.gif Binary files differdeleted file mode 100644 index 610116465..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/row-check-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/row-expand-sprite.gif b/deluge/ui/web/themes/images/yourtheme/grid/row-expand-sprite.gif Binary files differdeleted file mode 100644 index 6f4d874f5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/row-expand-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/row-over.gif b/deluge/ui/web/themes/images/yourtheme/grid/row-over.gif Binary files differdeleted file mode 100644 index b288e3873..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/row-over.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/row-sel.gif b/deluge/ui/web/themes/images/yourtheme/grid/row-sel.gif Binary files differdeleted file mode 100644 index 98209e6e7..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/row-sel.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/sort-hd.gif b/deluge/ui/web/themes/images/yourtheme/grid/sort-hd.gif Binary files differdeleted file mode 100644 index 45e545f74..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/sort-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/sort_asc.gif b/deluge/ui/web/themes/images/yourtheme/grid/sort_asc.gif Binary files differdeleted file mode 100644 index 67a2a4c66..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/sort_asc.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/sort_desc.gif b/deluge/ui/web/themes/images/yourtheme/grid/sort_desc.gif Binary files differdeleted file mode 100644 index 34db47c3b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/sort_desc.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/grid/wait.gif b/deluge/ui/web/themes/images/yourtheme/grid/wait.gif Binary files differdeleted file mode 100644 index 471c1a4f9..000000000 --- a/deluge/ui/web/themes/images/yourtheme/grid/wait.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/collapse.gif b/deluge/ui/web/themes/images/yourtheme/layout/collapse.gif Binary files differdeleted file mode 100644 index d87b0a9dd..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/expand.gif b/deluge/ui/web/themes/images/yourtheme/layout/expand.gif Binary files differdeleted file mode 100644 index 7b6e1c1ef..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/gradient-bg.gif b/deluge/ui/web/themes/images/yourtheme/layout/gradient-bg.gif Binary files differdeleted file mode 100644 index 8134e4994..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/gradient-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/mini-bottom.gif b/deluge/ui/web/themes/images/yourtheme/layout/mini-bottom.gif Binary files differdeleted file mode 100644 index c18f9e34a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/mini-bottom.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/mini-left.gif b/deluge/ui/web/themes/images/yourtheme/layout/mini-left.gif Binary files differdeleted file mode 100644 index 99f7993f2..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/mini-left.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/mini-right.gif b/deluge/ui/web/themes/images/yourtheme/layout/mini-right.gif Binary files differdeleted file mode 100644 index 5b13c5a8b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/mini-right.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/mini-top.gif b/deluge/ui/web/themes/images/yourtheme/layout/mini-top.gif Binary files differdeleted file mode 100644 index a4ca2bb20..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/mini-top.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/ns-collapse.gif b/deluge/ui/web/themes/images/yourtheme/layout/ns-collapse.gif Binary files differdeleted file mode 100644 index df2a77e9c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/ns-collapse.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/ns-expand.gif b/deluge/ui/web/themes/images/yourtheme/layout/ns-expand.gif Binary files differdeleted file mode 100644 index 77ab9dad2..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/ns-expand.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/panel-close.gif b/deluge/ui/web/themes/images/yourtheme/layout/panel-close.gif Binary files differdeleted file mode 100644 index 2bdd62399..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/panel-close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/panel-title-bg.gif b/deluge/ui/web/themes/images/yourtheme/layout/panel-title-bg.gif Binary files differdeleted file mode 100644 index d1daef54c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/panel-title-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/panel-title-light-bg.gif b/deluge/ui/web/themes/images/yourtheme/layout/panel-title-light-bg.gif Binary files differdeleted file mode 100644 index 8c2c83d82..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/panel-title-light-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/stick.gif b/deluge/ui/web/themes/images/yourtheme/layout/stick.gif Binary files differdeleted file mode 100644 index 5a1e8ba19..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/stick.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/stuck.gif b/deluge/ui/web/themes/images/yourtheme/layout/stuck.gif Binary files differdeleted file mode 100644 index 0a8de4db9..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/stuck.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/tab-close-on.gif b/deluge/ui/web/themes/images/yourtheme/layout/tab-close-on.gif Binary files differdeleted file mode 100644 index eacea39b6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/tab-close-on.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/layout/tab-close.gif b/deluge/ui/web/themes/images/yourtheme/layout/tab-close.gif Binary files differdeleted file mode 100644 index 45db61e60..000000000 --- a/deluge/ui/web/themes/images/yourtheme/layout/tab-close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/checked.gif b/deluge/ui/web/themes/images/yourtheme/menu/checked.gif Binary files differdeleted file mode 100644 index fad589372..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/checked.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/group-checked.gif b/deluge/ui/web/themes/images/yourtheme/menu/group-checked.gif Binary files differdeleted file mode 100644 index d30b3e5a8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/group-checked.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/item-over.gif b/deluge/ui/web/themes/images/yourtheme/menu/item-over.gif Binary files differdeleted file mode 100644 index 016783932..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/item-over.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/menu-parent.gif b/deluge/ui/web/themes/images/yourtheme/menu/menu-parent.gif Binary files differdeleted file mode 100644 index 1e375622f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/menu-parent.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/menu.gif b/deluge/ui/web/themes/images/yourtheme/menu/menu.gif Binary files differdeleted file mode 100644 index 30a2c4b6c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/menu.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/menu/unchecked.gif b/deluge/ui/web/themes/images/yourtheme/menu/unchecked.gif Binary files differdeleted file mode 100644 index 43823e52d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/menu/unchecked.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/corners-sprite.gif b/deluge/ui/web/themes/images/yourtheme/panel/corners-sprite.gif Binary files differdeleted file mode 100644 index aa0d0ed8f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/corners-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/left-right.gif b/deluge/ui/web/themes/images/yourtheme/panel/left-right.gif Binary files differdeleted file mode 100644 index 9fae2d594..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/left-right.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/light-hd.gif b/deluge/ui/web/themes/images/yourtheme/panel/light-hd.gif Binary files differdeleted file mode 100644 index 58d6747b5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/light-hd.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/tool-sprite-tpl.gif b/deluge/ui/web/themes/images/yourtheme/panel/tool-sprite-tpl.gif Binary files differdeleted file mode 100644 index e6478670e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/tool-sprite-tpl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/tool-sprites.gif b/deluge/ui/web/themes/images/yourtheme/panel/tool-sprites.gif Binary files differdeleted file mode 100644 index 9a3c5b9ac..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/tool-sprites.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/tools-sprites-trans.gif b/deluge/ui/web/themes/images/yourtheme/panel/tools-sprites-trans.gif Binary files differdeleted file mode 100644 index ead931ef6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/tools-sprites-trans.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.gif b/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.gif Binary files differdeleted file mode 100644 index be6c50e1c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.png b/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.png Binary files differdeleted file mode 100644 index 578ffb609..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/top-bottom.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/white-corners-sprite.gif b/deluge/ui/web/themes/images/yourtheme/panel/white-corners-sprite.gif Binary files differdeleted file mode 100644 index 22d4bbab4..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/white-corners-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/white-left-right.gif b/deluge/ui/web/themes/images/yourtheme/panel/white-left-right.gif Binary files differdeleted file mode 100644 index d82c33784..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/white-left-right.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/panel/white-top-bottom.gif b/deluge/ui/web/themes/images/yourtheme/panel/white-top-bottom.gif Binary files differdeleted file mode 100644 index fe7dd1c1e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/panel/white-top-bottom.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/progress/progress-bg.gif b/deluge/ui/web/themes/images/yourtheme/progress/progress-bg.gif Binary files differdeleted file mode 100644 index 1c1abeb4b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/progress/progress-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/qtip/bg.gif b/deluge/ui/web/themes/images/yourtheme/qtip/bg.gif Binary files differdeleted file mode 100644 index 43488afdb..000000000 --- a/deluge/ui/web/themes/images/yourtheme/qtip/bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/qtip/close.gif b/deluge/ui/web/themes/images/yourtheme/qtip/close.gif Binary files differdeleted file mode 100644 index 69ab915e4..000000000 --- a/deluge/ui/web/themes/images/yourtheme/qtip/close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/qtip/tip-anchor-sprite.gif b/deluge/ui/web/themes/images/yourtheme/qtip/tip-anchor-sprite.gif Binary files differdeleted file mode 100644 index 9cf485060..000000000 --- a/deluge/ui/web/themes/images/yourtheme/qtip/tip-anchor-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/qtip/tip-sprite.gif b/deluge/ui/web/themes/images/yourtheme/qtip/tip-sprite.gif Binary files differdeleted file mode 100644 index 9810acac5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/qtip/tip-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/s.gif b/deluge/ui/web/themes/images/yourtheme/s.gif Binary files differdeleted file mode 100644 index 1d11fa9ad..000000000 --- a/deluge/ui/web/themes/images/yourtheme/s.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shadow-c.png b/deluge/ui/web/themes/images/yourtheme/shadow-c.png Binary files differdeleted file mode 100644 index d435f80ae..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shadow-c.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shadow-lr.png b/deluge/ui/web/themes/images/yourtheme/shadow-lr.png Binary files differdeleted file mode 100644 index bb88b6f2b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shadow-lr.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shadow.png b/deluge/ui/web/themes/images/yourtheme/shadow.png Binary files differdeleted file mode 100644 index 75c0eba3e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shadow.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/blue-loading.gif b/deluge/ui/web/themes/images/yourtheme/shared/blue-loading.gif Binary files differdeleted file mode 100644 index 3bbf639ef..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/blue-loading.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/calendar.gif b/deluge/ui/web/themes/images/yourtheme/shared/calendar.gif Binary files differdeleted file mode 100644 index 133cf232b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/calendar.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/glass-bg.gif b/deluge/ui/web/themes/images/yourtheme/shared/glass-bg.gif Binary files differdeleted file mode 100644 index 26fbbae3b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/glass-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/hd-sprite.gif b/deluge/ui/web/themes/images/yourtheme/shared/hd-sprite.gif Binary files differdeleted file mode 100644 index 42da1ea1a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/hd-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/large-loading.gif b/deluge/ui/web/themes/images/yourtheme/shared/large-loading.gif Binary files differdeleted file mode 100644 index b36b555b4..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/large-loading.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/left-btn.gif b/deluge/ui/web/themes/images/yourtheme/shared/left-btn.gif Binary files differdeleted file mode 100644 index a0ddd9ee8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/left-btn.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/loading-balls.gif b/deluge/ui/web/themes/images/yourtheme/shared/loading-balls.gif Binary files differdeleted file mode 100644 index 9ce214beb..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/loading-balls.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/right-btn.gif b/deluge/ui/web/themes/images/yourtheme/shared/right-btn.gif Binary files differdeleted file mode 100644 index dee63e211..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/right-btn.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/shared/warning.gif b/deluge/ui/web/themes/images/yourtheme/shared/warning.gif Binary files differdeleted file mode 100644 index 806d4bc09..000000000 --- a/deluge/ui/web/themes/images/yourtheme/shared/warning.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/e-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/e-handle-dark.gif Binary files differdeleted file mode 100644 index b5486c1a9..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/e-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/e-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/e-handle.gif Binary files differdeleted file mode 100644 index 00ba83500..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/e-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle-dark.gif Binary files differdeleted file mode 100644 index 04e5ecf7d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle.gif Binary files differdeleted file mode 100644 index 09405c7ac..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/ne-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle-dark.gif Binary files differdeleted file mode 100644 index 6e49d6967..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle.gif Binary files differdeleted file mode 100644 index 2fcea8a92..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/nw-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/s-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/s-handle-dark.gif Binary files differdeleted file mode 100644 index 4eb5f0fcc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/s-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/s-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/s-handle.gif Binary files differdeleted file mode 100644 index bf069c243..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/s-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/se-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/se-handle-dark.gif Binary files differdeleted file mode 100644 index c4c108786..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/se-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/se-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/se-handle.gif Binary files differdeleted file mode 100644 index 972055e7b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/se-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/square.gif b/deluge/ui/web/themes/images/yourtheme/sizer/square.gif Binary files differdeleted file mode 100644 index 14ce6f725..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/square.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle-dark.gif b/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle-dark.gif Binary files differdeleted file mode 100644 index 77224b0c0..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle-dark.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle.gif b/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle.gif Binary files differdeleted file mode 100644 index 3ca0ed96d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/sizer/sw-handle.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/slider/slider-bg.png b/deluge/ui/web/themes/images/yourtheme/slider/slider-bg.png Binary files differdeleted file mode 100644 index 999919424..000000000 --- a/deluge/ui/web/themes/images/yourtheme/slider/slider-bg.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/slider/slider-thumb.png b/deluge/ui/web/themes/images/yourtheme/slider/slider-thumb.png Binary files differdeleted file mode 100644 index cd654a4c1..000000000 --- a/deluge/ui/web/themes/images/yourtheme/slider/slider-thumb.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/slider/slider-v-bg.png b/deluge/ui/web/themes/images/yourtheme/slider/slider-v-bg.png Binary files differdeleted file mode 100644 index 121450c28..000000000 --- a/deluge/ui/web/themes/images/yourtheme/slider/slider-v-bg.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/slider/slider-v-thumb.png b/deluge/ui/web/themes/images/yourtheme/slider/slider-v-thumb.png Binary files differdeleted file mode 100644 index 7b3d7258a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/slider/slider-v-thumb.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/scroll-left.gif b/deluge/ui/web/themes/images/yourtheme/tabs/scroll-left.gif Binary files differdeleted file mode 100644 index 9f2f6d1c9..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/scroll-left.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/scroll-right.gif b/deluge/ui/web/themes/images/yourtheme/tabs/scroll-right.gif Binary files differdeleted file mode 100644 index 4c5e7e395..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/scroll-right.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/scroller-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/scroller-bg.gif Binary files differdeleted file mode 100644 index 099b90d8a..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/scroller-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif Binary files differdeleted file mode 100644 index 188bf940c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-left-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif Binary files differdeleted file mode 100644 index e1f5e3c51..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-inactive-right-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-left-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-left-bg.gif Binary files differdeleted file mode 100644 index dde796870..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-left-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-left-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-left-bg.gif Binary files differdeleted file mode 100644 index da49c100d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-left-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-right-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-right-bg.gif Binary files differdeleted file mode 100644 index 45346ab14..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-over-right-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-right-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-right-bg.gif Binary files differdeleted file mode 100644 index e695186d5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-btm-right-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-close.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-close.gif Binary files differdeleted file mode 100644 index e69987848..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-close.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.gif Binary files differdeleted file mode 100644 index 34f133345..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.png b/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.png Binary files differdeleted file mode 100644 index fa8ab3f46..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-bg.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-btm-bg.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-btm-bg.gif Binary files differdeleted file mode 100644 index 5eaba1eaa..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tab-strip-btm-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tabs/tabs-sprite.gif b/deluge/ui/web/themes/images/yourtheme/tabs/tabs-sprite.gif Binary files differdeleted file mode 100644 index e969fb0b7..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tabs/tabs-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/bg.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/bg.gif Binary files differdeleted file mode 100644 index 0b085bf24..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow-light.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow-light.gif Binary files differdeleted file mode 100644 index b0e24b55e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow-light.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow.gif Binary files differdeleted file mode 100644 index 8acb4608d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-arrow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-over-bg.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/btn-over-bg.gif Binary files differdeleted file mode 100644 index ee2dd9860..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/btn-over-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/gray-bg.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/gray-bg.gif Binary files differdeleted file mode 100644 index bd49438f3..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/gray-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/more.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/more.gif Binary files differdeleted file mode 100644 index 02c2509fe..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/more.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-bg.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/tb-bg.gif Binary files differdeleted file mode 100644 index 4969e4efe..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-bg.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-btn-sprite.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/tb-btn-sprite.gif Binary files differdeleted file mode 100644 index 19bbef3c6..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-btn-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-btn-sprite.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-btn-sprite.gif Binary files differdeleted file mode 100644 index 1bc0420f0..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-btn-sprite.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-sep.gif b/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-sep.gif Binary files differdeleted file mode 100644 index 30555eecf..000000000 --- a/deluge/ui/web/themes/images/yourtheme/toolbar/tb-xl-sep.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/arrows.gif b/deluge/ui/web/themes/images/yourtheme/tree/arrows.gif Binary files differdeleted file mode 100644 index 268346391..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/arrows.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-add.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-add.gif Binary files differdeleted file mode 100644 index b22cd1448..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-add.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-between.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-between.gif Binary files differdeleted file mode 100644 index 5c6c09d98..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-between.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-no.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-no.gif Binary files differdeleted file mode 100644 index 9d9c6a9ce..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-no.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-over.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-over.gif Binary files differdeleted file mode 100644 index 30d1ca710..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-over.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-under.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-under.gif Binary files differdeleted file mode 100644 index 85f66b1e5..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-under.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/drop-yes.gif b/deluge/ui/web/themes/images/yourtheme/tree/drop-yes.gif Binary files differdeleted file mode 100644 index 8aacb307e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/drop-yes.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus-nl.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus-nl.gif Binary files differdeleted file mode 100644 index 928779e92..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus-nl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus.gif Binary files differdeleted file mode 100644 index 9a8d727d7..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-minus.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus-nl.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus-nl.gif Binary files differdeleted file mode 100644 index 9f7f69880..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus-nl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus.gif Binary files differdeleted file mode 100644 index 5943a01bc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end-plus.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-end.gif Binary files differdeleted file mode 100644 index f24ddee79..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-end.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-line.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-line.gif Binary files differdeleted file mode 100644 index 75e6da4f8..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-line.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus-nl.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus-nl.gif Binary files differdeleted file mode 100644 index 928779e92..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus-nl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus.gif Binary files differdeleted file mode 100644 index 97dcc7110..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-minus.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus-nl.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus-nl.gif Binary files differdeleted file mode 100644 index 9f7f69880..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus-nl.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus.gif Binary files differdeleted file mode 100644 index 698de4793..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow-plus.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/elbow.gif b/deluge/ui/web/themes/images/yourtheme/tree/elbow.gif Binary files differdeleted file mode 100644 index b8f420838..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/elbow.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/folder-open.gif b/deluge/ui/web/themes/images/yourtheme/tree/folder-open.gif Binary files differdeleted file mode 100644 index 56ba737bc..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/folder-open.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/folder.gif b/deluge/ui/web/themes/images/yourtheme/tree/folder.gif Binary files differdeleted file mode 100644 index 20412f7c1..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/folder.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/leaf.gif b/deluge/ui/web/themes/images/yourtheme/tree/leaf.gif Binary files differdeleted file mode 100644 index 445769d3f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/leaf.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/loading.gif b/deluge/ui/web/themes/images/yourtheme/tree/loading.gif Binary files differdeleted file mode 100644 index e846e1d6c..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/loading.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/tree/s.gif b/deluge/ui/web/themes/images/yourtheme/tree/s.gif Binary files differdeleted file mode 100644 index 1d11fa9ad..000000000 --- a/deluge/ui/web/themes/images/yourtheme/tree/s.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/icon-error.gif b/deluge/ui/web/themes/images/yourtheme/window/icon-error.gif Binary files differdeleted file mode 100644 index 397b655ab..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/icon-error.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/icon-info.gif b/deluge/ui/web/themes/images/yourtheme/window/icon-info.gif Binary files differdeleted file mode 100644 index 58281c306..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/icon-info.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/icon-question.gif b/deluge/ui/web/themes/images/yourtheme/window/icon-question.gif Binary files differdeleted file mode 100644 index 08abd82ae..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/icon-question.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/icon-warning.gif b/deluge/ui/web/themes/images/yourtheme/window/icon-warning.gif Binary files differdeleted file mode 100644 index 27ff98b4f..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/icon-warning.gif +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/left-corners.png b/deluge/ui/web/themes/images/yourtheme/window/left-corners.png Binary files differdeleted file mode 100644 index 1a518335d..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/left-corners.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/left-corners.psd b/deluge/ui/web/themes/images/yourtheme/window/left-corners.psd Binary files differdeleted file mode 100644 index 3d7f0623e..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/left-corners.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/left-right.png b/deluge/ui/web/themes/images/yourtheme/window/left-right.png Binary files differdeleted file mode 100644 index 7586ff333..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/left-right.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/left-right.psd b/deluge/ui/web/themes/images/yourtheme/window/left-right.psd Binary files differdeleted file mode 100644 index 59a3960a2..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/left-right.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/right-corners.png b/deluge/ui/web/themes/images/yourtheme/window/right-corners.png Binary files differdeleted file mode 100644 index e69a3ffc9..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/right-corners.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/right-corners.psd b/deluge/ui/web/themes/images/yourtheme/window/right-corners.psd Binary files differdeleted file mode 100644 index 86d509538..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/right-corners.psd +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/top-bottom.png b/deluge/ui/web/themes/images/yourtheme/window/top-bottom.png Binary files differdeleted file mode 100644 index 33779e76b..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/top-bottom.png +++ /dev/null diff --git a/deluge/ui/web/themes/images/yourtheme/window/top-bottom.psd b/deluge/ui/web/themes/images/yourtheme/window/top-bottom.psd Binary files differdeleted file mode 100644 index 48c5395e4..000000000 --- a/deluge/ui/web/themes/images/yourtheme/window/top-bottom.psd +++ /dev/null @@ -152,11 +152,12 @@ else: for include in os.environ.get("INCLUDEDIR", "").split(":"): _include_dirs.append(include) - _library_dirs += [sysconfig.get_config_var("LIBDIR"), '/opt/local/lib'] + _library_dirs += [sysconfig.get_config_var("LIBDIR"), '/opt/local/lib', '/usr/local/lib'] if osx_check(): _include_dirs += [ '/opt/local/include/boost-1_35', '/opt/local/include/boost-1_36', + '/usr/local/include' '/sw/include/boost-1_35', '/sw/include/boost' ] |