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 __init__(self): self.mappings = {} self.cur_label = None self.lv = component.get("AddTorrentDialog").listview_torrents self.handlers = [] self.blk_ext = None self.lbl_name = None self.btn_select = None self._build_ext_block() self.blk_ext.show_all() self.menu = LabelSelectionMenu() self.menu.on_select_label = self._do_set_mapping self.submenu = self.menu.get_submenu() self.handlers.append(( self.lv.get_selection(), self.lv.get_selection().connect("changed", self._do_update_label_text), )) self.btn_select.connect("button-release-event", self._do_show_menu) self._install_ext_block() self._register_button_handlers()
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_menu(self): menu = gtk.MenuItem(DISPLAY_NAME) menu.connect("activate", self._on_activate) submenu = gtk.Menu() self.label_selection_menu = LabelSelectionMenu(_("Set Label")) submenu.append(self.label_selection_menu) self.menu_jump_item = gtk.MenuItem(_("Go to Label")) self.menu_jump_item.connect("activate", self._do_go_to_label) submenu.append(self.menu_jump_item) menu.set_submenu(submenu) menu.show_all() return menu
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 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()
class AddTorrentExt(object): def __init__(self): self.mappings = {} self.cur_label = None self.lv = component.get("AddTorrentDialog").listview_torrents self.handlers = [] self.blk_ext = None self.lbl_name = None self.btn_select = None self._build_ext_block() self.blk_ext.show_all() self.menu = LabelSelectionMenu() self.menu.on_select_label = self._do_set_mapping self.submenu = self.menu.get_submenu() self.handlers.append(( self.lv.get_selection(), self.lv.get_selection().connect("changed", self._do_update_label_text), )) self.btn_select.connect("button-release-event", self._do_show_menu) self._install_ext_block() self._register_button_handlers() def unload(self): self._deregister_handlers() self.menu.destroy() self._uninstall_ext_block() self.blk_ext.destroy() def _build_ext_block(self): self.blk_ext = gtk.Frame() self.blk_ext.set_shadow_type(gtk.SHADOW_NONE) self.blk_ext.set_label_widget(gtk.Label()) self.blk_ext.get_label_widget().set_markup("<b>%s</b>" % DISPLAY_NAME) blk_align = gtk.Alignment(0.5, 0.5, 1.0, 1.0) blk_align.set_padding(5, 0, 5, 5) box = gtk.HBox() box.set_spacing(3) frame = gtk.Frame() frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) align = gtk.Alignment(0.5, 0.5, 1.0, 1.0) align.set_padding(0, 0, 3, 3) self.lbl_name = gtk.Label() self.lbl_name.set_alignment(0.0, 0.5) self.lbl_name.set_ellipsize(pango.ELLIPSIZE_END) self.lbl_name.set_text(_(ID_NONE)) self.btn_select = gtk.Button() self.btn_select.set_label(_("Select")) self.blk_ext.add(blk_align) blk_align.add(box) box.pack_start(frame, expand=True) frame.add(align) align.add(self.lbl_name) box.pack_start(self.btn_select, expand=False) @debug() def _install_ext_block(self): dialog = component.get("AddTorrentDialog") widget = dialog.glade.get_widget("button_revert") vbox = widget.get_ancestor(gtk.VBox()) vbox.pack_start(self.blk_ext, expand=False) pos = vbox.child_get(self.blk_ext, "position")[0] - 1 vbox.child_set(self.blk_ext, "position", pos) @debug() def _uninstall_ext_block(self): dialog = component.get("AddTorrentDialog") widget = dialog.glade.get_widget("button_revert") vbox = widget.get_ancestor(gtk.VBox()) vbox.remove(self.blk_ext) dialog.dialog.resize(1, 1) @debug(show_args=True) def _do_set_mapping(self, widget, label_id): self.cur_label = None model, row = self.lv.get_selection().get_selected() if row: id = model.get_value(row, 0) if label_id is None: if id in self.mappings: del self.mappings[id] else: name = [widget.get_label()] parent = widget.get_parent() while parent is not self.submenu: item = parent.get_attach_widget() name.append(item.get_label()) parent = item.get_parent() if len(name) > len(label_id.split(":"))-1: name.pop(0) self.mappings[id] = (label_id, "/".join(reversed(name))) self.cur_label = self.mappings[id] self._do_update_label_text(self.lv.get_selection()) def _do_update_label_text(self, selection): self.cur_label = None model, row = selection.get_selected() if row: id = model.get_value(row, 0) if id in self.mappings: self.lbl_name.set_text(self.mappings[id][1]) self.lbl_name.set_tooltip_text(self.mappings[id][1]) self.cur_label = self.mappings[id] return self.lbl_name.set_text(_(ID_NONE)) self.lbl_name.set_tooltip_text(None) def _do_show_menu(self, widget, event): self._do_set_mapping(None, None) self.menu.on_activate(self.menu) self.submenu.popup(None, None, None, event.button, event.time) def _register_button_handlers(self): dialog = component.get("AddTorrentDialog") btn = dialog.glade.get_widget("button_revert") self.handlers.append((btn, btn.connect("clicked", self._do_revert))) btn = dialog.glade.get_widget("button_apply") self.handlers.append((btn, btn.connect("clicked", self._do_apply_to_all))) btn = dialog.glade.get_widget("button_cancel") self.handlers.append((btn, btn.connect("clicked", self._do_clear))) btn = dialog.glade.get_widget("button_remove") self.handlers.append((btn, btn.connect("clicked", self._do_remove))) btn = dialog.glade.get_widget("button_add") self.handlers.append((btn, btn.connect("clicked", self._do_add))) def _deregister_handlers(self): for widget, handler in self.handlers: widget.disconnect(handler) @debug() def _do_revert(self, widget): self._do_set_mapping(None, None) @debug() def _do_apply_to_all(self, widget): def set_mapping(model, path, row): id = model.get_value(row, 0) self.mappings[id] = self.cur_label if self.cur_label is None: self.mappings.clear() else: self.lv.get_model().foreach(set_mapping) self._do_update_label_text(self.lv.get_selection()) @debug() def _do_clear(self, widget): self.mappings.clear() self._do_update_label_text(self.lv.get_selection()) @debug() def _do_remove(self, widget): dialog = component.get("AddTorrentDialog") ids = dialog.files.keys() for key in self.mappings.keys(): if key not in ids: del self.mappings[key] self._do_update_label_text(self.lv.get_selection()) @debug() def _do_add(self, widget): reverse_map = {} for torrent_id, label_tup in self.mappings.iteritems(): label_id = label_tup[0] if label_id not in reverse_map: reverse_map[label_id] = [] reverse_map[label_id].append(torrent_id) for label_id, torrent_ids in reverse_map.iteritems(): client.labelplus.set_torrent_labels(label_id, torrent_ids) self._do_clear(widget)