The AutoAdd plugin now supports multiusers.
This commit is contained in:
parent
51b5b23f76
commit
fb5005e3f6
|
@ -2,6 +2,7 @@
|
|||
# core.py
|
||||
#
|
||||
# Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
|
||||
# Copyright (C) 2011 Pedro Algarvio <ufs@ufsoft.org>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
|
@ -59,7 +60,7 @@ OPTIONS_AVAILABLE = { #option: builtin
|
|||
"enabled":False,
|
||||
"path":False,
|
||||
"append_extension":False,
|
||||
"abspath":False,
|
||||
"abspath":False,
|
||||
"download_location":True,
|
||||
"max_download_speed":True,
|
||||
"max_upload_speed":True,
|
||||
|
@ -74,7 +75,8 @@ OPTIONS_AVAILABLE = { #option: builtin
|
|||
"move_completed_path":True,
|
||||
"label":False,
|
||||
"add_paused":True,
|
||||
"queue_to_top":False
|
||||
"queue_to_top":False,
|
||||
"owner": "localclient"
|
||||
}
|
||||
|
||||
MAX_NUM_ATTEMPTS = 10
|
||||
|
@ -90,29 +92,17 @@ def CheckInput(cond, message):
|
|||
|
||||
class Core(CorePluginBase):
|
||||
def enable(self):
|
||||
|
||||
|
||||
#reduce typing, assigning some values to self...
|
||||
self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS)
|
||||
self.config.run_converter((0, 1), 2, self.__migrate_config_1_to_2)
|
||||
self.config.save()
|
||||
self.watchdirs = self.config["watchdirs"]
|
||||
self.core_cfg = deluge.configmanager.ConfigManager("core.conf")
|
||||
|
||||
# Dict of Filename:Attempts
|
||||
self.invalid_torrents = {}
|
||||
# Loopingcall timers for each enabled watchdir
|
||||
self.update_timers = {}
|
||||
# If core autoadd folder is enabled, move it to the plugin
|
||||
if self.core_cfg.config.get('autoadd_enable'):
|
||||
# Disable core autoadd
|
||||
self.core_cfg['autoadd_enable'] = False
|
||||
self.core_cfg.save()
|
||||
# Check if core autoadd folder is already added in plugin
|
||||
for watchdir in self.watchdirs:
|
||||
if os.path.abspath(self.core_cfg['autoadd_location']) == watchdir['abspath']:
|
||||
watchdir['enabled'] = True
|
||||
break
|
||||
else:
|
||||
# didn't find core watchdir, add it
|
||||
self.add({'path':self.core_cfg['autoadd_location'], 'enabled':True})
|
||||
deferLater(reactor, 5, self.enable_looping)
|
||||
|
||||
def enable_looping(self):
|
||||
|
@ -129,34 +119,38 @@ class Core(CorePluginBase):
|
|||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
|
||||
@export()
|
||||
def set_options(self, watchdir_id, options):
|
||||
"""Update the options for a watch folder."""
|
||||
watchdir_id = str(watchdir_id)
|
||||
options = self._make_unicode(options)
|
||||
CheckInput(watchdir_id in self.watchdirs , _("Watch folder does not exist."))
|
||||
CheckInput(
|
||||
watchdir_id in self.watchdirs, _("Watch folder does not exist.")
|
||||
)
|
||||
if options.has_key('path'):
|
||||
options['abspath'] = os.path.abspath(options['path'])
|
||||
CheckInput(os.path.isdir(options['abspath']), _("Path does not exist."))
|
||||
CheckInput(
|
||||
os.path.isdir(options['abspath']), _("Path does not exist.")
|
||||
)
|
||||
for w_id, w in self.watchdirs.iteritems():
|
||||
if options['abspath'] == w['abspath'] and watchdir_id != w_id:
|
||||
raise Exception("Path is already being watched.")
|
||||
for key in options.keys():
|
||||
if not key in OPTIONS_AVAILABLE:
|
||||
if not key in [key2+'_toggle' for key2 in OPTIONS_AVAILABLE.iterkeys()]:
|
||||
if key not in OPTIONS_AVAILABLE:
|
||||
if key not in [key2+'_toggle' for key2 in OPTIONS_AVAILABLE.iterkeys()]:
|
||||
raise Exception("autoadd: Invalid options key:%s" % key)
|
||||
#disable the watch loop if it was active
|
||||
if watchdir_id in self.update_timers:
|
||||
self.disable_watchdir(watchdir_id)
|
||||
|
||||
|
||||
self.watchdirs[watchdir_id].update(options)
|
||||
#re-enable watch loop if appropriate
|
||||
if self.watchdirs[watchdir_id]['enabled']:
|
||||
self.enable_watchdir(watchdir_id)
|
||||
self.config.save()
|
||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||
|
||||
|
||||
def load_torrent(self, filename):
|
||||
try:
|
||||
log.debug("Attempting to open %s for add.", filename)
|
||||
|
@ -173,7 +167,7 @@ class Core(CorePluginBase):
|
|||
info = lt.torrent_info(lt.bdecode(filedump))
|
||||
|
||||
return filedump
|
||||
|
||||
|
||||
def update_watchdir(self, watchdir_id):
|
||||
"""Check the watch folder for new torrents to add."""
|
||||
watchdir_id = str(watchdir_id)
|
||||
|
@ -187,12 +181,12 @@ class Core(CorePluginBase):
|
|||
log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"])
|
||||
self.disable_watchdir(watchdir_id)
|
||||
return
|
||||
|
||||
|
||||
# Generate options dict for watchdir
|
||||
opts = {}
|
||||
if 'stop_at_ratio_toggle' in watchdir:
|
||||
watchdir['stop_ratio_toggle'] = watchdir['stop_at_ratio_toggle']
|
||||
# We default to True wher reading _toggle values, so a config
|
||||
# We default to True when reading _toggle values, so a config
|
||||
# without them is valid, and applies all its settings.
|
||||
for option, value in watchdir.iteritems():
|
||||
if OPTIONS_AVAILABLE.get(option):
|
||||
|
@ -203,7 +197,8 @@ class Core(CorePluginBase):
|
|||
try:
|
||||
filepath = os.path.join(watchdir["abspath"], filename)
|
||||
except UnicodeDecodeError, e:
|
||||
log.error("Unable to auto add torrent due to inproper filename encoding: %s", e)
|
||||
log.error("Unable to auto add torrent due to improper "
|
||||
"filename encoding: %s", e)
|
||||
continue
|
||||
try:
|
||||
filedump = self.load_torrent(filepath)
|
||||
|
@ -222,7 +217,10 @@ class Core(CorePluginBase):
|
|||
continue
|
||||
|
||||
# The torrent looks good, so lets add it to the session.
|
||||
torrent_id = component.get("TorrentManager").add(filedump=filedump, filename=filename, options=opts)
|
||||
torrent_id = component.get("TorrentManager").add(
|
||||
filedump=filedump, filename=filename, options=opts,
|
||||
owner=watchdir.get("owner", "localclient")
|
||||
)
|
||||
# If the torrent added successfully, set the extra options.
|
||||
if torrent_id:
|
||||
if 'Label' in component.get("CorePluginManager").get_enabled_plugins():
|
||||
|
@ -247,32 +245,35 @@ class Core(CorePluginBase):
|
|||
def on_update_watchdir_error(self, failure, watchdir_id):
|
||||
"""Disables any watch folders with unhandled exceptions."""
|
||||
self.disable_watchdir(watchdir_id)
|
||||
log.error("Disabling '%s', error during update: %s" % (self.watchdirs[watchdir_id]["path"], failure))
|
||||
|
||||
log.error("Disabling '%s', error during update: %s",
|
||||
self.watchdirs[watchdir_id]["path"], failure)
|
||||
|
||||
@export
|
||||
def enable_watchdir(self, watchdir_id):
|
||||
watchdir_id = str(watchdir_id)
|
||||
w_id = str(watchdir_id)
|
||||
# Enable the looping call
|
||||
if watchdir_id not in self.update_timers or not self.update_timers[watchdir_id].running:
|
||||
self.update_timers[watchdir_id] = LoopingCall(self.update_watchdir, watchdir_id)
|
||||
self.update_timers[watchdir_id].start(5).addErrback(self.on_update_watchdir_error, watchdir_id)
|
||||
if w_id not in self.update_timers or not self.update_timers[w_id].running:
|
||||
self.update_timers[w_id] = LoopingCall(self.update_watchdir, w_id)
|
||||
self.update_timers[w_id].start(5).addErrback(
|
||||
self.on_update_watchdir_error, w_id
|
||||
)
|
||||
# Update the config
|
||||
if not self.watchdirs[watchdir_id]['enabled']:
|
||||
self.watchdirs[watchdir_id]['enabled'] = True
|
||||
if not self.watchdirs[w_id]['enabled']:
|
||||
self.watchdirs[w_id]['enabled'] = True
|
||||
self.config.save()
|
||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||
|
||||
|
||||
@export
|
||||
def disable_watchdir(self, watchdir_id):
|
||||
watchdir_id = str(watchdir_id)
|
||||
w_id = str(watchdir_id)
|
||||
# Disable the looping call
|
||||
if watchdir_id in self.update_timers:
|
||||
if self.update_timers[watchdir_id].running:
|
||||
self.update_timers[watchdir_id].stop()
|
||||
del self.update_timers[watchdir_id]
|
||||
if w_id in self.update_timers:
|
||||
if self.update_timers[w_id].running:
|
||||
self.update_timers[w_id].stop()
|
||||
del self.update_timers[w_id]
|
||||
# Update the config
|
||||
if self.watchdirs[watchdir_id]['enabled']:
|
||||
self.watchdirs[watchdir_id]['enabled'] = False
|
||||
if self.watchdirs[w_id]['enabled']:
|
||||
self.watchdirs[w_id]['enabled'] = False
|
||||
self.config.save()
|
||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||
|
||||
|
@ -289,7 +290,7 @@ class Core(CorePluginBase):
|
|||
def get_config(self):
|
||||
"""Returns the config dictionary."""
|
||||
return self.config.config
|
||||
|
||||
|
||||
@export()
|
||||
def get_watchdirs(self):
|
||||
return self.watchdirs.keys()
|
||||
|
@ -321,7 +322,7 @@ class Core(CorePluginBase):
|
|||
self.config.save()
|
||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||
return watchdir_id
|
||||
|
||||
|
||||
@export
|
||||
def remove(self, watchdir_id):
|
||||
"""Remove a watch folder."""
|
||||
|
@ -332,3 +333,8 @@ class Core(CorePluginBase):
|
|||
del self.watchdirs[watchdir_id]
|
||||
self.config.save()
|
||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||
|
||||
def __migrate_config_1_to_2(self, config):
|
||||
for watchdir_id in config['watchdirs'].iterkeys():
|
||||
config['watchdirs'][watchdir_id]['owner'] = 'localclient'
|
||||
return config
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.16 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
|
@ -83,11 +83,9 @@
|
|||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkNotebook" id="notebook1">
|
||||
<property name="visible">True</property>
|
||||
|
@ -96,7 +94,6 @@
|
|||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
|
@ -109,7 +106,6 @@
|
|||
<child>
|
||||
<widget class="GtkVBox" id="vbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
|
@ -117,7 +113,7 @@
|
|||
<widget class="GtkEntry" id="path_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
|
@ -174,6 +170,37 @@
|
|||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="OwnerFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment5">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="OwnerCombobox">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Owner</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
|
@ -189,15 +216,14 @@
|
|||
<child>
|
||||
<widget class="GtkVBox" id="vbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkRadioButton" id="isnt_append_extension">
|
||||
<property name="label" translatable="yes">Delete .torrent after adding</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_toggle_toggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
|
@ -224,7 +250,7 @@
|
|||
<widget class="GtkEntry" id="append_extension">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="text" translatable="yes">.added</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -236,6 +262,75 @@
|
|||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkTable" id="table4">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">2</property>
|
||||
<child>
|
||||
<widget class="GtkRadioButton" id="copy_torrent_toggle">
|
||||
<property name="label" translatable="yes">Copy of .torrent files to:</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">isnt_append_extension</property>
|
||||
<signal name="toggled" handler="on_toggle_toggled"/>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="copy_torrent_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFileChooserButton" id="copy_torrent_chooser">
|
||||
<property name="visible">True</property>
|
||||
<property name="action">select-folder</property>
|
||||
<property name="show_hidden">True</property>
|
||||
<property name="title" translatable="yes">Select A Folder</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="delete_copy_torrent_toggle">
|
||||
<property name="label" translatable="yes">Delete copy of torrent file on remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="has_tooltip">True</property>
|
||||
<property name="tooltip" translatable="yes">Delete the copy of the torrent file
|
||||
created when the torrent is removed</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_padding">15</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
@ -254,7 +349,7 @@
|
|||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -269,7 +364,6 @@
|
|||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="download_location_toggle">
|
||||
<property name="label" translatable="yes">Set download location</property>
|
||||
|
@ -293,7 +387,7 @@
|
|||
<widget class="GtkEntry" id="download_location_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
|
@ -332,7 +426,7 @@
|
|||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -347,7 +441,6 @@
|
|||
<child>
|
||||
<widget class="GtkVBox" id="vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="move_completed_toggle">
|
||||
<property name="label" translatable="yes">Set move completed location</property>
|
||||
|
@ -371,7 +464,7 @@
|
|||
<widget class="GtkEntry" id="move_completed_path_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
|
@ -425,7 +518,7 @@
|
|||
</widget>
|
||||
<packing>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -456,10 +549,8 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="label">
|
||||
<widget class="GtkComboBoxEntry" id="label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
|
@ -481,7 +572,7 @@
|
|||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
@ -500,7 +591,6 @@
|
|||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
|
@ -574,7 +664,7 @@
|
|||
<widget class="GtkSpinButton" id="max_download_speed">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">-1 -1 10000 1 10 0</property>
|
||||
<property name="adjustment">0 -1 10000 1 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
<property name="digits">1</property>
|
||||
</widget>
|
||||
|
@ -588,7 +678,7 @@
|
|||
<widget class="GtkSpinButton" id="max_upload_speed">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">-1 -1 10000 1 10 0</property>
|
||||
<property name="adjustment">0 -1 10000 1 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
<property name="digits">1</property>
|
||||
</widget>
|
||||
|
@ -604,7 +694,7 @@
|
|||
<widget class="GtkSpinButton" id="max_connections">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">-1 -1 10000 1 10 0</property>
|
||||
<property name="adjustment">0 -1 10000 1 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -619,7 +709,7 @@
|
|||
<widget class="GtkSpinButton" id="max_upload_slots">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">-1 -1 10000 1 10 0</property>
|
||||
<property name="adjustment">0 -1 10000 1 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -814,7 +904,7 @@
|
|||
<widget class="GtkSpinButton" id="stop_ratio">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="adjustment">2 0 100 0.10000000149 10 0</property>
|
||||
<property name="climb_rate">1</property>
|
||||
<property name="digits">1</property>
|
||||
|
@ -1050,7 +1140,6 @@
|
|||
<child>
|
||||
<widget class="GtkHButtonBox" id="hbuttonbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
|
|
|
@ -53,9 +53,12 @@ log = getPluginLogger(__name__)
|
|||
class OptionsDialog():
|
||||
spin_ids = ["max_download_speed", "max_upload_speed", "stop_ratio"]
|
||||
spin_int_ids = ["max_upload_slots", "max_connections"]
|
||||
chk_ids = ["stop_at_ratio", "remove_at_ratio", "move_completed", "add_paused", "auto_managed", "queue_to_top"]
|
||||
chk_ids = ["stop_at_ratio", "remove_at_ratio", "move_completed",
|
||||
"add_paused", "auto_managed", "queue_to_top"]
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
self.accounts = gtk.ListStore(str)
|
||||
self.labels = gtk.ListStore(str)
|
||||
|
||||
def show(self, options={}, watchdir_id=None):
|
||||
self.glade = gtk.glade.XML(get_resource("autoadd_options.glade"))
|
||||
|
@ -72,6 +75,7 @@ class OptionsDialog():
|
|||
self.dialog.set_transient_for(component.get("Preferences").pref_dialog)
|
||||
self.err_dialog = self.glade.get_widget("error_dialog")
|
||||
self.err_dialog.set_transient_for(self.dialog)
|
||||
|
||||
if watchdir_id:
|
||||
#We have an existing watchdir_id, we are editing
|
||||
self.glade.get_widget('opts_add_button').hide()
|
||||
|
@ -84,15 +88,40 @@ class OptionsDialog():
|
|||
self.watchdir_id = None
|
||||
|
||||
self.load_options(options)
|
||||
|
||||
# Not implemented feateures present in UI
|
||||
self.glade.get_widget("copy_torrent_toggle").hide()
|
||||
self.glade.get_widget("copy_torrent_entry").hide()
|
||||
self.glade.get_widget("copy_torrent_chooser").hide()
|
||||
self.glade.get_widget("delete_copy_torrent_toggle").hide()
|
||||
|
||||
self.dialog.run()
|
||||
|
||||
def load_options(self, options):
|
||||
self.glade.get_widget('enabled').set_active(options.get('enabled', False))
|
||||
self.glade.get_widget('append_extension_toggle').set_active(options.get('append_extension_toggle', False))
|
||||
self.glade.get_widget('append_extension').set_text(options.get('append_extension', '.added'))
|
||||
self.glade.get_widget('download_location_toggle').set_active(options.get('download_location_toggle', False))
|
||||
self.glade.get_widget('label').set_text(options.get('label', ''))
|
||||
self.glade.get_widget('append_extension_toggle').set_active(
|
||||
options.get('append_extension_toggle', False)
|
||||
)
|
||||
self.glade.get_widget('append_extension').set_text(
|
||||
options.get('append_extension', '.added')
|
||||
)
|
||||
self.glade.get_widget('download_location_toggle').set_active(
|
||||
options.get('download_location_toggle', False)
|
||||
)
|
||||
self.accounts.clear()
|
||||
self.labels.clear()
|
||||
combobox = self.glade.get_widget('OwnerCombobox')
|
||||
combobox_render = gtk.CellRendererText()
|
||||
combobox.pack_start(combobox_render, True)
|
||||
combobox.add_attribute(combobox_render, 'text', 0)
|
||||
combobox.set_model(self.accounts)
|
||||
|
||||
label_widget = self.glade.get_widget('label')
|
||||
label_widget.child.set_text(options.get('label', ''))
|
||||
label_widget.set_model(self.labels)
|
||||
label_widget.set_text_column(0)
|
||||
self.glade.get_widget('label_toggle').set_active(options.get('label_toggle', False))
|
||||
|
||||
for id in self.spin_ids + self.spin_int_ids:
|
||||
self.glade.get_widget(id).set_value(options.get(id, 0))
|
||||
self.glade.get_widget(id+'_toggle').set_active(options.get(id+'_toggle', False))
|
||||
|
@ -105,32 +134,66 @@ class OptionsDialog():
|
|||
self.glade.get_widget('isnt_queue_to_top').set_active(True)
|
||||
if not options.get('auto_managed', True):
|
||||
self.glade.get_widget('isnt_auto_managed').set_active(True)
|
||||
for field in ['move_completed_path', 'path', 'download_location']:
|
||||
for field in ['move_completed_path', 'path', 'download_location',
|
||||
'copy_torrent']:
|
||||
if client.is_localhost():
|
||||
self.glade.get_widget(field+"_chooser").set_filename(options.get(field, os.path.expanduser("~")))
|
||||
self.glade.get_widget(field+"_chooser").set_filename(
|
||||
options.get(field, os.path.expanduser("~"))
|
||||
)
|
||||
self.glade.get_widget(field+"_chooser").show()
|
||||
self.glade.get_widget(field+"_entry").hide()
|
||||
else:
|
||||
self.glade.get_widget(field+"_entry").set_text(options.get(field, ""))
|
||||
self.glade.get_widget(field+"_entry").set_text(
|
||||
options.get(field, "")
|
||||
)
|
||||
self.glade.get_widget(field+"_entry").show()
|
||||
self.glade.get_widget(field+"_chooser").hide()
|
||||
self.set_sensitive()
|
||||
|
||||
|
||||
def on_accounts(accounts, owner):
|
||||
log.debug("Got Accounts")
|
||||
selected_idx = None
|
||||
for idx, account in enumerate(accounts):
|
||||
iter = self.accounts.append()
|
||||
self.accounts.set_value(
|
||||
iter, 0, account['username']
|
||||
)
|
||||
if account['username'] == owner:
|
||||
selected_idx = idx
|
||||
self.glade.get_widget('OwnerCombobox').set_active(selected_idx)
|
||||
|
||||
def on_labels(labels):
|
||||
log.debug("Got Labels: %s", labels)
|
||||
for label in labels:
|
||||
self.labels.set_value(self.labels.append(), 0, label)
|
||||
label_widget = self.glade.get_widget('label')
|
||||
label_widget.set_model(self.labels)
|
||||
label_widget.set_text_column(0)
|
||||
|
||||
def on_failure(failure):
|
||||
log.exception(failure)
|
||||
|
||||
def on_get_enabled_plugins(result):
|
||||
if 'Label' in result:
|
||||
if 'Label' in result:
|
||||
self.glade.get_widget('label_frame').show()
|
||||
client.label.get_labels().addCallback(on_labels).addErrback(on_failure)
|
||||
else:
|
||||
self.glade.get_widget('label_frame').hide()
|
||||
self.glade.get_widget('label_toggle').set_active(False)
|
||||
|
||||
|
||||
client.core.get_enabled_plugins().addCallback(on_get_enabled_plugins)
|
||||
|
||||
client.core.get_known_accounts().addCallback(
|
||||
on_accounts, options.get('owner', 'localclient')
|
||||
).addErrback(on_failure)
|
||||
|
||||
def set_sensitive(self):
|
||||
maintoggles = ['download_location', 'append_extension', 'move_completed', 'label', \
|
||||
'max_download_speed', 'max_upload_speed', 'max_connections', \
|
||||
'max_upload_slots', 'add_paused', 'auto_managed', 'stop_at_ratio', 'queue_to_top']
|
||||
maintoggles = ['download_location', 'append_extension',
|
||||
'move_completed', 'label', 'max_download_speed',
|
||||
'max_upload_speed', 'max_connections',
|
||||
'max_upload_slots', 'add_paused', 'auto_managed',
|
||||
'stop_at_ratio', 'queue_to_top', 'copy_torrent']
|
||||
[self.on_toggle_toggled(self.glade.get_widget(x+'_toggle')) for x in maintoggles]
|
||||
|
||||
|
||||
def on_toggle_toggled(self, tb):
|
||||
toggle = str(tb.name).replace("_toggle", "")
|
||||
isactive = tb.get_active()
|
||||
|
@ -139,6 +202,10 @@ class OptionsDialog():
|
|||
self.glade.get_widget('download_location_entry').set_sensitive(isactive)
|
||||
elif toggle == 'append_extension':
|
||||
self.glade.get_widget('append_extension').set_sensitive(isactive)
|
||||
elif toggle == 'copy_torrent':
|
||||
self.glade.get_widget('copy_torrent_entry').set_sensitive(isactive)
|
||||
self.glade.get_widget('copy_torrent_chooser').set_sensitive(isactive)
|
||||
self.glade.get_widget('delete_copy_torrent_toggle').set_sensitive(isactive)
|
||||
elif toggle == 'move_completed':
|
||||
self.glade.get_widget('move_completed_path_chooser').set_sensitive(isactive)
|
||||
self.glade.get_widget('move_completed_path_entry').set_sensitive(isactive)
|
||||
|
@ -168,29 +235,31 @@ class OptionsDialog():
|
|||
self.glade.get_widget('stop_at_ratio').set_active(isactive)
|
||||
self.glade.get_widget('stop_ratio').set_sensitive(isactive)
|
||||
self.glade.get_widget('remove_at_ratio').set_sensitive(isactive)
|
||||
|
||||
|
||||
def on_apply(self, Event=None):
|
||||
client.autoadd.set_options(str(self.watchdir_id), self.generate_opts()).addCallbacks(self.on_added, self.on_error_show)
|
||||
|
||||
client.autoadd.set_options(
|
||||
str(self.watchdir_id), self.generate_opts()
|
||||
).addCallbacks(self.on_added, self.on_error_show)
|
||||
|
||||
def on_error_show(self, result):
|
||||
self.glade.get_widget('error_label').set_text(result.value.exception_msg)
|
||||
self.err_dialog = self.glade.get_widget('error_dialog')
|
||||
self.err_dialog.set_transient_for(self.dialog)
|
||||
result.cleanFailure()
|
||||
self.err_dialog.show()
|
||||
|
||||
|
||||
def on_added(self, result):
|
||||
self.dialog.destroy()
|
||||
|
||||
|
||||
def on_error_ok(self, Event=None):
|
||||
self.err_dialog.hide()
|
||||
|
||||
|
||||
def on_add(self, Event=None):
|
||||
client.autoadd.add(self.generate_opts()).addCallbacks(self.on_added, self.on_error_show)
|
||||
|
||||
|
||||
def on_cancel(self, Event=None):
|
||||
self.dialog.destroy()
|
||||
|
||||
|
||||
def generate_opts(self):
|
||||
# generate options dict based on gtk objects
|
||||
options = {}
|
||||
|
@ -203,10 +272,14 @@ class OptionsDialog():
|
|||
options['path'] = self.glade.get_widget('path_entry').get_text()
|
||||
options['download_location'] = self.glade.get_widget('download_location_entry').get_text()
|
||||
options['move_completed_path'] = self.glade.get_widget('move_completed_path_entry').get_text()
|
||||
|
||||
options['owner'] = self.accounts[
|
||||
self.glade.get_widget('OwnerCombobox').get_active()][0]
|
||||
|
||||
options['append_extension_toggle'] = self.glade.get_widget('append_extension_toggle').get_active()
|
||||
options['append_extension'] = self.glade.get_widget('append_extension').get_text()
|
||||
options['download_location_toggle'] = self.glade.get_widget('download_location_toggle').get_active()
|
||||
options['label'] = self.glade.get_widget('label').get_text().lower()
|
||||
options['label'] = self.glade.get_widget('label').child.get_text().lower()
|
||||
options['label_toggle'] = self.glade.get_widget('label_toggle').get_active()
|
||||
|
||||
for id in self.spin_ids:
|
||||
|
@ -219,11 +292,11 @@ class OptionsDialog():
|
|||
options[id] = self.glade.get_widget(id).get_active()
|
||||
options[id+'_toggle'] = self.glade.get_widget(id+'_toggle').get_active()
|
||||
return options
|
||||
|
||||
|
||||
|
||||
class GtkUI(GtkPluginBase):
|
||||
def enable(self):
|
||||
|
||||
|
||||
self.glade = gtk.glade.XML(get_resource("config.glade"))
|
||||
self.glade.signal_autoconnect({
|
||||
"on_add_button_clicked": self.on_add_button_clicked,
|
||||
|
@ -231,18 +304,18 @@ class GtkUI(GtkPluginBase):
|
|||
"on_remove_button_clicked": self.on_remove_button_clicked
|
||||
})
|
||||
self.opts_dialog = OptionsDialog()
|
||||
|
||||
|
||||
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.register_event_handler("AutoaddOptionsChangedEvent", self.on_options_changed_event)
|
||||
|
||||
|
||||
self.watchdirs = {}
|
||||
|
||||
|
||||
vbox = self.glade.get_widget("watchdirs_vbox")
|
||||
sw = gtk.ScrolledWindow()
|
||||
sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
|
||||
vbox.pack_start(sw, True, True, 0)
|
||||
|
||||
self.store = self.create_model()
|
||||
|
@ -258,65 +331,76 @@ class GtkUI(GtkPluginBase):
|
|||
component.get("Preferences").add_page("AutoAdd", self.glade.get_widget("prefs_box"))
|
||||
self.on_show_prefs()
|
||||
|
||||
|
||||
|
||||
def disable(self):
|
||||
component.get("Preferences").remove_page("AutoAdd")
|
||||
component.get("PluginManager").deregister_hook("on_apply_prefs", self.on_apply_prefs)
|
||||
component.get("PluginManager").deregister_hook("on_show_prefs", self.on_show_prefs)
|
||||
|
||||
|
||||
def create_model(self):
|
||||
|
||||
store = gtk.ListStore(str, bool, str)
|
||||
store = gtk.ListStore(str, bool, str, str)
|
||||
for watchdir_id, watchdir in self.watchdirs.iteritems():
|
||||
store.append([watchdir_id, watchdir['enabled'], watchdir['path']])
|
||||
store.append([
|
||||
watchdir_id, watchdir['enabled'],
|
||||
watchdir.get('owner', 'localclient'), watchdir['path']
|
||||
])
|
||||
return store
|
||||
|
||||
|
||||
def create_columns(self, treeView):
|
||||
rendererToggle = gtk.CellRendererToggle()
|
||||
column = gtk.TreeViewColumn("On", rendererToggle, activatable=True, active=1)
|
||||
column.set_sort_column_id(1)
|
||||
column = gtk.TreeViewColumn(
|
||||
_("Active"), rendererToggle, activatable=True, active=1
|
||||
)
|
||||
column.set_sort_column_id(1)
|
||||
treeView.append_column(column)
|
||||
tt = gtk.Tooltip()
|
||||
tt.set_text('Double-click to toggle')
|
||||
tt.set_text(_('Double-click to toggle'))
|
||||
treeView.set_tooltip_cell(tt, None, None, rendererToggle)
|
||||
|
||||
|
||||
rendererText = gtk.CellRendererText()
|
||||
column = gtk.TreeViewColumn("Path", rendererText, text=2)
|
||||
column = gtk.TreeViewColumn(_("Owner"), rendererText, text=2)
|
||||
column.set_sort_column_id(2)
|
||||
treeView.append_column(column)
|
||||
tt2 = gtk.Tooltip()
|
||||
tt2.set_text('Double-click to edit')
|
||||
#treeView.set_tooltip_cell(tt2, None, column, None)
|
||||
tt2.set_text(_('Double-click to edit'))
|
||||
treeView.set_has_tooltip(True)
|
||||
|
||||
rendererText = gtk.CellRendererText()
|
||||
column = gtk.TreeViewColumn(_("Path"), rendererText, text=3)
|
||||
column.set_sort_column_id(3)
|
||||
treeView.append_column(column)
|
||||
tt2 = gtk.Tooltip()
|
||||
tt2.set_text(_('Double-click to edit'))
|
||||
treeView.set_has_tooltip(True)
|
||||
|
||||
def load_watchdir_list(self):
|
||||
pass
|
||||
|
||||
|
||||
def add_watchdir_entry(self):
|
||||
pass
|
||||
|
||||
|
||||
def on_add_button_clicked(self, Event=None):
|
||||
#display options_window
|
||||
self.opts_dialog.show()
|
||||
|
||||
|
||||
def on_remove_button_clicked(self, Event=None):
|
||||
tree, tree_id = self.treeView.get_selection().get_selected()
|
||||
watchdir_id = str(self.store.get_value(tree_id, 0))
|
||||
if watchdir_id:
|
||||
client.autoadd.remove(watchdir_id)
|
||||
|
||||
|
||||
def on_edit_button_clicked(self, Event=None, a=None, col=None):
|
||||
tree, tree_id = self.treeView.get_selection().get_selected()
|
||||
watchdir_id = str(self.store.get_value(tree_id, 0))
|
||||
if watchdir_id:
|
||||
if col and col.get_title() == 'On':
|
||||
if col and col.get_title() == _("Active"):
|
||||
if self.watchdirs[watchdir_id]['enabled']:
|
||||
client.autoadd.disable_watchdir(watchdir_id)
|
||||
else:
|
||||
client.autoadd.enable_watchdir(watchdir_id)
|
||||
else:
|
||||
self.opts_dialog.show(self.watchdirs[watchdir_id], watchdir_id)
|
||||
|
||||
|
||||
def on_listitem_activated(self, treeview):
|
||||
tree, tree_id = self.treeView.get_selection().get_selected()
|
||||
if tree_id:
|
||||
|
@ -325,7 +409,7 @@ class GtkUI(GtkPluginBase):
|
|||
else:
|
||||
self.glade.get_widget('edit_button').set_sensitive(False)
|
||||
self.glade.get_widget('remove_button').set_sensitive(False)
|
||||
|
||||
|
||||
def on_apply_prefs(self):
|
||||
log.debug("applying prefs for AutoAdd")
|
||||
for watchdir_id, watchdir in self.watchdirs.iteritems():
|
||||
|
@ -333,7 +417,7 @@ class GtkUI(GtkPluginBase):
|
|||
|
||||
def on_show_prefs(self):
|
||||
client.autoadd.get_config().addCallback(self.cb_get_config)
|
||||
|
||||
|
||||
def on_options_changed_event(self):
|
||||
client.autoadd.get_config().addCallback(self.cb_get_config)
|
||||
|
||||
|
@ -342,8 +426,11 @@ class GtkUI(GtkPluginBase):
|
|||
self.watchdirs = config.get('watchdirs', {})
|
||||
self.store.clear()
|
||||
for watchdir_id, watchdir in self.watchdirs.iteritems():
|
||||
self.store.append([watchdir_id, watchdir['enabled'], watchdir['path']])
|
||||
self.store.append([
|
||||
watchdir_id, watchdir['enabled'],
|
||||
watchdir.get('owner', 'localclient'), watchdir['path']
|
||||
])
|
||||
# Disable the remove and edit buttons, because nothing in the store is selected
|
||||
self.glade.get_widget('remove_button').set_sensitive(False)
|
||||
self.glade.get_widget('edit_button').set_sensitive(False)
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# setup.py
|
||||
#
|
||||
# Copyright (C) 2009 GazpachoKing <chase.sterling@gmail.com>
|
||||
# Copyright (C) 2011 Pedro Algarvio <ufs@ufsoft.org>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
|
@ -40,8 +41,8 @@
|
|||
from setuptools import setup
|
||||
|
||||
__plugin_name__ = "AutoAdd"
|
||||
__author__ = "Chase Sterling"
|
||||
__author_email__ = "chase.sterling@gmail.com"
|
||||
__author__ = "Chase Sterling, Pedro Algarvio"
|
||||
__author_email__ = "chase.sterling@gmail.com, ufs@ufsoft.org"
|
||||
__version__ = "1.02"
|
||||
__url__ = "http://forum.deluge-torrent.org/viewtopic.php?f=9&t=26775"
|
||||
__license__ = "GPLv3"
|
||||
|
|
Loading…
Reference in New Issue