Added plug-in deactivation mechanism, which allows plug-ins to clean up after themselves (eg. disconnecting handlers made in GUI); GUI extension points handlers are removed from list.

Updated Length Notifier plug-in so that it can be properly deactivated.
This commit is contained in:
Mateusz Biliński 2008-06-03 13:40:27 +00:00
parent 77f10031f1
commit 654e157eff
2 changed files with 51 additions and 12 deletions

View File

@ -74,9 +74,17 @@ length of message is exceeded.'''
if self.jid_is_ok(jid): if self.jid_is_ok(jid):
d = {'prev_color' : None} d = {'prev_color' : None}
tv = chat_control.msg_textview tv = chat_control.msg_textview
b = tv.get_buffer() tb = tv.get_buffer()
h_id = b.connect('changed', self.textview_length_warning, chat_control) h_id = tb.connect('changed', self.textview_length_warning, chat_control)
d['h_id'] = h_id d['h_id'] = h_id
t = tb.get_text(tb.get_start_iter(), tb.get_end_iter())
if t:
len_t = len(t)
if len_t>self.MESSAGE_WARNING_LENGTH:
d['prev_color'] = tv.style.copy().base[gtk.STATE_NORMAL]
tv.modify_base(gtk.STATE_NORMAL, self.WARNING_COLOR)
chat_control.length_notifier_plugin_data = d chat_control.length_notifier_plugin_data = d
return True return True
@ -86,9 +94,10 @@ length of message is exceeded.'''
@log_calls('LengthNotifierPlugin') @log_calls('LengthNotifierPlugin')
def disconnect_from_chat_control(self, chat_control): def disconnect_from_chat_control(self, chat_control):
d = chat_control.length_notifier_plugin_data d = chat_control.length_notifier_plugin_data
chat_control.msg_textview.get_buffer().disconnect(d['h_id']) tv = chat_control.msg_textview
tv.get_buffer().disconnect(d['h_id'])
if d['prev_color']: if d['prev_color']:
tv.modify_base(gtk.STATE_NORMAL, self.PREV_COLOR) tv.modify_base(gtk.STATE_NORMAL, d['prev_color'])
@log_calls('LengthNotifierPlugin') @log_calls('LengthNotifierPlugin')
def jid_is_ok(self, jid): def jid_is_ok(self, jid):

View File

@ -49,14 +49,22 @@ class PluginManager(object):
:todo: add list of available GUI extension points :todo: add list of available GUI extension points
:todo: implement mechanism to dynamically load plugins where GUI extension :todo: implement mechanism to dynamically load plugins where GUI extension
points have been already called (i.e. when plugin is activated points have been already called (i.e. when plugin is activated
after GUI object creation) after GUI object creation). [DONE?]
:todo: implement mechanism to dynamically deactive plugins (call plugin's :todo: implement mechanism to dynamically deactive plugins (call plugin's
deactivation handler) deactivation handler) [DONE?]
:todo: when plug-in is deactivated all GUI extension points are removed
from `PluginManager.gui_extension_points_handlers`. But when
object that invoked GUI extension point is abandoned by Gajim, eg.
closed ChatControl object, the reference to called GUI extension
points is still in `PluginManager.gui_extension_points`. These
should be removed, so that object can be destroyed by Python.
Possible solution: add call to clean up method in classes
'destructors' (classes that register GUI extension points)
''' '''
__metaclass__ = Singleton __metaclass__ = Singleton
@log_calls('PluginManager') #@log_calls('PluginManager')
def __init__(self): def __init__(self):
self.plugins = [] self.plugins = []
''' '''
@ -68,7 +76,7 @@ class PluginManager(object):
''' '''
self.active_plugins = [] self.active_plugins = []
''' '''
Objectsof active plugins. Instance objects of active plugins.
These are object instances of classes held `plugins`, but only those These are object instances of classes held `plugins`, but only those
that were activated. that were activated.
@ -90,7 +98,7 @@ class PluginManager(object):
log.debug('plugins: %s'%(self.plugins)) log.debug('plugins: %s'%(self.plugins))
#self._activate_all_plugins() self.activate_all_plugins()
log.debug('active: %s'%(self.active_plugins)) log.debug('active: %s'%(self.active_plugins))
@ -133,7 +141,7 @@ class PluginManager(object):
handlers[0](*args) handlers[0](*args)
@log_calls('PluginManager') @log_calls('PluginManager')
def _activate_plugin(self, plugin): def activate_plugin(self, plugin):
''' '''
:param plugin: plugin to be activated :param plugin: plugin to be activated
:type plugin: class object of `GajimPlugin` subclass :type plugin: class object of `GajimPlugin` subclass
@ -151,6 +159,28 @@ class PluginManager(object):
return success return success
def deactivate_plugin(self, plugin_object):
# 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():
for gui_extension_point_args in self.gui_extension_points[gui_extpoint_name]:
gui_extpoint_handlers[1](*gui_extension_point_args)
# 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():
self.gui_extension_points_handlers[gui_extpoint_name].remove(gui_extpoint_handlers)
# removing plug-in from active plug-ins list
self.active_plugins.remove(plugin_object)
def deactivate_all_plugins(self):
for plugin_object in self.active_plugins:
self.deactivate_plugin(plugin_object)
@log_calls('PluginManager') @log_calls('PluginManager')
def _add_gui_extension_points_handlers_from_plugin(self, plugin_object): def _add_gui_extension_points_handlers_from_plugin(self, plugin_object):
for gui_extpoint_name, gui_extpoint_handlers in \ for gui_extpoint_name, gui_extpoint_handlers in \
@ -167,7 +197,7 @@ class PluginManager(object):
gui_extpoint_handlers[0](*gui_extension_point_args) gui_extpoint_handlers[0](*gui_extension_point_args)
@log_calls('PluginManager') @log_calls('PluginManager')
def _activate_all_plugins(self): def activate_all_plugins(self):
''' '''
Activates all plugins in `plugins`. Activates all plugins in `plugins`.
@ -175,7 +205,7 @@ class PluginManager(object):
''' '''
self.active_plugins = [] self.active_plugins = []
for plugin in self.plugins: for plugin in self.plugins:
self._activate_plugin(plugin) self.activate_plugin(plugin)
@staticmethod @staticmethod
@log_calls('PluginManager') @log_calls('PluginManager')