예제 #1
0
  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
예제 #2
0
  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
예제 #3
0
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)
예제 #4
0
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()