The AutoAdd plugin now supports multiusers.

This commit is contained in:
Pedro Algarvio 2011-04-25 13:16:11 +01:00
parent 51b5b23f76
commit fb5005e3f6
4 changed files with 314 additions and 131 deletions

View File

@ -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

View File

@ -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">&#x25CF;</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">&lt;b&gt;Owner&lt;/b&gt;</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">&#x2022;</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">&#x25CF;</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">&#x25CF;</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">&#x25CF;</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">&#x25CF;</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>

View File

@ -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)

View File

@ -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"