label plugin;gtk-disabled

This commit is contained in:
Martijn Voncken 2008-07-11 18:12:51 +00:00
parent cdf55da8d6
commit 5b60bc2604
11 changed files with 1320 additions and 0 deletions

View File

@ -0,0 +1,62 @@
#
# __init__.py
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
from deluge.log import LOG as log
from deluge.plugins.init import PluginBase
class CorePlugin(PluginBase):
def __init__(self, plugin_api, plugin_name):
# Load the Core portion of the plugin
try:
from core import Core
self.plugin = Core(plugin_api, plugin_name)
except Exception, e:
log.debug("Did not load a Core plugin: %s", e)
class WebUIPlugin(PluginBase):
def __init__(self, plugin_api, plugin_name):
try:
from webui import WebUI
self.plugin = WebUI(plugin_api, plugin_name)
except Exception, e:
log.debug("Did not load a WebUI plugin: %s", e)
class GtkUIPlugin(PluginBase):
def __init__(self, plugin_api, plugin_name):
# Load the GtkUI portion of the plugin
try:
from gtkui import GtkUI
self.plugin = GtkUI(plugin_api, plugin_name)
except Exception, e:
log.debug("Did not load a GtkUI plugin: %s", e)

View File

@ -0,0 +1,366 @@
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
"""
torrent-label core plugin.
adds a status field for tracker.
"""
from deluge.log import LOG as log
from deluge.plugins.corepluginbase import CorePluginBase
from deluge.configmanager import ConfigManager
from urlparse import urlparse
KNOWN_STATES = ['Downloading','Seeding','Paused','Checking','Allocating','Queued','Error']
STATE = "state"
TRACKER = "tracker"
KEYWORD = "keyword"
LABEL = "label"
CONFIG_DEFAULTS = {
"torrent_labels":{}, #torrent_id:label_id
"labels":{}, #label_id:{name:value}
"hide_zero_hits":False,
"gtk_alfa":False
}
OPTIONS_KEYS = ["max_download_speed", "max_upload_speed",
"max_connections", "max_upload_slots", "prioritize_first_last"]
NO_LABEL = "No Label"
import traceback
class Core(CorePluginBase):
def enable(self):
log.info("*** Start Label plugin ***")
self.plugin.register_status_field("tracker_host", self._status_get_tracker)
self.plugin.register_status_field("label", self._status_get_label)
#__init__
core = self.plugin.get_core()
self.config = ConfigManager("label.conf")
self.core_cfg = ConfigManager("core.conf")
self.set_config_defaults()
#reduce typing, assigning some values to self...
self.torrents = core.torrents.torrents
self.labels = self.config.get("labels")
self.torrent_labels = self.config.get("torrent_labels")
log.debug("Label plugin enabled..")
def clean_config(self):
"remove invalid data from config-file"
for torrent_id, label_id in list(self.torrent_labels.iteritems()):
if (not label_id in self.labels) or (not torrent_id in self.torrents):
log.debug("label: rm %s:%s" % (torrent_id,label_id))
del self.torrent_labels[torrent_id]
def save_config(self):
self.clean_config()
self.config.save()
def set_config_defaults(self):
changed = False
for key, value in CONFIG_DEFAULTS.iteritems():
if not key in self.config.config:
self.config.config[key] = value
changed = True
if changed:
pass
#self.config.save()
log.debug("label_config=%s" % self.config.config)
def disable(self):
# De-register the label field
self.plugin.deregister_status_field("tracker_host")
self.plugin.deregister_status_field("label")
def update(self):
pass
## Utils ##
def get_tracker(self, torrent):
"""
returns 1st tracker hostname
save space: reduced to *.com without any subdomain dots before
TODO: CLEANUP
"""
log.debug(torrent)
log.debug(torrent.trackers)
if not torrent.trackers:
return 'tracker-less'
url = urlparse(torrent.trackers[0]['url'])
if hasattr(url,'hostname'):
host = (url.hostname or 'unknown?')
parts = host.split(".")
if len(parts) > 2:
host = ".".join(parts[-2:])
return host
return 'No-tracker?'
## Filters ##
def filter_state(self, torrents, value):
"in/out: a list of torrent objects."
log.debug("filter-state:%s" % value)
for t in torrents:
log.debug("s=%s" % t.state)
return [t for t in torrents if t.state == value]
def filter_tracker(self, torrents, value):
"in/out: a list of torrent objects."
return [t for t in torrents if self.get_tracker(t) == value]
def filter_label(self, torrents, value):
"in/out: a list of torrent objects."
if value == NO_LABEL:
value = None
log.debug("NO_LABEL")
return [t for t in torrents if self.torrent_labels.get(t.torrent_id) == value]
def filter_keyword(self, torrents, value):
value = value.lower().strip()
"in/out: a list of torrent objects."
return [t for t in torrents if value in t.filename.lower()]
## Items ##
def get_state_filter_items(self):
states = dict([(state, 0) for state in KNOWN_STATES])
state_order = list(KNOWN_STATES)
#state-simple:
for t in self.torrents.values():
if not t.state in state_order:
state_order.append(t.state)
states[t.state] = 0
states[t.state] +=1
#specialized-state:
#todo: traffic.
log.debug("hide-z:%s" % self.config["hide_zero_hits"])
if self.config["hide_zero_hits"]:
for state in set(KNOWN_STATES):
log.debug(states.keys())
if states[state] == 0 :
#del states[state]
state_order.remove(state)
#return the filters sorted by STATES + add unknown states.
return ([("All",len(self.torrents))] +
[(state, states[state]) for state in state_order]
)
def get_tracker_filter_items(self):
#trackers:
trackers = {}
for t in self.torrents.values():
tracker = self.get_tracker(t)
if not tracker in trackers:
trackers[tracker] = 0
trackers[tracker] +=1
return [(tracker , trackers[tracker]) for tracker in sorted(trackers.keys())]
def get_label_filter_items(self):
no_label = 0
labels = dict([(label_id, 0) for label_id in self.labels])
for torrent_id in self.torrents:
label_id = self.torrent_labels.get(torrent_id)
if label_id:
labels[label_id] +=1
else:
no_label +=1
if self.config["hide_zero_hits"]:
for label , count in list(labels.iteritems()):
if count == 0:
del labels[label]
return [(NO_LABEL, no_label)] + [(label_id, labels[label_id]) for label_id in sorted(labels.keys())]
## Public ##
def export_filter_items(self):
"""
returns :
{
"CATEGORY" : [("filter_value",count), ...] , ...
}
--
category's : ["state","tracker","label"]
"""
result = {}
result[STATE] = self.get_state_filter_items()
result[TRACKER] = self.get_tracker_filter_items()
result[LABEL] = self.get_label_filter_items()
return result
def export_get_labels(self):
return sorted(self.labels.keys())
def export_get_filtered_ids(self, filter_dict):
"""
input : {"filter_cat":"filter_value",..}
returns : a list of torrent_id's
"""
torrents = self.torrents.values()
if KEYWORD in filter_dict:
torrents = self.filter_keyword(torrents, filter_dict[KEYWORD])
if STATE in filter_dict and filter_dict[STATE] <> "":
torrents = self.filter_state(torrents, filter_dict[STATE])
if TRACKER in filter_dict:
torrents = self.filter_tracker(torrents, filter_dict[TRACKER])
if LABEL in filter_dict:
torrents = self.filter_label(torrents, filter_dict[LABEL])
return [t.torrent_id for t in torrents]
#Labels:
def export_add(self, label_id):
"""add a label
see label_set_options for more options.
"""
assert label_id
assert not (label_id in self.labels)
#default to current global per-torrent settings.
self.labels[label_id] = {
"max_download_speed":self.core_cfg.config["max_download_speed_per_torrent"],
"max_upload_speed":self.core_cfg.config["max_upload_speed_per_torrent"],
"max_connections":self.core_cfg.config["max_connections_per_torrent"],
"max_upload_slots":self.core_cfg.config["max_upload_slots_per_torrent"],
"prioritize_first_last":self.core_cfg.config["prioritize_first_last_pieces"]
}
def export_remove(self, label_id):
"remove a label"
assert label_id in self.labels
del self.labels[label_id]
self.clean_config()
self.config.save()
def export_set_options(self, label_id, options_dict , apply = False):
"""update the label options
options_dict :
{"max_download_speed":float(),
"max_upload_speed":float(),
"max_connections":int(),
"max_upload_slots":int(),
"prioritize_first_last":bool(),
}
apply : applies download-options to all torrents currently labelled by label_id
"""
assert label_id in self.labels
for key in options_dict.keys():
if not key in OPTIONS_KEYS:
raise Exception("label: Invalid options_dict key:%s" % key)
self.labels[label_id].update(options_dict)
options = self.labels[label_id]
if apply:
for torrent_id,label in self.torrent_labels.iteritems():
if label_id == label:
torrent = self.torrents[torrent_id]
torrent.set_max_download_speed(options["max_download_speed"])
torrent.set_max_upload_speed(options["max_upload_speed"])
torrent.set_max_connections(options["max_connections"])
torrent.set_max_upload_slots(options["max_upload_slots"])
torrent.set_prioritize_first_last(options["prioritize_first_last"])
self.config.save()
def export_get_options(self, label_id):
"""returns the label options"""
return self.labels[label_id]
def export_set_torrent(self, torrent_id , label_id):
"""
assign a label to a torrent
removes a label if the label_id parameter is empty.
"""
log.debug(torrent_id)
log.debug(self.torrents.keys())
assert (not label_id) or (label_id in self.labels)
assert torrent_id in self.torrents
if not label_id:
if label_id in self.labels:
del self.torrent_labels[torrent_id]
self.clean_config()
else:
self.torrent_labels[torrent_id] = label_id
#set speeds, etc:
options = self.labels[label_id]
torrent = self.torrents[torrent_id]
torrent.set_max_download_speed(options["max_download_speed"])
torrent.set_max_upload_speed(options["max_upload_speed"])
torrent.set_max_connections(options["max_connections"])
torrent.set_max_upload_slots(options["max_upload_slots"])
torrent.set_prioritize_first_last(options["prioritize_first_last"])
self.config.save()
def export_get_global_options(self):
"see : label_set_global_options"
return {
"hide_zero_hits":self.config.get("hide_zero_hits"),
"gtk_alfa":self.config.get("gtk_alfa")
}
def export_set_global_options(self, options):
"""global_options:
{
"hide_zero":bool() #label_filter_items only returns items with more than 0 hits.
}
"""
for key in ["hide_zero_hits", "gtk_alfa"]:
if options.has_key(key):
self.config.set(key, key)
self.config.save()
## Status fields ##
def _status_get_tracker(self, torrent_id):
return self.get_tracker(self.torrents[torrent_id])
def _status_get_label(self, torrent_id):
return self.torrent_labels.get(torrent_id) or ""
if __name__ == "__main__":
import test

