[kupfer: 51/67] alternatives: Use notifications on changes, update preferences window



commit c97d880d2e46698d6dcfc859b5e49c9b324cb0d4
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sat Mar 19 01:53:38 2011 +0100

    alternatives: Use notifications on changes, update preferences window

 kupfer/core/settings.py         |   39 +++++++++++++++++++++
 kupfer/desktop_launch.py        |    8 ++--
 kupfer/plugin/core/__init__.py  |    4 ++-
 kupfer/plugin/core/terminals.py |   46 +++++++++++++++++++++++++
 kupfer/plugin_support.py        |   58 ++++++++++++++++++++++++--------
 kupfer/terminal.py              |   70 +++------------------------------------
 kupfer/ui/preferences.py        |   48 +++++++++++++++++++-------
 kupfer/utils.py                 |   16 +++++----
 8 files changed, 185 insertions(+), 104 deletions(-)
---
diff --git a/kupfer/core/settings.py b/kupfer/core/settings.py
index 9f8a545..b81c50a 100644
--- a/kupfer/core/settings.py
+++ b/kupfer/core/settings.py
@@ -47,6 +47,8 @@ class SettingsController (gobject.GObject, pretty.OutputMixin):
 		self._defaults_path = None
 		self._config = self._read_config()
 		self._save_timer = scheduler.Timer(True)
+		self._alternatives = {}
+		self._alternative_validators = {}
 
 	def _update_config_save_timer(self):
 		self._save_timer.set(60, self._save_config)
@@ -378,6 +380,38 @@ class SettingsController (gobject.GObject, pretty.OutputMixin):
 	def set_preferred_tool(self, tool_id, value):
 		return self._set_config("Tools", tool_id, value)
 
