Added new 'init' method to Plugin class that plugins can implement to make actions that need to be done only once - when plugin is added (not activated) to Gajim. In this method plugins should declare handlers for GUI extension points. This was created so that __init__ method doesn't have to be reimplemented in specific way (create config, load config) - it is all done by __init__ in Plugin class. If __init__ is reimplemented, it must call Plugin __init__ (eg. using super() ) to plugin work properly.

Example plug-ins were modified to use init() instead of __init__().

Added new category in configuration - 'plugins'. It only holds one option for each plugin - 'active', which determines whether plugin should be activated on startup.

Now, Gajim remembers which plugins are active on exit, and activates them on next startup.
This commit is contained in:
Mateusz Biliński 2008-06-18 20:45:22 +00:00
parent b6593b9493
commit 8581b862e1
8 changed files with 109 additions and 70 deletions

View File

@ -19,7 +19,7 @@
Acronyms expander plugin.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 06/10/2008
:since: 9th June 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
@ -39,10 +39,11 @@ class AcronymsExpanderPlugin(GajimPlugin):
authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
homepage = u'http://blog.bilinski.it'
@log_calls('AcronymsExpanderPlugin')
def __init__(self):
super(AcronymsExpanderPlugin, self).__init__()
#@log_calls('AcronymsExpanderPlugin')
#def __init__(self):
#super(AcronymsExpanderPlugin, self).__init__()
def init(self):
self.gui_extension_points = {
'chat_control_base' : (self.connect_with_chat_control_base,
self.disconnect_from_chat_control_base)
@ -56,7 +57,7 @@ class AcronymsExpanderPlugin(GajimPlugin):
'GNT-' : 'http://trac.gajim.org/newticket',
'GW-' : 'http://trac.gajim.org/',
'GTS-' : 'http://trac.gajim.org/report'
}
}
@log_calls('AcronymsExpanderPlugin')
def textbuffer_live_acronym_expander(self, tb):
@ -98,4 +99,5 @@ class AcronymsExpanderPlugin(GajimPlugin):
d = chat_control.acronyms_expander_plugin_data
tv = chat_control.msg_textview
tv.get_buffer().disconnect(d['h_id'])

View File

