From 9113744c4016213e2c1bef60dcb5d2d2e3cbc194 Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Sat, 18 Oct 2008 01:53:13 +0000 Subject: [PATCH] add 'add peer' and create gtkui common --- deluge/common.py | 123 +-- deluge/core/core.py | 5 + deluge/core/torrent.py | 9 +- deluge/ui/client.py | 2 +- deluge/ui/gtkui/aboutdialog.py | 3 +- deluge/ui/gtkui/common.py | 160 +++ deluge/ui/gtkui/connectionmanager.py | 6 +- deluge/ui/gtkui/edittrackersdialog.py | 3 +- deluge/ui/gtkui/glade/dgtkpopups.glade | 78 +- deluge/ui/gtkui/glade/main_window.glade | 1216 ++++++++++++----------- deluge/ui/gtkui/mainwindow.py | 3 +- deluge/ui/gtkui/menubar.py | 17 +- deluge/ui/gtkui/notification.py | 3 +- deluge/ui/gtkui/peers_tab.py | 20 + deluge/ui/gtkui/preferences.py | 3 +- deluge/ui/gtkui/queuedtorrents.py | 3 +- deluge/ui/gtkui/removetorrentdialog.py | 3 +- deluge/ui/gtkui/statusbar.py | 13 +- deluge/ui/gtkui/systemtray.py | 9 +- 19 files changed, 943 insertions(+), 736 deletions(-) create mode 100644 deluge/ui/gtkui/common.py diff --git a/deluge/common.py b/deluge/common.py index cba7cd12a..b2ea5a8a5 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -135,16 +135,6 @@ def get_pixmap(fname): return pkg_resources.resource_filename("deluge", os.path.join("data", \ "pixmaps", fname)) -def get_logo(size): - """Returns a deluge logo pixbuf based on the size parameter.""" - import gtk - if windows_check(): - return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.png"), \ - size, size) - else: - return gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap("deluge.svg"), \ - size, size) - def open_file(path): """Opens a file or folder.""" if windows_check(): @@ -170,102 +160,6 @@ def open_url_in_browser(url): gobject.idle_add(start_browser) -def build_menu_radio_list(value_list, callback, pref_value=None, - suffix=None, show_notset=False, notset_label=None, notset_lessthan=0, - show_other=False, show_activated=False, activated_label=None): - # Build a menu with radio menu items from a list and connect them to - # the callback. The pref_value is what you would like to test for the - # default active radio item. - import gtk - if notset_label is None: - notset_label = _("Unlimited") - - if activated_label is None: - activated_label = _("Activated") - - menu = gtk.Menu() - group = None - if show_activated is False: - if pref_value > -1 and pref_value not in value_list: - value_list.pop() - value_list.append(pref_value) - - for value in sorted(value_list): - if suffix != None: - menuitem = gtk.RadioMenuItem(group, str(value) + " " + \ - suffix) - else: - menuitem = gtk.RadioMenuItem(group, str(value)) - - group = menuitem - - if value == pref_value and pref_value != None: - menuitem.set_active(True) - - if callback != None: - menuitem.connect("toggled", callback) - - menu.append(menuitem) - - if show_activated is True: - for value in sorted(value_list): - menuitem = gtk.RadioMenuItem(group, str(activated_label)) - - group = menuitem - - if value == pref_value and pref_value != None: - menuitem.set_active(True) - - if callback != None: - menuitem.connect("toggled", callback) - - menu.append(menuitem) - - if show_notset: - menuitem = gtk.RadioMenuItem(group, notset_label) - menuitem.set_name(notset_label) - if pref_value < notset_lessthan and pref_value != None: - menuitem.set_active(True) - if show_activated and pref_value == 1: - menuitem.set_active(True) - menuitem.connect("toggled", callback) - menu.append(menuitem) - - # Add the Other... menuitem - if show_other is True: - menuitem = gtk.SeparatorMenuItem() - menu.append(menuitem) - menuitem = gtk.MenuItem(_("Other...")) - menuitem.set_name(_("Other...")) - menuitem.connect("activate", callback) - menu.append(menuitem) - - return menu - -def show_other_dialog(string, default=None): - """Shows a dialog to get an 'other' speed and return the value""" - import gtk - import gtk.glade - dialog_glade = gtk.glade.XML( - pkg_resources.resource_filename("deluge.ui.gtkui", - "glade/dgtkpopups.glade")) - speed_dialog = dialog_glade.get_widget("speed_dialog") - spin_title = dialog_glade.get_widget("spin_title") - spin_title.set_text(_("%s" % string)) - spin_speed = dialog_glade.get_widget("spin_speed") - if default != None: - spin_speed.set_value(default) - spin_speed.select_region(0, -1) - response = speed_dialog.run() - if response == 1: # OK Response - value = spin_speed.get_value() - else: - speed_dialog.destroy() - return None - - speed_dialog.destroy() - return value - ## Formatting text functions def fsize(fsize_b): @@ -403,3 +297,20 @@ def free_space(path): disk_data = os.statvfs(path) block_size = disk_data.f_bsize return disk_data.f_bavail * block_size + +def is_ip(ip): + """a simple test to see if we're given a valid ip""" + import socket + #first we test ipv4 + try: + if socket.inet_pton(socket.AF_INET, "%s" % (ip)): + return True + except socket.error: + if not socket.has_ipv6: + return False + #now test ipv6 + try: + if socket.inet_pton(socket.AF_INET6, "%s" % (ip)): + return True + except socket.error: + return False diff --git a/deluge/core/core.py b/deluge/core/core.py index 3ce6e5715..7bd709094 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -450,6 +450,11 @@ class Core( if not self.torrents[torrent_id].pause(): log.warning("Error pausing torrent %s", torrent_id) + def export_connect_peer(self, torrent_id, ip): + log.debug("adding peer %s to %s", ip, torrent_id) + if not self.torrents[torrent_id].connect_peer(ip): + log.warning("Error adding peer %s to %s", ip, torrent_id) + def export_move_storage(self, torrent_ids, dest): log.debug("Moving storage %s to %s", torrent_ids, dest) for torrent_id in torrent_ids: diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index c4add491c..18b48b50c 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -698,6 +698,14 @@ class Torrent: return True + def connect_peer(self, ip): + """adds manual peer""" + try: + self.handle.connect_peer(ip) + except: + return False + return True + def move_storage(self, dest): """Move a torrent's storage location""" try: @@ -812,4 +820,3 @@ class Torrent: # Keep a list of filerenames we're waiting on self.waiting_on_folder_rename.append(f["index"]) self.handle.rename_file(f["index"], f["path"].replace(folder, new_folder, 1)) - diff --git a/deluge/ui/client.py b/deluge/ui/client.py index f2798860d..00f335b27 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -159,7 +159,7 @@ class BaseClient(object): """ no_callback_list = ["add_torrent_url", "pause_all_torrents", "resume_all_torrents", "set_config", "enable_plugin", - "disable_plugin", "set_torrent_trackers", + "disable_plugin", "set_torrent_trackers", "connect_peer", "set_torrent_max_connections", "set_torrent_max_upload_slots", "set_torrent_max_upload_speed", "set_torrent_max_download_speed", "set_torrent_private_flag", "set_torrent_file_priorities", diff --git a/deluge/ui/gtkui/aboutdialog.py b/deluge/ui/gtkui/aboutdialog.py index 34df8db41..189df4340 100644 --- a/deluge/ui/gtkui/aboutdialog.py +++ b/deluge/ui/gtkui/aboutdialog.py @@ -37,6 +37,7 @@ import gtk import pkg_resources import deluge.common +import deluge.ui.gtkui.common as common from deluge.ui.client import aclient as client class AboutDialog: @@ -73,7 +74,7 @@ should have received a copy of the GNU General Public License along with this pr if not, see .")) self.about.set_website("http://deluge-torrent.org") self.about.set_website_label("http://deluge-torrent.org") - self.about.set_icon(deluge.common.get_logo(32)) + self.about.set_icon(common.get_logo(32)) self.about.set_logo(gtk.gdk.pixbuf_new_from_file( deluge.common.get_pixmap("deluge-about.png"))) diff --git a/deluge/ui/gtkui/common.py b/deluge/ui/gtkui/common.py new file mode 100644 index 000000000..514e73768 --- /dev/null +++ b/deluge/ui/gtkui/common.py @@ -0,0 +1,160 @@ +# +# common.py +# +# Copyright (C) 2008 Marcos Pinto ('markybob') +# +# 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 3 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. +"""Common functions for various parts of gtkui to use.""" + +import pygtk +pygtk.require('2.0') +import gtk, gtk.glade + +import pkg_resources + +from deluge.ui.client import aclient as client +import deluge.component as component +from deluge.log import LOG as log +import deluge.common + +def get_logo(size): + """Returns a deluge logo pixbuf based on the size parameter.""" + if deluge.common.windows_check(): + return gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap("deluge.png"), \ + size, size) + else: + return gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap("deluge.svg"), \ + size, size) + +def build_menu_radio_list(value_list, callback, pref_value=None, + suffix=None, show_notset=False, notset_label=None, notset_lessthan=0, + show_other=False, show_activated=False, activated_label=None): + # Build a menu with radio menu items from a list and connect them to + # the callback. The pref_value is what you would like to test for the + # default active radio item. + if notset_label is None: + notset_label = _("Unlimited") + + if activated_label is None: + activated_label = _("Activated") + + menu = gtk.Menu() + group = None + if show_activated is False: + if pref_value > -1 and pref_value not in value_list: + value_list.pop() + value_list.append(pref_value) + + for value in sorted(value_list): + if suffix != None: + menuitem = gtk.RadioMenuItem(group, str(value) + " " + \ + suffix) + else: + menuitem = gtk.RadioMenuItem(group, str(value)) + + group = menuitem + + if value == pref_value and pref_value != None: + menuitem.set_active(True) + + if callback != None: + menuitem.connect("toggled", callback) + + menu.append(menuitem) + + if show_activated is True: + for value in sorted(value_list): + menuitem = gtk.RadioMenuItem(group, str(activated_label)) + + group = menuitem + + if value == pref_value and pref_value != None: + menuitem.set_active(True) + + if callback != None: + menuitem.connect("toggled", callback) + + menu.append(menuitem) + + if show_notset: + menuitem = gtk.RadioMenuItem(group, notset_label) + menuitem.set_name(notset_label) + if pref_value < notset_lessthan and pref_value != None: + menuitem.set_active(True) + if show_activated and pref_value == 1: + menuitem.set_active(True) + menuitem.connect("toggled", callback) + menu.append(menuitem) + + # Add the Other... menuitem + if show_other is True: + menuitem = gtk.SeparatorMenuItem() + menu.append(menuitem) + menuitem = gtk.MenuItem(_("Other...")) + menuitem.set_name(_("Other...")) + menuitem.connect("activate", callback) + menu.append(menuitem) + + return menu + +def show_other_dialog(string, default=None): + """Shows a dialog to get an 'other' speed and return the value""" + dialog_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/dgtkpopups.glade")) + speed_dialog = dialog_glade.get_widget("speed_dialog") + spin_title = dialog_glade.get_widget("spin_title") + spin_title.set_text(_("%s" % string)) + spin_speed = dialog_glade.get_widget("spin_speed") + if default != None: + spin_speed.set_value(default) + spin_speed.select_region(0, -1) + response = speed_dialog.run() + if response == 1: # OK Response + value = spin_speed.get_value() + else: + speed_dialog.destroy() + return None + + speed_dialog.destroy() + return value + +def add_peer_dialog(): + dialog_glade = gtk.glade.XML( + pkg_resources.resource_filename("deluge.ui.gtkui", + "glade/dgtkpopups.glade")) + peer_dialog = dialog_glade.get_widget("connect_peer_dialog") + txt_ip = dialog_glade.get_widget("txt_ip") + response = peer_dialog.run() + if response: + value = txt_ip.get_text() + if deluge.common.is_ip(value): + client.connect_peer(component.get("TorrentView").get_selected_torrent(), value) + peer_dialog.destroy() + return True diff --git a/deluge/ui/gtkui/connectionmanager.py b/deluge/ui/gtkui/connectionmanager.py index b028b7e09..0bb68e453 100644 --- a/deluge/ui/gtkui/connectionmanager.py +++ b/deluge/ui/gtkui/connectionmanager.py @@ -43,6 +43,7 @@ import threading import deluge.component as component import deluge.xmlrpclib as xmlrpclib import deluge.common +import deluge.ui.gtkui.common as common from deluge.ui.client import aclient as client from deluge.configmanager import ConfigManager from deluge.log import LOG as log @@ -79,10 +80,9 @@ class ConnectionManager(component.Component): # Make the Connection Manager window a transient for the main window. self.connection_manager.set_transient_for(self.window.window) self.hostlist = self.glade.get_widget("hostlist") - self.connection_manager.set_icon(deluge.common.get_logo(32)) + self.connection_manager.set_icon(common.get_logo(32)) - self.glade.get_widget("image1").set_from_pixbuf( - deluge.common.get_logo(32)) + self.glade.get_widget("image1").set_from_pixbuf(common.get_logo(32)) self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, int) diff --git a/deluge/ui/gtkui/edittrackersdialog.py b/deluge/ui/gtkui/edittrackersdialog.py index d332ea1e3..cf002b19e 100644 --- a/deluge/ui/gtkui/edittrackersdialog.py +++ b/deluge/ui/gtkui/edittrackersdialog.py @@ -35,6 +35,7 @@ import gtk, gtk.glade import pkg_resources import deluge.common +import deluge.ui.gtkui.common as common from deluge.ui.client import aclient as client import deluge.component as component from deluge.log import LOG as log @@ -53,7 +54,7 @@ class EditTrackersDialog: self.edit_tracker_entry = self.glade.get_widget("edit_tracker_entry") self.edit_tracker_entry.set_transient_for(self.dialog) - self.dialog.set_icon(deluge.common.get_logo(32)) + self.dialog.set_icon(common.get_logo(32)) if parent != None: self.dialog.set_transient_for(parent) diff --git a/deluge/ui/gtkui/glade/dgtkpopups.glade b/deluge/ui/gtkui/glade/dgtkpopups.glade index 249640db1..9b0bef57d 100644 --- a/deluge/ui/gtkui/glade/dgtkpopups.glade +++ b/deluge/ui/gtkui/glade/dgtkpopups.glade @@ -1,6 +1,6 @@ - + True @@ -98,4 +98,80 @@ + + 5 + Add Peer + GTK_WIN_POS_MOUSE + GDK_WINDOW_TYPE_HINT_DIALOG + True + True + False + False + + + True + 2 + + + True + + + True + Enter Peer IP to Add + + + + + True + True + 39 + + + 1 + + + + + False + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + 1 + + + 1 + + + + + False + GTK_PACK_END + + + + + diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade index d334d122c..a814e3f7b 100644 --- a/deluge/ui/gtkui/glade/main_window.glade +++ b/deluge/ui/gtkui/glade/main_window.glade @@ -691,287 +691,137 @@ - - True - - - 5 - 6 - 3 - 4 - GTK_FILL - - - - - True - 0 - <b>Auto Managed:</b> - True - - - 4 - 5 - 3 - 4 - GTK_FILL - - - - - True - - - 7 - 8 - 2 - 3 - GTK_FILL - - - - - True - - - 7 - 8 - 1 - 2 - GTK_FILL - - - - - True - 0 - <b>Seed Rank:</b> - True - - - 6 - 7 - 2 - 3 - GTK_FILL - - - - - True - 0 - <b>Seeding Time:</b> - True - - - 6 - 7 - 1 - 2 - GTK_FILL - - - - - True - - - 7 - 8 - GTK_FILL - - - - - True - 0 - <b>Active Time:</b> - True - - - 6 - 7 - GTK_FILL - - - - - True - 0 - True - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - 0 - - - 3 - 4 - 3 - 4 - GTK_FILL - - - - - True - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 8 - 4 - 5 - GTK_FILL - - - - - True - 0 - 0 - <b>Tracker Status:</b> - True - - - 4 - 5 - GTK_FILL - GTK_FILL - - - - - True - 0 - True - PANGO_WRAP_WORD_CHAR - - - 5 - 6 - 2 - 3 - GTK_FILL - - - - - - True - 0 - 1 - <b>Availability:</b> - True - - - 4 - 5 - 2 - 3 - GTK_FILL - - - - - True - 0 - - - 3 - 4 - 2 - 3 - GTK_FILL - - - - + True 0 1 2 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Downloaded:</b> + True + + + + + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Uploaded:</b> + True + + + + + 1 + 2 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Share Ratio:</b> + True + + + + 2 3 GTK_FILL - + True - 0 + 5 + + + True + 0 + <b>Next Announce:</b> + True + + - 5 - 6 - 1 - 2 + 3 + 4 GTK_FILL - - True - 0 - <b>Peers:</b> - True - - - 4 - 5 - 1 - 2 - GTK_FILL - - - - - True - 0 - - - 5 - 6 - GTK_FILL - - - - - True - 0 - <b>Seeders:</b> - True - - - 4 - 5 - GTK_FILL - - - - + True 15 5 - + True 0 - <b>Pieces:</b> + <b>Speed:</b> True @@ -979,30 +829,6 @@ 2 3 - 3 - 4 - GTK_FILL - - - - - True - 15 - 5 - - - True - 0 - <b>ETA:</b> - True - - - - - 2 - 3 - 2 - 3 GTK_FILL @@ -1029,15 +855,15 @@ - + True 15 5 - + True 0 - <b>Speed:</b> + <b>ETA:</b> True @@ -1045,128 +871,302 @@ 2 3 - GTK_FILL - - - - - True - 5 - - - True - 0 - <b>Next Announce:</b> - True - - - - - 3 - 4 - GTK_FILL - - - - - True - 5 - - - True - 0 - <b>Share Ratio:</b> - True - - - - 2 3 GTK_FILL - + True + 15 5 - + True 0 - <b>Uploaded:</b> + <b>Pieces:</b> True - 1 - 2 + 2 + 3 + 3 + 4 GTK_FILL - + True - 5 - - - True - 0 - <b>Downloaded:</b> - True - - + 0 + <b>Seeders:</b> + True + 4 + 5 GTK_FILL - + True 0 - 3 - 4 + 5 + 6 + GTK_FILL + + + + + True + 0 + <b>Peers:</b> + True + + + 4 + 5 1 2 GTK_FILL - + + True + 0 + + + 5 + 6 + 1 + 2 + GTK_FILL + + + + True 0 1 2 - 1 - 2 + 2 + 3 GTK_FILL - + True 0 3 4 + 2 + 3 GTK_FILL - + + True + 0 + 1 + <b>Availability:</b> + True + + + 4 + 5 + 2 + 3 + GTK_FILL + + + + + True + 0 + True + PANGO_WRAP_WORD_CHAR + + + 5 + 6 + 2 + 3 + GTK_FILL + + + + + + True + 0 + 0 + <b>Tracker Status:</b> + True + + + 4 + 5 + GTK_FILL + GTK_FILL + + + + + True + 0 + True + PANGO_WRAP_CHAR + True + + + 1 + 8 + 4 + 5 + GTK_FILL + + + + True 0 + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + True + 0 + True + 1 2 + 3 + 4 + GTK_FILL + + + + + True + 0 + <b>Active Time:</b> + True + + + 6 + 7 + GTK_FILL + + + + + True + + + 7 + 8 + GTK_FILL + + + + + True + 0 + <b>Seeding Time:</b> + True + + + 6 + 7 + 1 + 2 + GTK_FILL + + + + + True + 0 + <b>Seed Rank:</b> + True + + + 6 + 7 + 2 + 3 + GTK_FILL + + + + + True + + + 7 + 8 + 1 + 2 + GTK_FILL + + + + + True + + + 7 + 8 + 2 + 3 + GTK_FILL + + + + + True + 0 + <b>Auto Managed:</b> + True + + + 4 + 5 + 3 + 4 + GTK_FILL + + + + + True + + + 5 + 6 + 3 + 4 GTK_FILL @@ -1253,7 +1253,7 @@ - + True 0 True @@ -1261,114 +1261,45 @@ 1 2 - 4 - 5 - - - - - - True - 0 - 1 - <b># of files:</b> - True - - - 4 - 5 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - True - PANGO_WRAP_CHAR - True - - - 1 - 4 - 1 - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Hash:</b> - True - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - PANGO_WRAP_CHAR - True - - - 1 - 4 - 6 - 7 - - - - - - True - 0 - 1 - <b>Tracker:</b> - True - - - 6 - 7 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 1 - <b>Total Size:</b> - True - - - - 3 4 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + True + + + 1 + 4 + 5 + 6 + + + + + + True + 0 + 1 + <b>Status:</b> + True + + + 5 + 6 GTK_FILL - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_STRUCTURE_MASK + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 True PANGO_WRAP_CHAR @@ -1377,27 +1308,8 @@ 1 4 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - 0 - 0 - 1 - <b>Name:</b> - True - - - - - GTK_FILL + 2 + 3 @@ -1424,7 +1336,110 @@ - + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + 0 + 0 + 1 + <b>Name:</b> + True + + + + + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_STRUCTURE_MASK + 0 + True + PANGO_WRAP_CHAR + True + + + 1 + 4 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + 0 + 1 + <b>Total Size:</b> + True + + + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + 1 + <b>Tracker:</b> + True + + + 6 + 7 + GTK_FILL + + + + + + True + 0 + PANGO_WRAP_CHAR + True + + + 1 + 4 + 6 + 7 + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Hash:</b> + True + + + 1 + 2 + GTK_FILL + + + + + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 @@ -1435,43 +1450,28 @@ 1 4 - 2 - 3 + 1 + 2 - + True 0 1 - <b>Status:</b> + <b># of files:</b> True - 5 - 6 + 4 + 5 GTK_FILL - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - True - - - 1 - 4 - 5 - 6 - - - - - + True 0 True @@ -1479,8 +1479,8 @@ 1 2 - 3 - 4 + 4 + 5 @@ -1663,7 +1663,7 @@ - + True True 6 @@ -1673,8 +1673,100 @@ 1 2 + 3 + 4 + + + + + + + True + 0 + Max Upload Slots: + + + 3 + 4 + GTK_FILL + + + + + + True + KiB/s + + + 2 + 3 + 1 + 2 + + + + + + + True + KiB/s + + + 2 + 3 + + + + + + + True + 0 + Max Download Speed: + + + GTK_FILL + + + + + + True + 0 + Max Upload Speed: + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Max Connections: + + 2 3 + GTK_FILL + + + + + + True + True + 6 + 1 + -1 -1 999999 1 10 10 + 1 + + + 1 + 2 @@ -1698,110 +1790,18 @@ - + True True 6 1 -1 -1 999999 1 10 10 - 1 1 2 - - - - - - - True - 0 - Max Connections: - - 2 3 - GTK_FILL - - - - - - True - 0 - Max Upload Speed: - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Max Download Speed: - - - GTK_FILL - - - - - - True - KiB/s - - - 2 - 3 - - - - - - - True - KiB/s - - - 2 - 3 - 1 - 2 - - - - - - - True - 0 - Max Upload Slots: - - - 3 - 4 - GTK_FILL - - - - - - True - True - 6 - 1 - -1 -1 999999 1 10 10 - - - 1 - 2 - 3 - 4 @@ -1935,8 +1935,8 @@ True False - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER False + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER Select A Folder @@ -2439,14 +2439,23 @@ 10 2 - + + True + 0 + <i>Current Version:</i> + True + + + GTK_FILL + + + + True 1 2 - 1 - 2 @@ -2464,26 +2473,17 @@ - + True 1 2 + 1 + 2 - - - True - 0 - <i>Current Version:</i> - True - - - GTK_FILL - - @@ -2560,4 +2560,22 @@ + + True + + + True + Add a peer by its IP + Add Peer + True + + + + gtk-add + 1 + + + + + diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py index 369c724bb..efdb6d726 100644 --- a/deluge/ui/gtkui/mainwindow.py +++ b/deluge/ui/gtkui/mainwindow.py @@ -45,6 +45,7 @@ from deluge.configmanager import ConfigManager from deluge.ui.gtkui.ipcinterface import process_args import deluge.common +import deluge.ui.gtkui.common as common from deluge.log import LOG as log @@ -58,7 +59,7 @@ class MainWindow(component.Component): "glade/main_window.glade")) self.window = self.main_glade.get_widget("main_window") - self.window.set_icon(deluge.common.get_logo(32)) + self.window.set_icon(common.get_logo(32)) self.vpaned = self.main_glade.get_widget("vpaned") # Load the window state diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index 1e4ba11dd..800119278 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -39,7 +39,8 @@ import pkg_resources import deluge.error import deluge.component as component from deluge.ui.client import aclient as client -import deluge.common as common +import deluge.common +import deluge.ui.gtkui.common as common from deluge.configmanager import ConfigManager from deluge.log import LOG as log @@ -67,9 +68,9 @@ class MenuBar(component.Component): self.torrentmenu_glade.get_widget("menuitem_options").set_submenu( self.torrentmenu_glade.get_widget("options_torrent_menu")) self.torrentmenu_glade.get_widget("download-limit-image").set_from_file( - common.get_pixmap("downloading16.png")) + deluge.common.get_pixmap("downloading16.png")) self.torrentmenu_glade.get_widget("upload-limit-image").set_from_file( - common.get_pixmap("seeding16.png")) + deluge.common.get_pixmap("seeding16.png")) for menuitem in ("menuitem_down_speed", "menuitem_up_speed", "menuitem_max_connections", "menuitem_upload_slots"): @@ -330,7 +331,7 @@ class MenuBar(component.Component): def on_menuitem_open_folder_activate(self, data=None): log.debug("on_menuitem_open_folder") def _on_torrent_status(status): - deluge.common.open_file(status["save_path"]) + deluge.deluge.common.open_file(status["save_path"]) for torrent_id in component.get("TorrentView").get_selected_torrents(): client.get_torrent_status(_on_torrent_status, torrent_id, ["save_path"]) @@ -344,7 +345,7 @@ class MenuBar(component.Component): gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_CANCEL, \ gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) chooser.set_local_only(True) - if not common.windows_check(): + if not deluge.common.windows_check(): chooser.set_icon(common.get_logo(18)) chooser.set_property("skip-taskbar-hint", True) chooser.set_current_folder(config["choose_directory_dialog_path"]) @@ -408,15 +409,15 @@ class MenuBar(component.Component): ## Help Menu ## def on_menuitem_homepage_activate(self, data=None): log.debug("on_menuitem_homepage_activate") - common.open_url_in_browser("http://deluge-torrent.org") + deluge.common.open_url_in_browser("http://deluge-torrent.org") def on_menuitem_faq_activate(self, data=None): log.debug("on_menuitem_faq_activate") - common.open_url_in_browser("http://dev.deluge-torrent.org/wiki/Faq") + deluge.common.open_url_in_browser("http://dev.deluge-torrent.org/wiki/Faq") def on_menuitem_community_activate(self, data=None): log.debug("on_menuitem_community_activate") - common.open_url_in_browser("http://forum.deluge-torrent.org/") + deluge.common.open_url_in_browser("http://forum.deluge-torrent.org/") def on_menuitem_about_activate(self, data=None): log.debug("on_menuitem_about_activate") diff --git a/deluge/ui/gtkui/notification.py b/deluge/ui/gtkui/notification.py index 60b437ba6..645b928fe 100644 --- a/deluge/ui/gtkui/notification.py +++ b/deluge/ui/gtkui/notification.py @@ -33,6 +33,7 @@ import deluge.component as component import deluge.common +import deluge.ui.gtkui.common as common from deluge.log import LOG as log from deluge.configmanager import ConfigManager from deluge.ui.client import aclient as client @@ -73,7 +74,7 @@ class Notification: if pynotify.init("Deluge"): self.note = pynotify.Notification(_("Torrent complete"), status["name"] + "\n" + _("Including %i files" % status["num_files"])) - self.note.set_icon_from_pixbuf(deluge.common.get_logo(48)) + self.note.set_icon_from_pixbuf(common.get_logo(48)) if not self.note.show(): log.warning("pynotify failed to show notification") diff --git a/deluge/ui/gtkui/peers_tab.py b/deluge/ui/gtkui/peers_tab.py index bc9f77f54..65544750a 100644 --- a/deluge/ui/gtkui/peers_tab.py +++ b/deluge/ui/gtkui/peers_tab.py @@ -42,6 +42,7 @@ from deluge.ui.client import aclient as client from deluge.configmanager import ConfigManager import deluge.component as component import deluge.common +import deluge.ui.gtkui.common as common from deluge.ui.gtkui.listview import cell_data_speed as cell_data_speed from deluge.ui.gtkui.torrentdetails import Tab from deluge.log import LOG as log @@ -67,8 +68,13 @@ class PeersTab(Tab): self._name = "Peers" self._child_widget = glade.get_widget("peers_tab") self._tab_label = glade.get_widget("peers_tab_label") + self.peer_menu = glade.get_widget("menu_peer_tab") + glade.signal_autoconnect({ + "on_menuitem_add_peer_activate": self._on_menuitem_add_peer_activate, + }) self.listview = glade.get_widget("peers_listview") + self.listview.connect("button-press-event", self._on_button_press_event) # country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon, progress self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, int, int, str, gobject.TYPE_UINT, gtk.gdk.Pixbuf, float) self.cached_flag_pixbufs = {} @@ -320,3 +326,17 @@ class PeersTab(Tab): def clear(self): self.liststore.clear() + + def _on_button_press_event(self, widget, event): + """This is a callback for showing the right-click context menu.""" + log.debug("on_button_press_event") + # We only care about right-clicks + if self.torrent_id and event.button == 3: + self.peer_menu.popup(None, None, None, event.button, event.time) + return True + + def _on_menuitem_add_peer_activate(self, menuitem): + """This is a callback for manually adding a peer""" + log.debug("on_menuitem_add_peer") + common.add_peer_dialog() + return True diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index 01ba4519c..9cdebbdb3 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -41,6 +41,7 @@ from deluge.log import LOG as log from deluge.ui.client import aclient as client import deluge.common import deluge.error +import deluge.ui.gtkui.common as common from deluge.configmanager import ConfigManager class Preferences(component.Component): @@ -51,7 +52,7 @@ class Preferences(component.Component): pkg_resources.resource_filename("deluge.ui.gtkui", "glade/preferences_dialog.glade")) self.pref_dialog = self.glade.get_widget("pref_dialog") - self.pref_dialog.set_icon(deluge.common.get_logo(32)) + self.pref_dialog.set_icon(common.get_logo(32)) self.treeview = self.glade.get_widget("treeview") self.notebook = self.glade.get_widget("notebook") self.gtkui_config = ConfigManager("gtkui.conf") diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py index 0f244d7ca..f9d844103 100644 --- a/deluge/ui/gtkui/queuedtorrents.py +++ b/deluge/ui/gtkui/queuedtorrents.py @@ -42,6 +42,7 @@ from deluge.ui.client import aclient as client import deluge.common from deluge.configmanager import ConfigManager from deluge.log import LOG as log +import deluge.ui.gtkui.common as common class QueuedTorrents(component.Component): def __init__(self): @@ -56,7 +57,7 @@ class QueuedTorrents(component.Component): self.glade.get_widget("chk_autoadd").set_active( self.config["autoadd_queued"]) self.dialog = self.glade.get_widget("queued_torrents_dialog") - self.dialog.set_icon(deluge.common.get_logo(32)) + self.dialog.set_icon(common.get_logo(32)) self.glade.signal_autoconnect({ "on_button_remove_clicked": self.on_button_remove_clicked, diff --git a/deluge/ui/gtkui/removetorrentdialog.py b/deluge/ui/gtkui/removetorrentdialog.py index 1b74ebc21..29cfd48b7 100644 --- a/deluge/ui/gtkui/removetorrentdialog.py +++ b/deluge/ui/gtkui/removetorrentdialog.py @@ -38,6 +38,7 @@ import deluge.common from deluge.ui.client import aclient as client import deluge.component as component from deluge.log import LOG as log +import deluge.ui.gtkui.common as common class RemoveTorrentDialog: def __init__(self, torrent_ids, remove_torrentfile=False, remove_data=False): @@ -50,7 +51,7 @@ class RemoveTorrentDialog: "glade/remove_torrent_dialog.glade")) self.dialog = self.glade.get_widget("remove_torrent_dialog") - self.dialog.set_icon(deluge.common.get_logo(32)) + self.dialog.set_icon(common.get_logo(32)) self.dialog.set_transient_for(component.get("MainWindow").window) self.glade.signal_autoconnect({ diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index 41fab4692..22bbe640f 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -36,6 +36,7 @@ import gobject import deluge.component as component import deluge.common +import deluge.ui.gtkui.common as common from deluge.configmanager import ConfigManager from deluge.ui.client import aclient as client from deluge.log import LOG as log @@ -345,7 +346,7 @@ class StatusBar(component.Component): self.send_status_request() def _on_download_item_clicked(self, widget, event): - menu = deluge.common.build_menu_radio_list( + menu = common.build_menu_radio_list( self.config["tray_download_speed_list"], self._on_set_download_speed, self.max_download_speed, @@ -359,7 +360,7 @@ class StatusBar(component.Component): if widget.get_name() == _("Unlimited"): value = -1 elif widget.get_name() == _("Other..."): - value = deluge.common.show_other_dialog( + value = common.show_other_dialog( _("Download Speed (KiB/s):"), self.max_download_speed) if value == None: return @@ -373,7 +374,7 @@ class StatusBar(component.Component): client.set_config({"max_download_speed": value}) def _on_upload_item_clicked(self, widget, event): - menu = deluge.common.build_menu_radio_list( + menu = common.build_menu_radio_list( self.config["tray_upload_speed_list"], self._on_set_upload_speed, self.max_upload_speed, @@ -387,7 +388,7 @@ class StatusBar(component.Component): if widget.get_name() == _("Unlimited"): value = -1 elif widget.get_name() == _("Other..."): - value = deluge.common.show_other_dialog( + value = common.show_other_dialog( _("Upload Speed (KiB/s):"), self.max_upload_speed) if value == None: return @@ -401,7 +402,7 @@ class StatusBar(component.Component): client.set_config({"max_upload_speed": value}) def _on_connection_item_clicked(self, widget, event): - menu = deluge.common.build_menu_radio_list( + menu = common.build_menu_radio_list( self.config["connection_limit_list"], self._on_set_connection_limit, self.max_connections, show_notset=True, show_other=True) @@ -414,7 +415,7 @@ class StatusBar(component.Component): if widget.get_name() == _("Unlimited"): value = -1 elif widget.get_name() == _("Other..."): - value = deluge.common.show_other_dialog( + value = common.show_other_dialog( _("Connection Limit:"), self.max_connections) if value == None: return diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py index b8bb15cf1..b53bec5a6 100644 --- a/deluge/ui/gtkui/systemtray.py +++ b/deluge/ui/gtkui/systemtray.py @@ -39,6 +39,7 @@ from deluge.ui.client import aclient as client import deluge.common from deluge.configmanager import ConfigManager from deluge.log import LOG as log +import deluge.ui.gtkui.common as common class SystemTray(component.Component): def __init__(self): @@ -80,7 +81,7 @@ class SystemTray(component.Component): if deluge.common.windows_check(): self.tray = gtk.status_icon_new_from_pixbuf( - deluge.common.get_logo(32)) + common.get_logo(32)) else: try: self.tray = gtk.status_icon_new_from_icon_name("deluge") @@ -203,13 +204,13 @@ class SystemTray(component.Component): def build_tray_bwsetsubmenu(self): # Create the Download speed list sub-menu - submenu_bwdownset = deluge.common.build_menu_radio_list( + submenu_bwdownset = common.build_menu_radio_list( self.config["tray_download_speed_list"], self.tray_setbwdown, self.max_download_speed, _("KiB/s"), show_notset=True, show_other=True) # Create the Upload speed list sub-menu - submenu_bwupset = deluge.common.build_menu_radio_list( + submenu_bwupset = common.build_menu_radio_list( self.config["tray_upload_speed_list"], self.tray_setbwup, self.max_upload_speed, _("KiB/s"), show_notset=True, show_other=True) @@ -335,7 +336,7 @@ class SystemTray(component.Component): value = -1 if value == _("Other..."): - value = deluge.common.show_other_dialog( + value = common.show_other_dialog( string + " Speed (KiB/s):", default) if value == None: return