Add ListView state saving.

Have TorrentView save and load state on startup/shutdown.
Add new method to components shutdown() which is called when the UI is 
exiting to allow components to clean-up.
Clean up some debug output.
This commit is contained in:
Andrew Resch 2007-12-08 05:02:29 +00:00
parent 7522ecf719
commit 589df97add
9 changed files with 107 additions and 10 deletions

1
TODO
View file

@ -1,4 +1,3 @@
* Add state saving to listview.. this includes saving column size and position.
* Queue plugin 'apply_queue' stuff.. Just finishing the queue plugin and it's
intended functionality.
* Figure out easy way for user-made plugins to add i18n support.

View file

@ -55,6 +55,7 @@ from deluge.core.signalmanager import SignalManager
from deluge.log import LOG as log
DEFAULT_PREFS = {
"config_location": deluge.common.get_config_dir(),
"daemon_port": 58846,
"allow_remote": False,
"compact_allocation": True,

View file

@ -63,7 +63,6 @@ class PluginManagerBase:
self.enable_plugin(name)
def shutdown(self):
log.debug("PluginManager shutting down..")
for plugin in self.plugins.values():
plugin.disable()
del self.plugins

View file

@ -60,6 +60,9 @@ class Component:
def _stop(self):
self._state = COMPONENT_STATE.index("Stopped")
def shutdown(self):
pass
def update(self):
pass
@ -100,6 +103,7 @@ class ComponentRegistry:
# Only start if the component is stopped.
if self.components[name].get_state() == \
COMPONENT_STATE.index("Stopped"):
log.debug("Starting component %s..", name)
self.components[name].start()
self.components[name]._start()
@ -107,6 +111,7 @@ class ComponentRegistry:
def stop(self):
"""Stops all components"""
for component in self.components.keys():
log.debug("Stopping component %s..", component)
self.components[component].stop()
self.components[component]._stop()
# Stop the update timer
@ -122,6 +127,17 @@ class ComponentRegistry:
return True
def shutdown(self):
"""Shuts down all components. This should be called when the program
exits so that components can do any necessary clean-up."""
for component in self.components.keys():
log.debug("Shutting down component %s..", component)
try:
self.components[component].shutdown()
except Exception, e:
log.debug("Unable to call shutdown(): %s", e)
_ComponentRegistry = ComponentRegistry()
def register(name, obj, depend=None):
@ -140,6 +156,10 @@ def update():
"""Updates all components"""
_ComponentRegistry.update()
def shutdown():
"""Shutdowns all components"""
_ComponentRegistry.shutdown()
def get(component):
"""Return a reference to the component"""
return _ComponentRegistry.get(component)

View file

@ -55,10 +55,12 @@ from pluginmanager import PluginManager
from dbusinterface import DbusInterface
from queuedtorrents import QueuedTorrents
from deluge.configmanager import ConfigManager
import deluge.common
from deluge.log import LOG as log
import deluge.configmanager
DEFAULT_PREFS = {
"config_location": deluge.common.get_config_dir(),
"interactive_add": False,
"enable_files_dialog": False,
"enable_system_tray": True,
@ -151,6 +153,8 @@ class GtkUI:
del config
# Clean-up
# Shutdown all components
component.shutdown()
del self.mainwindow
del self.systemtray
del self.menubar

View file

@ -31,11 +31,15 @@
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import cPickle
import os.path
import pygtk
pygtk.require('2.0')
import gtk
import gettext
from deluge.configmanager import ConfigManager
import deluge.common
from deluge.log import LOG as log
@ -84,6 +88,16 @@ def cell_data_ratio(column, cell, model, row, data):
ratio_str = "%.3f" % ratio
cell.set_property('text', ratio_str)
class ListViewColumnState:
"""Used for saving/loading column state"""
def __init__(self, name, position, width, visible, sort, sort_order):
self.name = name
self.position = position
self.width = width
self.visible = visible
self.sort = sort
self.sort_order = sort_order
class ListView:
"""ListView is used to make custom GtkTreeViews. It supports the adding
and removing of columns, creating a menu for a column toggle list and
@ -106,8 +120,7 @@ class ListView:
# If column is 'hidden' then it will not be visible and will not
# show up in any menu listing; it cannot be shown ever.
self.hidden = False
def __init__(self, treeview_widget=None):
log.debug("ListView initialized..")
@ -138,6 +151,50 @@ class ListView:
# created.
self.checklist_menus = []
def save_state(self, filename):
"""Saves the listview state (column positions and visibility) to
filename."""
# A list of ListViewColumnStates
state = []
# Get the list of TreeViewColumns from the TreeView
treeview_columns = self.treeview.get_columns()
counter = 0
for column in treeview_columns:
# Append a new column state to the state list
state.append(ListViewColumnState(column.get_title(), counter,
column.get_width(), column.get_visible(),
column.get_sort_indicator(), int(column.get_sort_order())))
# Increase the counter because this is how we determine position
counter += 1
# Get the config location for saving the state file
config_location = ConfigManager("gtkui.conf")["config_location"]
try:
log.debug("Saving ListView 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):
"""Load the listview state from filename."""
# Get the config location for loading the state file
config_location = ConfigManager("gtkui.conf")["config_location"]
try:
log.debug("Loading ListView state file: %s", filename)
state_file = open(os.path.join(config_location, filename), "rb")
state = cPickle.load(state_file)
state_file.close()
except IOError:
log.warning("Unable to load state file: %s", e)
# Keep the state in self.state so we can access it as we add new columns
self.state = state
def set_treeview(self, treeview_widget):
"""Set the treeview widget that this listview uses."""
self.treeview = treeview_widget
@ -317,6 +374,7 @@ class ListView:
elif column_type == None:
return
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_sort_column_id(self.columns[header].column_indices[sortid])
column.set_clickable(True)
column.set_resizable(True)
@ -324,10 +382,23 @@ class ListView:
column.set_min_width(10)
column.set_reorderable(True)
column.set_visible(not hidden)
# Check for loaded state and apply
for column_state in self.state:
if header == column_state.name:
# We found a loaded state
if column_state.width > 0:
column.set_fixed_width(column_state.width)
column.set_sort_indicator(column_state.sort)
column.set_sort_order(column_state.sort_order)
column.set_visible(column_state.visible)
position = column_state.position
if position is not None:
self.treeview.insert_column(column, position)
else:
self.treeview.append_column(column)
# Set hidden in the column
self.columns[header].hidden = hidden
self.columns[header].column = column

View file

@ -107,7 +107,6 @@ class StatusBar(component.Component):
self.show_not_connected()
def start(self):
log.debug("StatusBar start..")
# Add in images and labels
self.remove_item(self.not_connected_item)
self.connections_item = StatusBarItem(

View file

@ -99,7 +99,6 @@ class SystemTray(component.Component):
self.tray_glade.get_widget(widget).hide()
def start(self):
log.debug("SystemTray start..")
if self.config["enable_system_tray"]:
# Show widgets in the hide list because we've connected to a host
for widget in self.hide_widget_list:
@ -109,7 +108,6 @@ class SystemTray(component.Component):
self.build_tray_bwsetsubmenu()
def stop(self):
log.debug("SystemTray stop..")
try:
# Hide widgets in hide list because we're not connected to a host
for widget in self.hide_widget_list:

View file

@ -116,7 +116,9 @@ class TorrentView(listview.ListView, component.Component):
listview.ListView.__init__(self,
self.window.main_glade.get_widget("torrent_view"))
log.debug("TorrentView Init..")
# Try to load the state file if available
self.load_state("torrentview.state")
# Register the columns menu with the listview so it gets updated
# accordingly.
self.register_checklist_menu(
@ -185,7 +187,7 @@ class TorrentView(listview.ListView, component.Component):
# changes.
self.treeview.get_selection().connect("changed",
self.on_selection_changed)
def start(self):
"""Start the torrentview"""
# We need to get the core session state to know which torrents are in
@ -198,7 +200,11 @@ class TorrentView(listview.ListView, component.Component):
"""Stops the torrentview"""
# We need to clear the liststore
self.liststore.clear()
def shutdown(self):
"""Called when GtkUi is exiting"""
self.save_state("torrentview.state")
def set_filter(self, field, condition):
"""Sets filters for the torrentview.."""
self.filter = (field, condition)