mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-21 20:14:51 +00:00
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:
parent
7522ecf719
commit
589df97add
9 changed files with 107 additions and 10 deletions
1
TODO
1
TODO
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue