gtg-user team mailing list archive
-
gtg-user team
-
Mailing list archive
-
Message #00437
[Merge] lp:~gtg-user/gtg/plugins-preferences-separation into lp:gtg
Izidor Matušov has proposed merging lp:~gtg-user/gtg/plugins-preferences-separation into lp:gtg.
Requested reviews:
Bertrand Rousseau (bertrand-rousseau)
Related bugs:
Bug #965955 in Getting Things GNOME!: "Move plugins to Edit menu"
https://bugs.launchpad.net/gtg/+bug/965955
For more details, see:
https://code.launchpad.net/~gtg-user/gtg/plugins-preferences-separation/+merge/108265
Move Plugins dialog into Edit menu. I also cleaned the code a little bit. A little problem is that moving Plugins into a standalone dialogs from Gtk.Notebook creates weird looking dialogs. See the screenshots. Little playing with GLADE should solve that, patches are welcomed!
--
https://code.launchpad.net/~gtg-user/gtg/plugins-preferences-separation/+merge/108265
Your team Gtg users is subscribed to branch lp:~gtg-user/gtg/plugins-preferences-separation.
=== modified file 'GTG/gtk/__init__.py'
--- GTG/gtk/__init__.py 2012-03-17 02:20:46 +0000
+++ GTG/gtk/__init__.py 2012-06-01 00:18:21 +0000
@@ -26,4 +26,5 @@
current_rep = os.path.dirname(os.path.abspath(__file__))
DELETE_GLADE_FILE = os.path.join(current_rep, "deletion.glade")
PREFERENCES_GLADE_FILE = os.path.join(current_rep, "preferences.glade")
+ PLUGINS_GLADE_FILE = os.path.join(current_rep, "plugins.glade")
BACKENDS_GLADE_FILE = os.path.join(current_rep, "backends_dialog.glade")
=== modified file 'GTG/gtk/browser/browser.py'
--- GTG/gtk/browser/browser.py 2012-05-24 11:48:45 +0000
+++ GTG/gtk/browser/browser.py 2012-06-01 00:18:21 +0000
@@ -333,6 +333,8 @@
lambda w: openurl(info.REPORT_BUG_URL),
"on_preferences_activate":
self.open_preferences,
+ "on_edit_plugins_activate":
+ self.open_plugins,
"on_edit_backends_activate":
self.open_edit_backends,
}
@@ -401,6 +403,9 @@
def open_preferences(self, widget):
self.vmanager.open_preferences(self.config)
+ def open_plugins(self, widget):
+ self.vmanager.configure_plugins()
+
def open_edit_backends(self, widget):
self.vmanager.open_edit_backends()
=== modified file 'GTG/gtk/browser/taskbrowser.glade'
--- GTG/gtk/browser/taskbrowser.glade 2012-05-27 18:20:57 +0000
+++ GTG/gtk/browser/taskbrowser.glade 2012-06-01 00:18:21 +0000
@@ -187,11 +187,22 @@
</object>
</child>
<child>
+ <object class="GtkMenuItem" id="plugins_mi">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="label">P_lugins</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_edit_plugins_activate" swapped="no"/>
+ </object>
+ </child>
+ <child>
<object class="GtkMenuItem" id="backends_mi">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
- <property name="label">Setup Sync. Services</property>
+ <property name="label">_Synchronization Services</property>
+ <property name="use_underline">True</property>
<signal name="activate" handler="on_edit_backends_activate" swapped="no"/>
</object>
</child>
=== modified file 'GTG/gtk/manager.py'
--- GTG/gtk/manager.py 2012-05-03 22:05:05 +0000
+++ GTG/gtk/manager.py 2012-06-01 00:18:21 +0000
@@ -34,6 +34,7 @@
from GTG.gtk.browser.browser import TaskBrowser
from GTG.gtk.editor.editor import TaskEditor
from GTG.gtk.preferences import PreferencesDialog
+from GTG.gtk.plugins import PluginsDialog
from GTG.gtk.dbuswrapper import DBusTaskWrapper
from GTG.tools import clipboard
from GTG.core.plugins.engine import PluginEngine
@@ -83,7 +84,8 @@
#Preferences and Backends windows
# Initialize dialogs
- self.preferences_dialog = None
+ self.preferences = PreferencesDialog(self.req)
+ self.plugins = PluginsDialog(self.config_obj)
self.edit_backends_dialog = None
# Tag Editor
@@ -224,10 +226,11 @@
def configure_backend(self, backend_id):
self.open_edit_backends(None, backend_id)
- def open_preferences(self, config_priv, sender=None):
- if not hasattr(self, "preferences"):
- self.preferences = PreferencesDialog(self.config_obj, self.req)
- self.preferences.activate(config_priv)
+ def open_preferences(self, config_priv):
+ self.preferences.activate()
+
+ def configure_plugins(self):
+ self.plugins.activate()
def ask_delete_tasks(self, tids):
if not self.delete_dialog:
=== added file 'GTG/gtk/plugins.glade'
--- GTG/gtk/plugins.glade 1970-01-01 00:00:00 +0000
+++ GTG/gtk/plugins.glade 2012-06-01 00:18:21 +0000
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAboutDialog" id="PluginAboutDialog">
+ <property name="border_width">5</property>
+ <property name="window_position">mouse</property>
+ <property name="type_hint">dialog</property>
+ <signal name="close" handler="on_PluginAboutDialog_close"/>
+ <signal name="response" handler="on_PluginAboutDialog_close"/>
+ <signal name="delete-event" handler="on_PluginAboutDialog_close" swapped="no"/>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="pa-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkFrame" id="pa-frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="pa-alignment1">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkLabel" id="PluginDepends">
+ <property name="visible">True</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="pa-label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Dependencies</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="pa-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkDialog" id="PluginsDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Plugins - Getting Things GNOME!</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="default_width">500</property>
+ <property name="default_height">500</property>
+ <property name="type_hint">dialog</property>
+ <signal name="delete-event" handler="on_PluginsDialog_delete_event" swapped="no"/>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="plugins_help">
+ <property name="label">gtk-help</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="released" handler="on_plugins_help" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="plugins_close">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="released" handler="on_plugins_close" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="plugins-vbox6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="plugins-label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>Available Plugins</b></property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="plugins-scrolledwindow2">
+ <property name="width_request">240</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="PluginTree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">True</property>
+ <property name="show_expanders">False</property>
+ <signal name="cursor_changed" handler="on_PluginTree_cursor_changed"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="plugins-hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="plugin_about">
+ <property name="label" translatable="yes">_About Plugin</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="image">img_plugin_about</property>
+ <signal name="released" handler="on_plugin_about"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="plugin_configure">
+ <property name="label">C_onfigure Plugin</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="image">img_plugin_conf</property>
+ <signal name="released" handler="on_plugin_configure"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">plugins_help</action-widget>
+ <action-widget response="0">plugins_close</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkImage" id="img_plugin_about">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-about</property>
+ </object>
+ <object class="GtkImage" id="img_plugin_conf">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-preferences</property>
+ </object>
+</interface>
=== added file 'GTG/gtk/plugins.py'
--- GTG/gtk/plugins.py 1970-01-01 00:00:00 +0000
+++ GTG/gtk/plugins.py 2012-06-01 00:18:21 +0000
@@ -0,0 +1,319 @@
+# -*- coding: utf-8 -*-
+# -----------------------------------------------------------------------------
+# Gettings Things Gnome! - a personal organizer for the GNOME desktop
+# Copyright (c) 2008-2012 - Lionel Dricot & Bertrand Rousseau
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+# -----------------------------------------------------------------------------
+
+""" Dialog for configuring plugins """
+
+import gtk
+import pango
+
+from GTG.core.plugins import GnomeConfig
+from GTG.core.plugins.engine import PluginEngine
+from GTG.gtk import ViewConfig
+
+# columns in PluginsDialog.plugin_store
+PLUGINS_COL_ID = 0
+PLUGINS_COL_ENABLED = 1
+PLUGINS_COL_NAME = 2
+PLUGINS_COL_SHORT_DESC = 3
+PLUGINS_COL_ACTIVATABLE = 4
+
+
+def plugin_icon(column, cell, store, iterator): # pylint: disable-msg=W0613
+ """ Callback to set the content of a PluginTree cell.
+
+ See PluginsDialog._init_plugin_tree().
+ """
+ cell.set_property('icon-name', 'gtg-plugin')
+ cell.set_property('sensitive',
+ store.get_value(iterator, PLUGINS_COL_ACTIVATABLE))
+
+
+def plugin_error_short_text(plugin):
+ """ Return small version of description of missing module dependencies
+ for displaying in plugin markup """
+ if not plugin.error:
+ return ""
+
+ # get lists
+ modules = plugin.missing_modules
+ dbus = plugin.missing_dbus
+
+ # convert to strings
+ if modules:
+ modules = "<small><b>%s</b></small>" % ', '.join(modules)
+ if dbus:
+ ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
+ dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
+
+ # combine
+ if modules and not dbus:
+ text = '\n'.join((GnomeConfig.miss2, modules))
+ elif dbus and not modules:
+ text = '\n'.join((GnomeConfig.dmiss2, dbus))
+ elif modules and dbus:
+ text = '\n'.join((GnomeConfig.bmiss2, modules, dbus))
+ else:
+ text = ""
+
+ return text
+
+
+def plugin_error_text(plugin):
+ """ Generate some helpful text about missing module dependencies. """
+ if not plugin.error:
+ return GnomeConfig.CANLOAD
+
+ # describe missing dependencies
+ text = "<b>%s</b>. \n" % GnomeConfig.CANNOTLOAD
+ # get lists
+ modules = plugin.missing_modules
+ dbus = plugin.missing_dbus
+
+ # convert to strings
+ if modules:
+ modules = "<small><b>%s</b></small>" % ', '.join(modules)
+ if dbus:
+ ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
+ dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
+
+ # combine
+ if modules and not dbus:
+ text += '\n'.join((GnomeConfig.MODULEMISSING, modules))
+ elif dbus and not modules:
+ text += '\n'.join((GnomeConfig.DBUSMISSING, dbus))
+ elif modules and dbus:
+ text += '\n'.join((GnomeConfig.MODULANDDBUS, modules, dbus))
+ else:
+ text += GnomeConfig.UNKNOWN
+
+ return text
+
+
+def plugin_markup(column, cell, store, iterator, self):
+ # pylint: disable-msg=W0613
+ """ Callback to set the content of a PluginTree cell.
+
+ See PluginsDialog._init_plugin_tree().
+ """
+ name = store.get_value(iterator, PLUGINS_COL_NAME)
+ desc = store.get_value(iterator, PLUGINS_COL_SHORT_DESC)
+
+ plugin_id = store.get_value(iterator, PLUGINS_COL_ID)
+ plugin = self.pengine.get_plugin(plugin_id)
+ error_text = plugin_error_short_text(plugin)
+ if error_text != "":
+ text = "<b>%s</b>\n%s\n<i>%s</i>" % (name, desc, error_text)
+ else:
+ text = "<b>%s</b>\n%s" % (name, desc)
+
+ cell.set_property('markup', text)
+ cell.set_property('sensitive',
+ store.get_value(iterator, PLUGINS_COL_ACTIVATABLE))
+
+
+class PluginsDialog:
+ """ Dialog for Plugins configuration """
+ # pylint: disable-msg=R0902
+ def __init__(self, config_obj):
+ self.config_obj = config_obj
+ self.config = self.config_obj.conf_dict
+ builder = gtk.Builder()
+ builder.add_from_file(ViewConfig.PLUGINS_GLADE_FILE)
+
+ self.dialog = builder.get_object("PluginsDialog")
+ self.plugin_tree = builder.get_object("PluginTree")
+ self.plugin_configure = builder.get_object("plugin_configure")
+ self.plugin_about = builder.get_object("PluginAboutDialog")
+ self.plugin_depends = builder.get_object('PluginDepends')
+
+ self.pengine = PluginEngine()
+ #plugin config initiation, if never used
+ if "plugins" in self.config:
+ if "enabled" not in self.config["plugins"]:
+ self.config["plugins"]["enabled"] = []
+
+ if "disabled" not in self.config["plugins"]:
+ self.config["plugins"]["disabled"] = []
+ elif self.pengine.get_plugins():
+ self.config["plugins"] = {}
+ self.config["plugins"]["disabled"] = \
+ [p.module_name for p in self.pengine.get_plugins("disabled")]
+ self.config["plugins"]["enabled"] = \
+ [p.module_name for p in self.pengine.get_plugins("enabled")]
+
+ # see constants PLUGINS_COL_* for column meanings
+ self.plugin_store = gtk.ListStore(str, bool, str, str, bool)
+
+ builder.connect_signals({
+ 'on_plugins_help':
+ self.on_help,
+ 'on_plugins_close':
+ self.on_close,
+ 'on_PluginsDialog_delete_event':
+ self.on_close,
+ 'on_PluginTree_cursor_changed':
+ self.on_plugin_select,
+ 'on_plugin_about':
+ self.on_plugin_about,
+ 'on_plugin_configure':
+ self.on_plugin_configure,
+ 'on_PluginAboutDialog_close':
+ self.on_plugin_about_close,
+ })
+
+ def _init_plugin_tree(self):
+ """ Initialize the PluginTree gtk.TreeView.
+
+ The format is modelled after the one used in gedit; see
+ http://git.gnome.org/browse/gedit/tree/gedit/gedit-plugin-mapnager.c
+ """
+ # force creation of the gtk.ListStore so we can reference it
+ self._refresh_plugin_store()
+
+ # renderer for the toggle column
+ renderer = gtk.CellRendererToggle()
+ renderer.set_property('xpad', 6)
+ renderer.connect('toggled', self.on_plugin_toggle)
+ # toggle column
+ column = gtk.TreeViewColumn(None, renderer, active=PLUGINS_COL_ENABLED,
+ activatable=PLUGINS_COL_ACTIVATABLE,
+ sensitive=PLUGINS_COL_ACTIVATABLE)
+ self.plugin_tree.append_column(column)
+
+ # plugin name column
+ column = gtk.TreeViewColumn()
+ column.set_spacing(6)
+ # icon renderer for the plugin name column
+ icon_renderer = gtk.CellRendererPixbuf()
+ icon_renderer.set_property('stock-size', gtk.ICON_SIZE_SMALL_TOOLBAR)
+ icon_renderer.set_property('xpad', 3)
+ column.pack_start(icon_renderer, expand=False)
+ column.set_cell_data_func(icon_renderer, plugin_icon)
+ # text renderer for the plugin name column
+ name_renderer = gtk.CellRendererText()
+ name_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
+ column.pack_start(name_renderer)
+ column.set_cell_data_func(name_renderer, plugin_markup, self)
+
+ self.plugin_tree.append_column(column)
+
+ # finish setup
+ self.plugin_tree.set_model(self.plugin_store)
+ self.plugin_tree.set_search_column(2)
+
+ def _refresh_plugin_store(self):
+ """ Refresh status of plugins and put it in a gtk.ListStore """
+ self.plugin_store.clear()
+ self.pengine.recheck_plugin_errors(True)
+ for name, plugin in self.pengine.plugins.iteritems():
+ # activateable if there is no error
+ self.plugin_store.append((name, plugin.enabled, plugin.full_name,
+ plugin.short_description, not plugin.error))
+
+ def activate(self):
+ """ Refresh status of plugins and show the dialog """
+ if len(self.plugin_tree.get_columns()) == 0:
+ self._init_plugin_tree()
+ else:
+ self._refresh_plugin_store()
+ self.dialog.show_all()
+
+ def on_close(self, widget, data=None): # pylint: disable-msg=W0613
+ """ Close the plugins dialog."""
+ self.dialog.hide()
+ return True
+
+ @classmethod
+ def on_help(cls, widget): # pylint: disable-msg=W0613
+ """ In future, this will open help for plugins """
+ return True
+
+ def on_plugin_toggle(self, widget, path): # pylint: disable-msg=W0613
+ """Toggle a plugin enabled/disabled."""
+ iterator = self.plugin_store.get_iter(path)
+ plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
+ plugin = self.pengine.get_plugin(plugin_id)
+ plugin.enabled = not self.plugin_store.get_value(iterator,
+ PLUGINS_COL_ENABLED)
+ if plugin.enabled:
+ self.pengine.activate_plugins([plugin])
+ self.config["plugins"]["enabled"].append(plugin.module_name)
+ if plugin.module_name in self.config["plugins"]["disabled"]:
+ self.config["plugins"]["disabled"].remove(plugin.module_name)
+ else:
+ self.pengine.deactivate_plugins([plugin])
+ self.config["plugins"]["disabled"].append(plugin.module_name)
+ if plugin.module_name in self.config["plugins"]["enabled"]:
+ self.config["plugins"]["enabled"].remove(plugin.module_name)
+ self.plugin_store.set_value(iterator, PLUGINS_COL_ENABLED,
+ plugin.enabled)
+ self._update_plugin_configure(plugin)
+
+ self.config_obj.save()
+
+ def on_plugin_select(self, plugin_tree):
+ """ Callback when user select/unselect a plugin
+
+ Update the button "Configure plugin" sensitivity """
+ model, iterator = plugin_tree.get_selection().get_selected()
+ if iterator is not None:
+ plugin_id = model.get_value(iterator, PLUGINS_COL_ID)
+ plugin = self.pengine.get_plugin(plugin_id)
+ self._update_plugin_configure(plugin)
+
+ def _update_plugin_configure(self, plugin):
+ """ Enable the button "Configure Plugin" appropriate. """
+ configurable = plugin.active and plugin.is_configurable()
+ self.plugin_configure.set_property('sensitive', configurable)
+
+ def on_plugin_configure(self, widget): # pylint: disable-msg=W0613
+ """ Show the dialog for plugin configuration """
+ _, iterator = self.plugin_tree.get_selection().get_selected()
+ if iterator is None:
+ return
+ plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
+ plugin = self.pengine.get_plugin(plugin_id)
+ plugin.instance.configure_dialog(self.dialog)
+
+ def on_plugin_about(self, widget): # pylint: disable-msg=W0613
+ """ Display information about a plugin. """
+ _, iterator = self.plugin_tree.get_selection().get_selected()
+ if iterator is None:
+ return
+ plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
+ plugin = self.pengine.get_plugin(plugin_id)
+
+ self.plugin_about.set_name(plugin.full_name)
+ self.plugin_about.set_version(plugin.version)
+ authors = plugin.authors
+ if isinstance(authors, str):
+ authors = "\n".join(author.strip()
+ for author in authors.split(','))
+ authors = [authors, ]
+ self.plugin_about.set_authors(authors)
+ description = plugin.description.replace(r'\n', "\n")
+ self.plugin_about.set_comments(description)
+ self.plugin_depends.set_label(plugin_error_text(plugin))
+ self.plugin_about.show_all()
+
+ def on_plugin_about_close(self, widget, data=None):
+ # pylint: disable-msg=W0613
+ """ Close the PluginAboutDialog. """
+ self.plugin_about.hide()
+ return True
=== modified file 'GTG/gtk/preferences.glade'
--- GTG/gtk/preferences.glade 2012-05-24 11:48:45 +0000
+++ GTG/gtk/preferences.glade 2012-06-01 00:18:21 +0000
@@ -1,376 +1,34 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkAccelGroup" id="accelgroup1"/>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="stock">gtk-save-as</property>
- </object>
<object class="GtkDialog" id="PreferencesDialog">
+ <property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Preferences - Getting Things GNOME!</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">500</property>
<property name="default_height">500</property>
<property name="type_hint">dialog</property>
- <signal name="delete_event" handler="on_PreferencesDialog_delete_event"/>
+ <signal name="delete-event" handler="on_PreferencesDialog_delete_event" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="prefs-vbox1">
<property name="visible">True</property>
- <child>
- <object class="GtkAlignment" id="prefs-alignment1">
- <property name="visible">True</property>
- <property name="top_padding">6</property>
- <property name="bottom_padding">6</property>
- <property name="left_padding">6</property>
- <property name="right_padding">6</property>
- <child>
- <object class="GtkNotebook" id="prefs-notebook1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child>
- <object class="GtkAlignment" id="prefs-alignment2">
- <property name="visible">True</property>
- <property name="top_padding">10</property>
- <property name="bottom_padding">10</property>
- <property name="left_padding">10</property>
- <property name="right_padding">10</property>
- <child>
- <object class="GtkVBox" id="prefs-vbox2">
- <property name="visible">True</property>
- <child>
- <object class="GtkFrame" id="prefs-frame3">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="prefs-alignment7">
- <property name="visible">True</property>
- <property name="bottom_padding">15</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkVBox" id="prefs-vbox7">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="pref_autostart">
- <property name="label" translatable="yes">Start Getting Things GNOME! on every login</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_pref_autostart_toggled"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="padding">3</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="prefs-label8">
- <property name="visible">True</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes"><b>Startup</b></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="prefs-frame1">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="prefs-alignment5">
- <property name="visible">True</property>
- <property name="bottom_padding">15</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkVBox" id="prefs-vbox3">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="pref_show_preview">
- <property name="label" translatable="yes">Show description preview in the task list.</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_pref_show_preview_toggled"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="padding">3</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="bg_color_enable">
- <property name="label" translatable="yes">Enable colored backgrounds in the task list</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_bg_color_toggled"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="padding">3</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="prefs-hbox1">
- <property name="no_show_all">True</property>
- <child>
- <object class="GtkCheckButton" id="pref_hide_closed">
- <property name="label" translatable="yes">Hide closed tasks older than </property>
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBox" id="pref_hide_closed_age">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="padding">3</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="prefs-label4">
- <property name="visible">True</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes"><b>Task Browser</b></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="prefs-frame2">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="prefs-alignment6">
- <property name="visible">True</property>
- <property name="bottom_padding">15</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkVBox" id="prefs-vbox4">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="pref_check_spelling">
- <property name="label" translatable="yes">Check spelling</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="no_show_all">True</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_pref_check_spelling_toggled"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="padding">3</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="prefs-label5">
- <property name="no_show_all">True</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes"><b>Task Editor</b></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="prefs-label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">General</property>
- </object>
- <packing>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <object class="GtkAlignment" id="prefs-alignment4">
- <property name="visible">True</property>
- <property name="top_padding">10</property>
- <property name="bottom_padding">10</property>
- <property name="left_padding">10</property>
- <property name="right_padding">10</property>
- <child>
- <object class="GtkVBox" id="prefs-vbox6">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="prefs-label7">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Active _Plugins:</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="prefs-scrolledwindow2">
- <property name="width_request">240</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="PluginTree">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- <property name="rules_hint">True</property>
- <property name="show_expanders">False</property>
- <signal name="cursor_changed" handler="on_PluginTree_cursor_changed"/>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkHButtonBox" id="prefs-hbuttonbox1">
- <property name="visible">True</property>
- <property name="spacing">8</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="plugin_about">
- <property name="label" translatable="yes">_About Plugin</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">pref_img_plugin_about</property>
- <property name="use_underline">True</property>
- <signal name="released" handler="on_plugin_about"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="plugin_configure">
- <property name="label">C_onfigure Plugin</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">pref_img_plugin_conf</property>
- <property name="use_underline">True</property>
- <signal name="released" handler="on_plugin_configure"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="prefs-label3">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Plugins</property>
- </object>
- <packing>
- <property name="position">2</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="can_focus">False</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="prefs-action_area">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="prefs_help">
<property name="label">gtk-help</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
<property name="no_show_all">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
- <signal name="activate" handler="on_prefs_help"/>
+ <signal name="activate" handler="on_prefs_help" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -384,8 +42,9 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
- <signal name="released" handler="on_prefs_close"/>
+ <signal name="released" handler="on_prefs_close" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -396,10 +55,145 @@
</object>
<packing>
<property name="expand">False</property>
+ <property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkVBox" id="prefs-vbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkFrame" id="prefs-frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="prefs-alignment7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="bottom_padding">15</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="prefs-vbox7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="pref_autostart">
+ <property name="label" translatable="yes">Start Getting Things GNOME! on every login</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_pref_autostart_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">3</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="prefs-label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="ypad">5</property>
+ <property name="label" translatable="yes"><b>Startup</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="prefs-frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="prefs-alignment5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="bottom_padding">15</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="prefs-vbox3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="pref_show_preview">
+ <property name="label" translatable="yes">Show description preview in the task list.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_pref_show_preview_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">3</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="bg_color_enable">
+ <property name="label" translatable="yes">Enable colored backgrounds in the task list</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_bg_color_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">3</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="prefs-label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="ypad">5</property>
+ <property name="label" translatable="yes"><b>Task Browser</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
</child>
<action-widgets>
@@ -407,113 +201,4 @@
<action-widget response="0">prefs_close</action-widget>
</action-widgets>
</object>
- <object class="GtkImage" id="pref_img_plugin_conf">
- <property name="visible">True</property>
- <property name="stock">gtk-preferences</property>
- </object>
- <object class="GtkImage" id="pref_img_plugin_about">
- <property name="visible">True</property>
- <property name="stock">gtk-about</property>
- </object>
- <object class="GtkAboutDialog" id="PluginAboutDialog">
- <property name="border_width">5</property>
- <property name="window_position">mouse</property>
- <property name="type_hint">dialog</property>
- <signal name="close" handler="on_PluginAboutDialog_close"/>
- <signal name="response" handler="on_PluginAboutDialog_close"/>
- <child internal-child="vbox">
- <object class="GtkVBox" id="pa-vbox1">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkFrame" id="pa-frame1">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="pa-alignment1">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkLabel" id="PluginDepends">
- <property name="visible">True</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="pa-label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>Dependencies</b></property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="pa-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <object class="GtkImage" id="pref_img_plugin">
- <property name="visible">True</property>
- <property name="icon_name">gtg-plugin</property>
- </object>
- <object class="GtkDialog" id="PluginConfigDialog">
- <property name="border_width">5</property>
- <property name="window_position">mouse</property>
- <property name="type_hint">dialog</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="pc-vbox1">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <placeholder/>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="pc-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="PluginConfigClose">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- <signal name="released" handler="on_PluginConfigClose_released"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="0">PluginConfigClose</action-widget>
- </action-widgets>
- </object>
</interface>
=== modified file 'GTG/gtk/preferences.py'
--- GTG/gtk/preferences.py 2012-05-27 15:33:03 +0000
+++ GTG/gtk/preferences.py 2012-06-01 00:18:21 +0000
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Gettings Things Gnome! - a personal organizer for the GNOME desktop
-# Copyright (c) 2008-2009 - Lionel Dricot & Bertrand Rousseau
+# Copyright (c) 2008-2012 - Lionel Dricot & Bertrand Rousseau
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
@@ -16,447 +16,132 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
-""" The Preferences Dialog for loading plugins and configuring GTG """
+
+""" The Preferences Dialog for configuring GTG """
+
import os
import shutil
import gtk
-import pango
+from GTG.gtk import ViewConfig
from xdg.BaseDirectory import xdg_config_home
-from GTG import _
-from GTG.core.plugins import GnomeConfig
-from GTG.gtk import ViewConfig
-from GTG.core.plugins.engine import PluginEngine
-
-
-__all__ = [
- 'PreferencesDialog',
- ]
-
-# Default plugin information text
-PLUGINS_DEFAULT_DESC = _("Click on a plugin name to view its description here.")
-
-# columns in PreferencesDialog.plugin_store
-PLUGINS_COL_ID = 0
-PLUGINS_COL_ENABLED = 1
-PLUGINS_COL_NAME = 2
-PLUGINS_COL_SHORT_DESC = 3
-PLUGINS_COL_DESC = 4
-PLUGINS_COL_ACTIVATABLE = 5
-
-def plugin_icon(column, cell, store, iter):
- """Callback to set the content of a PluginTree cell.
-
- See PreferencesDialog._init_plugin_tree().
-
- """
- cell.set_property('icon-name', 'gtg-plugin')
- cell.set_property('sensitive', store.get_value(iter,
- PLUGINS_COL_ACTIVATABLE))
-
-
-def plugin_markup(column, cell, store, iter, self):
- """Callback to set the content of a PluginTree cell.
-
- See PreferencesDialog._init_plugin_tree().
-
- """
- name = store.get_value(iter, PLUGINS_COL_NAME)
- desc = store.get_value(iter, PLUGINS_COL_SHORT_DESC)
- plugin_id = store.get_value(iter, PLUGINS_COL_ID)
- p = self.pengine.get_plugin(plugin_id)
- error_text = plugin_error_short_text(p)
- if error_text != "":
- cell.set_property('markup', "<b>%s</b>\n%s\n<i>%s</i>" % (name, desc, error_text))
- else:
- cell.set_property('markup', "<b>%s</b>\n%s" % (name, desc))
- cell.set_property('sensitive', store.get_value(iter,
- PLUGINS_COL_ACTIVATABLE))
-
-def plugin_error_short_text(plugin):
- """ Return small version of description of missing module dependencies
- for displaying in plugin markup """
- if not plugin.error:
- return ""
-
- # get lists
- modules = plugin.missing_modules
- dbus = plugin.missing_dbus
-
- # convert to strings
- if modules:
- modules = "<small><b>%s</b></small>" % ', '.join(modules)
- if dbus:
- ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
- dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
- # combine
- if modules and not dbus:
- text = '\n'.join((GnomeConfig.miss2, modules))
- elif dbus and not modules:
- text = '\n'.join((GnomeConfig.dmiss2, dbus))
- elif modules and dbus:
- text = '\n'.join((GnomeConfig.bmiss2, modules, dbus))
- else:
- text = ""
- return text
-
-def plugin_error_text(plugin):
- """Generate some helpful text about missing module dependencies."""
- if not plugin.error:
- return GnomeConfig.CANLOAD
- # describe missing dependencies
- text = "<b>%s</b>. \n" % GnomeConfig.CANNOTLOAD
- # get lists
- modules = plugin.missing_modules
- dbus = plugin.missing_dbus
- # convert to strings
- if modules:
- modules = "<small><b>%s</b></small>" % ', '.join(modules)
- if dbus:
- ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
- dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
- # combine
- if modules and not dbus:
- text += '\n'.join((GnomeConfig.MODULEMISSING, modules))
- elif dbus and not modules:
- text += '\n'.join((GnomeConfig.DBUSMISSING, dbus))
- elif modules and dbus:
- text += '\n'.join((GnomeConfig.MODULANDDBUS, modules, dbus))
- else:
- text += GnomeConfig.UNKNOWN
- return text
+AUTOSTART_DIRECTORY = os.path.join(xdg_config_home, "autostart")
+AUTOSTART_FILE = "gtg.desktop"
+AUTOSTART_PATH = os.path.join(AUTOSTART_DIRECTORY, AUTOSTART_FILE)
+
+
+def enable_gtg_autostart():
+ """ Enable autostart
+
+ Firstly, locate gtg.desktop file. Then link it in AUTOSTART_FILE.
+ On Windows, there is no os.symlink, just copy the file. """
+ desktop_file_path = None
+ this_directory = os.path.dirname(os.path.abspath(__file__))
+ for path in ["../..", "../../../applications",
+ "../../../../../share/applications"]:
+ fullpath = os.path.join(this_directory, path, AUTOSTART_FILE)
+ fullpath = os.path.normpath(fullpath)
+ if os.path.isfile(fullpath):
+ desktop_file_path = fullpath
+ break
+
+ if desktop_file_path:
+ if not os.path.exists(AUTOSTART_DIRECTORY):
+ os.mkdir(AUTOSTART_DIRECTORY)
+
+ if os.path.isdir(AUTOSTART_DIRECTORY) and \
+ not os.path.exists(AUTOSTART_PATH):
+ if hasattr(os, "symlink"):
+ os.symlink(desktop_file_path, AUTOSTART_PATH)
+ else:
+ shutil.copyfile(desktop_file_path, AUTOSTART_PATH)
+
+
+def disable_gtg_autostart():
+ """ Disable autostart, removing the file in autostart_path """
+ if os.path.isfile(AUTOSTART_PATH):
+ os.remove(AUTOSTART_PATH)
class PreferencesDialog:
-
- __AUTOSTART_DIRECTORY = os.path.join(xdg_config_home, "autostart")
- __AUTOSTART_FILE = "gtg.desktop"
-
- def __init__(self, config_obj, req):
- """Constructor."""
- self.config_obj = config_obj
+ """ Show preference dialog """
+
+ def __init__(self, req):
self.req = req
- self.config = self.config_obj.conf_dict
- self.builder = gtk.Builder()
- self.builder.add_from_file(ViewConfig.PREFERENCES_GLADE_FILE)
- # store references to some objects
- widgets = {
- 'dialog': 'PreferencesDialog',
- 'backend_tree': 'BackendTree',
- 'plugin_tree': 'PluginTree',
- 'plugin_about_dialog': 'PluginAboutDialog',
- 'plugin_configure': 'plugin_configure',
- 'plugin_depends': 'PluginDepends',
- 'plugin_config_dialog': 'PluginConfigDialog',
- 'pref_autostart': 'pref_autostart',
- 'pref_show_preview': 'pref_show_preview',
- 'bg_color_enable': 'bg_color_enable',
- }
- for attr, widget in widgets.iteritems():
- setattr(self, attr, self.builder.get_object(widget))
- # keep a reference to the parent task browser
- self.pengine = PluginEngine()
- #plugin config initiation, if never used
- if "plugins" in self.config:
- if "enabled" not in self.config["plugins"]:
- self.config["plugins"]["enabled"] = []
-
- if "disabled" not in self.config["plugins"]:
- self.config["plugins"]["disabled"] = []
- elif self.pengine.get_plugins():
- self.config["plugins"] = {}
- self.config["plugins"]["disabled"] = \
- [p.module_name for p in self.pengine.get_plugins("disabled")]
- self.config["plugins"]["enabled"] = \
- [p.module_name for p in self.pengine.get_plugins("enabled")]
- # initialize tree models
- self._init_backend_tree()
- # this can't happen yet, due to the order of things in
- # TaskBrowser.__init__(). Happens in activate() instead.
- # self._init_plugin_tree()
- pref_signals_dic = self.get_signals_dict()
- self.builder.connect_signals(pref_signals_dic)
-
- #this line enables the about dialog widget to be reused
- self.plugin_about_dialog.connect("delete-event", lambda w, e: self.plugin_about_dialog.hide() or True)
-
- def _init_backend_tree(self):
- """Initialize the BackendTree gtk.TreeView."""
- self._refresh_backend_store()
- # TODO
-
- def _refresh_backend_store(self):
- """Populate a gtk.ListStore with backend information."""
- # create and clear a gtk.ListStore for backend information
- if not hasattr(self, 'backend_store'):
- # TODO: create the liststore. It should have one column for each
- # backend.
- self.backend_store = gtk.ListStore(str)
- self.backend_store.clear()
- # TODO
-
- def _refresh_plugin_store(self):
- """Populate a gtk.ListStore with plugin information."""
- # create and clear a gtk.ListStore
- if not hasattr(self, 'plugin_store'):
- # see constants PLUGINS_COL_* for column meanings
- self.plugin_store = gtk.ListStore(str, 'gboolean', str, str, str,
- 'gboolean', )
- self.plugin_store.clear()
- # refresh the status of all plugins
- self.pengine.recheck_plugin_errors(True)
- # repopulate the store
- for name, p in self.pengine.plugins.iteritems():
- self.plugin_store.append([name, p.enabled, p.full_name,
- p.short_description, p.description, not p.error, ]) # activateable if there is no error
-
- def _refresh_preferences_store(self):
- """Sets the correct value in the preferences checkboxes"""
- autostart_path = os.path.join(self.__AUTOSTART_DIRECTORY, \
- self.__AUTOSTART_FILE)
- self.pref_autostart.set_active(os.path.isfile(autostart_path))
-
- show_preview = self.config_priv.get("contents_preview_enable")
- self.pref_show_preview.set_active(show_preview)
-
- bg_color = self.config_priv.get("bg_color_enable")
- self.bg_color_enable.set_active(bg_color)
-
- def _init_plugin_tree(self):
- """Initialize the PluginTree gtk.TreeView.
-
- The format is modelled after the one used in gedit; see
- http://git.gnome.org/browse/gedit/tree/gedit/gedit-plugin-mapnager.c
-
- """
- # force creation of the gtk.ListStore so we can reference it
- self._refresh_plugin_store()
-
- # renderer for the toggle column
- renderer = gtk.CellRendererToggle()
- renderer.set_property('xpad', 6)
- renderer.connect('toggled', self.on_plugin_toggle)
- # toggle column
- column = gtk.TreeViewColumn(None, renderer, active=PLUGINS_COL_ENABLED,
- activatable=PLUGINS_COL_ACTIVATABLE,
- sensitive=PLUGINS_COL_ACTIVATABLE)
- self.plugin_tree.append_column(column)
-
- # plugin name column
- column = gtk.TreeViewColumn()
- column.set_spacing(6)
- # icon renderer for the plugin name column
- icon_renderer = gtk.CellRendererPixbuf()
- icon_renderer.set_property('stock-size', gtk.ICON_SIZE_SMALL_TOOLBAR)
- icon_renderer.set_property('xpad', 3)
- column.pack_start(icon_renderer, expand=False)
- column.set_cell_data_func(icon_renderer, plugin_icon)
- # text renderer for the plugin name column
- name_renderer = gtk.CellRendererText()
- name_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
- column.pack_start(name_renderer)
- column.set_cell_data_func(name_renderer, plugin_markup, self)
-
- self.plugin_tree.append_column(column)
-
- # finish setup
- self.plugin_tree.set_model(self.plugin_store)
- self.plugin_tree.set_search_column(2)
-
- ## GTK signals & related functions
- def get_signals_dict(self):
- """A dictionary of signals and functions to be connected."""
- SIGNAL_CONNECTIONS_DIC = {
-# 'on_preferences_activate':
-# self.activate,
- # buttons in the dialog itself
- 'on_prefs_close':
- self.on_close,
- 'on_prefs_help':
- self.on_help,
- # preferences on the Tasks tab
+ self.config = self.req.get_config('browser')
+ builder = gtk.Builder()
+ builder.add_from_file(ViewConfig.PREFERENCES_GLADE_FILE)
+
+ self.dialog = builder.get_object("PreferencesDialog")
+ self.pref_autostart = builder.get_object("pref_autostart")
+ self.pref_show_preview = builder.get_object("pref_show_preview")
+ self.bg_color_enable = builder.get_object("bg_color_enable")
+
+ builder.connect_signals({
+ 'on_pref_autostart_toggled':
+ self.on_autostart_toggled,
'on_pref_show_preview_toggled':
self.toggle_preview,
'on_bg_color_toggled':
self.on_bg_color_toggled,
- 'on_pref_check_spelling_toggled':
- self.toggle_spellcheck,
- # buttons on the Plugins tab
- 'on_PluginTree_cursor_changed':
- self.on_plugin_select,
- 'on_plugin_about':
- self.on_plugin_about,
- 'on_plugin_configure':
- self.on_plugin_configure,
- # the PluginAboutDialog
- 'on_PluginAboutDialog_close':
- self.on_plugin_about_close,
- 'on_PluginAboutDialog_response':
- self.on_plugin_about_close,
- # the PluginConfigDialog
- 'on_PluginConfigClose_released':
- self.on_plugin_config_close,
+ 'on_prefs_help':
+ self.on_help,
+ 'on_prefs_close':
+ self.on_close,
'on_PreferencesDialog_delete_event':
self.on_close,
- 'on_pref_autostart_toggled':
- self.on_autostart_toggled,
- }
- return SIGNAL_CONNECTIONS_DIC
-
- def activate(self, config_priv, widget=None):
- """Activate the preferences dialog."""
- self.config_priv = config_priv
- if len(self.plugin_tree.get_columns()) == 0:
- # late setup of PluginTree
- self._init_plugin_tree()
- else:
- self._refresh_plugin_store()
- self._refresh_backend_store()
+ })
+
+ def _refresh_preferences_store(self):
+ """ Sets the correct value in the preferences checkboxes """
+ has_autostart = os.path.isfile(AUTOSTART_PATH)
+ self.pref_autostart.set_active(has_autostart)
+
+ show_preview = self.config.get("contents_preview_enable")
+ self.pref_show_preview.set_active(show_preview)
+
+ bg_color = self.config.get("bg_color_enable")
+ self.bg_color_enable.set_active(bg_color)
+
+ def _refresh_task_browser(self):
+ """ Refresh tasks in task browser """
+ task_tree = self.req.get_tasks_tree(refresh=False).get_basetree()
+ task_tree.refresh_all()
+
+ def activate(self):
+ """ Activate the preferences dialog."""
self._refresh_preferences_store()
- self.dialog.present()
self.dialog.show_all()
- def on_close(self, widget, data = None):
- """Close the preferences dialog."""
-
+ def on_close(self, widget, data=None): # pylint: disable-msg=W0613
+ """ Close the preferences dialog."""
self.dialog.hide()
return True
- def on_help(self, widget):
- """Provide help for the preferences dialog."""
+ @classmethod
+ def on_help(cls, widget): # pylint: disable-msg=W0613
+ """ In future, this will open help for preferences """
return True
- def on_plugin_about(self, widget):
- """Display information about a plugin."""
- _, iterator = self.plugin_tree.get_selection().get_selected()
- if iterator is None:
- return
- plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
- p = self.pengine.get_plugin(plugin_id)
-
- pad = self.plugin_about_dialog
- pad.set_name(p.full_name)
- pad.set_version(p.version)
- authors = p.authors
- if isinstance(authors, str):
- authors = [authors, ]
- pad.set_authors(authors)
- pad.set_comments(p.description.replace(r'\n', "\n"))
- self.plugin_depends.set_label(plugin_error_text(p))
- pad.show_all()
-
- def on_plugin_about_close(self, widget, *args):
- """Close the PluginAboutDialog."""
- self.plugin_about_dialog.hide()
-
- def on_plugin_configure(self, widget):
- """Configure a plugin."""
- _, iterator = self.plugin_tree.get_selection().get_selected()
- if iterator is None:
- return
- plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
- # TODO: load plugin's configuration UI and insert into pc-vbox1 in
- # position 0. Something like...
- #pcd = self.plugin_config_dialog
- #pcd.show_all()
- # ...for now, use existing code.
- plugin = self.pengine.get_plugin(plugin_id)
- plugin.instance.configure_dialog(self.dialog)
-
- def on_plugin_config_close(self, widget):
- """Close the PluginConfigDialog."""
- self.plugin_config_dialog.hide()
-
- def on_plugin_select(self, plugin_tree):
- """ Callback when user select/unselect a plugin
-
- Update the button "Configure plugin" sensitivity """
- model, iterator = plugin_tree.get_selection().get_selected()
- if iterator is not None:
- plugin_id = model.get_value(iterator, PLUGINS_COL_ID)
- plugin = self.pengine.get_plugin(plugin_id)
- self._update_plugin_configure(plugin)
-
- def on_plugin_toggle(self, widget, path):
- """Toggle a plugin enabled/disabled."""
- iter = self.plugin_store.get_iter(path)
- plugin_id = self.plugin_store.get_value(iter, PLUGINS_COL_ID)
- p = self.pengine.get_plugin(plugin_id)
- p.enabled = not self.plugin_store.get_value(iter, PLUGINS_COL_ENABLED)
- if p.enabled:
- self.pengine.activate_plugins([p])
- self.config["plugins"]["enabled"].append(p.module_name)
- if p.module_name in self.config["plugins"]["disabled"]:
- self.config["plugins"]["disabled"].remove(p.module_name)
+ @classmethod
+ def on_autostart_toggled(cls, widget):
+ """ Toggle GTG autostarting with the GNOME desktop """
+ if widget.get_active():
+ enable_gtg_autostart()
else:
- self.pengine.deactivate_plugins([p])
- self.config["plugins"]["disabled"].append(p.module_name)
- if p.module_name in self.config["plugins"]["enabled"]:
- self.config["plugins"]["enabled"].remove(p.module_name)
- self.plugin_store.set_value(iter, PLUGINS_COL_ENABLED, p.enabled)
- self._update_plugin_configure(p)
-
- self.config_obj.save()
+ disable_gtg_autostart()
def toggle_preview(self, widget):
- """Toggle previews in the task view on or off."""
- curstate = self.config_priv.get("contents_preview_enable")
+ """ Toggle previews in the task view on or off."""
+ curstate = self.config.get("contents_preview_enable")
if curstate != widget.get_active():
- self.config_priv.set("contents_preview_enable", not curstate)
- view = self.req.get_tasks_tree(refresh=False)
- view.refresh_all()
+ self.config.set("contents_preview_enable", not curstate)
+ self._refresh_task_browser()
def on_bg_color_toggled(self, widget):
""" Save configuration and refresh nodes to apply the change """
- curstate = self.config_priv.get("bg_color_enable")
+ curstate = self.config.get("bg_color_enable")
if curstate != widget.get_active():
- self.config_priv.set("bg_color_enable", not curstate)
- task_tree = self.req.get_tasks_tree(refresh=False).get_basetree()
- task_tree.refresh_all()
-
- def toggle_spellcheck(self, widget):
- """Toggle spell checking on or off."""
- print __name__
-
- def _update_plugin_configure(self, plugin):
- """ Enable the button "Configure Plugin" appropriate. """
- configurable = plugin.active and plugin.is_configurable()
- self.plugin_configure.set_property('sensitive', configurable)
-
- def on_autostart_toggled(self, widget):
- """Toggle GTG autostarting with the GNOME desktop"""
- autostart_path = os.path.join(self.__AUTOSTART_DIRECTORY, \
- self.__AUTOSTART_FILE)
- if widget.get_active() == False:
- #Disable autostart, removing the file in autostart_path
- if os.path.isfile(autostart_path):
- os.remove(autostart_path)
- else:
- #Enable autostart
- #We look for the desktop file
- desktop_file_path = None
- desktop_file_directories = ["../..",
- "../../../applications",
- "../../../../../share/applications"]
- this_directory = os.path.dirname(os.path.abspath(__file__))
- for path in desktop_file_directories:
- fullpath = os.path.normpath(os.path.join(this_directory, path, \
- self.__AUTOSTART_FILE))
- if os.path.isfile(fullpath):
- desktop_file_path = fullpath
- break
- #If we have found the desktop file, we make a link to in in
- # autostart_path. If symbolic linking is not possible
- # (that is, if we are running on Windows), then copy the file
- if desktop_file_path:
- if not os.path.exists(self.__AUTOSTART_DIRECTORY):
- os.mkdir(self.__AUTOSTART_DIRECTORY)
- if os.path.isdir(self.__AUTOSTART_DIRECTORY) and \
- not os.path.exists(autostart_path):
- if hasattr(os, "symlink"):
- os.symlink(desktop_file_path, \
- autostart_path)
- else:
- shutil.copyfile(desktop_file_path, \
- autostart_path)
+ self.config.set("bg_color_enable", not curstate)
+ self._refresh_task_browser()
Follow ups