+	## Alternatives section
+	## Provide alternatives for each category
+	## for example the category "terminal"
+	def get_valid_alternative_ids(self, category_key):
+		"""
+		Get a list of (id_, name) tuples for the given @category_key
+		"""
+		validator = self._alternative_validators[category_key]
+		for (id_, alternative) in self._alternatives[category_key].iteritems():
+			name = alternative["name"]
+			if not validator or validator(alternative):
+				yield (id_, name)
+
+	def get_all_alternatives(self, category_key):
+		return self._alternatives[category_key]
+
+	def get_preferred_alternative(self, category_key):
+		"""
+		Get preferred alternative dict for @category_key
+		"""
+		tool_id = self.get_preferred_tool(category_key)
+		alternatives = self._alternatives[category_key]
+		alt = alternatives.get(tool_id)
+		if not alt:
+			self.output_debug("Warning, no configuration for", category_key)
+		return alt or next(alternatives.itervalues(), None)
+
+	def _update_alternatives(self, category_key, alternatives, validator):
+		self._alternatives[category_key] = alternatives
+		self._alternative_validators[category_key] = validator
+		self.emit("alternatives-changed", category_key)
+
 
 # Section, Key, Value
 gobject.signal_new("value-changed", SettingsController, gobject.SIGNAL_RUN_LAST,
@@ -394,6 +428,11 @@ gobject.signal_new("plugin-toplevel-changed", SettingsController,
 		gobject.SIGNAL_RUN_LAST, gobject.TYPE_BOOLEAN,
 		(gobject.TYPE_STRING, gobject.TYPE_INT))
 
+# Arguments: Alternative-category
+gobject.signal_new("alternatives-changed", SettingsController,
+		gobject.SIGNAL_RUN_LAST, gobject.TYPE_BOOLEAN,
+		(gobject.TYPE_STRING, ))
+
 _settings_controller = None
 def GetSettingsController():
 	global _settings_controller
diff --git a/kupfer/desktop_launch.py b/kupfer/desktop_launch.py
index 6df1a5b..965a7d9 100644
--- a/kupfer/desktop_launch.py
+++ b/kupfer/desktop_launch.py
@@ -305,14 +305,14 @@ def launch_app_info(app_info, gfiles=[], in_terminal=None, timestamp=None,
 		in_terminal = desktop_info["Terminal"]
 	if in_terminal:
 		term = terminal.get_configured_terminal()
-		notify = notify or term.startup_notify
+		notify = notify or term["startup_notify"]
 
 	for argv, gfiles in launch_records:
 		if in_terminal:
 			term = terminal.get_configured_terminal()
-			targv = list(term.argv)
-			if term.exearg:
-				targv.append(term.exearg)
+			targv = list(term["argv"])
+			if term["exearg"]:
+				targv.append(term["exearg"])
 			argv = targv + argv
 		ret = spawn_app(app_info, argv, gfiles, workdir, notify,
 		                timestamp=timestamp, launch_cb=launch_cb)
diff --git a/kupfer/plugin/core/__init__.py b/kupfer/plugin/core/__init__.py
index c8f5df9..bc8a951 100644
--- a/kupfer/plugin/core/__init__.py
+++ b/kupfer/plugin/core/__init__.py
@@ -22,6 +22,7 @@ from kupfer import commandexec
 from kupfer import interface
 from kupfer import pretty
 from kupfer import task
+from kupfer import plugin_support
 
 
 def _is_debug():
@@ -40,7 +41,8 @@ def register_subplugin(module):
 		globals()[attr] += object_names
 		globals().update((sym, getattr(module, sym)) for sym in object_names)
 
-from kupfer.plugin.core import contents, selection, text, internal, commands
+from kupfer.plugin.core import (contents, selection, text, internal, commands,
+                                terminals)
 
 register_subplugin(contents)
 register_subplugin(selection)
diff --git a/kupfer/plugin/core/terminals.py b/kupfer/plugin/core/terminals.py
new file mode 100644
index 0000000..3e1c9ca
--- /dev/null
+++ b/kupfer/plugin/core/terminals.py
@@ -0,0 +1,46 @@
+from kupfer import plugin_support
+
+plugin_support.register_alternative(__name__, 'terminal', 'gnome-terminal',
+		**{
+			'name': _("GNOME Terminal"),
+			'argv': ['gnome-terminal'],
+			'exearg': '-x',
+			'desktopid': "gnome-terminal.desktop",
+			'startup_notify': True,
+		})
+
+plugin_support.register_alternative(__name__, 'terminal', 'xfce4-terminal',
+		**{
+			'name': _("XFCE Terminal"),
+			'argv': ['xfce4-terminal'],
+			'exearg': '-x',
+			'desktopid': "xfce4-terminal.desktop",
+			'startup_notify': True,
+		})
+
+plugin_support.register_alternative(__name__, 'terminal', 'lxterminal',
+		**{
+			'name': _("LXTerminal"),
+			'argv': ['lxterminal'],
+			'exearg': '-e',
+			'desktopid': "lxterminal.desktop",
+			'startup_notify': False,
+		})
+
+plugin_support.register_alternative(__name__, 'terminal', 'xterm',
+		**{
+			'name': _("X Terminal"),
+			'argv': ['xterm'],
+			'exearg': '-e',
+			'desktopid': "xterm.desktop",
+			'startup_notify': False,
+		})
+
+plugin_support.register_alternative(__name__, 'terminal', 'urxvt',
+		**{
+			'name': _("Urxvt"),
+			'argv': ['urxvt'],
+			'exearg': '-e',
+			'desktopid': "urxvt.desktop",
+			'startup_notify': False,
+		})
diff --git a/kupfer/plugin_support.py b/kupfer/plugin_support.py
index 11d1e5b..a6ed9e9 100644
--- a/kupfer/plugin_support.py
+++ b/kupfer/plugin_support.py
@@ -1,3 +1,5 @@
+import os
+
 import gobject
 
 try:
@@ -184,24 +186,44 @@ if not keyring:
 def _plugin_configuration_error(plugin, err):
 	pretty.print_error(__name__, err)
 
+
+def _is_valid_terminal(term_dict):
+	if len(term_dict["argv"]) < 1:
+		return False
+	exe = term_dict["argv"][0]
+	# iterate over $PATH directories
+	PATH = os.environ.get("PATH") or os.defpath
+	for execdir in PATH.split(os.pathsep):
+		exepath = os.path.join(execdir, exe)
+		if os.access(exepath, os.R_OK|os.X_OK) and os.path.isfile(exepath):
+			return True
+
 _available_alternatives = {
 	"terminal": {
-		"constructor": terminal.Terminal,
-		"registrator": terminal.register_terminal,
-		"unregistrator": terminal.unregister_terminal,
-		"key": "terminal",
+		"filter": _is_valid_terminal,
+		"required_keys": {
+			'name': unicode,
+			'argv': list,
+			'exearg': str,
+			'desktopid': str,
+			'startup_notify': bool,
+			},
+		},
 	}
+
+_alternatives = {
+	"terminal": {},
 }
 
-def register_alternative(caller, category_key, id_, *arguments, **kwargs):
+
+def register_alternative(caller, category_key, id_, **kwargs):
 	"""
 	Register a new alternative for the category @category_key
 
 	@caller: Must be the caller's plugin id (Plugin __name__ variable)
 
 	@id_ is a string identifier for the object to register
-	All the @arguments are passed to the alternative constructor
-	All @kwargs are ignored at the moment.
+	@kwargs are the keyed arguments for the alternative constructor
 
 	Returns True with success
 	"""
@@ -215,17 +237,20 @@ def register_alternative(caller, category_key, id_, *arguments, **kwargs):
 		return
 	alt = _available_alternatives[category_key]
 	id_ = caller + "." + id_
-	try:
-		alt_obj = alt["constructor"](*arguments)
-		alt["registrator"](id_, alt_obj)
-	except Exception as exc:
+	kw_set = set(kwargs)
+	req_set = set(alt["required_keys"])
+	if not req_set.issubset(kw_set):
 		_plugin_configuration_error(caller,
 			"Configuration error for alternative '%s':" % category_key)
-		_plugin_configuration_error(caller, exc)
+		_plugin_configuration_error(caller, "Missing keys: %s" %
+				(req_set - kw_set))
 		return
+	_alternatives[category_key][id_] = kwargs
 	pretty.print_debug(__name__,
 		"Registered alternative %s.%s from %s" % (category_key, id_, caller))
-
+	setctl = settings.GetSettingsController()
+	setctl._update_alternatives(category_key, _alternatives[category_key],
+	                            alt["filter"])
 	return True
 
 def unregister_alternative(caller, category_key, id_):
@@ -242,11 +267,16 @@ def unregister_alternative(caller, category_key, id_):
 	alt = _available_alternatives[category_key]
 	id_ = caller + "." + id_
 	try:
-		alt["unregistrator"](id_)
+		del _alternatives[category_key][id_]
 	except KeyError:
 		_plugin_configuration_error(caller,
 				"Alternative '%s' does not exist" % (id_, ))
 		return
 	pretty.print_debug(__name__,
 		"Unregistered alternative %s.%s from %s" % (category_key, id_, caller))
+	setctl = settings.GetSettingsController()
+	setctl._update_alternatives(category_key, _alternatives[category_key],
+	                            alt["filter"])
 	return True
+
+
diff --git a/kupfer/terminal.py b/kupfer/terminal.py
index a6c5fef..d7d076a 100644
--- a/kupfer/terminal.py
+++ b/kupfer/terminal.py
@@ -1,77 +1,17 @@
-import os
-
-_TERMINALS = {}
-
-class Terminal (object):
-	"""
-	@id_ should be unique and if possible the
-	application id
-	"""
-	def __init__(self, name, argv, exearg, id_, startup_notify=False):
-		self.name = unicode(name)
-		self.argv = list(argv)
-		self.exearg = str(exearg)
-		self.startup_notify = bool(startup_notify)
-		self.app_id = str(id_)
-	def __unicode__(self):
-		return self.name
-	def get_id(self):
-		return self.app_id
-
-def register_terminal(id_, terminal_description):
-	"""Register @terminal_description (can be used by plugins)"""
-	_TERMINALS[id_] = terminal_description
-
-def unregister_terminal(terminal_id):
-	_TERMINALS.pop(terminal_id, None)
+from kupfer.core import settings
 
 def is_known_terminal_executable(exearg):
-	"Return True if @exearg is a known terminal"
-	for term in _TERMINALS.itervalues():
-		if exearg == term.argv[0]:
+	setctl = settings.GetSettingsController()
+	for id_, term in setctl.get_all_alternatives('terminal').iteritems():
+		if exearg == term["argv"][0]:
 			return True
 	return False
 
-def get_valid_terminals():
-	""" Yield (identifier, unicode name) tuples """
-	for id_, term in _TERMINALS.iteritems():
-		# iterate over $PATH directories
-		PATH = os.environ.get("PATH") or os.defpath
-		for execdir in PATH.split(os.pathsep):
-			exepath = os.path.join(execdir, term.argv[0])
-			if os.access(exepath, os.R_OK|os.X_OK) and os.path.isfile(exepath):
-				yield (id_, unicode(term))
-				break
 
 def get_configured_terminal():
 	"""
 	Return the configured Terminal object
 	"""
-	from kupfer.core import settings
 	setctl = settings.GetSettingsController()
-	id_ = setctl.get_preferred_tool('terminal')
-	return _TERMINALS.get(id_) or _TERMINALS["default"]
-
-# Insert default terminals
-
-register_terminal("gnome-terminal",
-                  Terminal(_("GNOME Terminal"), ["gnome-terminal"],
-                  "-x", "gnome-terminal.desktop", True))
-
-register_terminal("xfce4-terminal",
-                  Terminal(_("XFCE Terminal"), ["xfce4-terminal"],
-                  "-x", "xfce4-terminal.desktop", True))
-
-register_terminal("urxvt",
-                  Terminal(_("Urxvt"), ["urxvt"],
-                  "-e", "urxvt.desktop", False))
-
-register_terminal("lxterminal",
-                  Terminal(_("LXTerminal"), ["lxterminal"],
-                  "-e", "lxterminal.desktop", False))
-
-register_terminal("default",
-                  Terminal(_("X Terminal"), ["xterm"],
-                  "-e", "xterm.desktop", False))
-
+	return setctl.get_preferred_alternative('terminal')
 
diff --git a/kupfer/ui/preferences.py b/kupfer/ui/preferences.py
index 8c1472d..2528190 100644
--- a/kupfer/ui/preferences.py
+++ b/kupfer/ui/preferences.py
@@ -127,17 +127,11 @@ class PreferencesWindowController (pretty.OutputMixin):
 		terminal_combobox.pack_start(terminal_combobox_cell, True)
 		terminal_combobox.add_attribute(terminal_combobox_cell, 'text', 0)
 
-		term_id = setctl.get_preferred_tool('terminal')
-		# fill in the available terminals
-		terminals = utils.locale_sort(terminal.get_valid_terminals(),
-		                              key=lambda t:t[1])
-		term_iter = None
-		for (id_, name) in terminals:
-			_it = terminal_combobox_store.append((name, id_))
-			if id_ == term_id:
-				term_iter = _it
-		term_iter = term_iter or terminal_combobox_store.get_iter_first()
-		terminal_combobox.set_active_iter(term_iter)
+		self._update_terminal_combobox(terminal_combobox,
+		                               terminal_combobox_store)
+		self.terminal_combobox = terminal_combobox
+		self.terminal_combobox_store = terminal_combobox_store
+		setctl.connect("alternatives-changed", self._on_alternatives_changed)
 
 		# Plugin List
 		columns = [
@@ -766,8 +760,36 @@ class PreferencesWindowController (pretty.OutputMixin):
 	def on_terminal_combobox_changed(self, widget):
 		setctl = settings.GetSettingsController()
 		itr = widget.get_active_iter()
-		term_id = widget.get_model().get_value(itr, 1)
-		setctl.set_preferred_tool('terminal', term_id)
+		if itr:
+			term_id = widget.get_model().get_value(itr, 1)
+			setctl.set_preferred_tool('terminal', term_id)
+
+	def _update_terminal_combobox(self, combobox, combobox_store):
+		"""
+		Terminals changed
+		"""
+		print "_update_terminal_combobox"
+		combobox_store.clear()
+		setctl = settings.GetSettingsController()
+		term_id = setctl.get_preferred_tool('terminal')
+		print term_id
+		# fill in the available terminals
+		terminals = utils.locale_sort(
+				setctl.get_valid_alternative_ids('terminal'), key=lambda t:t[1])
+		term_iter = None
+		for (id_, name) in terminals:
+			_it = combobox_store.append((name, id_))
+			if id_ == term_id:
+				term_iter = _it
+		# Update selection
+		term_iter = term_iter or combobox_store.get_iter_first()
+		combobox.set_active_iter(term_iter)
+
+	def _on_alternatives_changed(self, setctl, category_key):
+		if category_key == 'terminal':
+			self._update_terminal_combobox(
+					self.terminal_combobox,
+					self.terminal_combobox_store)
 
 	def show(self):
 		self.window.present()
diff --git a/kupfer/utils.py b/kupfer/utils.py
index 50b25c3..6dba507 100644
--- a/kupfer/utils.py
+++ b/kupfer/utils.py
@@ -182,17 +182,19 @@ class AsyncCommand (object):
 
 def spawn_terminal(workdir=None):
 	term = terminal.get_configured_terminal()
-	notify = term.startup_notify
-	desktop_launch.spawn_app_id(term.app_id, term.argv, workdir, notify)
+	notify = term["startup_notify"]
+	app_id = term["desktopid"]
+	argv = term["argv"]
+	desktop_launch.spawn_app_id(app_id, argv, workdir, notify)
 
 def spawn_in_terminal(argv, workdir=None):
 	term = terminal.get_configured_terminal()
-	notify = term.startup_notify
-	_argv = list(term.argv)
-	if term.exearg:
-		_argv.append(term.exearg)
+	notify = term["startup_notify"]
+	_argv = list(term["argv"])
+	if term["exearg"]:
+		_argv.append(term["exearg"])
 	_argv.extend(argv)
-	desktop_launch.spawn_app_id(term.app_id, _argv , workdir, notify)
+	desktop_launch.spawn_app_id(term["desktopid"], _argv , workdir, notify)
 
 def spawn_async_notify_as(app_id, argv):
 	"""



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]