From afa3c03691592d0be86cbe0adcaacb721f4c480c Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Mon, 19 May 2008 02:28:47 +0000 Subject: [PATCH] Add the tabs to the View menu and allow them to be shown/hidden. Some minor UI tweaks. --- deluge/ui/gtkui/details_tab.py | 15 +- deluge/ui/gtkui/files_tab.py | 8 +- deluge/ui/gtkui/glade/main_window.glade | 2573 +++++++++++------------ deluge/ui/gtkui/menubar.py | 16 +- deluge/ui/gtkui/options_tab.py | 8 +- deluge/ui/gtkui/peers_tab.py | 8 +- deluge/ui/gtkui/statistics_tab.py | 7 +- deluge/ui/gtkui/statusbar.py | 8 +- deluge/ui/gtkui/torrentdetails.py | 222 +- 9 files changed, 1536 insertions(+), 1329 deletions(-) diff --git a/deluge/ui/gtkui/details_tab.py b/deluge/ui/gtkui/details_tab.py index 32c713bc3..d48e2c68e 100644 --- a/deluge/ui/gtkui/details_tab.py +++ b/deluge/ui/gtkui/details_tab.py @@ -36,26 +36,30 @@ import gtk, gtk.glade from deluge.ui.client import aclient as client import deluge.component as component import deluge.common +from deluge.ui.gtkui.torrentdetails import Tab from deluge.log import LOG as log -class DetailsTab: +class DetailsTab(Tab): def __init__(self): # Get the labels we need to update. # widgetname, modifier function, status keys glade = component.get("MainWindow").main_glade + self._name = "Details" + self._child_widget = glade.get_widget("details_tab") + self._tab_label = glade.get_widget("details_tab_label") + self.label_widgets = [ (glade.get_widget("summary_name"), None, ("name",)), (glade.get_widget("summary_total_size"), deluge.common.fsize, ("total_size",)), (glade.get_widget("summary_num_files"), str, ("num_files",)), (glade.get_widget("summary_tracker"), None, ("tracker",)), (glade.get_widget("summary_torrent_path"), None, ("save_path",)), - (glade.get_widget("summary_private"), str, ("private",)), (glade.get_widget("summary_message"), str, ("message",)), (glade.get_widget("summary_hash"), str, ("hash",)) ] - + def update(self): # Get the first selected torrent selected = component.get("TorrentView").get_selected_torrents() @@ -65,15 +69,16 @@ class DetailsTab: selected = selected[0] else: # No torrent is selected in the torrentview + self.clear() return # Get the torrent status status_keys = ["name", "total_size", "num_files", - "tracker", "save_path", "private", "message", "hash"] + "tracker", "save_path", "message", "hash"] client.get_torrent_status( self._on_get_torrent_status, selected, status_keys) - + def _on_get_torrent_status(self, status): # Check to see if we got valid data from the core if status is None: diff --git a/deluge/ui/gtkui/files_tab.py b/deluge/ui/gtkui/files_tab.py index af18f07d2..00ca88cbf 100644 --- a/deluge/ui/gtkui/files_tab.py +++ b/deluge/ui/gtkui/files_tab.py @@ -37,6 +37,7 @@ import gettext import os.path import cPickle +from deluge.ui.gtkui.torrentdetails import Tab from deluge.ui.client import aclient as client from deluge.configmanager import ConfigManager import deluge.component as component @@ -72,9 +73,14 @@ class ColumnState: self.sort = sort self.sort_order = sort_order -class FilesTab: +class FilesTab(Tab): def __init__(self): glade = component.get("MainWindow").get_glade() + + self._name = "Files" + self._child_widget = glade.get_widget("files_tab") + self._tab_label = glade.get_widget("files_tab_label") + self.listview = glade.get_widget("files_listview") # filename, size, progress string, progress value, priority, file index self.liststore = gtk.ListStore(str, gobject.TYPE_UINT64, str, int, int, int) diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade index 2051385d7..63f09a5d4 100644 --- a/deluge/ui/gtkui/glade/main_window.glade +++ b/deluge/ui/gtkui/glade/main_window.glade @@ -133,22 +133,34 @@ - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Sidebar + _Labels True True - + - + True - _Info Pane + Status_bar True True - + + + + + + True + + + + + True + T_abs + True @@ -471,1288 +483,6 @@ True False - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_NEVER - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - 10 - 10 - 15 - 15 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - True - 0.10000000149 - - - False - False - - - - - True - 5 - 6 - 15 - 5 - - - - - - - - - True - 0 - True - True - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - 0 - - - 3 - 4 - 3 - 4 - GTK_FILL - - - - - True - 0 - PANGO_WRAP_CHAR - True - - - 1 - 6 - 4 - 5 - GTK_FILL - - - - - True - 0 - <b>Tracker Status:</b> - True - - - 4 - 5 - 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 - 2 - 3 - GTK_FILL - - - - - True - 0 - - - 5 - 6 - 1 - 2 - 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> - True - - - - - 2 - 3 - 3 - 4 - GTK_FILL - - - - - True - 15 - 5 - - - True - 0 - <b>ETA:</b> - True - - - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - True - 15 - 5 - - - True - 0 - <b>Speed:</b> - True - - - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - True - 15 - 5 - - - True - 0 - <b>Speed:</b> - True - - - - - 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 - 5 - - - True - 0 - <b>Uploaded:</b> - True - - - - - 1 - 2 - GTK_FILL - - - - - True - 5 - - - True - 0 - <b>Downloaded:</b> - True - - - - - GTK_FILL - - - - - True - 0 - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - True - 0 - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - 0 - - - 3 - 4 - GTK_FILL - - - - - True - 0 - - - 1 - 2 - GTK_FILL - - - - - False - 1 - - - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-dialog-info - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Statistics - True - - - 1 - - - - - tab - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 10 - 15 - 15 - - - True - 6 - 4 - 2 - - - 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 - True - - - 1 - 4 - 5 - 6 - - - - - - True - 0 - 1 - <b>Tracker:</b> - True - - - 5 - 6 - 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 - GTK_FILL - - - - - - True - 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 - 0 - 1 - <b>Name:</b> - True - - - - - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Path:</b> - True - - - - - 2 - 3 - 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 - 2 - 2 - 3 - - - - - - True - 0 - 1 - <b>Status:</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 - - - 1 - 4 - 4 - 5 - - - - - - True - 0 - 1 - <b># of files:</b> - True - - - 2 - 3 - 3 - 4 - GTK_FILL - - - - - - True - 0 - True - - - 3 - 4 - 3 - 4 - - - - - - True - 0 - True - - - 1 - 2 - 3 - 4 - - - - - - True - 0 - 1 - <b>Private:</b> - True - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - - True - 0 - True - PANGO_WRAP_CHAR - True - - - 3 - 4 - 2 - 3 - - - - - - - - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-properties - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Details - True - - - 1 - - - - - tab - 1 - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-copy - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Files - True - - - 1 - - - - - tab - 2 - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-network - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Peers - True - - - 1 - - - - - tab - 3 - False - - - - - True - True - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - - - True - 5 - GTK_RESIZE_QUEUE - GTK_SHADOW_NONE - - - True - - - True - 0 - GTK_SHADOW_NONE - - - True - 12 - - - True - 5 - 4 - 3 - 5 - - - - - - - - - True - True - 6 - 1 - -1 -1 999999 1 10 10 - - - 1 - 2 - 2 - 3 - - - - - - - True - True - 6 - 1 - -1 -1 99999 1 10 10 - 1 - - - 1 - 2 - 1 - 2 - - - - - - - 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 - - - - - - - - - - - True - <b>Bandwidth</b> - True - - - label_item - - - - - False - False - - - - - True - - - True - 0 - GTK_SHADOW_NONE - - - True - 12 - - - True - - - True - True - Private - 0 - True - - - False - False - - - - - True - True - Prioritize First/Last - 0 - True - - - False - False - 1 - - - - - True - True - True - 0 - - - - True - 5 - - - True - gtk-edit - - - False - False - - - - - True - _Edit Trackers - True - - - False - False - 1 - - - - - - - False - False - 2 - - - - - - - - - True - <b>General</b> - True - - - label_item - - - - - False - False - - - - - True - 0 - GTK_SHADOW_NONE - - - True - 12 - - - True - True - True - gtk-apply - True - 0 - - - - - - - - - label_item - - - - - False - False - 1 - - - - - False - False - 1 - - - - - - - - - 4 - - - - - True - 2 - - - True - gtk-preferences - - - - - True - _Options - True - - - 1 - - - - - tab - 4 - False - - False @@ -1855,4 +585,1271 @@ + + + + True + True + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_NEVER + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + 10 + 10 + 15 + 15 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + True + 0.10000000149 + + + False + False + + + + + True + 5 + 6 + 15 + 5 + + + + + + + + + True + 0 + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + True + 0 + PANGO_WRAP_CHAR + True + + + 1 + 6 + 4 + 5 + GTK_FILL + + + + + True + 0 + <b>Tracker Status:</b> + True + + + 4 + 5 + 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 + 2 + 3 + GTK_FILL + + + + + True + 0 + + + 5 + 6 + 1 + 2 + 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> + True + + + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>ETA:</b> + True + + + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>Speed:</b> + True + + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + True + 15 + 5 + + + True + 0 + <b>Speed:</b> + True + + + + + 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 + 5 + + + True + 0 + <b>Uploaded:</b> + True + + + + + 1 + 2 + GTK_FILL + + + + + True + 5 + + + True + 0 + <b>Downloaded:</b> + True + + + + + GTK_FILL + + + + + True + 0 + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 3 + 4 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + GTK_FILL + + + + + False + 1 + + + + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-info + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Statistics + True + + + 1 + + + + + tab + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 10 + 15 + 15 + + + True + 7 + 4 + 2 + + + + + + + + + + + + + + + True + 0 + True + + + 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 + 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 + GTK_FILL + + + + + + True + 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 + 0 + 1 + <b>Name:</b> + True + + + + + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Path:</b> + True + + + + + 2 + 3 + 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 + 2 + 3 + + + + + + True + 0 + 1 + <b>Status:</b> + True + + + 5 + 6 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + + + 1 + 4 + 5 + 6 + + + + + + True + 0 + True + + + 1 + 2 + 3 + 4 + + + + + + + + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-properties + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Details + True + + + 1 + + + + + tab + 1 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-copy + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Files + True + + + 1 + + + + + tab + 2 + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-network + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Peers + True + + + 1 + + + + + tab + 3 + False + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + 5 + GTK_RESIZE_QUEUE + GTK_SHADOW_NONE + + + True + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + 5 + 4 + 3 + 5 + + + + + + + + + True + True + 6 + 1 + -1 -1 999999 1 10 10 + + + 1 + 2 + 2 + 3 + + + + + + + True + True + 6 + 1 + -1 -1 99999 1 10 10 + 1 + + + 1 + 2 + 1 + 2 + + + + + + + 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 + + + + + + + + + + + True + <b>Bandwidth</b> + True + + + label_item + + + + + False + False + + + + + True + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + + + True + True + Private + 0 + True + + + False + False + + + + + True + True + Prioritize First/Last + 0 + True + + + False + False + 1 + + + + + True + True + True + 0 + + + + True + 5 + + + True + gtk-edit + + + False + False + + + + + True + _Edit Trackers + True + + + False + False + 1 + + + + + + + False + False + 2 + + + + + + + + + True + <b>General</b> + True + + + label_item + + + + + False + False + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + True + True + gtk-apply + True + 0 + + + + + + + + + label_item + + + + + False + False + 1 + + + + + False + False + 1 + + + + + + + + + 4 + + + + + True + 2 + + + True + gtk-preferences + + + + + True + _Options + True + + + 1 + + + + + tab + 4 + False + + + + + diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index 964d9fd4f..1117e967a 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -114,8 +114,8 @@ class MenuBar(component.Component): ## View Menu "on_menuitem_toolbar_toggled": self.on_menuitem_toolbar_toggled, - "on_menuitem_sidebar_toggled": self.on_menuitem_sidebar_toggled, - "on_menuitem_infopane_toggled": self.on_menuitem_infopane_toggled, + "on_menuitem_labels_toggled": self.on_menuitem_labels_toggled, + "on_menuitem_statusbar_toggled": self.on_menuitem_statusbar_toggled, ## Help Menu "on_menuitem_homepage_activate": self.on_menuitem_homepage_activate, @@ -322,14 +322,14 @@ class MenuBar(component.Component): log.debug("on_menuitem_toolbar_toggled") component.get("ToolBar").visible(value.get_active()) - def on_menuitem_sidebar_toggled(self, value): - log.debug("on_menuitem_sidebar_toggled") + def on_menuitem_labels_toggled(self, value): + log.debug("on_menuitem_labels_toggled") component.get("SideBar").visible(value.get_active()) - def on_menuitem_infopane_toggled(self, value): - log.debug("on_menuitem_infopane_toggled") - component.get("TorrentDetails").visible(value.get_active()) - + def on_menuitem_statusbar_toggled(self, value): + log.debug("on_menuitem_statusbar_toggled") + component.get("StatusBar").visible(value.get_active()) + ## Help Menu ## def on_menuitem_homepage_activate(self, data=None): log.debug("on_menuitem_homepage_activate") diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py index 5a6ec1507..e1b254426 100644 --- a/deluge/ui/gtkui/options_tab.py +++ b/deluge/ui/gtkui/options_tab.py @@ -33,10 +33,16 @@ import deluge.component as component from deluge.ui.client import aclient as client +from deluge.ui.gtkui.torrentdetails import Tab -class OptionsTab: +class OptionsTab(Tab): def __init__(self): glade = component.get("MainWindow").get_glade() + + self._name = "Options" + self._child_widget = glade.get_widget("options_tab") + self._tab_label = glade.get_widget("options_tab_label") + self.spin_max_download = glade.get_widget("spin_max_download") self.spin_max_upload = glade.get_widget("spin_max_upload") self.spin_max_connections = glade.get_widget("spin_max_connections") diff --git a/deluge/ui/gtkui/peers_tab.py b/deluge/ui/gtkui/peers_tab.py index cfd8215a7..1b9f33556 100644 --- a/deluge/ui/gtkui/peers_tab.py +++ b/deluge/ui/gtkui/peers_tab.py @@ -43,6 +43,7 @@ from deluge.configmanager import ConfigManager import deluge.component as component import deluge.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 class ColumnState: @@ -53,9 +54,14 @@ class ColumnState: self.sort = sort self.sort_order = sort_order -class PeersTab: +class PeersTab(Tab): def __init__(self): glade = component.get("MainWindow").get_glade() + + self._name = "Peers" + self._child_widget = glade.get_widget("peers_tab") + self._tab_label = glade.get_widget("peers_tab_label") + self.listview = glade.get_widget("peers_listview") # country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, int, int, str, gobject.TYPE_UINT, gtk.gdk.Pixbuf) diff --git a/deluge/ui/gtkui/statistics_tab.py b/deluge/ui/gtkui/statistics_tab.py index 81e4cc246..b0e9ad5e4 100644 --- a/deluge/ui/gtkui/statistics_tab.py +++ b/deluge/ui/gtkui/statistics_tab.py @@ -36,6 +36,7 @@ import gtk, gtk.glade from deluge.ui.client import aclient as client import deluge.component as component import deluge.common +from deluge.ui.gtkui.torrentdetails import Tab def fpeer_sized(first, second): return "%s (%s)" % (deluge.common.fsize(first), deluge.common.fsize(second)) @@ -55,12 +56,16 @@ def fspeed(value, max_value=-1): else: return deluge.common.fspeed(value) -class StatisticsTab: +class StatisticsTab(Tab): def __init__(self): # Get the labels we need to update. # widgetname, modifier function, status keys glade = component.get("MainWindow").main_glade + self._name = "Statistics" + self._child_widget = glade.get_widget("statistics_tab") + self._tab_label = glade.get_widget("statistics_tab_label") + self.label_widgets = [ (glade.get_widget("summary_pieces"), fpeer_size_second, ("num_pieces", "piece_length")), (glade.get_widget("summary_availability"), fratio, ("distributed_copies",)), diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index b96512550..ef99d965d 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -187,7 +187,13 @@ class StatusBar(component.Component): except Exception, e: log.debug("Unable to remove StatusBar item: %s", e) self.show_not_connected() - + + def visible(self, visible): + if visible: + self.statusbar.show() + else: + self.statusbar.hide() + def show_not_connected(self): self.hbox.pack_start( self.not_connected_item.get_eventbox(), expand=False, fill=False) diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py index 53c368021..441e0ad77 100644 --- a/deluge/ui/gtkui/torrentdetails.py +++ b/deluge/ui/gtkui/torrentdetails.py @@ -34,17 +34,37 @@ """The torrent details component shows info about the selected torrent.""" import gtk, gtk.glade +import os +import os.path +import cPickle import deluge.component as component from deluge.ui.client import aclient as client -from statistics_tab import StatisticsTab -from details_tab import DetailsTab -from files_tab import FilesTab -from peers_tab import PeersTab -from options_tab import OptionsTab +from deluge.configmanager import ConfigManager from deluge.log import LOG as log +class Tab: + def __init__(self): + pass + + def get_name(self): + return self._name + + def get_child_widget(self): + parent = self._child_widget.get_parent() + if parent is not None: + parent.remove(self._child_widget) + + return self._child_widget + + def get_tab_label(self): + parent = self._tab_label.get_parent() + if parent is not None: + parent.remove(self._tab_label) + + return self._tab_label + class TorrentDetails(component.Component): def __init__(self): component.Component.__init__(self, "TorrentDetails", interval=2000) @@ -52,49 +72,205 @@ class TorrentDetails(component.Component): glade = self.window.main_glade self.notebook = glade.get_widget("torrent_info") - self.details_tab = glade.get_widget("torrentdetails_tab") + + # This is the menu item we'll attach the tabs checklist menu to + self.menu_tabs = glade.get_widget("menu_tabs") self.notebook.connect("switch-page", self._on_switch_page) - statistics_tab = StatisticsTab() - details_tab = DetailsTab() - files_tab = FilesTab() - peers_tab = PeersTab() - options_tab = OptionsTab() + # Tab index is a list of tab names in the order which they presented + # to the user. + self.tab_index = [] - self.tabs = [] - self.tabs.insert(0, statistics_tab) - self.tabs.insert(1, details_tab) - self.tabs.insert(2, files_tab) - self.tabs.insert(3, peers_tab) - self.tabs.insert(4, options_tab) + # Tabs holds references to the Tab objects by their name + self.tabs = {} + + # tab_name: (tab_object, position) + self.hidden_tabs = {} + + # Add the default tabs + from statistics_tab import StatisticsTab + from details_tab import DetailsTab + from files_tab import FilesTab + from peers_tab import PeersTab + from options_tab import OptionsTab + + default_tabs = { + "Statistics": StatisticsTab, + "Details": DetailsTab, + "Files": FilesTab, + "Peers": PeersTab, + "Options": OptionsTab + } + + default_order = [ + "Statistics", + "Details", + "Files", + "Peers", + "Options" + ] + + # Get the state from saved file + state = self.load_state() + + # The state is a list of tab_names in the order they should appear + if state == None: + # Set the default order + state = default_order + + # Add the tabs in the order from the state + for tab_name in state: + self.add_tab(default_tabs[tab_name]()) + if len(state) < len(default_order): + # We have hidden tabs and need to add them to the hidden_tabs dict + for i, tab_name in enumerate(default_order): + if tab_name not in state: + self.hidden_tabs[tab_name] = (default_tabs[tab_name](), i) + + # Generate the checklist menu + self.generate_menu() + + def add_tab(self, tab_object, position=-1, generate_menu=True): + """Adds a tab object to the notebook.""" + self.tabs[tab_object.get_name()] = tab_object + pos = self.notebook.insert_page( + tab_object.get_child_widget(), + tab_object.get_tab_label(), + position) + self.tab_index.insert(pos, tab_object.get_name()) + if generate_menu: + self.generate_menu() + + if not self.notebook.get_property("visible"): + # If the notebook isn't visible, show it + self.visible(True) + + def remove_tab(self, tab_name): + """Removes a tab by name.""" + index = self.tab_index.index(tab_name) + self.notebook.remove_page(index) + del self.tabs[tab_name] + del self.tab_index[index] + self.generate_menu() + + # If there are no tabs visible, then do not show the notebook + if len(self.tabs) == 0: + self.visible(False) + + def generate_menu(self): + """Generates the checklist menu for all the tabs and attaches it""" + menu = gtk.Menu() + # Add all the tabs to the menu + for tab in self.tab_index: + menuitem = gtk.CheckMenuItem(tab) + menuitem.connect("toggled", self._on_menuitem_toggled) + menuitem.set_active(True) + menu.append(menuitem) + + # Add all hidden_tabs to the menu too + for tab in self.hidden_tabs.keys(): + menuitem = gtk.CheckMenuItem(tab) + menuitem.connect("toggled", self._on_menuitem_toggled) + menuitem.set_active(False) + # Try to keep position in sync + menu.insert(menuitem, self.hidden_tabs[tab][1]) + + self.menu_tabs.set_submenu(menu) + self.menu_tabs.show_all() + def visible(self, visible): if visible: self.notebook.show() else: self.notebook.hide() self.window.vpaned.set_position(-1) - + + def set_tab_visible(self, tab_name, visible): + """Sets the tab to visible""" + log.debug("set_tab_visible name: %s visible: %s", tab_name, visible) + if visible: + # We need to show tab, make sure it's not already shown + if tab_name not in self.hidden_tabs.keys(): + return + # Add the tab back to the notebook + self.add_tab(self.hidden_tabs[tab_name][0], self.hidden_tabs[tab_name][1], generate_menu=False) + del self.hidden_tabs[tab_name] + else: + # Check to see if tab is already hidden + if tab_name in self.hidden_tabs.keys(): + return + # Remove the tab from the notebook and store it in hidden_tabs + self.hidden_tabs[tab_name] = (self.tabs[tab_name], self.tab_index.index(tab_name)) + self.remove_tab(tab_name) + def stop(self): # Save the state of the tabs for tab in self.tabs: try: - tab.save_state() + self.tabs[tab].save_state() except AttributeError: pass self.clear() + # Save tabs state + self.save_state() - def update(self): + def update(self, page_num=None): if self.notebook.get_property("visible"): + if page_num == None: + page_num = self.notebook.get_current_page() + try: + # Get the tab name + name = self.tab_index[page_num] + except IndexError: + return # Update the tab that is in view - self.tabs[self.notebook.get_current_page()].update() + self.tabs[name].update() def clear(self): - self.tabs[self.notebook.get_current_page()].clear() + # Get the tab name + name = self.tab_index[self.notebook.get_current_page()] + self.tabs[name].clear() def _on_switch_page(self, notebook, page, page_num): - self.tabs[page_num].update() + self.update(page_num) client.force_call(False) + def _on_menuitem_toggled(self, widget): + # Get the tab name + name = widget.get_child().get_text() + self.set_tab_visible(name, widget.get_active()) + + def save_state(self): + """We save the state, which is basically the tab_index list""" + filename = "tabs.state" + state = self.tab_index + + # Get the config location for saving the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + + try: + log.debug("Saving TorrentDetails state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "wb") + cPickle.dump(state, state_file) + state_file.close() + except IOError, e: + log.warning("Unable to save state file: %s", e) + + def load_state(self): + filename = "tabs.state" + # Get the config location for loading the state file + config_location = ConfigManager("gtkui.conf")["config_location"] + state = None + + try: + log.debug("Loading TorrentDetails state file: %s", filename) + state_file = open(os.path.join(config_location, filename), "rb") + state = cPickle.load(state_file) + state_file.close() + except IOError, e: + log.warning("Unable to load state file: %s", e) + + return state