@ -19,7 +19,7 @@
Message length notifier plugin.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 06/01/2008
:since: 1st June 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
@ -39,10 +39,12 @@ class LengthNotifierPlugin(GajimPlugin):
authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
homepage = u'http://blog.bilinski.it'
#@log_calls('LengthNotifierPlugin')
#def __init__(self):
#super(LengthNotifierPlugin, self).__init__()
@log_calls('LengthNotifierPlugin')
def __init__(self):
super(LengthNotifierPlugin, self).__init__()
def init(self):
self.gui_extension_points = {
'chat_control' : (self.connect_with_chat_control,
self.disconnect_from_chat_control)

View File

@ -19,7 +19,7 @@
Roster buttons plug-in.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 06/10/2008
:since: 14th June 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
@ -44,23 +44,24 @@ class RosterButtonsPlugin(GajimPlugin):
#@log_calls('RosterButtonsPlugin')
#def __init__(self):
#super(RosterButtonsPlugin, self).__init__()
@log_calls('RosterButtonsPlugin')
def activate(self):
@log_calls('RosterButtonsPlugin')
def init(self):
#log.debug('self.__path__==%s'%(self.__path__))
self.GLADE_FILE_PATH = self.local_file_path('roster_buttons.glade')
self.roster_vbox = gajim.interface.roster.xml.get_widget('roster_vbox2')
self.show_offline_contacts_menuitem = gajim.interface.roster.xml.get_widget('show_offline_contacts_menuitem')
@log_calls('RosterButtonsPlugin')
def activate(self):
self.xml = gtk.glade.XML(self.GLADE_FILE_PATH, root='roster_buttons_buttonbox', domain=i18n.APP)
self.buttonbox = self.xml.get_widget('roster_buttons_buttonbox')
self.roster_vbox = gajim.interface.roster.xml.get_widget('roster_vbox2')
self.roster_vbox.pack_start(self.buttonbox, expand=False)
self.roster_vbox.reorder_child(self.buttonbox, 0)
self.show_offline_contacts_menuitem = gajim.interface.roster.xml.get_widget('show_offline_contacts_menuitem')
self.xml.signal_autoconnect(self)
@log_calls('RosterButtonsPlugin')
def deactivate(self):
self.roster_vbox.remove(self.buttonbox)
@ -72,7 +73,6 @@ class RosterButtonsPlugin(GajimPlugin):
def on_roster_button_1_clicked(self, button):
#gajim.interface.roster.on_show_offline_contacts_menuitem_activate(None)
self.show_offline_contacts_menuitem.set_active(not self.show_offline_contacts_menuitem.get_active())
@log_calls('RosterButtonsPlugin')
def on_roster_button_2_clicked(self, button):

View File

@ -390,6 +390,9 @@ class Config:
'roster': [opt_str, '', _("'yes', 'no' or ''")],
'urgency_hint': [opt_bool, False],
}, {}),
'plugins': ({
'active': [opt_bool, False, _('State whether plugins should be activated on exit (this is saved on Gajim exit). This option SHOULD NOT be used to (de)activate plug-ins. Use GUI instead.')],
},{}),
}
statusmsg_default = {

View File

@ -377,6 +377,8 @@ class GajimRemote:
except:
raise exceptions.SessionBusNotPresent
from pprint import pprint
pprint(list(self.sbus.list_names()))
if not self.check_gajim_running():
send_error(_('It seems Gajim is not running. So you can\'t use gajim-remote.'))
obj = self.sbus.get_object(SERVICE, OBJ_PATH)

View File

@ -139,20 +139,20 @@ class PluginsWindow(object):
self.installed_plugins_model.clear()
self.installed_plugins_model.set_sort_column_id(0, gtk.SORT_ASCENDING)
for plugin_class in pm.plugins:
self.installed_plugins_model.append([plugin_class,
plugin_class.name,
plugin_class._active])
for plugin in pm.plugins:
self.installed_plugins_model.append([plugin,
plugin.name,
plugin.active])
@log_calls('PluginsWindow')
def installed_plugins_toggled_cb(self, cell, path):
is_active = self.installed_plugins_model[path][2]
plugin_class = self.installed_plugins_model[path][0]
plugin = self.installed_plugins_model[path][0]
if is_active:
gajim.plugin_manager.deactivate_plugin(plugin_class._instance)
gajim.plugin_manager.deactivate_plugin(plugin)
else:
gajim.plugin_manager.activate_plugin(plugin_class)
gajim.plugin_manager.activate_plugin(plugin)
self.installed_plugins_model[path][2] = not is_active

View File

@ -19,7 +19,7 @@
Base class for implementing plugin.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 06/01/2008
:since: 1st June 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
@ -104,15 +104,15 @@ class GajimPlugin(object):
:type: `plugins.plugin.Config`
'''
self._load_config()
self.load_config()
self.init()
@log_calls('GajimPlugin')
def _save_config(self):
def save_config(self):
pass
@log_calls('GajimPlugin')
def _load_config(self):
def load_config(self):
pass
@log_calls('GajimPlugin')
@ -122,6 +122,10 @@ class GajimPlugin(object):
@log_calls('GajimPlugin')
def local_file_path(self, file_name):
return os.path.join(self.__path__, file_name)
@log_calls('GajimPlugin')
def init(self):
pass
@log_calls('GajimPlugin')
def activate(self):

View File

@ -19,7 +19,7 @@
Plug-in management related classes.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 05/30/2008
:since: 30th May 2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
@ -94,29 +94,42 @@ class PluginManager(object):
'''
for path in gajim.PLUGINS_DIRS:
self._add_plugins(PluginManager.scan_dir_for_plugins(path))
self.add_plugins(PluginManager.scan_dir_for_plugins(path))
log.debug('plugins: %s'%(self.plugins))
self.activate_all_plugins()
self._activate_all_plugins_from_global_config()
log.debug('active: %s'%(self.active_plugins))
@log_calls('PluginManager')
def _plugin_has_entry_in_global_config(self, plugin):
if gajim.config.get_per('plugins', plugin.short_name) is None:
return False
else:
return True
@log_calls('PluginManager')
def _create_plugin_entry_in_global_config(self, plugin):
gajim.config.add_per('plugins', plugin.short_name)
@log_calls('PluginManager')
def _add_plugin(self, plugin_class):
def add_plugin(self, plugin_class):
'''
:todo: what about adding plug-ins that are already added? Module reload
and adding class from reloaded module or ignoring adding plug-in?
'''
plugin_class._active = False
plugin_class._instance = None
self.plugins.append(plugin_class)
plugin = plugin_class()
if not self._plugin_has_entry_in_global_config(plugin):
self._create_plugin_entry_in_global_config(plugin)
self.plugins.append(plugin)
plugin.active = False
@log_calls('PluginManager')
def _add_plugins(self, plugin_classes):
def add_plugins(self, plugin_classes):
for plugin_class in plugin_classes:
self._add_plugin(plugin_class)
self.add_plugin(plugin_class)
@log_calls('PluginManager')
def gui_extension_point(self, gui_extpoint_name, *args):
@ -156,33 +169,36 @@ class PluginManager(object):
handlers[0](*args)
@log_calls('PluginManager')
def activate_plugin(self, plugin_class):
def activate_plugin(self, plugin):
'''
:param plugin: plugin to be activated
:type plugin: class object of `GajimPlugin` subclass
'''
plugin_object = plugin_class()
success = True
self._add_gui_extension_points_handlers_from_plugin(plugin_object)
self._handle_all_gui_extension_points_with_plugin(plugin_object)
if success:
self.active_plugins.append(plugin_object)
plugin_object.activate()
plugin_class._instance = plugin_object
plugin_class._active = True
:todo: success checks should be implemented using exceptions. Such
control should also be implemented in deactivation.
'''
success = False
if not plugin.active:
self._add_gui_extension_points_handlers_from_plugin(plugin)
self._handle_all_gui_extension_points_with_plugin(plugin)
success = True
if success:
self.active_plugins.append(plugin)
plugin.activate()
self._set_plugin_active_in_global_config(plugin)
plugin.active = True
return success
def deactivate_plugin(self, plugin_object):
def deactivate_plugin(self, plugin):
# detaching plug-in from handler GUI extension points (calling
# cleaning up method that must be provided by plug-in developer
# for each handled GUI extension point)
for gui_extpoint_name, gui_extpoint_handlers in \
plugin_object.gui_extension_points.iteritems():
plugin.gui_extension_points.iteritems():
if gui_extpoint_name in self.gui_extension_points:
for gui_extension_point_args in self.gui_extension_points[gui_extpoint_name]:
gui_extpoint_handlers[1](*gui_extension_point_args)
@ -190,45 +206,55 @@ class PluginManager(object):
# remove GUI extension points handlers (provided by plug-in) from
# handlers list
for gui_extpoint_name, gui_extpoint_handlers in \
plugin_object.gui_extension_points.iteritems():
plugin.gui_extension_points.iteritems():
self.gui_extension_points_handlers[gui_extpoint_name].remove(gui_extpoint_handlers)
# removing plug-in from active plug-ins list
plugin_object.deactivate()
self.active_plugins.remove(plugin_object)
plugin_object.__class__._active = False
plugin_object.__class__._instance = None
del plugin_object
plugin.deactivate()
self.active_plugins.remove(plugin)
self._set_plugin_active_in_global_config(plugin, False)
plugin.active = False
def deactivate_all_plugins(self):
def _deactivate_all_plugins(self):
for plugin_object in self.active_plugins:
self.deactivate_plugin(plugin_object)
@log_calls('PluginManager')
def _add_gui_extension_points_handlers_from_plugin(self, plugin_object):
def _add_gui_extension_points_handlers_from_plugin(self, plugin):
for gui_extpoint_name, gui_extpoint_handlers in \
plugin_object.gui_extension_points.iteritems():
plugin.gui_extension_points.iteritems():
self.gui_extension_points_handlers.setdefault(gui_extpoint_name, []).append(
gui_extpoint_handlers)
@log_calls('PluginManager')
def _handle_all_gui_extension_points_with_plugin(self, plugin_object):
def _handle_all_gui_extension_points_with_plugin(self, plugin):
for gui_extpoint_name, gui_extpoint_handlers in \
plugin_object.gui_extension_points.iteritems():
plugin.gui_extension_points.iteritems():
if gui_extpoint_name in self.gui_extension_points:
for gui_extension_point_args in self.gui_extension_points[gui_extpoint_name]:
gui_extpoint_handlers[0](*gui_extension_point_args)
@log_calls('PluginManager')
def activate_all_plugins(self):
def _activate_all_plugins(self):
'''
Activates all plugins in `plugins`.
Activated plugins are appended to `active_plugins` list.
'''
self.active_plugins = []
#self.active_plugins = []
for plugin in self.plugins:
self.activate_plugin(plugin)
def _activate_all_plugins_from_global_config(self):
for plugin in self.plugins:
if self._plugin_is_active_in_global_config(plugin):
self.activate_plugin(plugin)
def _plugin_is_active_in_global_config(self, plugin):
return gajim.config.get_per('plugins', plugin.short_name, 'active')
def _set_plugin_active_in_global_config(self, plugin, active=True):
gajim.config.set_per('plugins', plugin.short_name, 'active', active)
@staticmethod
@log_calls('PluginManager')