[conduit] Changed config dialog to "Restore/Close" from "Cancel/Apply".
- From: Alexandre Rosenfeld <arosenfeld src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [conduit] Changed config dialog to "Restore/Close" from "Cancel/Apply".
- Date: Mon, 21 Sep 2009 00:14:46 +0000 (UTC)
commit ac22bdfff9b42ca70e74529efdd1a01273a5c77e
Author: Alexandre Rosenfeld <airmind gmail com>
Date: Fri Jun 12 21:52:32 2009 -0300
Changed config dialog to "Restore/Close" from "Cancel/Apply".
Fixed YouTube (Google module) behaviour to work with Restore.
Added getter for ConfigContainer and changed Flickr config to use it.
conduit/gtkui/ConfigContainer.py | 89 ++++++++++++++++++--------
conduit/gtkui/ConfigItems.py | 23 ++++---
conduit/gtkui/WindowConfigurator.py | 46 +++++++++----
conduit/modules/FlickrModule/FlickrModule.py | 17 +++--
conduit/modules/GoogleModule/GoogleModule.py | 3 +
5 files changed, 119 insertions(+), 59 deletions(-)
---
diff --git a/conduit/gtkui/ConfigContainer.py b/conduit/gtkui/ConfigContainer.py
index a6a5fec..a92f75f 100644
--- a/conduit/gtkui/ConfigContainer.py
+++ b/conduit/gtkui/ConfigContainer.py
@@ -39,10 +39,11 @@ class ConfigContainer(Configurator.BaseConfigContainer):
self.section = None
self.sections = []
self.items = []
+ self.item_names = {}
self.built_items = False
self.config_values = None
- self._reset_modified_items()
+ self.__modified_items = None
#the child widget to contain the custom settings
self.widgetTable = gtk.Table(rows=1, columns=2)
@@ -52,11 +53,19 @@ class ConfigContainer(Configurator.BaseConfigContainer):
self.config_widget = self.widgetTable
self.firstRow = True
+
+ def __len__(self):
+ return len(self.item_names)
+
+ def __getitem__(self, key):
+ return self.item_names[key]
def _reset_modified_items(self, empty = True):
'''
- Reset the list of modified items. If empty is true, just create a new
- empty list of modified items (so that no item is modified).
+ Reset the list of modified items.
+
+ If empty is True, just create a new empty list of modified items (so
+ that no item is modified).
If empty is False, set the list to None, so that it will be recreated
next time get_modified_items is called.
'''
@@ -67,8 +76,6 @@ class ConfigContainer(Configurator.BaseConfigContainer):
def _item_changed(self, item, initial_state, value):
self.emit("item-changed", item)
- if self.modified_items is None:
- self.get_modified_items()
if not initial_state:
self.modified_items.add(item)
elif item in self.modified_items:
@@ -77,7 +84,7 @@ class ConfigContainer(Configurator.BaseConfigContainer):
def _rebuild_widgets(self):
'''
- Rebuild widgets if needed
+ Rebuild widgets if needed.
'''
self.modified_items = None
if self.showing:
@@ -85,7 +92,7 @@ class ConfigContainer(Configurator.BaseConfigContainer):
def _build_widgets(self):
'''
- Creates all necessary widgets
+ Creates all necessary widgets.
'''
table = self.widgetTable
if self.showing:
@@ -130,36 +137,58 @@ class ConfigContainer(Configurator.BaseConfigContainer):
self._rebuild_widgets()
return self.section
- def add_item(self, title, kind, order = 0, **kwargs):
+ def add_item(self, title, kind, order = 0, name = None, **kwargs):
'''
Add a configuration item. Returns the Item object.
- You can pass properties to the configuration item in kwargs.
+ Title is used for the label next to this item.
+ Kind is the type of item used for the widget. See the ConfigItems file
+ for a list of default kinds provided. Descendants of ItemBase are auto-
+ matically registered and can be used here.
+ Name is used to access this item via __getitem__ or with config[name].
+ If name is not specified here it will use the config_name defined in
+ kwargs, if availiable.
+
+ You can pass other properties to the configuration item in kwargs.
+ For documentation on which properties to use, check the ConfigItems file.
'''
+ # Check if this kind of item is registered
+ if kind not in ConfigItems.ItemBase.items:
+ raise Error("Config kind %s not found" % kind)
+ # We only add a Section for this item if no previous section is defined.
if not self.section:
self.add_section()
- # If we have a saved configuration in the config dict from the dp,
- # use it as initial value.
+ # If we have a saved configuration in the config dict from the
+ # dataprovider use it as initial value.
+ # Note that we only get the configuration dict once for this
+ # dataprovider, so that next items will get this cached version.
+ # Because dataproviders usually add several items in a row, this is
+ # usually faster then retrieving it every time.
if self.config_values is None:
if self.dataprovider:
self.config_values = self.dataprovider.get_configuration()
else:
- self.config_values = {}
- if kwargs.get('config_name', None):
- if kwargs['config_name'] in self.config_values:
- kwargs['initial_value'] = self.config_values[kwargs['config_name']]
+ self.config_values = {}
+ config_name = kwargs.get('config_name', None)
+ if config_name:
+ if config_name in self.config_values:
+ kwargs['initial_value'] = self.config_values[config_name]
else:
- raise Error("Value for %s (configuration item %s) not found in dataprovider" % (kwargs['config_name'], title))
+ raise Error("Value for %s (configuration item %s) not found in dataprovider" % (config_name, title))
+ # The name of this item will be either the explicitely defined name or
+ # the config_name value.
+ name = name or config_name
if 'enabled' not in kwargs:
kwargs['enabled'] = self.section.enabled
- try:
- item_cls = ConfigItems.ItemBase.items[kind]
- except KeyError:
- raise Error("Config kind %s not found" % kind)
+ item_cls = ConfigItems.ItemBase.items[kind]
item = item_cls(container = self, title = title, order = order, **kwargs)
item.connect("value-changed", self._item_changed)
self.items.append(item)
+ if name:
+ self.item_names[name] = item
self.section.add_item(item)
+ # If we are already showing the configuration dialog, we need to
+ # recreate the table of items.
self._rebuild_widgets()
return item
@@ -167,15 +196,20 @@ class ConfigContainer(Configurator.BaseConfigContainer):
'''
Return a list of items that has been modified
'''
- if self.modified_items is None:
- self.modified_items = set([item for item in self.items if not item.is_initial_value()])
- return self.modified_items
+ if self.__modified_items is None:
+ self.__modified_items = set([item for item in self.items if not item.is_initial_value()])
+ return self.__modified_items
+
+ def set_modified_items(self, value):
+ self.__modified_items = value
+
+ modified_items = property(get_modified_items, set_modified_items)
def is_modified(self):
'''
Returns true if any item has been modified
'''
- return len(self.get_modified_items()) != 0
+ return len(self.modified_items) != 0
def get_config_values(self, items):
'''
@@ -231,10 +265,11 @@ class ConfigContainer(Configurator.BaseConfigContainer):
self.dataprovider.set_configuration(config_values)
for item in items:
item.save_state()
- if not items and not sections:
- self._reset_modified_items()
+ if items or sections:
+ self._reset_modified_items(empty = False)
else:
- self._reset_modified_items(False)
+ self._reset_modified_items(empty = True)
+ self.emit('changed', self.is_modified())
def cancel_config(self):
'''
diff --git a/conduit/gtkui/ConfigItems.py b/conduit/gtkui/ConfigItems.py
index be56032..5fc5ce6 100644
--- a/conduit/gtkui/ConfigItems.py
+++ b/conduit/gtkui/ConfigItems.py
@@ -275,6 +275,10 @@ class ItemBase(gobject.GObject):
table.attach(align, 0, 2, row - 1, row, xoptions = gtk.FILL | gtk.EXPAND, yoptions = yoptions)
return row
+ def _enabled_check_toggled(self, widget):
+ self.set_enabled(widget.get_active())
+ self.emit('value-changed')
+
def get_label(self):
'''
Returns the gtk.Label to this item (if needed)
@@ -334,6 +338,12 @@ class ItemBase(gobject.GObject):
heavy processing in this method.
It is called every time the user changes the value.
'''
+ #FIXME: This is a hack to allow the Youtube configuration to work.
+ # The way this should be implemented is adding a callback to this function
+ # or something similar. But because we already have too much callbacks
+ # this way is simpler
+ if (not self.enabled) and (self.disabled_value is not None):
+ return self.disabled_value
if not self.__widget:
return self.initial_value
return self._get_value()
@@ -368,14 +378,7 @@ class ItemBase(gobject.GObject):
'''
if not self.config_name:
return None
- #FIXME: This is a hack to allow the Youtube configuration to work.
- # The way this should be implemented is adding a callback to this function
- # or something similar. But because we already have too much callbacks
- # this way is simpler
- if (not self.enabled) and (self.disabled_value is not None):
- value = self.disabled_value
- else:
- value = self.get_value()
+ value = self.get_value()
try:
if self.config_type:
self.config_type(value)
@@ -406,7 +409,9 @@ class ItemBase(gobject.GObject):
self.__enabled = enabled
if self.__widget:
self._set_enabled(enabled)
- #self.widget.set_sensitive(enabled)
+ if self.disabled_value is not None:
+ log.critical("Toggling enabled")
+ self._value_changed()
enabled = property(lambda self: self.__enabled, lambda self, enabled: self.set_enabled(enabled))
diff --git a/conduit/gtkui/WindowConfigurator.py b/conduit/gtkui/WindowConfigurator.py
index d140381..c67ddf8 100644
--- a/conduit/gtkui/WindowConfigurator.py
+++ b/conduit/gtkui/WindowConfigurator.py
@@ -28,27 +28,36 @@ class WindowConfigurator:
@type window: C{gtk.Window}
"""
self.showing = False
- self.built_configs = False
+ self.built_containers = False
self.dialog = gtk.Dialog(self.CONFIG_WINDOW_TITLE_TEXT,
window,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OK, gtk.RESPONSE_OK,
- gtk.STOCK_HELP, gtk.RESPONSE_HELP))
+ (gtk.STOCK_REVERT_TO_SAVED, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_CLOSE, gtk.RESPONSE_OK))
#TODO: Unless we actually have a help to show, make the help button
#disabled.
#BTW, modules should be able to define their own help
self.dialog.set_has_separator(False)
- self.dialog.set_response_sensitive(gtk.RESPONSE_HELP, False)
- self.dialog.set_default_size(300, -1)
+ #self.dialog.set_response_sensitive(gtk.RESPONSE_HELP, False)
+ self.dialog.set_response_sensitive(gtk.RESPONSE_CANCEL, False)
+ self.dialog.set_default_size(-1, -1)
+ #self.dialog.set_border_width(12)
+
+ self.dialog_box = self.dialog.get_content_area()
+ align = gtk.Alignment()
+ align.set_padding(0, 8, 0, 0)
+ align.add(self._make_config_widget())
- self.dialog_box = self.dialog.vbox
- self.dialog_box.pack_start(self._make_config_widget())
+ self.dialog_box.pack_start(align)
self.dialog_box.show_all()
+ self.container_signals = {}
self.container_widgets = {}
+ def _container_changed(self, container, changed):
+ self.dialog.set_response_sensitive(gtk.RESPONSE_CANCEL, changed)
+
def _make_config_widget(self):
if self.NOTEBOOK:
self.tabs = {}
@@ -57,24 +66,26 @@ class WindowConfigurator:
self.notebook.set_show_tabs(self.MULTIPLE_VIEW)
return self.notebook
else:
- self.containers_box = gtk.VBox(spacing = 8)
- self.containers_box.set_border_width(6)
+ self.containers_box = gtk.VBox(spacing = 6)
+ self.containers_box.set_border_width(12)
return self.containers_box
def set_containers(self, containers):
self._clear_containers()
self.built_containers = False
-
self.containers = containers
def _clear_containers(self):
+ for container, signal_id in self.container_signals.iteritems():
+ container.disconnect(signal_id)
+ self.container_signals = {}
if self.NOTEBOOK:
while self.notebook.get_n_pages() > 0:
self.notebook.remove_page(0)
self.tabs = {}
else:
for container, widget in self.container_widgets.iteritems():
- self.containers_box.remove(widget)
+ self.containers_box.remove(widget)
container_widget = container.get_config_widget()
container_widget.get_parent().remove(container_widget)
self.container_widgets = {}
@@ -102,9 +113,10 @@ class WindowConfigurator:
title_box.show_all()
container_box.pack_start(title_box, False, False)
container_box.pack_start(container_widget, True, True)
- container_box.pack_start(gtk.HSeparator(), False, False)
+ #container_box.pack_start(gtk.HSeparator(), False, False)
self.containers_box.pack_start(container_box)
self.containers_box.show_all()
+ self.container_signals[container] = container.connect('changed', self._container_changed)
self.container_widgets[container] = widget
def build_containers(self):
@@ -133,8 +145,8 @@ class WindowConfigurator:
if busy:
self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
else:
- self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW))
-
+ self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
+
@property
def window(self):
return self.dialog
@@ -166,6 +178,10 @@ class WindowConfigurator:
self.notebook.set_current_page(self.tabs[config_container])
self.dialog.reshow_with_initial_size()
resp = self.dialog.run()
+ while resp == gtk.RESPONSE_CANCEL:
+ for container in containers:
+ container.cancel_config()
+ resp = self.dialog.run()
for container in containers:
container.hide()
self.dialog.hide()
diff --git a/conduit/modules/FlickrModule/FlickrModule.py b/conduit/modules/FlickrModule/FlickrModule.py
index d932140..52ad725 100644
--- a/conduit/modules/FlickrModule/FlickrModule.py
+++ b/conduit/modules/FlickrModule/FlickrModule.py
@@ -279,28 +279,28 @@ class FlickrTwoWay(Image.ImageTwoWay):
def _login_finished(*args):
try:
if self.logged_in:
- status_label.value = _('Loading album list...')
+ config['status'].value = _('Loading album list...')
try:
#FIXME: Blocks and brings the whole UI with it.
photosets = self._get_photosets()
except:
- status_label.value = _('Failed to connect.')
+ config['status'].value = _('Failed to connect.')
else:
- photoset_config.choices = [name for name, photoSetId in photosets]
- status_label.value = _('Album names loaded.')
+ config['photoSetName'].choices = [name for name, photoSetId in photosets]
+ config['status'].value = _('Album names loaded.')
else:
- status_label.value = _('Failed to login.')
+ config['status'].value = _('Failed to login.')
finally:
- load_photosets_config.enabled = True
+ config['photoSetName'].enabled = True
account_section.enabled = True
config.set_busy(False)
def _load_photosets(button):
config.set_busy(True)
- load_photosets_config.enabled = False
+ config['photoSetName'].enabled = False
account_section.enabled = False
username_config.apply()
- status_label.value = _('Logging in, please wait...')
+ config['status'].value = _('Logging in, please wait...')
conduit.GLOBALS.syncManager.run_blocking_dataprovider_function_calls(
self, _login_finished, self._login)
@@ -311,6 +311,7 @@ class FlickrTwoWay(Image.ImageTwoWay):
username_config.connect('value-changed',
lambda item, initial, value: load_photosets_config.set_enabled(bool(value)))
status_label = config.add_item(None, 'label',
+ name = 'status',
initial_value = self.status,
use_markup = True,
xalignment = 0.5,
diff --git a/conduit/modules/GoogleModule/GoogleModule.py b/conduit/modules/GoogleModule/GoogleModule.py
index 78f4cab..08cddf9 100644
--- a/conduit/modules/GoogleModule/GoogleModule.py
+++ b/conduit/modules/GoogleModule/GoogleModule.py
@@ -1376,6 +1376,9 @@ class YouTubeTwoWay(_GoogleBase, DataProvider.TwoWay):
disable_check = True,
disabled_value = 0,
enabled = self.max_downloads > 0)
+
+ def config_cancel(self, config):
+ config['max_downloads'].enabled = (self.max_downloads > 0)
def _get_video_info (self, id):
if self.entries.has_key(id):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]