label plugin (clean label/build dir)
This commit is contained in:
parent
8f8b87987b
commit
99a5c07c8c
|
@ -0,0 +1,13 @@
|
||||||
|
*grey bars in sidebar are ugly
|
||||||
|
*label sub-menu is broken on 1'st popup.
|
||||||
|
*replacing/restoring the sidebar model is a hack
|
||||||
|
*config should save a label on bottom ok-button, not a seperate save-button per label
|
||||||
|
*filters : add "Traffic" , use label-core for filtering ; needs hooks in torrentview.
|
||||||
|
*torrentview: bugs/hacks in adding and removing columns
|
||||||
|
*webui is functional but not polished.
|
||||||
|
*move_torrent_to is not implemeted
|
||||||
|
*no client-side validation (could be solved by a ui.aclient exception-plugin)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ import re
|
||||||
RE_VALID = re.compile("[a-z0-9_-]*\Z")
|
RE_VALID = re.compile("[a-z0-9_-]*\Z")
|
||||||
RE_VALID = re.compile("[a-z0-9_-]*\Z")
|
RE_VALID = re.compile("[a-z0-9_-]*\Z")
|
||||||
|
|
||||||
KNOWN_STATES = ['Downloading','Seeding','Paused','Checking','Allocating','Queued','Error']
|
KNOWN_STATES = ['Downloading','Seeding','Paused','Checking','Queued','Error']
|
||||||
STATE = "state"
|
STATE = "state"
|
||||||
TRACKER = "tracker"
|
TRACKER = "tracker"
|
||||||
KEYWORD = "keyword"
|
KEYWORD = "keyword"
|
||||||
|
@ -58,7 +58,7 @@ CONFIG_DEFAULTS = {
|
||||||
"gtk_alfa":False
|
"gtk_alfa":False
|
||||||
}
|
}
|
||||||
OPTIONS_KEYS = ["max_download_speed", "max_upload_speed",
|
OPTIONS_KEYS = ["max_download_speed", "max_upload_speed",
|
||||||
"max_connections", "max_upload_slots", "prioritize_first_last"]
|
"max_connections", "max_upload_slots", "prioritize_first_last","apply_max","move_completed_to"]
|
||||||
NO_LABEL = "No Label"
|
NO_LABEL = "No Label"
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ class Core(CorePluginBase):
|
||||||
label_id = label_id.lower()
|
label_id = label_id.lower()
|
||||||
CheckInput(RE_VALID.match(label_id) , _("Invalid label, valid characters:[a-z0-9_-]"))
|
CheckInput(RE_VALID.match(label_id) , _("Invalid label, valid characters:[a-z0-9_-]"))
|
||||||
CheckInput(label_id, _("Empty Label"))
|
CheckInput(label_id, _("Empty Label"))
|
||||||
CheckInput(not (label_id in self.labels) , _("Unknown Label"))
|
CheckInput(not (label_id in self.labels) , _("Label already exists"))
|
||||||
|
|
||||||
|
|
||||||
#default to current global per-torrent settings.
|
#default to current global per-torrent settings.
|
||||||
|
@ -273,7 +273,9 @@ class Core(CorePluginBase):
|
||||||
"max_upload_speed":self.core_cfg.config["max_upload_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_connections":self.core_cfg.config["max_connections_per_torrent"],
|
||||||
"max_upload_slots":self.core_cfg.config["max_upload_slots_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"]
|
"prioritize_first_last":self.core_cfg.config["prioritize_first_last_pieces"],
|
||||||
|
"apply_max":True,
|
||||||
|
"move_completed_to":None
|
||||||
}
|
}
|
||||||
|
|
||||||
def export_remove(self, label_id):
|
def export_remove(self, label_id):
|
||||||
|
@ -291,12 +293,14 @@ class Core(CorePluginBase):
|
||||||
"max_upload_speed":float(),
|
"max_upload_speed":float(),
|
||||||
"max_connections":int(),
|
"max_connections":int(),
|
||||||
"max_upload_slots":int(),
|
"max_upload_slots":int(),
|
||||||
"prioritize_first_last":bool(),
|
#"prioritize_first_last":bool(),
|
||||||
|
"apply_max":bool(),
|
||||||
|
"move_completed_to":string() or None
|
||||||
}
|
}
|
||||||
|
|
||||||
apply : applies download-options to all torrents currently labelled by label_id
|
apply : applies download-options to all torrents currently labelled by label_id
|
||||||
"""
|
"""
|
||||||
CheckInput(not (label_id in self.labels) , _("Unknown Label"))
|
CheckInput(label_id in self.labels , _("Unknown Label"))
|
||||||
for key in options_dict.keys():
|
for key in options_dict.keys():
|
||||||
if not key in OPTIONS_KEYS:
|
if not key in OPTIONS_KEYS:
|
||||||
raise Exception("label: Invalid options_dict key:%s" % key)
|
raise Exception("label: Invalid options_dict key:%s" % key)
|
||||||
|
@ -339,12 +343,13 @@ class Core(CorePluginBase):
|
||||||
self.torrent_labels[torrent_id] = label_id
|
self.torrent_labels[torrent_id] = label_id
|
||||||
#set speeds, etc:
|
#set speeds, etc:
|
||||||
options = self.labels[label_id]
|
options = self.labels[label_id]
|
||||||
torrent = self.torrents[torrent_id]
|
if ("apply_max" in options) and options["apply_max"]:
|
||||||
torrent.set_max_download_speed(options["max_download_speed"])
|
torrent = self.torrents[torrent_id]
|
||||||
torrent.set_max_upload_speed(options["max_upload_speed"])
|
torrent.set_max_download_speed(options["max_download_speed"])
|
||||||
torrent.set_max_connections(options["max_connections"])
|
torrent.set_max_upload_speed(options["max_upload_speed"])
|
||||||
torrent.set_max_upload_slots(options["max_upload_slots"])
|
torrent.set_max_connections(options["max_connections"])
|
||||||
torrent.set_prioritize_first_last(options["prioritize_first_last"])
|
torrent.set_max_upload_slots(options["max_upload_slots"])
|
||||||
|
torrent.set_prioritize_first_last(options["prioritize_first_last"])
|
||||||
|
|
||||||
self.config.save()
|
self.config.save()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,450 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||||
|
<!--Generated with glade3 3.4.5 on Sun Jul 20 22:26:59 2008 -->
|
||||||
|
<glade-interface>
|
||||||
|
<widget class="GtkWindow" id="window1">
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="label_prefs_box">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkFrame" id="frame1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label_xalign">0</property>
|
||||||
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkAlignment" id="alignment1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="left_padding">12</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="vbox2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="hbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkCheckButton" id="hide_zero_hits">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Hide zero hits</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="ypad">5</property>
|
||||||
|
<property name="label" translatable="yes"><b>General</b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="type">label_item</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkFrame" id="frame2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label_xalign">0</property>
|
||||||
|
<property name="shadow_type">GTK_SHADOW_NONE</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHPaned" id="hpaned1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="position">150</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkTable" id="table2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="n_rows">1</property>
|
||||||
|
<property name="n_columns">2</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="btn_add">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="label" translatable="yes">add</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="txt_add">
|
||||||
|
<property name="width_request">100</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkTreeView" id="label_view">
|
||||||
|
<property name="height_request">250</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="headers_clickable">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="btn_remove">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="label" translatable="yes">Remove</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="resize">False</property>
|
||||||
|
<property name="shrink">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkVBox" id="vbox3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="txt_label">
|
||||||
|
<property name="height_request">30</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes"><b>label</b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkTable" id="table1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="n_rows">12</property>
|
||||||
|
<property name="n_columns">3</property>
|
||||||
|
<property name="column_spacing">5</property>
|
||||||
|
<property name="row_spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="btn_apply">
|
||||||
|
<property name="width_request">50</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="label" translatable="yes">Apply to all</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">5</property>
|
||||||
|
<property name="bottom_attach">6</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkFileChooserButton" id="move_completed_to">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="title" translatable="yes">Select A Folder</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">7</property>
|
||||||
|
<property name="bottom_attach">8</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkSpinButton" id="max_upload_speed">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="bottom_attach">4</property>
|
||||||
|
<property name="x_options">GTK_EXPAND</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkCheckButton" id="apply_max">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Apply maximum limits on add:</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkCheckButton" id="chk_move_completed">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Move completed to:</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">6</property>
|
||||||
|
<property name="bottom_attach">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label9">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">Kib/s</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">2</property>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
<property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkSpinButton" id="max_download_speed">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
<property name="x_options">GTK_EXPAND</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkSpinButton" id="max_connections">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||||
|
<property name="numeric">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
|
<property name="x_options"></property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Upload Slots: </property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">4</property>
|
||||||
|
<property name="bottom_attach">5</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label6">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Upload Speed:</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="bottom_attach">4</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label5">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Download Speed:</property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label4">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Connections:</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label8">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">Kib/s</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">2</property>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">3</property>
|
||||||
|
<property name="bottom_attach">4</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkSpinButton" id="max_upload_slots">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||||
|
<property name="numeric">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">4</property>
|
||||||
|
<property name="bottom_attach">5</property>
|
||||||
|
<property name="x_options">GTK_EXPAND</property>
|
||||||
|
<property name="y_options">GTK_EXPAND</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="btn_save">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="label" translatable="yes">Save Label Settings</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="top_attach">9</property>
|
||||||
|
<property name="bottom_attach">10</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="resize">True</property>
|
||||||
|
<property name="shrink">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label10">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="ypad">5</property>
|
||||||
|
<property name="label" translatable="yes"><b>Labels</b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="type">label_item</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</glade-interface>
|
|
@ -1,366 +0,0 @@
|
||||||
#
|
|
||||||
# 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
|
|
||||||
import gtk_sidebar
|
|
||||||
|
|
||||||
from deluge.configmanager import ConfigManager
|
|
||||||
config = ConfigManager("label.conf")
|
|
||||||
GTK_ALFA = config.get("gtk_alfa")
|
|
||||||
NO_LABEL = "No Label"
|
|
||||||
|
|
||||||
|
|
||||||
def cell_data_label(column, cell, model, row, data):
|
|
||||||
cell.set_property('text', str(model.get_value(row, data)))
|
|
||||||
|
|
||||||
def cell_data_tracker_host(column, cell, model, row, data):
|
|
||||||
cell.set_property('text', str(model.get_value(row, data)))
|
|
||||||
|
|
||||||
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("replace sidebar")
|
|
||||||
|
|
||||||
try :
|
|
||||||
labelsidebar = gtk_sidebar.LabelSideBar()
|
|
||||||
#sidebar.hpaned.remove(sidebar.scrolled)
|
|
||||||
except Exception, e:
|
|
||||||
log.debug(e)
|
|
||||||
|
|
||||||
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 columns")
|
|
||||||
|
|
||||||
component.get("TorrentView").add_func_column(_("Label"),
|
|
||||||
cell_data_label,
|
|
||||||
[str],
|
|
||||||
status_field=["label"])
|
|
||||||
|
|
||||||
component.get("TorrentView").add_func_column(_("Tracker"),
|
|
||||||
cell_data_tracker_host,
|
|
||||||
[str],
|
|
||||||
status_field=["tracker_host"])
|
|
||||||
|
|
||||||
component.get("TorrentView").create_model_filter() #todo:improve.
|
|
||||||
#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")
|
|
||||||
self.show_all()
|
|
||||||
|
|
||||||
#attach..
|
|
||||||
torrentmenu = component.get("MenuBar").torrentmenu
|
|
||||||
torrentmenu.connect("show", self.on_show, None)
|
|
||||||
|
|
||||||
aclient.connect_on_new_core(self._on_new_core)
|
|
||||||
|
|
||||||
def _on_new_core(self, data):
|
|
||||||
self.on_show()
|
|
||||||
|
|
||||||
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 [NO_LABEL] + 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 = []
|
|
||||||
aclient.connect_on_new_core(self._on_new_core)
|
|
||||||
|
|
||||||
def _on_new_core(self, data):
|
|
||||||
log.debug("NEW CORE")
|
|
||||||
self.load_settings()
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
#
|
||||||
|
# blocklist/gtkui.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
|
||||||
|
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
|
||||||
|
|
||||||
|
import sidebar
|
||||||
|
import label_config
|
||||||
|
import submenu
|
||||||
|
|
||||||
|
from deluge.configmanager import ConfigManager
|
||||||
|
config = ConfigManager("label.conf")
|
||||||
|
NO_LABEL = "No Label"
|
||||||
|
|
||||||
|
|
||||||
|
def cell_data_label(column, cell, model, row, data):
|
||||||
|
cell.set_property('text', str(model.get_value(row, data)))
|
||||||
|
|
||||||
|
def cell_data_tracker_host(column, cell, model, row, data):
|
||||||
|
cell.set_property('text', str(model.get_value(row, data)))
|
||||||
|
|
||||||
|
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..")
|
||||||
|
self.labelcfg = None
|
||||||
|
self.sidebar = None
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self.load_interface()
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
self.labelcfg.unload()
|
||||||
|
try:
|
||||||
|
component.get("TorrentView").remove_column(_("Label"))
|
||||||
|
log.debug(1.1)
|
||||||
|
component.get("TorrentView").remove_column(_("Tracker"))
|
||||||
|
log.debug(1.2)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug(e) #fix this!
|
||||||
|
log.debug(1.2)
|
||||||
|
self.sidebar.unload()
|
||||||
|
log.debug(2)
|
||||||
|
|
||||||
|
|
||||||
|
def get_pixmap(self, fname):
|
||||||
|
"""Returns a pixmap file included with plugin"""
|
||||||
|
return pkg_resources.resource_filename("blocklist", os.path.join("data", fname))
|
||||||
|
|
||||||
|
|
||||||
|
def load_interface(self):
|
||||||
|
#sidebar
|
||||||
|
log.debug("replace sidebar")
|
||||||
|
try :
|
||||||
|
if not self.sidebar:
|
||||||
|
self.sidebar = sidebar.LabelSideBar()
|
||||||
|
self.sidebar.load()
|
||||||
|
except Exception, e:
|
||||||
|
log.debug(e)
|
||||||
|
|
||||||
|
#menu:
|
||||||
|
log.debug("add items to torrentview-popup menu.")
|
||||||
|
torrentmenu = component.get("MenuBar").torrentmenu
|
||||||
|
self.label_menu = submenu.LabelMenu()
|
||||||
|
torrentmenu.append(self.label_menu)
|
||||||
|
self.label_menu.show_all()
|
||||||
|
|
||||||
|
#columns:
|
||||||
|
self.load_columns()
|
||||||
|
|
||||||
|
#config:
|
||||||
|
if not self.labelcfg:
|
||||||
|
self.labelcfg = label_config.LabelConfig(self.plugin)
|
||||||
|
self.labelcfg.load()
|
||||||
|
|
||||||
|
log.debug('Finished loading Label plugin')
|
||||||
|
|
||||||
|
def load_columns(self):
|
||||||
|
log.debug("add columns")
|
||||||
|
|
||||||
|
component.get("TorrentView").add_func_column(_("Label"),
|
||||||
|
cell_data_label,
|
||||||
|
[str],
|
||||||
|
status_field=["label"])
|
||||||
|
|
||||||
|
component.get("TorrentView").add_func_column(_("Tracker"),
|
||||||
|
cell_data_tracker_host,
|
||||||
|
[str],
|
||||||
|
status_field=["tracker_host"])
|
||||||
|
|
||||||
|
component.get("TorrentView").create_model_filter() #todo:improve.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
#
|
||||||
|
# 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 gtk
|
||||||
|
import gtk.glade
|
||||||
|
import os
|
||||||
|
import pkg_resources # access plugin egg
|
||||||
|
import deluge.component as component
|
||||||
|
import deluge.common
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
from deluge.ui.client import aclient
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class LabelConfig(object):
|
||||||
|
def __init__(self, plugin):
|
||||||
|
self.plugin = plugin
|
||||||
|
self.labels = []
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
#self.glade = gtk.glade.XML(self.get_resource("label_pref.glade"))
|
||||||
|
log.debug('Adding Label Preferences page')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.glade = gtk.glade.XML(self.get_resource("label_pref.glade"))
|
||||||
|
self.prefs_box = self.glade.get_widget("label_prefs_box")
|
||||||
|
self.label_view = self.glade.get_widget("label_view")
|
||||||
|
self.txt_add = self.glade.get_widget("txt_add")
|
||||||
|
self.btn_add = self.glade.get_widget("btn_add")
|
||||||
|
self.btn_remove = self.glade.get_widget("btn_remove")
|
||||||
|
self.label_view = self.glade.get_widget("label_view")
|
||||||
|
|
||||||
|
|
||||||
|
self.btn_remove.connect("clicked", self.on_remove, None)
|
||||||
|
self.btn_add.connect("clicked", self.on_add, None)
|
||||||
|
|
||||||
|
self.build_label_view()
|
||||||
|
|
||||||
|
self.plugin.add_preferences_page("Label", self.glade.get_widget("label_prefs_box"))
|
||||||
|
self.plugin.register_hook("on_show_prefs", self.load_settings)
|
||||||
|
self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs)
|
||||||
|
|
||||||
|
self.glade.get_widget("chk_move_completed").connect("clicked",self.on_chk_move_changed)
|
||||||
|
self.glade.get_widget("apply_max").connect("clicked",self.on_apply_max_changed)
|
||||||
|
self.glade.get_widget("btn_save").connect("clicked",self.on_save_label)
|
||||||
|
self.glade.get_widget("btn_apply").connect("clicked",self.on_apply_label)
|
||||||
|
|
||||||
|
|
||||||
|
self.load_settings()
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
self.plugin.remove_preferences_page("Label")
|
||||||
|
self.plugin.deregister_hook("on_show_prefs", self.load_settings)
|
||||||
|
|
||||||
|
def get_resource(self, filename):
|
||||||
|
return pkg_resources.resource_filename("label", os.path.join("data", filename))
|
||||||
|
|
||||||
|
def load_settings(self ,widget = None , data = None):
|
||||||
|
aclient.label_get_labels(self.cb_update_labels)
|
||||||
|
aclient.label_get_global_options(self.cb_global_options)
|
||||||
|
|
||||||
|
def cb_global_options(self, data):
|
||||||
|
self.glade.get_widget("hide_zero_hits").set_active(data["hide_zero_hits"])
|
||||||
|
|
||||||
|
def cb_update_labels(self, labels):
|
||||||
|
log.debug("update labels")
|
||||||
|
self.labels = labels
|
||||||
|
self.label_store.clear()
|
||||||
|
for label in labels:
|
||||||
|
self.label_store.append([label])
|
||||||
|
self.label_view.get_selection().select_iter(self.label_store.get_iter_first())
|
||||||
|
|
||||||
|
def cb_label_options(self, data):
|
||||||
|
for key in ["max_download_speed", "max_upload_speed", "max_connections" ,"max_upload_slots"]:
|
||||||
|
spin = self.glade.get_widget(key)
|
||||||
|
spin.set_value(data[key])
|
||||||
|
|
||||||
|
self.glade.get_widget("apply_max").set_active(data["apply_max"])
|
||||||
|
self.glade.get_widget("chk_move_completed").set_active(bool(data["move_completed_to"]))
|
||||||
|
self.glade.get_widget("move_completed_to").set_filename(data["move_completed_to"] or "")
|
||||||
|
|
||||||
|
self.on_apply_max_changed()
|
||||||
|
self.on_chk_move_changed()
|
||||||
|
|
||||||
|
def on_apply_prefs(self):
|
||||||
|
options = {"hide_zero_hits":self.glade.get_widget("hide_zero_hits").get_active()}
|
||||||
|
aclient.label_set_global_options(None, options)
|
||||||
|
|
||||||
|
def on_chk_move_changed(self, data = None):
|
||||||
|
self.glade.get_widget("move_completed_to").set_sensitive(
|
||||||
|
self.glade.get_widget("chk_move_completed").get_active())
|
||||||
|
|
||||||
|
def on_apply_max_changed(self, data = None):
|
||||||
|
active = self.glade.get_widget("apply_max").get_active()
|
||||||
|
for key in ["max_download_speed", "max_upload_speed", "max_connections" ,"max_upload_slots","btn_apply"]:
|
||||||
|
spin = self.glade.get_widget(key)
|
||||||
|
spin.set_sensitive(active)
|
||||||
|
|
||||||
|
|
||||||
|
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(None , label)
|
||||||
|
aclient.label_get_labels(self.cb_update_labels)
|
||||||
|
aclient.force_call(block=True)
|
||||||
|
self.select_label(label)
|
||||||
|
|
||||||
|
def on_remove(self, widget, data=None):
|
||||||
|
label = self.get_selected_label()
|
||||||
|
aclient.label_remove(None, label)
|
||||||
|
aclient.label_get_labels(self.cb_update_labels)
|
||||||
|
self.select_label(0)
|
||||||
|
|
||||||
|
def on_save_label(self, arg = None, apply = False):
|
||||||
|
options = {}
|
||||||
|
for key in ["max_download_speed", "max_upload_speed", "max_connections" ,"max_upload_slots"]:
|
||||||
|
options[key] = self.glade.get_widget(key).get_value()
|
||||||
|
options["apply_max"] = self.glade.get_widget("apply_max").get_active()
|
||||||
|
|
||||||
|
if self.glade.get_widget("chk_move_completed").get_active():
|
||||||
|
options["move_completed_to"] = self.glade.get_widget("move_completed_to").get_filename()
|
||||||
|
else:
|
||||||
|
options["move_completed_to"] = None
|
||||||
|
|
||||||
|
aclient.label_set_options(None, self.label, options , apply)
|
||||||
|
|
||||||
|
def on_apply_label(self, arg = None):
|
||||||
|
self.on_save_label(apply = True)
|
||||||
|
|
||||||
|
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.set_model(self.label_store)
|
||||||
|
self.label_view.append_column(column)
|
||||||
|
self.label_view.set_headers_visible(False)
|
||||||
|
|
||||||
|
self.label_view.get_selection().connect("changed", self.on_label_changed)
|
||||||
|
|
||||||
|
def on_label_changed(self, selection):
|
||||||
|
(model, row) = self.label_view.get_selection().get_selected()
|
||||||
|
self.label = model.get_value(row, 0)
|
||||||
|
self.glade.get_widget("txt_label").set_markup("<b>%s</b>" % self.label)
|
||||||
|
aclient.label_get_options(self.cb_label_options, self.label)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
"""
|
|
@ -62,11 +62,23 @@ class LabelSideBar(component.Component):
|
||||||
self.filters = {}
|
self.filters = {}
|
||||||
|
|
||||||
# Create the liststore
|
# Create the liststore
|
||||||
#cat,value,count , pixmap.
|
#cat,value,count , pixmap , visible
|
||||||
self.liststore = gtk.ListStore(str, str, int, gtk.gdk.Pixbuf)
|
self.treestore = gtk.TreeStore(str, str, int, gtk.gdk.Pixbuf, bool)
|
||||||
self.filters[("state", "All")] = self.liststore.append(["state","All",0,gtk.gdk.pixbuf_new_from_file(
|
|
||||||
deluge.common.get_pixmap("dht16.png"))])
|
|
||||||
|
|
||||||
|
#add Cat nodes:
|
||||||
|
self.cat_nodes = {}
|
||||||
|
self.cat_nodes["state"] = self.treestore.append(None, ["cat", "State", 0, None, True])
|
||||||
|
self.cat_nodes["tracker"] = self.treestore.append(None, ["cat","Tracker", 0,None, True])
|
||||||
|
self.cat_nodes["label"] = self.treestore.append(None, ["cat", "Label", 0, None, True])
|
||||||
|
|
||||||
|
#default node:
|
||||||
|
self.filters[("state", "All")] = self.treestore.append(self.cat_nodes["state"],
|
||||||
|
["state", "All", 0, gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap("dht16.png")), True])
|
||||||
|
|
||||||
|
|
||||||
|
#remove all old columns:
|
||||||
|
for c in self.label_view.get_columns():
|
||||||
|
self.label_view.remove_column(c)
|
||||||
|
|
||||||
# Create the column
|
# Create the column
|
||||||
column = gtk.TreeViewColumn(_("Filters"))
|
column = gtk.TreeViewColumn(_("Filters"))
|
||||||
|
@ -75,44 +87,80 @@ class LabelSideBar(component.Component):
|
||||||
column.pack_start(render, expand=False)
|
column.pack_start(render, expand=False)
|
||||||
column.add_attribute(render, 'pixbuf', 3)
|
column.add_attribute(render, 'pixbuf', 3)
|
||||||
render = gtk.CellRendererText()
|
render = gtk.CellRendererText()
|
||||||
column.pack_start(render, expand=True)
|
column.pack_start(render, expand=False)
|
||||||
column.set_cell_data_func(render, self.render_cell_data,None)
|
column.set_cell_data_func(render, self.render_cell_data,None)
|
||||||
|
|
||||||
self.label_view.append_column(column)
|
self.label_view.append_column(column)
|
||||||
|
self.label_view.set_show_expanders(False)
|
||||||
|
|
||||||
self.label_view.set_model(self.liststore)
|
self.label_view.set_model(self.treestore)
|
||||||
|
|
||||||
self.label_view.get_selection().connect("changed",
|
self.label_view.get_selection().connect("changed",
|
||||||
self.on_selection_changed)
|
self.on_selection_changed)
|
||||||
|
|
||||||
# Select the 'All' label on init
|
# Select the 'All' label on init
|
||||||
self.label_view.get_selection().select_iter(
|
self.label_view.get_selection().select_iter(
|
||||||
self.liststore.get_iter_first())
|
self.treestore.get_iter_first())
|
||||||
|
|
||||||
|
self.create_model_filter()
|
||||||
#init.....
|
#init.....
|
||||||
self._start()
|
self._start()
|
||||||
|
self.label_view.expand_all()
|
||||||
|
self.hpaned.set_position(170)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.label_view.set_model(self.model_filter)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
#hacks!
|
||||||
|
old_sidebar = component.get("SideBar")
|
||||||
|
del old_sidebar
|
||||||
|
new_sidebar = deluge.ui.gtkui.sidebar.SideBar()
|
||||||
|
|
||||||
|
|
||||||
|
def create_model_filter(self):
|
||||||
|
self.model_filter = self.treestore.filter_new()
|
||||||
|
self.model_filter.set_visible_column(4)
|
||||||
|
self.label_view.set_model(self.model_filter)
|
||||||
|
|
||||||
def cb_update_filter_items(self, filter_items):
|
def cb_update_filter_items(self, filter_items):
|
||||||
|
visible_filters = []
|
||||||
for cat,filters in filter_items.iteritems():
|
for cat,filters in filter_items.iteritems():
|
||||||
for value, count in filters:
|
for value, count in filters:
|
||||||
self.update_row(cat, value , count)
|
self.update_row(cat, value , count)
|
||||||
|
visible_filters.append((cat, value))
|
||||||
|
|
||||||
def update_row(self, cat, value , count ):
|
for f in self.filters:
|
||||||
|
if not f in visible_filters:
|
||||||
|
self.treestore.set_value(self.filters[f], 4, False)
|
||||||
|
|
||||||
|
self.label_view.expand_all()
|
||||||
|
|
||||||
|
def update_row(self, cat, value , count):
|
||||||
if (cat, value) in self.filters:
|
if (cat, value) in self.filters:
|
||||||
row = self.filters[(cat, value)]
|
row = self.filters[(cat, value)]
|
||||||
self.liststore.set_value(row, 2, count)
|
self.treestore.set_value(row, 2, count)
|
||||||
else:
|
else:
|
||||||
pix = self.get_pixmap(cat, value)
|
pix = self.get_pixmap(cat, value)
|
||||||
row = self.liststore.append([cat, value, count , pix])
|
row = self.treestore.append(self.cat_nodes[cat],[cat, value, count , pix, True])
|
||||||
self.filters[(cat, value)] = row
|
self.filters[(cat, value)] = row
|
||||||
|
self.treestore.set_value(row, 4, True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def render_cell_data(self, column, cell, model, row, data):
|
def render_cell_data(self, column, cell, model, row, data):
|
||||||
"cell renderer"
|
"cell renderer"
|
||||||
|
cat = model.get_value(row, 0)
|
||||||
value = model.get_value(row, 1)
|
value = model.get_value(row, 1)
|
||||||
count = model.get_value(row, 2)
|
count = model.get_value(row, 2)
|
||||||
txt = "%s (%s)" % (value, count)
|
if cat == "cat":
|
||||||
|
txt = value
|
||||||
|
col = gtk.gdk.color_parse('gray')
|
||||||
|
else:
|
||||||
|
txt = "%s (%s)" % (value, count)
|
||||||
|
col = gtk.gdk.color_parse('white')
|
||||||
cell.set_property('text', txt)
|
cell.set_property('text', txt)
|
||||||
|
cell.set_property("cell-background-gdk",col)
|
||||||
|
|
||||||
def get_pixmap(self, cat, value):
|
def get_pixmap(self, cat, value):
|
||||||
if cat == "state":
|
if cat == "state":
|
||||||
|
@ -144,7 +192,7 @@ class LabelSideBar(component.Component):
|
||||||
cat = "tracker_host"
|
cat = "tracker_host"
|
||||||
|
|
||||||
filter = (cat, value)
|
filter = (cat, value)
|
||||||
if value == "All":
|
if value == "All" or cat == "cat":
|
||||||
filter = (None, None)
|
filter = (None, None)
|
||||||
elif (cat == "label" and value == "No Label"):
|
elif (cat == "label" and value == "No Label"):
|
||||||
filter = ("label","")
|
filter = ("label","")
|
||||||
|
@ -157,6 +205,9 @@ class LabelSideBar(component.Component):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
aclient.label_filter_items(self.cb_update_filter_items)
|
try:
|
||||||
|
aclient.label_filter_items(self.cb_update_filter_items)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug(e)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
#
|
||||||
|
# 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")
|
||||||
|
NO_LABEL = "No Label"
|
||||||
|
|
||||||
|
def cb_none(args):
|
||||||
|
"hack for empty callbacks."
|
||||||
|
pass
|
||||||
|
|
||||||
|
class LabelMenu(gtk.MenuItem):
|
||||||
|
def __init__(self):
|
||||||
|
gtk.MenuItem.__init__(self, "Label")
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
#attach..
|
||||||
|
torrentmenu = component.get("MenuBar").torrentmenu
|
||||||
|
torrentmenu.connect("show", self.on_show, None)
|
||||||
|
|
||||||
|
aclient.connect_on_new_core(self._on_new_core)
|
||||||
|
|
||||||
|
def _on_new_core(self, data):
|
||||||
|
self.on_show()
|
||||||
|
|
||||||
|
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 [NO_LABEL] + 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ from deluge.ui.client import sclient
|
||||||
from deluge import component
|
from deluge import component
|
||||||
import ui
|
import ui
|
||||||
|
|
||||||
import webui_config
|
import config
|
||||||
import webui_pages
|
import pages
|
||||||
|
|
||||||
class WebUI(ui.UI):
|
class WebUI(ui.UI):
|
||||||
def __init__(self, plugin_api, plugin_name):
|
def __init__(self, plugin_api, plugin_name):
|
||||||
|
@ -49,12 +49,12 @@ class WebUI(ui.UI):
|
||||||
log.debug("Label WebUI plugin initalized..")
|
log.debug("Label WebUI plugin initalized..")
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
webui_pages.register()
|
pages.register()
|
||||||
webui_config.register()
|
config.register()
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
webui_pages.unregister()
|
pages.unregister()
|
||||||
webui_config.unregister()
|
config.unregister()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -80,10 +80,12 @@ class LabelUpdateCfgForm(forms.Form):
|
||||||
sclient.label_set_options(label_id, dict(data), apply)
|
sclient.label_set_options(label_id, dict(data), apply)
|
||||||
|
|
||||||
#input fields :
|
#input fields :
|
||||||
|
apply_max = forms.CheckBox(_("Apply Maximum settings on add"))
|
||||||
max_connections = forms.DelugeInt(_("Maximum Connections"))
|
max_connections = forms.DelugeInt(_("Maximum Connections"))
|
||||||
max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)"))
|
max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)"))
|
||||||
max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
|
max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
|
||||||
max_upload_slots = forms.DelugeInt(_("Maximum Upload Slots"))
|
max_upload_slots = forms.DelugeInt(_("Maximum Upload Slots"))
|
||||||
|
move_completed_to = forms.ServerFolder(_("Move completed to"), required=False)
|
||||||
|
|
||||||
apply = forms.CheckBox(_("Apply"))
|
apply = forms.CheckBox(_("Apply"))
|
||||||
delete = forms.CheckBox(_("Delete"))
|
delete = forms.CheckBox(_("Delete"))
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ setup(
|
||||||
version="0.1",
|
version="0.1",
|
||||||
description=__doc__,
|
description=__doc__,
|
||||||
author=__author__,
|
author=__author__,
|
||||||
packages=["label"],
|
packages=["label","label.gtkui","label.webui"],
|
||||||
package_data = {"label": ["template/*"]},
|
package_data = {"label": ["template/*","data/*"]},
|
||||||
entry_points="""
|
entry_points="""
|
||||||
[deluge.plugin.core]
|
[deluge.plugin.core]
|
||||||
Label = label:CorePlugin
|
Label = label:CorePlugin
|
||||||
|
|
Loading…
Reference in New Issue