1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Gettings Things Gnome! - a personal organizer for the GNOME desktop
4
# Copyright (c) 2008-2012 - Lionel Dricot & Bertrand Rousseau
6
# This program is free software: you can redistribute it and/or modify it under
7
# the terms of the GNU General Public License as published by the Free Software
8
# Foundation, either version 3 of the License, or (at your option) any later
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16
# You should have received a copy of the GNU General Public License along with
17
# this program. If not, see <http://www.gnu.org/licenses/>.
18
# -----------------------------------------------------------------------------
20
""" Dialog for configuring plugins """
27
from GTG.core.plugins import GnomeConfig
28
from GTG.core.plugins.engine import PluginEngine
29
from GTG.gtk import ViewConfig
31
# columns in PluginsDialog.plugin_store
33
PLUGINS_COL_ENABLED = 1
35
PLUGINS_COL_SHORT_DESC = 3
36
PLUGINS_COL_ACTIVATABLE = 4
39
def plugin_icon(column, cell, store, iterator): # pylint: disable-msg=W0613
40
""" Callback to set the content of a PluginTree cell.
42
See PluginsDialog._init_plugin_tree().
44
cell.set_property('icon-name', 'gtg-plugin')
45
cell.set_property('sensitive',
46
store.get_value(iterator, PLUGINS_COL_ACTIVATABLE))
49
def plugin_error_short_text(plugin):
50
""" Return small version of description of missing module dependencies
51
for displaying in plugin markup """
56
modules = plugin.missing_modules
57
dbus = plugin.missing_dbus
61
modules = "<small><b>%s</b></small>" % ', '.join(modules)
63
ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
64
dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
67
if modules and not dbus:
68
text = '\n'.join((GnomeConfig.miss2, modules))
69
elif dbus and not modules:
70
text = '\n'.join((GnomeConfig.dmiss2, dbus))
71
elif modules and dbus:
72
text = '\n'.join((GnomeConfig.bmiss2, modules, dbus))
79
def plugin_error_text(plugin):
80
""" Generate some helpful text about missing module dependencies. """
82
return GnomeConfig.CANLOAD
84
# describe missing dependencies
85
text = "<b>%s</b>. \n" % GnomeConfig.CANNOTLOAD
87
modules = plugin.missing_modules
88
dbus = plugin.missing_dbus
92
modules = "<small><b>%s</b></small>" % ', '.join(modules)
94
ifaces = ["%s:%s" % (a, b) for (a, b) in dbus]
95
dbus = "<small><b>%s</b></small>" % ', '.join(ifaces)
98
if modules and not dbus:
99
text += '\n'.join((GnomeConfig.MODULEMISSING, modules))
100
elif dbus and not modules:
101
text += '\n'.join((GnomeConfig.DBUSMISSING, dbus))
102
elif modules and dbus:
103
text += '\n'.join((GnomeConfig.MODULANDDBUS, modules, dbus))
105
text += GnomeConfig.UNKNOWN
110
def plugin_markup(column, cell, store, iterator, self):
111
# pylint: disable-msg=W0613
112
""" Callback to set the content of a PluginTree cell.
114
See PluginsDialog._init_plugin_tree().
116
name = store.get_value(iterator, PLUGINS_COL_NAME)
117
desc = store.get_value(iterator, PLUGINS_COL_SHORT_DESC)
119
plugin_id = store.get_value(iterator, PLUGINS_COL_ID)
120
plugin = self.pengine.get_plugin(plugin_id)
121
error_text = plugin_error_short_text(plugin)
123
text = "<b>%s</b>\n%s\n<i>%s</i>" % (name, desc, error_text)
125
text = "<b>%s</b>\n%s" % (name, desc)
127
cell.set_property('markup', text)
128
cell.set_property('sensitive',
129
store.get_value(iterator, PLUGINS_COL_ACTIVATABLE))
133
""" Dialog for Plugins configuration """
134
# pylint: disable-msg=R0902
135
def __init__(self, config_obj):
136
self.config_obj = config_obj
137
self.config = self.config_obj.conf_dict
138
builder = gtk.Builder()
139
builder.add_from_file(ViewConfig.PLUGINS_GLADE_FILE)
141
self.dialog = builder.get_object("PluginsDialog")
142
self.dialog.set_title(_("Plugins - %s" % info.NAME))
143
self.plugin_tree = builder.get_object("PluginTree")
144
self.plugin_configure = builder.get_object("plugin_configure")
145
self.plugin_about = builder.get_object("PluginAboutDialog")
146
self.plugin_depends = builder.get_object('PluginDepends')
148
self.pengine = PluginEngine()
149
#plugin config initiation, if never used
150
if "plugins" in self.config:
151
if "enabled" not in self.config["plugins"]:
152
self.config["plugins"]["enabled"] = []
154
if "disabled" not in self.config["plugins"]:
155
self.config["plugins"]["disabled"] = []
156
elif self.pengine.get_plugins():
157
self.config["plugins"] = {}
158
self.config["plugins"]["disabled"] = \
159
[p.module_name for p in self.pengine.get_plugins("disabled")]
160
self.config["plugins"]["enabled"] = \
161
[p.module_name for p in self.pengine.get_plugins("enabled")]
163
# see constants PLUGINS_COL_* for column meanings
164
self.plugin_store = gtk.ListStore(str, bool, str, str, bool)
166
builder.connect_signals({
171
'on_PluginsDialog_delete_event':
173
'on_PluginTree_cursor_changed':
174
self.on_plugin_select,
176
self.on_plugin_about,
177
'on_plugin_configure':
178
self.on_plugin_configure,
179
'on_PluginAboutDialog_close':
180
self.on_plugin_about_close,
183
def _init_plugin_tree(self):
184
""" Initialize the PluginTree gtk.TreeView.
186
The format is modelled after the one used in gedit; see
187
http://git.gnome.org/browse/gedit/tree/gedit/gedit-plugin-mapnager.c
189
# force creation of the gtk.ListStore so we can reference it
190
self._refresh_plugin_store()
192
# renderer for the toggle column
193
renderer = gtk.CellRendererToggle()
194
renderer.set_property('xpad', 6)
195
renderer.connect('toggled', self.on_plugin_toggle)
197
column = gtk.TreeViewColumn(None, renderer, active=PLUGINS_COL_ENABLED,
198
activatable=PLUGINS_COL_ACTIVATABLE,
199
sensitive=PLUGINS_COL_ACTIVATABLE)
200
self.plugin_tree.append_column(column)
203
column = gtk.TreeViewColumn()
204
column.set_spacing(6)
205
# icon renderer for the plugin name column
206
icon_renderer = gtk.CellRendererPixbuf()
207
icon_renderer.set_property('stock-size', gtk.ICON_SIZE_SMALL_TOOLBAR)
208
icon_renderer.set_property('xpad', 3)
209
column.pack_start(icon_renderer, expand=False)
210
column.set_cell_data_func(icon_renderer, plugin_icon)
211
# text renderer for the plugin name column
212
name_renderer = gtk.CellRendererText()
213
name_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
214
column.pack_start(name_renderer)
215
column.set_cell_data_func(name_renderer, plugin_markup, self)
217
self.plugin_tree.append_column(column)
220
self.plugin_tree.set_model(self.plugin_store)
221
self.plugin_tree.set_search_column(2)
223
def _refresh_plugin_store(self):
224
""" Refresh status of plugins and put it in a gtk.ListStore """
225
self.plugin_store.clear()
226
self.pengine.recheck_plugin_errors(True)
227
for name, plugin in self.pengine.plugins.iteritems():
228
# activateable if there is no error
229
self.plugin_store.append((name, plugin.enabled, plugin.full_name,
230
plugin.short_description, not plugin.error))
233
""" Refresh status of plugins and show the dialog """
234
if len(self.plugin_tree.get_columns()) == 0:
235
self._init_plugin_tree()
237
self._refresh_plugin_store()
238
self.dialog.show_all()
240
def on_close(self, widget, data=None): # pylint: disable-msg=W0613
241
""" Close the plugins dialog."""
246
def on_help(cls, widget): # pylint: disable-msg=W0613
247
""" In future, this will open help for plugins """
250
def on_plugin_toggle(self, widget, path): # pylint: disable-msg=W0613
251
"""Toggle a plugin enabled/disabled."""
252
iterator = self.plugin_store.get_iter(path)
253
plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
254
plugin = self.pengine.get_plugin(plugin_id)
255
plugin.enabled = not self.plugin_store.get_value(iterator,
258
self.pengine.activate_plugins([plugin])
259
self.config["plugins"]["enabled"].append(plugin.module_name)
260
if plugin.module_name in self.config["plugins"]["disabled"]:
261
self.config["plugins"]["disabled"].remove(plugin.module_name)
263
self.pengine.deactivate_plugins([plugin])
264
self.config["plugins"]["disabled"].append(plugin.module_name)
265
if plugin.module_name in self.config["plugins"]["enabled"]:
266
self.config["plugins"]["enabled"].remove(plugin.module_name)
267
self.plugin_store.set_value(iterator, PLUGINS_COL_ENABLED,
269
self._update_plugin_configure(plugin)
271
self.config_obj.save()
273
def on_plugin_select(self, plugin_tree):
274
""" Callback when user select/unselect a plugin
276
Update the button "Configure plugin" sensitivity """
277
model, iterator = plugin_tree.get_selection().get_selected()
278
if iterator is not None:
279
plugin_id = model.get_value(iterator, PLUGINS_COL_ID)
280
plugin = self.pengine.get_plugin(plugin_id)
281
self._update_plugin_configure(plugin)
283
def _update_plugin_configure(self, plugin):
284
""" Enable the button "Configure Plugin" appropriate. """
285
configurable = plugin.active and plugin.is_configurable()
286
self.plugin_configure.set_property('sensitive', configurable)
288
def on_plugin_configure(self, widget): # pylint: disable-msg=W0613
289
""" Show the dialog for plugin configuration """
290
_, iterator = self.plugin_tree.get_selection().get_selected()
293
plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
294
plugin = self.pengine.get_plugin(plugin_id)
295
plugin.instance.configure_dialog(self.dialog)
297
def on_plugin_about(self, widget): # pylint: disable-msg=W0613
298
""" Display information about a plugin. """
299
_, iterator = self.plugin_tree.get_selection().get_selected()
302
plugin_id = self.plugin_store.get_value(iterator, PLUGINS_COL_ID)
303
plugin = self.pengine.get_plugin(plugin_id)
305
self.plugin_about.set_name(plugin.full_name)
306
self.plugin_about.set_version(plugin.version)
307
authors = plugin.authors
308
if isinstance(authors, str):
309
authors = "\n".join(author.strip()
310
for author in authors.split(','))
311
authors = [authors, ]
312
self.plugin_about.set_authors(authors)
313
description = plugin.description.replace(r'\n', "\n")
314
self.plugin_about.set_comments(description)
315
self.plugin_depends.set_label(plugin_error_text(plugin))
316
self.plugin_about.show_all()
318
def on_plugin_about_close(self, widget, data=None):
319
# pylint: disable-msg=W0613
320
""" Close the PluginAboutDialog. """
321
self.plugin_about.hide()