1
# -*- coding: utf-8 -*-
2
'''Handles the Plugin Dialog: starts/stops plugins, show description, ect.'''
4
# This file is part of emesene.
6
# Emesene is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
11
# emesene is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with emesene; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
class PluginManagerDialog( gtk.Window ):
26
'''This class show and manage all the plugins installed
27
in the plugins directory'''
29
def __init__( self, pluginManager, parent, config ):
32
gtk.Window.__init__( self )
36
self.pluginManager = pluginManager
37
self.set_transient_for( parent )
38
self.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_DIALOG )
39
pix = self.render_icon(gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
42
self.set_default_size( 500, 350 )
43
#self.set_geometry_hints( self, 500, 350, 500, 350 )
44
self.set_title( _( 'Plugin Manager' ) )
45
self.set_role( _( 'Plugin Manager' ) )
47
self.set_border_width( 12 )
48
self.set_resizable( True )
49
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
52
vbox.set_spacing( 12 )
54
self.listStore = gtk.ListStore( str, str, str, bool )
56
cellRendererTextName = gtk.CellRendererText()
57
cellRendererToggle = gtk.CellRendererToggle()
58
cellRendererTextDesc = gtk.CellRendererText()
60
cellRendererToggle.set_property( 'activatable', True )
62
plugOn = gtk.TreeViewColumn(_('Active'), cellRendererToggle, active=3)
63
plugOn.set_resizable( False )
64
plugName = gtk.TreeViewColumn(_('Name'), cellRendererTextName, markup=0)
65
plugName.add_attribute( cellRendererTextName, 'text', 0 )
66
plugName.set_resizable( True )
67
plugName.set_min_width( 60 )
68
plugDesc = gtk.TreeViewColumn(_('Description'), cellRendererTextDesc)
69
cellRendererTextDesc.set_property( 'ellipsize', pango.ELLIPSIZE_END )
70
plugDesc.add_attribute( cellRendererTextDesc, 'text', 2 )
71
plugDesc.set_expand( True )
72
plugDesc.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
74
self.list = gtk.TreeView( self.listStore )
75
self.list.append_column( plugOn )
76
self.list.append_column( plugName )
77
self.list.append_column( plugDesc )
78
self.list.set_reorderable( False )
79
self.list.set_headers_visible( True )
80
self.list.set_rules_hint( True )
82
self.scroll = gtk.ScrolledWindow()
83
self.scroll.set_policy( gtk.POLICY_NEVER , gtk.POLICY_AUTOMATIC )
84
self.scroll.set_shadow_type( gtk.SHADOW_OUT )
85
self.scroll.add( self.list )
87
table = gtk.Table( 3, 2 )
88
table.set_row_spacings( 6 )
89
table.set_col_spacings( 12 )
90
hButBox = gtk.HButtonBox()
91
hButBox.set_spacing( 6 )
92
hButBox.set_layout( gtk.BUTTONBOX_END )
94
self.description = gtk.Label()
95
self.author = gtk.Label()
96
self.web = gtk.Label()
98
self.description.set_alignment( 0.0, 0.0 )
99
self.author.set_alignment( 0.0, 0.5 )
100
self.web.set_alignment( 0.0, 0.5 )
102
self.description.set_line_wrap( True )
103
self.author.set_line_wrap( True )
104
self.web.set_line_wrap( True )
106
self.description.set_size_request( 476, 48 )
108
auth = gtk.Label( '<b>' + _( 'Author:' ) + '</b>' )
109
auth.set_alignment( 0.0, 0.5 )
110
auth.set_use_markup( True )
111
web = gtk.Label( '<b>' + _( 'Website:' ) + '</b>' )
112
web.set_alignment( 0.0, 0.5 )
113
web.set_use_markup( True )
115
table.attach( self.description , 0, 2, 0, 1, gtk.FILL | gtk.EXPAND )
117
table.attach( auth, 0, 1, 1, 2, gtk.FILL )
118
table.attach( self.author , 1, 2, 1, 2 )
120
table.attach( web, 0, 1, 2, 3, gtk.FILL )
121
table.attach( self.web , 1, 2, 2, 3 )
123
self.bConfigure = gtk.Button( _( 'Configure' ), gtk.STOCK_PROPERTIES )
124
self.bReload = gtk.Button( stock=gtk.STOCK_REFRESH )
125
self.bLoadNew = gtk.Button( _( 'Load New Plugins' ))
126
self.bclose = gtk.Button( stock=gtk.STOCK_CLOSE )
128
self.bConfigure.connect( 'clicked', self.configurePlugin )
129
self.bReload.connect( 'clicked', self.reloadPlugin )
130
self.bLoadNew.connect( 'clicked', self.loadNewPlugins )
131
self.bclose.connect( 'clicked', self.close )
133
hButBox.pack_start( self.bConfigure )
134
hButBox.pack_start( self.bReload )
135
hButBox.pack_start( self.bLoadNew )
136
hButBox.pack_start( self.bclose )
138
vbox.pack_start( self.scroll, True, True )
139
vbox.pack_start( table, False, False )
140
vbox.pack_start( hButBox, False, False )
147
self.list.columns_autosize()
149
self.connect( 'delete-event', self.close )
150
self.list.connect( 'cursor-changed', self.row_selected )
151
cellRendererToggle.connect( 'toggled', self.active_toggled, \
152
( self.listStore, 3 ) )
154
def fillList( self ):
155
'''fills the plugin list'''
156
self.listStore.clear()
158
for i in sorted(self.pluginManager.getPlugins(), key=lambda x: x.lower()):
159
plugin = self.pluginManager.getPluginData( i )
161
self.listStore.append(['<b>' + plugin['displayName'] + '</b>',
162
i, plugin['description'], self.pluginManager.isEnabled(i)])
164
def close( self, *args ):
165
'''close the window'''
169
def getSelected( self ):
170
'''Return the selected item'''
171
model = self.list.get_model()
172
selected = self.list.get_selection().get_selected()
174
return model.get(selected[1], 1)[0]
178
def row_selected( self, *args ):
179
'''callback for the row_selected event'''
181
name = self.getSelected()
182
plugin_instance = self.pluginManager.getPlugin(name)
183
self.setDescription(name)
184
if hasattr(plugin_instance, "configure") and callable(plugin_instance.configure) \
185
and self.pluginManager.isEnabled(name):
186
self.bConfigure.set_sensitive(True)
188
self.bConfigure.set_sensitive(False)
190
def configurePlugin( self, *args ):
191
'''call the configure method in the plugin'''
192
plugin_instance = self.pluginManager.getPlugin( self.getSelected() )
193
if hasattr(plugin_instance, "configure") and callable(plugin_instance.configure):
194
plugin_instance.configure()
196
def reloadPlugin( self, *args ):
197
'''Reloads the plugin python code'''
198
name = self.getSelected()
199
self.pluginManager.restartPlugin(name)
200
# update the metadata
202
self.setDescription(name)
204
def loadNewPlugins( self, *args ):
205
'''Loads new plugins'''
206
for i in self.pluginManager.getNewModules():
207
if i not in self.pluginManager.plugin_data:
208
self.pluginManager.inspectPlugin(i)
209
self.pluginManager.loadPlugin(i)
212
def setDescription( self, name ):
213
plugin_data = self.pluginManager.getPluginData(name)
215
self.description.set_label( plugin_data['description'] )
219
for (author,mail) in plugin_data['authors'].iteritems():
220
string += author + ' (' + mail + ')\n'
223
self.author.set_label( '' + string[ :-1 ] )
225
self.web.set_label( '' + plugin_data['website'] )
227
def active_toggled(self, cell, path, user_data):
228
'''enable or disable the plugin'''
230
model, column = user_data
231
iterator= model.get_iter_from_string(path)
233
plugin_name = model.get_value(iterator, 1)
234
plugin_instance = self.pluginManager.getPlugin(plugin_name, True)
236
if not plugin_instance:
238
if self.pluginManager.isEnabled(plugin_name):
239
self.pluginManager.stopPlugin(plugin_name)
240
model.set_value(iterator, column, False)
242
plugins = self.config.user['activePlugins'].split( ',' )
244
if plugin_name in plugins:
245
plugins.pop( plugins.index(plugin_name))
246
self.config.user['activePlugins'] = ','.join(plugins)
248
status = self.pluginManager.checkPlugin(plugin_name)
251
self.pluginManager.startPlugin(plugin_name)
252
model.set_value(iterator, column, True)
254
plugins = self.config.user['activePlugins'].split(',')
256
if plugins[0] == '' and len(plugins) == 1:
257
self.config.user['activePlugins'] = plugin_name
258
elif not plugin_name in plugins:
259
s = ','.join(plugins) + ',' + plugin_name
260
self.config.user['activePlugins'] = s
262
dialog.error(_('Plugin initialization failed: \n') \