mirror of
https://github.com/codex-storage/deluge.git
synced 2025-01-12 12:34:43 +00:00
Add the tabs to the View menu and allow them to be shown/hidden.
Some minor UI tweaks.
This commit is contained in:
parent
95d0b65785
commit
afa3c03691
@ -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:
|
||||
|
@ -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)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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",)),
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user