View File

@ -0,0 +1,327 @@
#
# blocklist/gtkui.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import os
import pkg_resources # access plugin egg
from deluge.log import LOG as log
from deluge import component # for systray
import ui
import gtk, gobject
from deluge.ui.client import aclient
from deluge.configmanager import ConfigManager
config = ConfigManager("label.conf")
GTK_ALFA = config.get("gtk_alfa")
class GtkUI(ui.UI):
def __init__(self, plugin_api, plugin_name):
log.debug("Calling UI init")
# Call UI constructor
ui.UI.__init__(self, plugin_api, plugin_name)
log.debug("Label GtkUI plugin initalized..")
def enable(self):
self.plugin.register_hook("on_apply_prefs", self.apply_prefs)
self.load_interface()
def disable(self):
#deluge.component.get("StatusBar").remove_item(self.blocklist_status)
self.plugin.deregister_hook("on_apply_prefs", self.apply_prefs)
self.plugin.remove_preferences_page("Label")
def get_pixmap(self, fname):
"""Returns a pixmap file included with plugin"""
return pkg_resources.resource_filename("blocklist", os.path.join("data", fname))
def unload_interface(self):
self.plugin.remove_preferences_page("Label")
def load_interface(self):
if not GTK_ALFA:
self.plugin.add_preferences_page("Label", gtk.Label(
"Sorry, the Gtk UI for the Label-plugin is still in development."))
return
log.debug("add items to torrentview-popup menu.")
torrentmenu = component.get("MenuBar").torrentmenu
self.label_menu = LabelMenu()
torrentmenu.append(self.label_menu)
self.label_menu.show_all()
log.debug("add label column")
#TODO!
log.debug("Beginning gtk pane initialization")
self.config_frame = LabelConfigFrame()
self.blocklist_pref_page = gtk.VBox()
self.blocklist_pref_page.set_spacing(6)
self.blocklist_pref_page.pack_start(self.config_frame,True,True)
# Add preferences page to preferences page
log.debug('Adding Label Preferences page')
self.plugin.add_preferences_page("Label", self.blocklist_pref_page)
# Load settings from config and fill widgets with settings
self.fetch_prefs()
#log.debug('Finished loading Label preferences')
def fetch_prefs(self): # Fetch settings dictionary from plugin core and pass it to GTK ui settings
log.info('LABEL: Fetching and loading Preferences via GTK ui')
#aclient.block_list_get_options(self.callback_load_prefs)
self.config_frame.load_settings()
def apply_prefs(self):
log.info('Blocklist: Preferences saved via Gtk ui')
"""settings_dict = {
"url": self.url.get_text(),
"listtype": self.get_ltype(),
"check_after_days": self.check_after_days.get_value_as_int(),
"load_on_start":self.load_on_start.get_active(),
"try_times": self.try_times.get_value_as_int(),
"timeout": self.timeout.get_value_as_int()
}
aclient.block_list_set_options(None, settings_dict)
# Needs to go in another thread or wait until window is closed
#gobject.idle_add(self.call_critical_setting)
"""
# GTK Gui Callback functions
def callback_load_prefs(self, dict):
self.config_frame.load_settings()
log.info('Blocklist: Callback Load Prefs GTK ui')
"""self.settings_url(dict['url'])
self.settings_listtype(dict['listtype'])
self.settings_load(dict['load_on_start'])
self.settings_check_after_days(dict['check_after_days'])
self.settings_timeout(dict['timeout'])
self.settings_try_times(dict['try_times'])
"""
def cb_none(args):
"hack for empty callbacks."
pass
"""
class LabelList(gtk.TreeView):
"a simple listbox is way too hard in gtk :(."
def __init__(self):
pass
"""
class LabelMenu(gtk.MenuItem):
def __init__(self):
gtk.MenuItem.__init__(self, "Label (wip)")
self.show_all()
#attach..
torrentmenu = component.get("MenuBar").torrentmenu
torrentmenu.connect("show", self.on_show, None)
def get_torrent_ids(self):
return component.get("TorrentView").get_selected_torrents()
def on_show(self, widget=None, data=None):
log.debug("label-on-show")
aclient.label_get_labels(self.cb_labels)
aclient.force_call(block=True)
def cb_labels(self , labels):
log.debug("cb_labels-start")
self.sub_menu = gtk.Menu()
for label in labels:
item = gtk.MenuItem(label)
item.connect("activate", self.on_select_label, label)
self.sub_menu.append(item)
self.set_submenu(self.sub_menu)
self.show_all()
log.debug("cb_labels-end")
def on_select_label(self, widget=None, label_id = None):
log.debug("select label:%s,%s" % (label_id ,self.get_torrent_ids()) )
for torrent_id in self.get_torrent_ids():
aclient.label_set_torrent(cb_none, torrent_id, label_id)
#aclient.force_call(block=True)
class LabelConfigFrame(gtk.Frame):
def __init__(self):
gtk.Frame.__init__(self)
self.build_label_view()
self.build_label_options()
self.build_ui()
self.labels = []
def load_settings(self ,widget=None ,data=None):
aclient.label_get_labels(self.cb_update_labels)
def cb_update_labels(self, labels):
self.labels = labels
self.label_store.clear()
for label in labels:
self.label_store.append([label])
def on_add(self, widget, data=None):
label = self.txt_add.get_text()
self.txt_add.set_text("")
if label in self.labels:
return
aclient.label_add(cb_none, label)
aclient.label_get_labels(self.cb_update_labels)
self.select_label(label)
#aclient.force_call(block=True)
def on_remove(self, widget, data=None):
label = self.get_selected_label()
aclient.label_remove(cb_none, label)
aclient.label_get_labels(self.cb_update_labels)
self.select_label(0)
def get_selected_label(self):
model , iter = self.label_view.get_selection().get_selected()
return self.label_store.get_value(iter,0)
def select_label(self, label):
aclient.force_call(block=True) #sync..
if label:
it = self.label_store.iter_nth_child(None,self.labels.index(label))
else:
it = self.label_store.iter_nth_child(None,0)
self.label_view.get_selection().select_iter(it)
def build_label_view(self):
"gtk should have a simple listbox widget..."
self.label_store = gtk.ListStore(str)
column = gtk.TreeViewColumn(_("Label"))
renderer = gtk.CellRendererText()
column.pack_start(renderer)
column.set_attributes(renderer, text = 0)
self.label_view = gtk.TreeView(self.label_store)
self.label_view.append_column(column)
self.label_view.set_headers_visible(False)
#self.label_scroll = gtk.ScrolledWindow()
#self.label_scroll.add_with_viewport(self.label_view)
def build_label_options(self):
self.label_options = gtk.Label("Per label options")
def build_ui(self):
#vbox
#general
#[x] stuff
#labels:
#hpaned : left-right
#right: listbox with labels
#left: label-options
#---
#label-add
#--
label = gtk.Label()
label.set_markup('<b>' + _('General') + '</b>')
self.set_shadow_type(gtk.SHADOW_NONE)
self.set_label_widget(label)
self.btn_load = gtk.Button("Load Settings")
self.btn_load.connect("clicked", self.load_settings, None)
self.btn_remove = gtk.Button("Remove")
self.btn_remove.connect("clicked", self.on_remove, None)
vb = gtk.VBox()
self.add(vb)
vb.add(self.btn_load)
vb.add(gtk.Label("Label is in developent, you're testing pre-alfa!!!"))
self.hide_zero_hits = gtk.CheckButton(_('Hide Zero Hits'))
vb.add(self.hide_zero_hits)
label = gtk.Label()
label.set_markup('<b>' + _('Labels') + '</b>')
vb.add(label)
hp = gtk.HPaned()
hp.add1(self.label_view)
hp.add2(self.label_options)
hp.set_position(100)
hp.set_size_request(400, 200) #bug..
hbAdd = gtk.HBox()
hbAdd.add(gtk.Label("Label:"))
self.txt_add = gtk.Entry()
hbAdd.add(self.txt_add)
btn_add = gtk.Button("Add")
hbAdd.add(btn_add)
btn_add.connect("clicked", self.on_add, None)
vb.pack_end(hbAdd)
label = gtk.Label()
label.set_markup('<b>' + _('Add') + '</b>')
vb.pack_end(label)
vb.pack_end(self.btn_remove, True , True)
vb.pack_end(hp,True , True)

View File

@ -0,0 +1,53 @@
$def with (filter_items)
<form method="GET" id="category_form">
<input type="hidden" name="sort" value="$get('sort')">
<input type="hidden" name="order" value="$get('order')">
<input type="hidden" name="filter_cat" value="keyword">
<div id="organize_block">
<div id="organize_state">
<div class="title">$_('Keyword')</div>
<input type="text" name="filter_value" id="filter_value"
$if get('filter_cat') == "keyword":
value="$get('filter_value')"
style="width:100px;padding:0px" title="$_('Filter on a keyword')"/>
$if get('filter_cat') == "keyword":
$if get('filter_value'):
<img src="$base/static/images/tango/edit-clear.png" alt="$_('Clear')"
onclick="el('keyword').value='';el('category_form').submit();"
>
</form>
<br /><br />
<!--
$filter_items
-->
$for cat in ["state", "tracker", "label"]:
<div class="title">$cat</div>
<ul>
$for value, count in filter_items[cat]:
<li
$if cat == get('filter_cat'):
$if value == get('filter_value'):
class="selected"
$# I hate this, special case for All
$# templetor sucks with multiple conditions in 1 if-statement, i need to find a better way,
$if cat == "state":
$if value == "All":
$if not get('filter_value'):
$if not get('filter_cat'):
class="selected"
>
<a href="$self_url(filter_cat=cat, filter_value=value)">
$if cat == "state":
<img src="/pixmaps/$(value.lower())"></img>
$value ($count)</a>
</li>
</ul>
</div>
</div>

View File

@ -0,0 +1,29 @@
$def with (torrent_ids, torrent_list, labels)
$:render.header(_("Label torrent"))
<div class="panel">
<form method="POST" action='$base/torrent/label/$torrent_ids'>
<div id="del_torrent">
<h2>$_("Label torrent")</h2>
<ul>
$for torrent in torrent_list:
<li>$torrent.name ($torrent.label)</li>
</ul>
<div class="form_row2">
<span class="form_label2">
<select size=$(len(labels) + 1) style="width:150px" name="label" id="label">
<option value="">No Label</option>
$for label in labels:
<option value="$label">$label</option>
</select>
</div>
<div class="form_row2">
<span class="form_label2"></span>
<input type="submit" name="submit"
value="$_('Label')" class="form_input">
</div>
</div>
</form>
</div>
$:render.footer()

View File

@ -0,0 +1,79 @@
from deluge.ui.client import sclient
sclient.set_core_uri()
print sclient.get_enabled_plugins()
#enable plugin.
if not "label" in sclient.get_enabled_plugins():
sclient.enable_plugin("label")
#test filter items.
print "# label_filter_items()"
for cat,filters in sclient.label_filter_items():
print "-- %s --" % cat
for filter in filters:
print " * %s (%s)" % (filter[0],filter[1])
# test filtering
print "#len(sclient.label_get_filtered_ids({'tracker':'tracker.aelitis.com'} ))"
print len(sclient.label_get_filtered_ids({'tracker':'tracker.aelitis.com'} ))
print "#len(sclient.label_get_filtered_ids({'state':'Paused'} ))"
print len(sclient.label_get_filtered_ids({'state':'Paused'} ))
print "#len(sclient.label_get_filtered_ids({'keyword':'az'} ))"
print len(sclient.label_get_filtered_ids({'keyword':'az'} ))
print "#len(sclient.label_get_filtered_ids({'state':'Paused','tracker':'tracker.aelitis.com'} ))"
print len(sclient.label_get_filtered_ids({'state':'Paused','tracker':'tracker.aelitis.com'} ))
print "#test status-fields:"
ids = sclient.get_session_state()
torrents = sclient.get_torrents_status(ids,['name', 'tracker_host', 'label'])
for id,torrent in torrents.iteritems():
print id, torrent
#test labels.
print "#init labels"
try:
sclient.label_remove("test")
except:
pass
id = sclient.get_session_state()[0]
print "#add"
sclient.label_add("test")
print "#set"
sclient.label_set_torrent(id,"test")
print "#len(sclient.label_get_filtered_ids({'label':'test'} ))"
print len(sclient.label_get_filtered_ids({'label':'test'} ))
#test filter items.
print "# label_filter_items()"
for cat,filters in sclient.label_filter_items():
if cat == "label":
print "-- %s --" % cat
for filter in filters:
print " * %s (%s)" % (filter[0],filter[1])
print "#set options"
sclient.label_set_options("test",{"max_download_speed":999}, True)
print sclient.get_torrent_status(id, ["max_download_speed"]) , "999"
sclient.label_set_options("test",{"max_download_speed":9}, True)
print sclient.get_torrent_status(id, ["max_download_speed"]) , "9"
sclient.label_set_options("test",{"max_download_speed":888}, False)
print sclient.get_torrent_status(id, ["max_download_speed"]) , "9 (888)"
print sclient.get_torrent_status(id,['name', 'tracker_host', 'label'])

View File

@ -0,0 +1,53 @@
#
# blocklist/ui.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
# Copyright (C) 2008 Mark Stahler ('kramed') <markstahler@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import gettext
import locale
import pkg_resources
import deluge.component
from deluge.ui.client import aclient as client
from deluge.log import LOG as log
class UI:
def __init__(self, plugin_api, plugin_name):
self.plugin = plugin_api
def enable(self):
pass
def disable(self):
pass

View File

@ -0,0 +1,63 @@
#
# blocklist/webui.py
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import os
from deluge.log import LOG as log
from deluge.ui.client import sclient
from deluge import component
import ui
import webui_config
import webui_pages
class WebUI(ui.UI):
def __init__(self, plugin_api, plugin_name):
log.debug("Calling UI init")
# Call UI constructor
ui.UI.__init__(self, plugin_api, plugin_name)
log.debug("Label WebUI plugin initalized..")
def enable(self):
webui_pages.register()
webui_config.register()
def disable(self):
webui_pages.unregister()
webui_config.unregister()

View File

@ -0,0 +1,149 @@
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import os
from deluge.log import LOG as log
from deluge.ui.client import sclient
from deluge import component
api = component.get("WebPluginApi")
forms = api.forms
class LabelUpdateCfgForm(forms.Form):
"""
a config form based on django forms.
see webui.lib.newforms_plus, config_forms, etc.
"""
#meta:
title = _("Labels")
def get_selected(self):
selected = api.web.input(label = None).label
labels = sclient.label_get_labels()
if not selected:
if labels:
selected = labels[0]
return selected
def pre_html(self):
selected = self.get_selected()
html = _("Select Label") + ":"
for label in sclient.label_get_labels():
html += """
<a href="/config/label_update?label=%(label)s">%(label)s</a> &nbsp;""" % {"label":label}
html += "<h2>%s</h2>" % selected
return html
#load/save:
def initial_data(self):
label_id = self.get_selected()
return sclient.label_get_options(label_id)
def save(self, data):
label_id = self.get_selected()
apply = data.apply
delete = data.delete
if delete:
sclient.label_remove(label_id)
raise Exception("DELETED")
else:
del data["apply"]
del data["delete"]
sclient.label_set_options(label_id, dict(data), apply)
#input fields :
max_connections = forms.DelugeInt(_("Maximum Connections"))
max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)"))
max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
max_upload_slots = forms.DelugeInt(_("Maximum Upload Slots"))
apply = forms.CheckBox(_("Apply"))
delete = forms.CheckBox(_("Delete"))
class LabelAddCfgForm(forms.Form):
"""
a config form based on django forms.
see webui.lib.newforms_plus, config_forms, etc.
"""
#meta:
title = _("Add Label")
#load/save:
def initial_data(self):
return { }
def save(self, data):
sclient.label_add(data.label)
label = forms.CharField(_("Label"))
class LabelCfgForm(forms.Form):
"""
global settings.
"""
#meta:
title = _("General")
#load/save:
def initial_data(self):
return sclient.label_get_global_options()
def save(self, data):
return sclient.label_set_global_options(dict(data))
hide_zero_hits = forms.CheckBox(_("Hide filter items with 0 hits"))
#gtk_alfa = forms.CheckBox(_("gtk_alfa"))
def register():
api.config_page_manager.register('label','label_general',LabelCfgForm)
api.config_page_manager.register('label','label_update',LabelUpdateCfgForm)
api.config_page_manager.register('label','label_add',LabelAddCfgForm)
def unregister():
api.config_page_manager.unregister('label_general')
api.config_page_manager.unregister('label_update')
api.config_page_manager.unregister('label_add')

View File

@ -0,0 +1,79 @@
#
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import os
from deluge.log import LOG as log
from deluge.ui.client import sclient
from deluge import component
api = component.get("WebPluginApi")
template_dir = os.path.join(os.path.dirname(__file__),"template")
class torrent_label:
@api.deco.deluge_page
@api.deco.torrent_list
def GET(self, torrent_list):
torrent_str = ",".join([t.id for t in torrent_list])
labels = sclient.label_get_labels()
return api.render.torrent_label(torrent_str , torrent_list , labels)
@api.deco.check_session
@api.deco.torrent_ids
def POST(self, torrent_ids):
label =api.web.input(label = None).label
for id in torrent_ids:
sclient.label_set_torrent(id , label)
api.utils.do_redirect()
def register():
api.render.register_template_path(template_dir)
api.page_manager.register_page('/torrent/label/(.*)', torrent_label)
api.menu_manager.register_toolbar_item("label",_("Label"), "label.png" ,2,
"GET","/torrent/label/", True)
def unregister():
api.render.unregister_template_path(template_dir)
api.page_manager.unregister_page('/torrent/label/(.*)')
api.menu_manager.unregister_toolbar_item("label")

View File

@ -0,0 +1,60 @@
# setup.py
#
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
"""
Label plugin.
Offers filters on state,tracker and keyword.
adds a tracker column.
future: Real labels.
"""
from setuptools import setup
__author__ = "Martijn Voncken <mvoncken@gmail.com>"
setup(
name="Label",
version="0.1",
description=__doc__,
author=__author__,
packages=["label"],
package_data = {"label": ["template/*"]},
entry_points="""
[deluge.plugin.core]
Label = label:CorePlugin
[deluge.plugin.webui]
Label = label:WebUIPlugin
[deluge.plugin.gtkui]
Label = label:GtkUIPlugin
"""
)