def _do_load(self): self.load_config() component.get("TorrentView").add_text_column(DISPLAY_NAME, col_type=[str, str], status_field=[STATUS_NAME, STATUS_ID]) component.get("TorrentView").treeview.connect( "button-press-event", self.on_tv_button_press) self.menu = self._create_context_menu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.status_item = None self.initialized = True
def _do_load(self): self._config = deluge.configmanager.ConfigManager( GTKUI_CONFIG, defaults=GTKUI_DEFAULTS) component.get("TorrentView").add_text_column(DISPLAY_NAME, status_field=[STATUS_NAME]) self.label_selection_menu = LabelSelectionMenu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.label_selection_menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.initialized = True
class GtkUI(GtkPluginBase): def __init__(self, plugin_name): super(GtkUI, self).__init__(plugin_name) self.initialized = False def enable(self): client.labelplus.is_initialized().addCallback(self.cb_check) def cb_check(self, result): if result == True: client.labelplus.get_label_data(None).addCallback(self.cb_data_init) else: reactor.callLater(1, self.enable) def cb_data_init(self, data): self.dialog = None self._config = None info = client.connection_info() self._daemon = "%s@%s:%s" % (info[2], info[0], info[1]) self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self._do_load() def _do_load(self): self.load_config() component.get("TorrentView").add_text_column(DISPLAY_NAME, col_type=[str, str], status_field=[STATUS_NAME, STATUS_ID]) component.get("TorrentView").treeview.connect( "button-press-event", self.on_tv_button_press) self.menu = self._create_context_menu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.status_item = None self.initialized = True def on_tv_button_press(self, widget, event): x, y = event.get_coords() path_info = widget.get_path_at_pos(int(x), int(y)) if not path_info: if event.button == 3: self._popup_jump_menu(widget, event) else: return if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: if path_info[1] and path_info[1].get_title() == DISPLAY_NAME: id = self.get_selected_torrent_label() if (self.label_sidebar.page_selected() and id == self.label_sidebar.get_selected_label()): self._do_open_label_options(widget, event) else: self._do_go_to_label(widget) def disable(self): if self.initialized: self.initialized = False self._config.save() deluge.configmanager.close(GTKUI_CONFIG) self._remove_status_bar_item() self.disable_dnd() component.get("MenuBar").torrentmenu.remove(self.sep) component.get("MenuBar").torrentmenu.remove(self.menu) self._destroy_menu() self.label_sidebar.unload() del self.label_sidebar self.preferences.unload() self.add_torrent_ext.unload() component.get("TorrentView").remove_column(DISPLAY_NAME) def _create_context_menu(self): menu = gtk.MenuItem(DISPLAY_NAME) submenu = gtk.Menu() jump_menu = self._create_jump_menu() submenu.append(jump_menu) set_label_menu = self._create_set_label_menu() submenu.append(set_label_menu) label_options_item = self._create_label_options_item() submenu.append(label_options_item) def on_activate(widget): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: label_options_item.show() else: label_options_item.hide() menu.connect("activate", on_activate) menu.set_submenu(submenu) menu.show_all() return menu def _create_label_options_item(self): def on_activate(widget): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: name = self.label_data[id]["name"] self.label_sidebar.menu.dialog = LabelOptionsDialog(id, name) self.label_sidebar.menu.dialog.register_close_func( self.label_sidebar.menu.close_func) item = gtk.MenuItem(_("Label Options")) item.connect("activate", on_activate) return item def _create_set_label_menu(self): def on_select_label(widget, label_id): torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(label_id, torrents) def hide_unavailable(widget): parent_item.hide() id = self.get_selected_torrent_label() if id: parent = get_parent(id) if parent and parent not in RESERVED_IDS: if getattr(parent_item, "handler", None): parent_item.disconnect(parent_item.handler) handler = parent_item.connect("activate", on_select_label, parent) parent_item.handler = handler parent_item.show() items = [] menu_item = gtk.MenuItem(_(ID_NONE)) menu_item.connect("activate", on_select_label, ID_NONE) items.append(menu_item) parent_item = gtk.MenuItem(_("Parent")) items.append(parent_item) menu_item = gtk.SeparatorMenuItem() items.append(menu_item) menu = LabelSelectionMenu(_("Set Label"), on_select_label, items) menu.connect("activate", hide_unavailable) return menu def _create_jump_menu(self): def on_select_label(widget, label_id): self._do_go_to_label(widget, label_id) def hide_unavailable(widget): selected_item.hide() parent_item.hide() id = self.get_selected_torrent_label() if id: if getattr(selected_item, "handler", None): selected_item.disconnect(selected_item.handler) handler = selected_item.connect("activate", on_select_label, id) selected_item.handler = handler selected_item.show() elif self.label_sidebar.page_selected(): id = self.label_sidebar.get_selected_label() if id: parent = get_parent(id) if parent and parent not in RESERVED_IDS: if getattr(parent_item, "handler", None): parent_item.disconnect(parent_item.handler) handler = parent_item.connect("activate", on_select_label, parent) parent_item.handler = handler parent_item.show() items = [] menu_item = gtk.MenuItem(_(ID_ALL)) menu_item.connect("activate", on_select_label, ID_ALL) items.append(menu_item) menu_item = gtk.MenuItem(_(ID_NONE)) menu_item.connect("activate", on_select_label, ID_NONE) items.append(menu_item) selected_item = gtk.MenuItem(_("Selected")) items.append(selected_item) parent_item = gtk.MenuItem(_("Parent")) items.append(parent_item) menu_item = gtk.SeparatorMenuItem() items.append(menu_item) menu = LabelSelectionMenu(_("Jump To"), on_select_label, items) menu.connect("activate", hide_unavailable) return menu def _popup_jump_menu(self, widget, event): top = gtk.Menu() menu = gtk.MenuItem(DISPLAY_NAME) submenu = gtk.Menu() submenu.append(self._create_jump_menu()) menu.set_submenu(submenu) top.append(menu) top.show_all() top.popup(None, None, None, event.button, event.time) def _destroy_menu(self): self.menu.destroy() del self.menu def _do_go_to_label(self, widget, id=None): if not id: id = self.get_selected_torrent_label() if id is not None: self.label_sidebar.select_label(id) def load_config(self): self._config = deluge.configmanager.ConfigManager(GTKUI_CONFIG) source = get_version(self._config.config) target = get_version(GTKUI_DEFAULTS) if len(self._config.config) == 0: self._config._Config__config = copy.deepcopy(GTKUI_DEFAULTS) else: if source != target: map = GTKUI_MAPS.get((source, target), None) if map: self._config._Config__config = convert(self._config.config, map) else: self._config._Config__config = copy.deepcopy(GTKUI_DEFAULTS) else: self.normalize_config() if target >= 2: daemons = self._config["daemon"] if self._daemon not in daemons: daemons[self._daemon] = copy.deepcopy(DAEMON_DEFAULTS) def normalize_config(self): commons = dict(GTKUI_DEFAULTS["common"]) commons.update(self._config.config["common"]) self._config.config["common"] = commons saved_daemons = component.get("ConnectionManager").config["hosts"] if not saved_daemons: self._config["daemon"] = {} else: daemons = ["%s@%s:%s" % (x[3], x[1], x[2]) for x in saved_daemons] for daemon in self._config["daemon"].keys(): if "@localhost:" in daemon or "@127.0.0.1:" in daemon: continue if daemon != self._daemon and daemon not in daemons: del self._config["daemon"][daemon] def update(self): if self.initialized: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_update_data) if self._config["common"]["show_label_bandwidth"]: if not self.status_item: self._add_status_bar_item() reactor.callLater(1, self._status_bar_update) else: self._remove_status_bar_item() def cb_update_data(self, data): if data is not None: self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self.label_sidebar.update_counts(self.label_data) def get_labels(self): data = self.label_data labels = [] for id in data: if id not in RESERVED_IDS: labels.append((id, data[id]["name"])) return labels def get_label_counts(self): return self.label_data def enable_dnd(self): def get_drag_icon(widget, x, y): num = widget.get_selection().count_selected_rows() if num > 1: pixbuf = self.icon_multiple else: pixbuf = self.icon_single return (pixbuf, 0, 0) def on_drag_end(widget, context): if self.label_sidebar.page_selected(): self.label_sidebar.label_tree.get_selection().emit("changed") def get_ids(widget, path, col, selection, *args): selection.set("TEXT", 8, "OK") return True def receive_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(id, torrents) return True def peek_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: return True class ModuleFilter(object): def filter(self, record): record.msg = "[%s] %s" % (PLUGIN_NAME, record.msg) return True dnd.log.setLevel(logging.INFO) dnd.log.addFilter(ModuleFilter()) src_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, data_func=get_ids, ) src_treeview = component.get("TorrentView").treeview self.icon_single = \ src_treeview.render_icon(gtk.STOCK_DND, gtk.ICON_SIZE_DND) self.icon_multiple = \ src_treeview.render_icon(gtk.STOCK_DND_MULTIPLE, gtk.ICON_SIZE_DND) self.src_proxy = dnd.TreeViewDragSourceProxy(src_treeview, get_drag_icon, on_drag_end) self.src_proxy.add_target(src_target) dest_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, pos=gtk.TREE_VIEW_DROP_INTO_OR_BEFORE, data_func=receive_ids, aux_func=peek_ids, ) dest_treeview = self.label_sidebar.label_tree self.dest_proxy = dnd.TreeViewDragDestProxy(dest_treeview) self.dest_proxy.add_target(dest_target) def disable_dnd(self): self.dest_proxy.unload() self.src_proxy.unload() def _add_status_bar_item(self): self.status_item = component.get("StatusBar").add_item( image=get_resource("labelplus_icon.png"), text="", callback=self._do_open_label_options_bandwidth, tooltip="") self.status_item._ebox.hide_all() def _remove_status_bar_item(self): if self.status_item: component.get("StatusBar").remove_item(self.status_item) self.status_item = None def get_selected_torrent_label(self): label_id = None tv = component.get("TorrentView") torrents = tv.get_selected_torrents() if len(torrents) > 0: id = torrents[0] status = tv.get_torrent_status(id) if STATUS_ID in status: label_id = status[STATUS_ID] or ID_NONE for t in torrents: status = tv.get_torrent_status(t) t_label_id = status[STATUS_ID] or ID_NONE if t_label_id != label_id: label_id = None break return label_id def _do_open_label_options_bandwidth(self, widget, event): self._do_open_label_options(widget, event, 1) def _do_open_label_options(self, widget, event, page=0): def on_close(widget): self.dialog = None if self.dialog == None: id = self.label_sidebar.get_selected_label() if id == ID_ALL or not self.label_sidebar.page_selected(): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: name = self.label_data[id]["full_name"] self.dialog = LabelOptionsDialog(id, name, page) self.dialog.register_close_func(on_close) def _status_bar_update(self): if self.status_item: id = self.get_selected_torrent_label() if not id and self.label_sidebar.page_selected(): id = self.label_sidebar.get_selected_label() if id == ID_NONE or (id not in RESERVED_IDS and id in self.label_data): self.status_item._ebox.show_all() tooltip = "Bandwidth Used By: %s" % self.label_data[id]["full_name"] include_sublabels = self._config["common"]["status_include_sublabel"] if include_sublabels and id != ID_NONE: tooltip += "/*" self.status_item.set_tooltip(tooltip) client.labelplus.get_label_bandwidth_usage( id, include_sublabels).addCallbacks( self._do_status_bar_update, self._err_status_bar_update) else: self.status_item._ebox.hide_all() reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update) def _err_status_bar_update(self, result): reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update) def _do_status_bar_update(self, result): if self.status_item: download_rate = result[0] download_unit = "B" upload_rate = result[1] upload_unit = "B" for (unit, bytes) in UNITS: if download_rate >= bytes: download_rate /= bytes download_unit = unit break for (unit, bytes) in UNITS: if upload_rate >= bytes: upload_rate /= bytes upload_unit = unit break self.status_item.set_text( "%.1f %s/s | %.1f %s/s" % ( download_rate, download_unit, upload_rate, upload_unit)) reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update)
class GtkUI(GtkPluginBase): def __init__(self, plugin_name): super(GtkUI, self).__init__(plugin_name) self.initialized = False self.retries = 0 def enable(self): self.timestamp = None self.label_data = None client.labelplus.is_initialized().addCallback(self.cb_check) def cb_check(self, result): if result == True: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_data_init) elif self.retries < MAX_RETRIES: reactor.callLater(WAIT_TIME, self.enable) self.retries += 1 def cb_data_init(self, data): self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self._do_load() def _do_load(self): self._config = deluge.configmanager.ConfigManager( GTKUI_CONFIG, defaults=GTKUI_DEFAULTS) component.get("TorrentView").add_text_column(DISPLAY_NAME, status_field=[STATUS_NAME]) self.label_selection_menu = LabelSelectionMenu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.label_selection_menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.initialized = True def disable(self): self.retries = MAX_RETRIES if self.initialized: self.initialized = False self._config.save() deluge.configmanager.close(self._config) self.disable_dnd() component.get("MenuBar").torrentmenu.remove(self.sep) component.get("MenuBar").torrentmenu.remove(self.label_selection_menu) self.label_selection_menu.destroy() del self.label_selection_menu self.label_sidebar.unload() del self.label_sidebar self.preferences.unload() self.add_torrent_ext.unload() component.get("TorrentView").remove_column(DISPLAY_NAME) def update(self): if self.initialized: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_update_data) def cb_update_data(self, data): if data is not None: self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self.label_sidebar.update_counts(self.label_data) def get_labels(self): data = self.label_data labels = [] for id in data: if id not in RESERVED_IDS: labels.append((id, data[id]["name"])) return labels def get_label_counts(self): return self.label_data def enable_dnd(self): def get_drag_icon(widget, x, y): num = widget.get_selection().count_selected_rows() if num > 1: pixbuf = self.icon_multiple else: pixbuf = self.icon_single return (pixbuf, 0, 0) def get_ids(widget, path, col, selection, *args): selection.set("TEXT", 8, "OK") return True def receive_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(id, torrents) return True def peek_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: return True class ModuleFilter(object): def filter(self, record): record.msg = "[%s] %s" % (PLUGIN_NAME, record.msg) return True dnd.log.setLevel(logging.INFO) dnd.log.addFilter(ModuleFilter()) src_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, data_func=get_ids, ) src_treeview = component.get("TorrentView").treeview self.icon_single = \ src_treeview.render_icon(gtk.STOCK_DND, gtk.ICON_SIZE_DND) self.icon_multiple = \ src_treeview.render_icon(gtk.STOCK_DND_MULTIPLE, gtk.ICON_SIZE_DND) self.src_proxy = dnd.TreeViewDragSourceProxy(src_treeview, get_drag_icon) self.src_proxy.add_target(src_target) dest_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, pos=gtk.TREE_VIEW_DROP_INTO_OR_BEFORE, data_func=receive_ids, aux_func=peek_ids, ) dest_treeview = self.label_sidebar.label_tree self.dest_proxy = dnd.TreeViewDragDestProxy(dest_treeview) self.dest_proxy.add_target(dest_target) def disable_dnd(self): self.dest_proxy.unload() self.src_proxy.unload()