From 0a1fe76172ebef8990bd297d4fe13c0ffd499987 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Fri, 17 Sep 2010 14:13:48 +0200 Subject: [PATCH 01/14] move acronyms expander plugin. see #5906 --- plugins/acronyms_expander/__init__.py | 1 + plugins/{ => acronyms_expander}/acronyms_expander.py | 0 2 files changed, 1 insertion(+) create mode 100644 plugins/acronyms_expander/__init__.py rename plugins/{ => acronyms_expander}/acronyms_expander.py (100%) diff --git a/plugins/acronyms_expander/__init__.py b/plugins/acronyms_expander/__init__.py new file mode 100644 index 000000000..25280942c --- /dev/null +++ b/plugins/acronyms_expander/__init__.py @@ -0,0 +1 @@ +from acronyms_expander import AcronymsExpanderPlugin diff --git a/plugins/acronyms_expander.py b/plugins/acronyms_expander/acronyms_expander.py similarity index 100% rename from plugins/acronyms_expander.py rename to plugins/acronyms_expander/acronyms_expander.py From 0899ab13db9e7367a3f9cedacf7a08c71bfded3f Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Fri, 17 Sep 2010 21:14:52 +0200 Subject: [PATCH 02/14] [Dicson] Fix building Gajim. Fixes #5916 --- plugins/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index bd4d7d15d..65b97ed6e 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -3,7 +3,6 @@ INCLUDES = \ gajimpluginsdir = $(gajim_pluginsdir) nobase_dist_gajimplugins_PYTHON = \ - $(srcdir)/*.py \ $(srcdir)/*/*.py \ $(srcdir)/*/*.ui From 90d1ee31761f87db96955474f61f268c541b4cb2 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Fri, 17 Sep 2010 21:16:17 +0200 Subject: [PATCH 03/14] [Dicson] remove plugin entry in global config when removing the plugin. Fixes #5918 --- src/plugins/pluginmanager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index 3560e4985..5328f4b72 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -117,6 +117,9 @@ class PluginManager(object): def _create_plugin_entry_in_global_config(self, plugin): gajim.config.add_per('plugins', plugin.short_name) + def _remove_plugin_entry_in_global_config(self, plugin): + gajim.config.del_per('plugins', plugin.short_name) + @log_calls('PluginManager') def add_plugin(self, plugin_class): ''' @@ -519,6 +522,8 @@ class PluginManager(object): self.deactivate_plugin(plugin) rmtree(plugin.__path__, False, on_error) self.plugins.remove(plugin) + if self._plugin_has_entry_in_global_config(plugin): + self._remove_plugin_entry_in_global_config(plugin) def get_plugin_by_path(self, plugin_dir): for plugin in self.plugins: From 0b448cfb104ff7c0bd2868f326afd56c0676bb53 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sat, 18 Sep 2010 23:00:43 +0200 Subject: [PATCH 04/14] [Dicson] use manifest.ini files in plugins to have a separate file for plugin's information. Fixes #5920 --- .../acronyms_expander/acronyms_expander.py | 6 - plugins/acronyms_expander/manifest.ini | 9 + plugins/banner_tweaks/manifest.ini | 10 + plugins/banner_tweaks/plugin.py | 9 - plugins/dbus_plugin/manifest.ini | 10 + plugins/dbus_plugin/plugin.py | 7 - plugins/events_dump/manifest.ini | 8 + plugins/events_dump/plugin.py | 6 - plugins/google_translation/manifest.ini | 8 + plugins/google_translation/plugin.py | 6 - plugins/length_notifier/length_notifier.py | 6 - plugins/length_notifier/manifest.ini | 9 + plugins/new_events_example/manifest.ini | 11 + plugins/new_events_example/plugin.py | 6 - plugins/roster_buttons/manifest.ini | 10 + plugins/roster_buttons/plugin.py | 6 - plugins/snarl_notifications/manifest.ini | 11 + plugins/snarl_notifications/plugin.py | 7 - src/plugins/gui.py | 2 +- src/plugins/pluginmanager.py | 215 +++++++++--------- 20 files changed, 198 insertions(+), 164 deletions(-) create mode 100644 plugins/acronyms_expander/manifest.ini create mode 100644 plugins/banner_tweaks/manifest.ini create mode 100644 plugins/dbus_plugin/manifest.ini create mode 100644 plugins/events_dump/manifest.ini create mode 100644 plugins/google_translation/manifest.ini create mode 100644 plugins/length_notifier/manifest.ini create mode 100644 plugins/new_events_example/manifest.ini create mode 100644 plugins/roster_buttons/manifest.ini create mode 100644 plugins/snarl_notifications/manifest.ini diff --git a/plugins/acronyms_expander/acronyms_expander.py b/plugins/acronyms_expander/acronyms_expander.py index 12ad677b0..919f1a12c 100644 --- a/plugins/acronyms_expander/acronyms_expander.py +++ b/plugins/acronyms_expander/acronyms_expander.py @@ -33,12 +33,6 @@ from plugins import GajimPlugin from plugins.helpers import log, log_calls class AcronymsExpanderPlugin(GajimPlugin): - name = u'Acronyms Expander' - short_name = u'acronyms_expander' - version = u'0.1' - description = u'''Replaces acronyms (or other strings) with given expansions/substitutes.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('AcronymsExpanderPlugin') def init(self): diff --git a/plugins/acronyms_expander/manifest.ini b/plugins/acronyms_expander/manifest.ini new file mode 100644 index 000000000..0674c2f88 --- /dev/null +++ b/plugins/acronyms_expander/manifest.ini @@ -0,0 +1,9 @@ +[info] +name: Acronyms Expander +short_name: acronyms_expander +version: 0.1 +description: Replaces acronyms (or other strings) with given expansions/substitutes. +authors: Mateusz Biliński +homepage: http://blog.bilinski.it + + diff --git a/plugins/banner_tweaks/manifest.ini b/plugins/banner_tweaks/manifest.ini new file mode 100644 index 000000000..4cc3652f7 --- /dev/null +++ b/plugins/banner_tweaks/manifest.ini @@ -0,0 +1,10 @@ +[info] +name: Banner Tweaks +short_name: banner_tweaks +version: 0.1 +description: Allows user to tweak chat window banner appearance (eg. make it compact). + Based on patch by pb in ticket #4133: + http://trac.gajim.org/attachment/ticket/4133. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + diff --git a/plugins/banner_tweaks/plugin.py b/plugins/banner_tweaks/plugin.py index 121606aa4..d959097e1 100644 --- a/plugins/banner_tweaks/plugin.py +++ b/plugins/banner_tweaks/plugin.py @@ -43,15 +43,6 @@ from plugins.helpers import log, log_calls from plugins.gui import GajimPluginConfigDialog class BannerTweaksPlugin(GajimPlugin): - name = u'Banner Tweaks' - short_name = u'banner_tweaks' - version = u'0.1' - description = u'''Allows user to tweak chat window banner appearance (eg. make it compact). - -Based on patch by pb in ticket #4133: -http://trac.gajim.org/attachment/ticket/4133''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('BannerTweaksPlugin') def init(self): diff --git a/plugins/dbus_plugin/manifest.ini b/plugins/dbus_plugin/manifest.ini new file mode 100644 index 000000000..6322eae99 --- /dev/null +++ b/plugins/dbus_plugin/manifest.ini @@ -0,0 +1,10 @@ +[info] +name: D-Bus Support +short_name: dbus +version: 0.1 +description: D-Bus support. Based on remote_control module from + Gajim core but uses new events handling system. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + + diff --git a/plugins/dbus_plugin/plugin.py b/plugins/dbus_plugin/plugin.py index c34e0ad0c..8db517c26 100644 --- a/plugins/dbus_plugin/plugin.py +++ b/plugins/dbus_plugin/plugin.py @@ -680,13 +680,6 @@ from plugins.helpers import log_calls, log from common import ged class DBusPlugin(GajimPlugin): - name = u'D-Bus Support' - short_name = u'dbus' - version = u'0.1' - description = u'''D-Bus support. Based on remote_control module from -Gajim core but uses new events handling system.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('DBusPlugin') def init(self): diff --git a/plugins/events_dump/manifest.ini b/plugins/events_dump/manifest.ini new file mode 100644 index 000000000..de46bca7f --- /dev/null +++ b/plugins/events_dump/manifest.ini @@ -0,0 +1,8 @@ +[info] +name: Events Dump +short_name: events_dump +version: 0.1 +description: Dumps info about selected events to console. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + diff --git a/plugins/events_dump/plugin.py b/plugins/events_dump/plugin.py index 3e816ae3a..0d1026165 100644 --- a/plugins/events_dump/plugin.py +++ b/plugins/events_dump/plugin.py @@ -33,12 +33,6 @@ from plugins.helpers import log_calls, log from common import ged class EventsDumpPlugin(GajimPlugin): - name = u'Events Dump' - short_name = u'events_dump' - version = u'0.1' - description = u'''Dumps info about selected events to console.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('EventsDumpPlugin') def init(self): diff --git a/plugins/google_translation/manifest.ini b/plugins/google_translation/manifest.ini new file mode 100644 index 000000000..5abbe3d9f --- /dev/null +++ b/plugins/google_translation/manifest.ini @@ -0,0 +1,8 @@ +[info] +name: Google Translation +short_name: google_translation +version: 0.1 +description: Translates (currently only incoming) messages using Google Translate. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + diff --git a/plugins/google_translation/plugin.py b/plugins/google_translation/plugin.py index 9b441a077..a0a4f6833 100644 --- a/plugins/google_translation/plugin.py +++ b/plugins/google_translation/plugin.py @@ -41,12 +41,6 @@ from common import ged from common import nec class GoogleTranslationPlugin(GajimPlugin): - name = u'Google Translation' - short_name = u'google_translation' - version = u'0.1' - description = u'''Translates (currently only incoming) messages using Google Translate.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('GoogleTranslationPlugin') def init(self): diff --git a/plugins/length_notifier/length_notifier.py b/plugins/length_notifier/length_notifier.py index cde132208..5a05c91c6 100644 --- a/plugins/length_notifier/length_notifier.py +++ b/plugins/length_notifier/length_notifier.py @@ -34,12 +34,6 @@ from plugins.helpers import log, log_calls from plugins.gui import GajimPluginConfigDialog class LengthNotifierPlugin(GajimPlugin): - name = u'Message Length Notifier' - short_name = u'length_notifier' - version = u'0.1' - description = u'''Highlights message entry field in chat window when given length of message is exceeded.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('LengthNotifierPlugin') def init(self): diff --git a/plugins/length_notifier/manifest.ini b/plugins/length_notifier/manifest.ini new file mode 100644 index 000000000..d50feaa8d --- /dev/null +++ b/plugins/length_notifier/manifest.ini @@ -0,0 +1,9 @@ +[info] +name: Message Length Notifier +short_name: length_notifier +version: 0.1 +description: Highlights message entry field in chat window when given length of message is exceeded. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + + diff --git a/plugins/new_events_example/manifest.ini b/plugins/new_events_example/manifest.ini new file mode 100644 index 000000000..a18423d6a --- /dev/null +++ b/plugins/new_events_example/manifest.ini @@ -0,0 +1,11 @@ +[info] +name: New Events Example +short_name: new_events_example +version: 0.1 +description: Shows how to generate new network events based on existing one using Network Events Controller. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + + + + diff --git a/plugins/new_events_example/plugin.py b/plugins/new_events_example/plugin.py index ff40dd56f..82712a422 100644 --- a/plugins/new_events_example/plugin.py +++ b/plugins/new_events_example/plugin.py @@ -38,12 +38,6 @@ from common import ged from common import nec class NewEventsExamplePlugin(GajimPlugin): - name = u'New Events Example' - short_name = u'new_events_example' - version = u'0.1' - description = u'''Shows how to generate new network events based on existing one using Network Events Controller.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('NewEventsExamplePlugin') def init(self): diff --git a/plugins/roster_buttons/manifest.ini b/plugins/roster_buttons/manifest.ini new file mode 100644 index 000000000..f928c1916 --- /dev/null +++ b/plugins/roster_buttons/manifest.ini @@ -0,0 +1,10 @@ +[info] +name: Roster Buttons +short_name: roster_buttons +version: 0.1 +description: Adds quick action buttons to roster window. +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + + + diff --git a/plugins/roster_buttons/plugin.py b/plugins/roster_buttons/plugin.py index a75fd8c6c..398804407 100644 --- a/plugins/roster_buttons/plugin.py +++ b/plugins/roster_buttons/plugin.py @@ -34,12 +34,6 @@ from plugins import GajimPlugin from plugins.helpers import log, log_calls class RosterButtonsPlugin(GajimPlugin): - name = u'Roster Buttons' - short_name = u'roster_buttons' - version = u'0.1' - description = u'''Adds quick action buttons to roster window.''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('RosterButtonsPlugin') def init(self): diff --git a/plugins/snarl_notifications/manifest.ini b/plugins/snarl_notifications/manifest.ini new file mode 100644 index 000000000..45597bfc0 --- /dev/null +++ b/plugins/snarl_notifications/manifest.ini @@ -0,0 +1,11 @@ +[info] +name: Snarl Notifications +short_name: snarl_notifications +version: 0.1 +description: Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system. + PySnarl bindings are used (http://code.google.com/p/pysnarl/). +authors = Mateusz Biliński +homepage = http://blog.bilinski.it + + + diff --git a/plugins/snarl_notifications/plugin.py b/plugins/snarl_notifications/plugin.py index 3e21acb77..c01194427 100644 --- a/plugins/snarl_notifications/plugin.py +++ b/plugins/snarl_notifications/plugin.py @@ -38,13 +38,6 @@ from plugins.helpers import log_calls, log from common import ged class SnarlNotificationsPlugin(GajimPlugin): - name = u'Snarl Notifications' - short_name = u'snarl_notifications' - version = u'0.1' - description = u'''Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system. -PySnarl bindings are used (http://code.google.com/p/pysnarl/).''' - authors = [u'Mateusz Biliński '] - homepage = u'http://blog.bilinski.it' @log_calls('SnarlNotificationsPlugin') def init(self): diff --git a/src/plugins/gui.py b/src/plugins/gui.py index 23de1fe84..aaecc707d 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -104,7 +104,7 @@ class PluginsWindow(object): def _display_installed_plugin_info(self, plugin): self.plugin_name_label.set_text(plugin.name) self.plugin_version_label.set_text(plugin.version) - self.plugin_authors_label.set_text(", ".join(plugin.authors)) + self.plugin_authors_label.set_text(plugin.authors) self.plugin_homepage_linkbutton.set_uri(plugin.homepage) self.plugin_homepage_linkbutton.set_label(plugin.homepage) self.plugin_homepage_linkbutton.set_property('sensitive', True) diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index 5328f4b72..b65e7e829 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -31,6 +31,7 @@ import sys import fnmatch import zipfile from shutil import rmtree +import ConfigParser from common import gajim from common import nec @@ -46,8 +47,9 @@ class PluginManager(object): Currently: - scans for plugins - activates them - - handles GUI extension points, when called by GUI objects after plugin - is activated (by dispatching info about call to handlers in plugins) + - handles GUI extension points, when called by GUI objects after + plugin is activated (by dispatching info about call to handlers + in plugins) :todo: add more info about how GUI extension points work :todo: add list of available GUI extension points @@ -58,10 +60,11 @@ class PluginManager(object): 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. + 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) ''' @@ -100,12 +103,8 @@ class PluginManager(object): for path in gajim.PLUGINS_DIRS: self.add_plugins(PluginManager.scan_dir_for_plugins(path)) - #log.debug('plugins: %s'%(self.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: @@ -135,8 +134,9 @@ class PluginManager(object): self.plugins.append(plugin) plugin.active = False else: - log.info('Not loading plugin %s v%s from module %s (identified by short name: %s). Plugin already loaded.'%( - plugin.name, plugin.version, plugin.__module__, plugin.short_name)) + log.info('Not loading plugin %s v%s from module %s (identified by + short name: %s). Plugin already loaded.' % (plugin.name, + plugin.version, plugin.__module__, plugin.short_name)) @log_calls('PluginManager') def add_plugins(self, plugin_classes): @@ -147,14 +147,14 @@ class PluginManager(object): def gui_extension_point(self, gui_extpoint_name, *args): ''' Invokes all handlers (from plugins) for particular GUI extension point - and adds it to collection for further processing (eg. by plugins not active - yet). + and adds it to collection for further processing (eg. by plugins not + active yet). :param gui_extpoint_name: name of GUI extension point. :type gui_extpoint_name: unicode :param args: parameters to be passed to extension point handlers - (typically and object that invokes `gui_extension_point`; however, - this can be practically anything) + (typically and object that invokes `gui_extension_point`; + however, this can be practically anything) :type args: tuple :todo: GUI extension points must be documented well - names with @@ -165,12 +165,13 @@ class PluginManager(object): :bug: what if only some handlers are successfully connected? we should revert all those connections that where successfully made. Maybe call 'self._deactivate_plugin()' or sth similar. - Looking closer - we only rewrite tuples here. Real check should be - made in method that invokes gui_extpoints handlers. + Looking closer - we only rewrite tuples here. Real check should + be made in method that invokes gui_extpoints handlers. ''' self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args) - self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args) + self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, + *args) @log_calls('PluginManager') def remove_gui_extension_point(self, gui_extpoint_name, *args): @@ -194,11 +195,11 @@ class PluginManager(object): extension points. The same arguments and the same name mean the same extension point. :todo: instead of using argument to identify which extpoint should be - removed, maybe add additional 'id' argument - this would work similar - hash in Python objects. 'id' would be calculated based on arguments - passed or on anything else (even could be constant). This would give - core developers (that add new extpoints) more freedom, but is this - necessary? + removed, maybe add additional 'id' argument - this would work + similar hash in Python objects. 'id' would be calculated based + on arguments passed or on anything else (even could be constant) + This would give core developers (that add new extpoints) more + freedom, but is this necessary? :param gui_extpoint_name: name of GUI extension point. :type gui_extpoint_name: unicode @@ -209,10 +210,8 @@ class PluginManager(object): ''' if gui_extpoint_name in self.gui_extension_points: - #log.debug('Removing GUI extpoint\n name: %s\n args: %s'%(gui_extpoint_name, args)) self.gui_extension_points[gui_extpoint_name].remove(args) - @log_calls('PluginManager') def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args): ''' @@ -229,36 +228,37 @@ class PluginManager(object): :type gui_extpoint_name: str :param args: parameters to be passed to extension point handlers - (typically and object that invokes `gui_extension_point`; however, - this can be practically anything) + (typically and object that invokes `gui_extension_point`; + however, this can be practically anything) :type args: tuple ''' if ((gui_extpoint_name not in self.gui_extension_points) - or (args not in self.gui_extension_points[gui_extpoint_name])): - self.gui_extension_points.setdefault(gui_extpoint_name, []).append(args) + or (args not in self.gui_extension_points[gui_extpoint_name])): + self.gui_extension_points.setdefault(gui_extpoint_name,[]).append( + args) @log_calls('PluginManager') - def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, *args): + def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, + *args): if gui_extpoint_name in self.gui_extension_points_handlers: - for handlers in self.gui_extension_points_handlers[gui_extpoint_name]: + for handlers in self.gui_extension_points_handlers[ + gui_extpoint_name]: handlers[0](*args) def _register_events_handlers_in_ged(self, plugin): for event_name, handler in plugin.events_handlers.iteritems(): priority = handler[0] handler_function = handler[1] - gajim.ged.register_event_handler(event_name, - priority, - handler_function) + gajim.ged.register_event_handler(event_name, priority, + handler_function) def _remove_events_handler_from_ged(self, plugin): for event_name, handler in plugin.events_handlers.iteritems(): priority = handler[0] handler_function = handler[1] - gajim.ged.remove_event_handler(event_name, - priority, - handler_function) + gajim.ged.remove_event_handler(event_name, priority, + handler_function) def _register_network_events_in_nec(self, plugin): for event_class in plugin.events: @@ -308,16 +308,18 @@ class PluginManager(object): # remove GUI extension points handlers (provided by plug-in) from # handlers list for gui_extpoint_name, gui_extpoint_handlers in \ - plugin.gui_extension_points.iteritems(): - self.gui_extension_points_handlers[gui_extpoint_name].remove(gui_extpoint_handlers) + plugin.gui_extension_points.iteritems(): + self.gui_extension_points_handlers[gui_extpoint_name].remove( + gui_extpoint_handlers) # 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.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]: + for gui_extension_point_args in self.gui_extension_points[ + gui_extpoint_name]: handler = gui_extpoint_handlers[1] if handler: handler(*gui_extension_point_args) @@ -338,16 +340,17 @@ class PluginManager(object): @log_calls('PluginManager') def _add_gui_extension_points_handlers_from_plugin(self, plugin): for gui_extpoint_name, gui_extpoint_handlers in \ - plugin.gui_extension_points.iteritems(): - self.gui_extension_points_handlers.setdefault(gui_extpoint_name, []).append( - gui_extpoint_handlers) + 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): for gui_extpoint_name, gui_extpoint_handlers in \ - plugin.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]: + for gui_extension_point_args in self.gui_extension_points[ + gui_extpoint_name]: handler = gui_extpoint_handlers[0] if handler: handler(*gui_extension_point_args) @@ -359,7 +362,6 @@ class PluginManager(object): Activated plugins are appended to `active_plugins` list. ''' - #self.active_plugins = [] for plugin in self.plugins: self.activate_plugin(plugin) @@ -393,71 +395,76 @@ class PluginManager(object): :todo: add scanning zipped modules ''' plugins_found = [] - if os.path.isdir(path): - dir_list = os.listdir(path) - #log.debug(dir_list) + conf = ConfigParser.ConfigParser() + fields = ('name', 'short_name', 'version', 'description', 'authors', + 'homepage') + if not os.path.isdir(path): + return - sys.path.insert(0, path) - #log.debug(sys.path) + dir_list = os.listdir(path) - for elem_name in dir_list: - #log.debug('- "%s"'%(elem_name)) - file_path = os.path.join(path, elem_name) - #log.debug(' "%s"'%(file_path)) + sys.path.insert(0, path) - module = None + for elem_name in dir_list: + file_path = os.path.join(path, elem_name) - if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'): - module_name = os.path.splitext(elem_name)[0] - #log.debug('Possible module detected.') - try: - module = __import__(module_name) - #log.debug('Module imported.') - except ValueError, value_error: - pass - #log.debug('Module not imported successfully. ValueError: %s'%(value_error)) - except ImportError, import_error: - pass - #log.debug('Module not imported successfully. ImportError: %s'%(import_error)) + module = None - elif os.path.isdir(file_path) and scan_dirs: - module_name = elem_name - file_path += os.path.sep - #log.debug('Possible package detected.') - try: - module = __import__(module_name) - #log.debug('Package imported.') - except ValueError, value_error: - pass - #log.debug('Package not imported successfully. ValueError: %s'%(value_error)) - except ImportError, import_error: - pass - #log.debug('Package not imported successfully. ImportError: %s'%(import_error)) + if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'): + module_name = os.path.splitext(elem_name)[0] + try: + module = __import__(module_name) + except ValueError, value_error: + pass + except ImportError, import_error: + pass + + elif os.path.isdir(file_path) and scan_dirs: + module_name = elem_name + file_path += os.path.sep + try: + module = __import__(module_name) + except ValueError, value_error: + pass + except ImportError, import_error: + pass - if module: - log.debug('Attributes processing started') - for module_attr_name in [attr_name for attr_name in dir(module) - if not (attr_name.startswith('__') or - attr_name.endswith('__'))]: - module_attr = getattr(module, module_attr_name) - log.debug('%s : %s'%(module_attr_name, module_attr)) + if module is None: + continue + log.debug('Attributes processing started') + for module_attr_name in [attr_name for attr_name in dir(module) + if not (attr_name.startswith('__') or attr_name.endswith('__'))]: + module_attr = getattr(module, module_attr_name) + log.debug('%s : %s' % (module_attr_name, module_attr)) - try: - if issubclass(module_attr, GajimPlugin) and \ - not module_attr is GajimPlugin: - log.debug('is subclass of GajimPlugin') - #log.debug('file_path: %s\nabspath: %s\ndirname: %s'%(file_path, os.path.abspath(file_path), os.path.dirname(os.path.abspath(file_path)))) - #log.debug('file_path: %s\ndirname: %s\nabspath: %s'%(file_path, os.path.dirname(file_path), os.path.abspath(os.path.dirname(file_path)))) - module_attr.__path__ = os.path.abspath(os.path.dirname(file_path)) - plugins_found.append(module_attr) - except TypeError, type_error: - pass - #log.debug('module_attr: %s, error : %s'%( - #module_name+'.'+module_attr_name, - #type_error)) + try: + if not issubclass(module_attr, GajimPlugin) or \ + module_attr is GajimPlugin: + continue + log.debug('is subclass of GajimPlugin') + module_attr.__path__ = os.path.abspath( + os.path.dirname(file_path)) - #log.debug(module) + manifest_path = os.path.join(module_attr.__path__, + 'manifest.ini') + # read metadata from manifest.ini + if not os.path.isfile(manifest_path): + continue + conf.readfp(open(manifest_path, 'r')) + for option in fields: + if conf.get('info', option) is '': + raise ConfigParser.NoOptionError, 'field empty' + setattr(module_attr, option, conf.get('info', option)) + conf.remove_section('info') + + plugins_found.append(module_attr) + + except TypeError, type_error: + pass + except ConfigParser.NoOptionError, type_error: + # all fields are required + pass return plugins_found From 05c7f05dd9447de9e26478fcc8d408143b4611f8 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sat, 18 Sep 2010 23:06:36 +0200 Subject: [PATCH 05/14] [Dicson] Don't always show Tray icon if "only when pending events" option is used. Fixes #5921 --- src/config.py | 2 -- src/statusicon.py | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config.py b/src/config.py index 49d8760de..9ec489b81 100644 --- a/src/config.py +++ b/src/config.py @@ -847,12 +847,10 @@ class PreferencesWindow: gajim.config.set('trayicon', 'on_event') gajim.interface.systray_enabled = True gajim.interface.systray.show_icon() - gajim.interface.systray.set_img() else: gajim.config.set('trayicon', 'always') gajim.interface.systray_enabled = True gajim.interface.systray.show_icon() - gajim.interface.systray.set_img() def on_advanced_notifications_button_clicked(self, widget): dialogs.AdvancedNotificationsWindow() diff --git a/src/statusicon.py b/src/statusicon.py index 6950fd41c..10d974ff0 100644 --- a/src/statusicon.py +++ b/src/statusicon.py @@ -97,7 +97,6 @@ class StatusIcon: self.on_status_icon_size_changed) self.set_img() - self.status_icon.set_visible(True) self.subscribe_events() def on_status_icon_right_clicked(self, widget, event_button, event_time): @@ -131,9 +130,14 @@ class StatusIcon: """ if not gajim.interface.systray_enabled: return + if gajim.config.get('trayicon') == 'always': + self.status_icon.set_visible(True) if gajim.events.get_nb_systray_events(): + self.status_icon.set_visible(True) self.status_icon.set_blinking(True) else: + if gajim.config.get('trayicon') == 'on_event': + self.status_icon.set_visible(False) self.status_icon.set_blinking(False) image = gajim.interface.jabber_state_images[self.statusicon_size][ From ba5725cb5d00a31569c67e2bd4de6076e66a3c0b Mon Sep 17 00:00:00 2001 From: Alexander Cherniuk Date: Sun, 19 Sep 2010 10:37:40 +0300 Subject: [PATCH 06/14] Can not break a string like that. --- src/plugins/pluginmanager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index b65e7e829..63b4f58db 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -134,8 +134,8 @@ class PluginManager(object): self.plugins.append(plugin) plugin.active = False else: - log.info('Not loading plugin %s v%s from module %s (identified by - short name: %s). Plugin already loaded.' % (plugin.name, + log.info('Not loading plugin %s v%s from module %s (identified by' + ' short name: %s). Plugin already loaded.' % (plugin.name, plugin.version, plugin.__module__, plugin.short_name)) @log_calls('PluginManager') From ae9d234dec6dc925dc1d67b5e9db1ec74b92dab1 Mon Sep 17 00:00:00 2001 From: Alexander Cherniuk Date: Sun, 19 Sep 2010 10:41:19 +0300 Subject: [PATCH 07/14] Add missing tooltips. Thanks to Dicson. Fixes #5924. --- data/gui/chat_control.ui | 18 ++++++++++++++++++ data/gui/groupchat_control.ui | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/data/gui/chat_control.ui b/data/gui/chat_control.ui index 6a4fcd9b8..e632a9c31 100644 --- a/data/gui/chat_control.ui +++ b/data/gui/chat_control.ui @@ -270,6 +270,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a list of emoticons (Alt+M) none False @@ -292,6 +294,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a list of formattings none False @@ -324,6 +328,8 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True + True + Add this contact to roster (Ctrl+D) none @@ -365,6 +371,8 @@ True True + True + Toggle audio session none @@ -383,6 +391,8 @@ True True + True + Toggle video session none @@ -403,6 +413,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Invite contacts to the conversation (Ctrl+G) none False @@ -425,6 +437,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show the contact's profile (Ctrl+I) none False @@ -447,6 +461,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Browse the chat history (Ctrl+H) none False @@ -480,6 +496,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a menu of advanced functions (Alt+D) none False diff --git a/data/gui/groupchat_control.ui b/data/gui/groupchat_control.ui index 86f9ee82b..d181491e8 100644 --- a/data/gui/groupchat_control.ui +++ b/data/gui/groupchat_control.ui @@ -166,6 +166,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a list of emoticons (Alt+M) none @@ -193,6 +195,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a list of formattings none False @@ -224,6 +228,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Change your nickname (Ctrl+N) none @@ -246,6 +252,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Change the room's subject (Alt+T) none @@ -269,6 +277,8 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True + True + Bookmark this room (Ctrl+B) none @@ -291,6 +301,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Browse the chat history (Ctrl+H) none @@ -323,6 +335,8 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Show a menu of advanced functions (Alt+D) none False From 07af278d0b78d982bd9b9dfbac1abf68db309d80 Mon Sep 17 00:00:00 2001 From: Alexander Cherniuk Date: Sun, 19 Sep 2010 10:59:44 +0300 Subject: [PATCH 08/14] Ignore nonexistent plugins directories --- src/plugins/pluginmanager.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index 63b4f58db..29091da63 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -99,9 +99,10 @@ class PluginManager(object): ''' Registered handlers of GUI extension points. ''' - for path in gajim.PLUGINS_DIRS: - self.add_plugins(PluginManager.scan_dir_for_plugins(path)) + pc = PluginManager.scan_dir_for_plugins(path) + if pc: + self.add_plugins(pc) self._activate_all_plugins_from_global_config() From 0a2458c69bae12267170c10cd93da37f5fcb2702 Mon Sep 17 00:00:00 2001 From: Alexander Cherniuk Date: Sun, 19 Sep 2010 11:03:25 +0300 Subject: [PATCH 09/14] A better fix for nonexistent plugins directories. --- src/plugins/pluginmanager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index 29091da63..de3d4e059 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -101,9 +101,7 @@ class PluginManager(object): ''' for path in gajim.PLUGINS_DIRS: pc = PluginManager.scan_dir_for_plugins(path) - if pc: - self.add_plugins(pc) - + self.add_plugins(pc) self._activate_all_plugins_from_global_config() @log_calls('PluginManager') @@ -400,7 +398,7 @@ class PluginManager(object): fields = ('name', 'short_name', 'version', 'description', 'authors', 'homepage') if not os.path.isdir(path): - return + return plugins_found dir_list = os.listdir(path) From 463eade6dc5b99f7449b96fd7762e6f4b1cc554a Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sun, 19 Sep 2010 22:14:43 +0200 Subject: [PATCH 10/14] don't request vcard to full JID but to barr JID --- src/groupchat_control.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/groupchat_control.py b/src/groupchat_control.py index 2cf491a3f..4fd329d1d 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -1444,8 +1444,6 @@ class GroupchatControl(ChatControlBase): con = gajim.connections[self.account] if gc_c and gc_c.jid: real_jid = gc_c.jid - if gc_c.resource: - real_jid += '/' + gc_c.resource else: real_jid = fake_jid if fake_jid in con.vcard_shas: From 2c9519203717c4e8f18b62f41f550978f536fb52 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Mon, 20 Sep 2010 07:08:47 +0200 Subject: [PATCH 11/14] [Dicson] check for manifest file when installing a plugin. Fixes #5925 --- src/dialogs.py | 9 ++++++--- src/plugins/gui.py | 25 +++++++++++++++++------- src/plugins/pluginmanager.py | 37 ++++++++++++++++++++++-------------- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/dialogs.py b/src/dialogs.py index e9ca65d96..558c5af2c 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -1467,12 +1467,15 @@ class WarningDialog(HigDialog): HIG compliant warning dialog """ - def __init__(self, pritext, sectext=''): + def __init__(self, pritext, sectext='', transient_for=None): HigDialog.__init__(self, None, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, pritext, sectext) self.set_modal(False) - if hasattr(gajim.interface, 'roster') and gajim.interface.roster: - self.set_transient_for(gajim.interface.roster.window) + if transient_for is None and hasattr(gajim.interface, 'roster') and \ + gajim.interface.roster: + transient_for = gajim.interface.roster.window + if transient_for: + self.set_transient_for(transient_for) self.popup() class InformationDialog(HigDialog): diff --git a/src/plugins/gui.py b/src/plugins/gui.py index aaecc707d..b0e526f1e 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -30,7 +30,7 @@ import pango import gtk, gobject import gtkgui_helpers -import dialogs +from dialogs import WarningDialog, YesNoDialog, ArchiveChooserDialog from common import gajim from plugins.helpers import log_calls, log from common.exceptions import PluginsystemError @@ -194,17 +194,26 @@ class PluginsWindow(object): try: gajim.plugin_manager.remove_plugin(plugin) except PluginsystemError, e: - dialogs.WarningDialog(_('Unable to properly remove the plugin'), + WarningDialog(_('Unable to properly remove the plugin'), str(e)) return model.remove(iter) @log_calls('PluginsWindow') def on_install_plugin_button_clicked(self, widget): + def show_warn_dialog(): + text = _('Archive is malformed') + dialog = WarningDialog(text, '', transient_for=self.window) + dialog.set_modal(False) + dialog.popup() + def _on_plugin_exists(zip_filename): def on_yes(is_checked): plugin = gajim.plugin_manager.install_from_zip(zip_filename, True) + if not plugin: + show_warn_dialog() + return model = self.installed_plugins_model for row in xrange(len(model)): @@ -216,8 +225,8 @@ class PluginsWindow(object): sel = self.installed_plugins_treeview.get_selection() sel.select_iter(iter_) - dialogs.YesNoDialog(_('Plugin already exists'), - sectext=_('Overwrite?'), on_response_yes=on_yes) + YesNoDialog(_('Plugin already exists'), sectext=_('Overwrite?'), + on_response_yes=on_yes) def _try_install(zip_filename): try: @@ -228,15 +237,17 @@ class PluginsWindow(object): _on_plugin_exists(zip_filename) return - dialogs.WarningDialog(error_text, '"%s"' % zip_filename) + WarningDialog(error_text, '"%s"' % zip_filename) + return + if not plugin: + show_warn_dialog() return - model = self.installed_plugins_model iter_ = model.append([plugin, plugin.name, False]) sel = self.installed_plugins_treeview.get_selection() sel.select_iter(iter_) - self.dialog = dialogs.ArchiveChooserDialog(on_response_ok=_try_install) + self.dialog = ArchiveChooserDialog(on_response_ok=_try_install) class GajimPluginConfigDialog(gtk.Dialog): diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index de3d4e059..d535081ae 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -431,6 +431,12 @@ class PluginManager(object): if module is None: continue + + manifest_path = os.path.join(os.path.dirname(file_path), + 'manifest.ini') + if scan_dirs and (not os.path.isfile(manifest_path)): + continue + log.debug('Attributes processing started') for module_attr_name in [attr_name for attr_name in dir(module) if not (attr_name.startswith('__') or attr_name.endswith('__'))]: @@ -445,11 +451,7 @@ class PluginManager(object): module_attr.__path__ = os.path.abspath( os.path.dirname(file_path)) - manifest_path = os.path.join(module_attr.__path__, - 'manifest.ini') # read metadata from manifest.ini - if not os.path.isfile(manifest_path): - continue conf.readfp(open(manifest_path, 'r')) for option in fields: if conf.get('info', option) is '': @@ -484,6 +486,7 @@ class PluginManager(object): raise PluginsystemError(_('Archive corrupted')) dirs = [] + manifest = None for filename in zip_file.namelist(): if filename.startswith('.') or filename.startswith('/') or \ ('/' not in filename): @@ -491,16 +494,18 @@ class PluginManager(object): raise PluginsystemError(_('Archive is malformed')) if filename.endswith('/') and filename.find('/', 0, -1) < 0: dirs.append(filename) - + if 'manifest.ini' in filename.split('/')[1]: + manifest = True + if not manifest: + return if len(dirs) > 1: - # several directories in the root of the archive raise PluginsystemError(_('Archive is malformed')) base_dir, user_dir = gajim.PLUGINS_DIRS plugin_dir = os.path.join(user_dir, dirs[0]) if os.path.isdir(plugin_dir): - # Plugin already exists + # Plugin dir already exists if not owerwrite: raise PluginsystemError(_('Plugin already exists')) self.remove_plugin(self.get_plugin_by_path(plugin_dir)) @@ -508,7 +513,10 @@ class PluginManager(object): zip_file.extractall(user_dir) zip_file.close() path = os.path.join(user_dir, dirs[0]) - self.add_plugin(self.scan_dir_for_plugins(plugin_dir, False)[0]) + plugins = self.scan_dir_for_plugins(plugin_dir, False) + if not plugins: + return + self.add_plugin(plugins[0]) plugin = self.plugins[-1] return plugin @@ -524,12 +532,13 @@ class PluginManager(object): # access is denied or other raise PluginsystemError(error[1]) - if plugin.active: - self.deactivate_plugin(plugin) - rmtree(plugin.__path__, False, on_error) - self.plugins.remove(plugin) - if self._plugin_has_entry_in_global_config(plugin): - self._remove_plugin_entry_in_global_config(plugin) + if plugin: + if plugin.active: + self.deactivate_plugin(plugin) + rmtree(plugin.__path__, False, on_error) + self.plugins.remove(plugin) + if self._plugin_has_entry_in_global_config(plugin): + self._remove_plugin_entry_in_global_config(plugin) def get_plugin_by_path(self, plugin_dir): for plugin in self.plugins: From 155595557d453e9fee4b7cab43963f2be7bc4aa9 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Mon, 20 Sep 2010 11:14:08 +0200 Subject: [PATCH 12/14] [Dicson] install manifest.ini files. Fixes #5927 --- plugins/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 65b97ed6e..36e963985 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -4,6 +4,7 @@ INCLUDES = \ gajimpluginsdir = $(gajim_pluginsdir) nobase_dist_gajimplugins_PYTHON = \ $(srcdir)/*/*.py \ + $(srcdir)/*/manifest.ini \ $(srcdir)/*/*.ui MAINTAINERCLEANFILES = Makefile.in From 8ce99327bd7d014a53a5b4b533eb256f92b17ded Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Tue, 21 Sep 2010 21:44:04 +0200 Subject: [PATCH 13/14] [Dicson] some error dialogs improvements. Fixes #5930 --- src/plugins/gui.py | 4 ++-- src/plugins/pluginmanager.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/gui.py b/src/plugins/gui.py index b0e526f1e..45e6b2927 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -195,7 +195,7 @@ class PluginsWindow(object): gajim.plugin_manager.remove_plugin(plugin) except PluginsystemError, e: WarningDialog(_('Unable to properly remove the plugin'), - str(e)) + str(e), self.window) return model.remove(iter) @@ -237,7 +237,7 @@ class PluginsWindow(object): _on_plugin_exists(zip_filename) return - WarningDialog(error_text, '"%s"' % zip_filename) + WarningDialog(error_text, '"%s"' % zip_filename, self.window) return if not plugin: show_warn_dialog() diff --git a/src/plugins/pluginmanager.py b/src/plugins/pluginmanager.py index d535081ae..5caefbe6b 100644 --- a/src/plugins/pluginmanager.py +++ b/src/plugins/pluginmanager.py @@ -530,7 +530,7 @@ class PluginManager(object): os.unlink(path) return # access is denied or other - raise PluginsystemError(error[1]) + raise PluginsystemError(error[1][1]) if plugin: if plugin.active: From 1d9a550ca85c35fc044f447eaeb613a993939d44 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Thu, 23 Sep 2010 13:05:33 +0200 Subject: [PATCH 14/14] ignore invalid payload types. Fixes #5919 --- src/common/jingle_rtp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/jingle_rtp.py b/src/common/jingle_rtp.py index c5e7a0441..62ae337fa 100644 --- a/src/common/jingle_rtp.py +++ b/src/common/jingle_rtp.py @@ -246,6 +246,9 @@ class JingleRTPContent(JingleContent): codecs = [] for codec in content.getTag('description').iterTags('payload-type'): + if not codec['id'] or not codec['name'] or not codec['clockrate']: + # ignore invalid payload-types + continue c = farsight.Codec(int(codec['id']), codec['name'], self.farsight_media, int(codec['clockrate'])) if 'channels' in codec: