mirror of
https://git.deluge-torrent.org/deluge
synced 2025-09-19 08:08:33 +00:00
label plugin;gtk-disabled
This commit is contained in:
parent
cdf55da8d6
commit
5b60bc2604
11 changed files with 1320 additions and 0 deletions
62
deluge/plugins/label/label/__init__.py
Normal file
62
deluge/plugins/label/label/__init__.py
Normal 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)
|
||||||
|
|
366
deluge/plugins/label/label/core.py
Normal file
366
deluge/plugins/label/label/core.py
Normal 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
|
||||||
|
|
327
deluge/plugins/label/label/gtkui.py
Normal file
327
deluge/plugins/label/label/gtkui.py
Normal 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
53
deluge/plugins/label/label/template/part_label_filters.html
Normal file
53
deluge/plugins/label/label/template/part_label_filters.html
Normal 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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
deluge/plugins/label/label/template/torrent_label.html
Normal file
29
deluge/plugins/label/label/template/torrent_label.html
Normal 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()
|
79
deluge/plugins/label/label/test.py
Normal file
79
deluge/plugins/label/label/test.py
Normal 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'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
53
deluge/plugins/label/label/ui.py
Normal file
53
deluge/plugins/label/label/ui.py
Normal 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
|
||||||
|
|
||||||
|
|
63
deluge/plugins/label/label/webui.py
Normal file
63
deluge/plugins/label/label/webui.py
Normal 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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
149
deluge/plugins/label/label/webui_config.py
Normal file
149
deluge/plugins/label/label/webui_config.py
Normal 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> """ % {"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')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
79
deluge/plugins/label/label/webui_pages.py
Normal file
79
deluge/plugins/label/label/webui_pages.py
Normal 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")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
60
deluge/plugins/label/setup.py
Normal file
60
deluge/plugins/label/setup.py
Normal 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
|
||||||
|
"""
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue