plugin_manager.py
Go to the documentation of this file.
00001 # Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt
00002 # All rights reserved.
00003 #
00004 # Redistribution and use in source and binary forms, with or without
00005 # modification, are permitted provided that the following conditions
00006 # are met:
00007 #
00008 #   * Redistributions of source code must retain the above copyright
00009 #     notice, this list of conditions and the following disclaimer.
00010 #   * Redistributions in binary form must reproduce the above
00011 #     copyright notice, this list of conditions and the following
00012 #     disclaimer in the documentation and/or other materials provided
00013 #     with the distribution.
00014 #   * Neither the name of the TU Darmstadt nor the names of its
00015 #     contributors may be used to endorse or promote products derived
00016 #     from this software without specific prior written permission.
00017 #
00018 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00028 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029 # POSSIBILITY OF SUCH DAMAGE.
00030 
00031 import os
00032 import time
00033 import traceback
00034 
00035 from python_qt_binding.QtCore import qCritical, qDebug, QObject, QSettings, Qt, qWarning, Signal, Slot
00036 
00037 from .errors import PluginLoadError
00038 from .plugin_handler_container import PluginHandlerContainer
00039 from .plugin_handler_direct import PluginHandlerDirect
00040 from .plugin_instance_id import PluginInstanceId
00041 from .plugin_menu import PluginMenu
00042 from .settings import Settings
00043 from .settings_proxy import SettingsProxy
00044 
00045 
00046 class PluginManager(QObject):
00047 
00048     """
00049     Manager of plugin life cycle.
00050     It creates a specific `PluginHandler` for each plugin instance and maintains the perspective specific set of running plugins.
00051     """
00052 
00053     plugins_about_to_change_signal = Signal()
00054     plugins_changed_signal = Signal()
00055     plugin_help_signal = Signal(object)
00056     save_settings_completed_signal = Signal()
00057     close_application_signal = Signal()
00058     _deferred_reload_plugin_signal = Signal(str)
00059 
00060     discovery_cache_max_age = 60 * 60 * 24  # one day
00061 
00062     def __init__(self, plugin_provider, settings, application_context, settings_prefix=''):
00063         super(PluginManager, self).__init__()
00064         self.setObjectName('PluginManager')
00065 
00066         self._plugin_provider = plugin_provider
00067         self._settings = Settings(SettingsProxy(settings), '/'.join([x for x in ['plugin_manager', settings_prefix] if x != '']))
00068         self._application_context = application_context
00069 
00070         self._main_window = None
00071         self._container_manager = None
00072         self._plugin_menu = None
00073         self._minimized_dock_widgets_toolbar = None
00074 
00075         self._global_settings = None
00076         self._perspective_settings = None
00077         self._plugin_descriptors = None
00078         self._running_plugins = {}
00079 
00080         self._number_of_ongoing_calls = None
00081 
00082         if self._application_context.options.multi_process or self._application_context.options.embed_plugin:
00083             try:
00084                 from .plugin_handler_xembed import PluginHandlerXEmbed  # @UnusedImport
00085             except ImportError:
00086                 qCritical('PluginManager.__init__() multiprocess-mode only available under linux')
00087                 exit(-1)
00088 
00089         # force connection type to queued, to delay the 'reloading' giving the 'unloading' time to finish
00090         self._deferred_reload_plugin_signal.connect(self._reload_plugin_load, type=Qt.QueuedConnection)
00091 
00092         if self._application_context.provide_app_dbus_interfaces:
00093             from .plugin_manager_dbus_interface import PluginManagerDBusInterface
00094             self._dbus_service = PluginManagerDBusInterface(self, self._application_context)
00095 
00096     def set_main_window(self, main_window, menu_bar, container_manager):
00097         self._main_window = main_window
00098         self._container_manager = container_manager
00099         self.plugins_changed_signal.connect(self._container_manager.restore_state_of_containers)
00100         if menu_bar is not None:
00101             self._plugin_menu = PluginMenu(menu_bar, self)
00102             self._plugin_menu.load_plugin_signal.connect(self.load_plugin)
00103             self._plugin_menu.unload_plugin_signal.connect(self.unload_plugin)
00104 
00105     def set_minimized_dock_widgets_toolbar(self, toolbar):
00106         self._minimized_dock_widgets_toolbar = toolbar
00107 
00108     def discover(self):
00109         # skip discover if called multiple times
00110         if self._plugin_descriptors is not None:
00111             return
00112         self._plugin_descriptors = {}
00113 
00114         # register discovered plugins
00115         plugin_descriptors = self._discover()
00116         for plugin_descriptor in plugin_descriptors:
00117             self._plugin_descriptors[plugin_descriptor.plugin_id()] = plugin_descriptor
00118 
00119             if self._plugin_menu is not None:
00120                 self._plugin_menu.add_plugin(plugin_descriptor)
00121 
00122         if self._container_manager is not None:
00123             descriptor = self._container_manager.get_container_descriptor()
00124             self._plugin_descriptors[descriptor.plugin_id()] = descriptor
00125             if self._plugin_menu is not None:
00126                 self._container_manager.add_to_plugin_menu(self._plugin_menu)
00127 
00128     def _discover(self):
00129         discovery_data = self._settings.get_settings('discovery_data')
00130         # check timestamp of the cached discovery data
00131         cache_stamp = self._settings.value('discovery_timestamp', default_value=None)
00132         if cache_stamp:
00133             cache_stamp = float(cache_stamp)
00134 
00135         # wipe cached data when forcing discovery or when cache is to old (or from the future)
00136         now = time.time()
00137         if self._application_context.options.force_discover or not cache_stamp or cache_stamp > now or cache_stamp + PluginManager.discovery_cache_max_age < now:
00138             qDebug('PluginManager._discover() force discovery of plugins')
00139             cache_stamp = None
00140             for k in discovery_data.all_keys():
00141                 discovery_data.remove(k)
00142         else:
00143             qDebug('PluginManager._discover() using cached plugin discovery information')
00144 
00145         plugin_descriptors = self._plugin_provider.discover(discovery_data)
00146 
00147         # store timestamp and newly discovered data
00148         if not cache_stamp:
00149             self._settings.set_value('discovery_timestamp', now)
00150 
00151         return plugin_descriptors
00152 
00153     def find_plugins_by_name(self, lookup_name):
00154         plugins = {}
00155         for plugin_id, plugin_full_name in self.get_plugins().items():
00156             if plugin_full_name.lower().find(lookup_name.lower()) >= 0 or plugin_id.lower().find(lookup_name.lower()) >= 0:
00157                 plugins[plugin_id] = plugin_full_name
00158         return plugins
00159 
00160     def get_plugins(self):
00161         self.discover()
00162         plugins = {}
00163         for plugin_id, plugin_descriptor in self._plugin_descriptors.items():
00164             plugins[plugin_id] = '/'.join(plugin_descriptor.attributes().get('class_type', 'unknown').split('::'))
00165         return plugins
00166 
00167     def get_plugin_descriptor(self, plugin_id):
00168         return self._plugin_descriptors.get(plugin_id, None)
00169 
00170     def is_plugin_running(self, plugin_id, serial_number):
00171         instance_id = PluginInstanceId(plugin_id, serial_number)
00172         return str(instance_id) in self._running_plugins
00173 
00174 
00175     @Slot(str)
00176     @Slot(str, int)
00177     def load_plugin(self, plugin_id, serial_number=None, argv=None):
00178         qDebug('PluginManager.load_plugin(%s, %s)' % (str(plugin_id), str(serial_number) if serial_number is not None else ''))
00179         # save state of top-level widgets
00180         self.plugins_about_to_change_signal.emit()
00181         if serial_number is None:
00182             serial_number = self._next_serial_number(plugin_id)
00183         instance_id = PluginInstanceId(plugin_id, serial_number)
00184         self._load_plugin_load(instance_id, self._load_plugin_restore, argv)
00185 
00186     def _next_serial_number(self, plugin_id):
00187         # convert from unicode
00188         plugin_id = str(plugin_id)
00189         # collect serial numbers of all running instances of the specific plugin
00190         used_serial_numbers = {}
00191         for info in self._running_plugins.values():
00192             if info['instance_id'].plugin_id == plugin_id:
00193                 used_serial_numbers[info['instance_id'].serial_number] = None
00194 
00195         # find first not used serial number
00196         serial_number = 1
00197         while serial_number in used_serial_numbers:
00198             serial_number = serial_number + 1
00199         return serial_number
00200 
00201     def _load_plugin_load(self, instance_id, callback, argv=None):
00202         # if the requested instance is already running, do nothing
00203         if str(instance_id) in self._running_plugins:
00204             raise Exception('PluginManager._load_plugin(%s) instance already loaded' % str(instance_id))
00205 
00206         # containers are pseudo-plugins and handled by a special handler
00207         if self._container_manager is not None and instance_id.plugin_id == self._container_manager.get_container_descriptor().plugin_id():
00208             handler = PluginHandlerContainer(self, self._main_window, instance_id, self._application_context, self._container_manager)
00209 
00210         # use platform specific handler for multiprocess-mode if available
00211         elif self._application_context.options.multi_process or self._application_context.options.embed_plugin:
00212             try:
00213                 from .plugin_handler_xembed import PluginHandlerXEmbed
00214                 handler = PluginHandlerXEmbed(self, self._main_window, instance_id, self._application_context, self._container_manager, argv)
00215             except ImportError:
00216                 qCritical('PluginManager._load_plugin() could not load plugin in a separate process')
00217                 return
00218 
00219         # use direct handler for in-process plugins
00220         else:
00221             handler = PluginHandlerDirect(self, self._main_window, instance_id, self._application_context, self._container_manager, argv)
00222 
00223         handler.set_minimized_dock_widgets_toolbar(self._minimized_dock_widgets_toolbar)
00224 
00225         plugin_descriptor = self._plugin_descriptors[instance_id.plugin_id]
00226         handler.set_plugin_descriptor(plugin_descriptor)
00227 
00228         self._add_running_plugin(instance_id, handler)
00229         handler.load(self._plugin_provider, callback)
00230 
00231     def _add_running_plugin(self, instance_id, handler):
00232         if self._plugin_menu is not None:
00233             plugin_descriptor = self._plugin_descriptors[instance_id.plugin_id]
00234             self._plugin_menu.add_instance(plugin_descriptor, instance_id)
00235             handler.label_updated.connect(self._plugin_menu.update_plugin_instance_label)
00236 
00237         info = {
00238             'handler': handler,
00239             'instance_id': instance_id
00240         }
00241         self._running_plugins[str(instance_id)] = info
00242 
00243     def _load_plugin_restore(self, handler, exception):
00244         qDebug('PluginManager._load_plugin_restore()')
00245         self._load_plugin_completed(handler, exception)
00246         if exception is None:
00247             # restore settings after load
00248             self._restore_plugin_settings(handler.instance_id(), self._emit_load_plugin_completed)
00249 
00250     def _load_plugin_completed(self, handler, exception):
00251         instance_id = handler.instance_id()
00252         if exception is not None:
00253             if isinstance(exception, PluginLoadError):
00254                 qWarning('PluginManager._load_plugin() could not load plugin "%s": %s' % (instance_id.plugin_id, exception))
00255             else:
00256                 qCritical('PluginManager._load_plugin() could not load plugin "%s"%s' % (instance_id.plugin_id, (':\n%s' % traceback.format_exc() if exception != True else '')))
00257             self._remove_running_plugin(instance_id)
00258             # quit embed application
00259             if self._application_context.options.embed_plugin:
00260                 exit(-1)
00261             return
00262 
00263         qDebug('PluginManager._load_plugin(%s) successful' % str(instance_id))
00264 
00265         handler.close_signal.connect(self.unload_plugin)
00266         handler.reload_signal.connect(self.reload_plugin)
00267         handler.help_signal.connect(self._emit_plugin_help_signal)
00268 
00269     def _emit_plugin_help_signal(self, instance_id_str):
00270         instance_id = PluginInstanceId(instance_id=instance_id_str)
00271         plugin_descriptor = self._plugin_descriptors[instance_id.plugin_id]
00272         self.plugin_help_signal.emit(plugin_descriptor)
00273 
00274     def _restore_plugin_settings(self, instance_id, callback):
00275         if self._global_settings is not None and self._perspective_settings is not None:
00276             info = self._running_plugins[str(instance_id)]
00277             plugin_settings = self._global_settings.get_settings('plugin__' + instance_id.tidy_plugin_str())
00278             instance_settings = self._perspective_settings.get_settings('plugin__' + instance_id.tidy_str())
00279             handler = info['handler']
00280             handler.restore_settings(plugin_settings, instance_settings, callback)
00281         else:
00282             callback(instance_id)
00283 
00284     def _emit_load_plugin_completed(self, instance_id):
00285         qDebug('PluginManager._emit_load_plugin_completed()')
00286         # restore state of top-level widgets
00287         self.plugins_changed_signal.emit()
00288 
00289 
00290     @Slot(str)
00291     def unload_plugin(self, instance_id_str):
00292         # unloading a plugin with locked perspective or running standalone triggers close of application
00293         if self._application_context.options.lock_perspective or self._application_context.options.standalone_plugin:
00294             self._close_application_signal()
00295             return
00296         instance_id = PluginInstanceId(instance_id=instance_id_str)
00297         qDebug('PluginManager.unload_plugin(%s)' % str(instance_id))
00298         # save state of top-level widgets
00299         self.plugins_about_to_change_signal.emit()
00300         # save settings before shutdown and unloading
00301         self._save_plugin_settings(instance_id, self._unload_plugin_shutdown)
00302 
00303     def _save_plugin_settings(self, instance_id, callback):
00304         if self._global_settings is not None and self._perspective_settings is not None:
00305             info = self._running_plugins[str(instance_id)]
00306             plugin_settings = self._global_settings.get_settings('plugin__' + instance_id.tidy_plugin_str())
00307             instance_settings = self._perspective_settings.get_settings('plugin__' + instance_id.tidy_str())
00308             handler = info['handler']
00309             handler.save_settings(plugin_settings, instance_settings, callback)
00310         else:
00311             callback(instance_id)
00312 
00313     def _unload_plugin_shutdown(self, instance_id):
00314         qDebug('PluginManager._unload_plugin_shutdown(%s)' % str(instance_id))
00315         self._shutdown_plugin(instance_id, self._unload_plugin_unload)
00316 
00317     def _shutdown_plugin(self, instance_id, callback):
00318         # shutdown plugin before unloading
00319         info = self._running_plugins[str(instance_id)]
00320         handler = info['handler']
00321         handler.close_signal.disconnect(self.unload_plugin)
00322         handler.shutdown_plugin(callback)
00323 
00324     def _unload_plugin_unload(self, instance_id):
00325         qDebug('PluginManager._unload_plugin_unload(%s)' % str(instance_id))
00326         self._unload_plugin(instance_id, self._unload_plugin_completed)
00327 
00328     def _unload_plugin(self, instance_id, callback=None):
00329         # unload plugin
00330         info = self._running_plugins[str(instance_id)]
00331         handler = info['handler']
00332         handler.unload(callback)
00333 
00334     def _unload_plugin_completed(self, instance_id):
00335         qDebug('PluginManager._unload_plugin_completed(%s)' % str(instance_id))
00336         self._remove_running_plugin(instance_id)
00337 
00338     def _remove_running_plugin(self, instance_id):
00339         info = self._running_plugins[str(instance_id)]
00340         if self._plugin_menu is not None:
00341             self._plugin_menu.remove_instance(instance_id)
00342             info['handler'].label_updated.disconnect(self._plugin_menu.update_plugin_instance_label)
00343         self._running_plugins.pop(str(instance_id))
00344 
00345 
00346     @Slot(str)
00347     def reload_plugin(self, instance_id_str):
00348         instance_id = PluginInstanceId(instance_id=instance_id_str)
00349         qDebug('PluginManager.reload_plugin(%s)' % str(instance_id))
00350         # save state of top-level widgets
00351         self.plugins_about_to_change_signal.emit()
00352         self._reload_plugin_save(instance_id)
00353 
00354     def _reload_plugin_save(self, instance_id):
00355         # save settings before unloading
00356         self._save_plugin_settings(instance_id, self._reload_plugin_shutdown)
00357 
00358     def _reload_plugin_shutdown(self, instance_id):
00359         qDebug('PluginManager._reload_plugin_shutdown(%s)' % str(instance_id))
00360         self._shutdown_plugin(instance_id, self._reload_plugin_unload)
00361 
00362     def _reload_plugin_unload(self, instance_id):
00363         qDebug('PluginManager._reload_plugin_unload(%s)' % str(instance_id))
00364         self._unload_plugin(instance_id, self._reload_plugin_schedule_load)
00365 
00366     def _reload_plugin_schedule_load(self, instance_id):
00367         qDebug('PluginManager._reload_plugin_schedule_load(%s)' % str(instance_id))
00368         self._remove_running_plugin(instance_id)
00369         self._deferred_reload_plugin_signal.emit(str(instance_id))
00370 
00371     def _reload_plugin_load(self, instance_id_str):
00372         instance_id = PluginInstanceId(instance_id=instance_id_str)
00373         qDebug('PluginManager._reload_plugin_load(%s)' % str(instance_id))
00374         self._load_plugin_load(instance_id, self._reload_plugin_restore)
00375 
00376     def _reload_plugin_restore(self, handler, exception):
00377         qDebug('PluginManager._reload_plugin_restore()')
00378         self._load_plugin_completed(handler, exception)
00379         if exception is None:
00380             # restore settings after load
00381             self._restore_plugin_settings(handler.instance_id(), self._emit_load_plugin_completed)
00382 
00383 
00384     def save_settings(self, global_settings, perspective_settings):
00385         self._save_settings(global_settings, perspective_settings, self._save_settings_callback)
00386 
00387     def _save_settings(self, global_settings, perspective_settings, callback):
00388         qDebug('PluginManager.save_settings()')
00389         self._global_settings = global_settings.get_settings('pluginmanager')
00390         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00391         self._store_running_plugins()
00392         # trigger async call on all running plugins
00393         self._number_of_ongoing_calls = len(self._running_plugins)
00394         if self._number_of_ongoing_calls > 0:
00395             for info in self._running_plugins.values():
00396                 self._save_plugin_settings(info['instance_id'], callback)
00397         else:
00398             callback()
00399 
00400     def _store_running_plugins(self):
00401         if self._perspective_settings is not None:
00402             plugins = {}
00403             for info in self._running_plugins.values():
00404                 instance_id = info['instance_id']
00405                 plugin_id = instance_id.plugin_id
00406                 if plugin_id not in plugins:
00407                     plugins[plugin_id] = []
00408                 plugins[plugin_id].append(instance_id.serial_number)
00409             self._perspective_settings.set_value('running-plugins', plugins)
00410 
00411     def _save_settings_callback(self, instance_id=None):
00412         if instance_id is not None:
00413             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00414         if self._number_of_ongoing_calls == 0:
00415             qDebug('PluginManager.save_settings() completed')
00416             self._number_of_ongoing_calls = None
00417             self.save_settings_completed_signal.emit()
00418 
00419 
00420     def close_application(self, global_settings, perspective_settings):
00421         self._save_settings(global_settings, perspective_settings, self._close_application_save_callback)
00422 
00423     def _close_application_save_callback(self, instance_id=None):
00424         self._save_settings_callback(instance_id)
00425         if self._number_of_ongoing_calls is None:
00426             self._close_application_shutdown_plugins()
00427 
00428     def _close_application_shutdown_plugins(self):
00429         # trigger async call on all running plugins
00430         self._number_of_ongoing_calls = len(self._running_plugins)
00431         if self._number_of_ongoing_calls > 0:
00432             for info in self._running_plugins.values():
00433                 self._shutdown_plugin(info['instance_id'], self._close_application_shutdown_callback)
00434         else:
00435             self._close_application_shutdown_callback()
00436 
00437     def _close_application_shutdown_callback(self, instance_id=None):
00438         if instance_id is not None:
00439             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00440         if self._number_of_ongoing_calls == 0:
00441             qDebug('PluginManager.close_application() completed')
00442             self._number_of_ongoing_calls = None
00443             self._close_application_signal()
00444 
00445     def _close_application_signal(self):
00446         self._plugin_provider.shutdown()
00447         self.close_application_signal.emit()
00448 
00449 
00450     def restore_settings(self, global_settings, perspective_settings):
00451         qDebug('PluginManager.restore_settings()')
00452         self._global_settings = global_settings.get_settings('pluginmanager')
00453         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00454         self._restore_settings_save_obsolete()
00455 
00456     def _restore_settings_save_obsolete(self):
00457         # trigger shutdown of obsolete plugins
00458         plugins = self._restore_running_plugins_get_plugins()
00459         obsolete = []
00460         for instance_id in self._running_plugins.keys():
00461             if instance_id not in plugins.keys():
00462                 obsolete.append(PluginInstanceId(instance_id=instance_id))
00463         self._number_of_ongoing_calls = len(obsolete)
00464         if self._number_of_ongoing_calls > 0:
00465             qDebug('PluginManager.restore_settings() unloading %d obsolete plugins' % self._number_of_ongoing_calls)
00466             for instance_id in obsolete:
00467                 self._shutdown_plugin(instance_id, self._restore_settings_unload_obsolete)
00468         else:
00469             self._restore_settings_unload_obsolete_callback()
00470 
00471     def _restore_running_plugins_get_plugins(self):
00472         plugins = {}
00473         if self._perspective_settings is not None:
00474             data = self._perspective_settings.value('running-plugins', {})
00475             for plugin_id, serial_numbers in data.items():
00476                 for serial_number in serial_numbers:
00477                     instance_id = PluginInstanceId(plugin_id, serial_number)
00478                     plugins[str(instance_id)] = instance_id
00479         return plugins
00480 
00481     def _restore_settings_unload_obsolete(self, instance_id):
00482         # trigger unload of obsolete plugins
00483         self._unload_plugin(instance_id, self._restore_settings_unload_obsolete_callback)
00484 
00485     def _restore_settings_unload_obsolete_callback(self, instance_id=None):
00486         if instance_id is not None:
00487             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00488             self._remove_running_plugin(instance_id)
00489         if self._number_of_ongoing_calls == 0:
00490             if instance_id is not None:
00491                 qDebug('PluginManager.restore_settings() all obsolete plugins unloaded')
00492             self._number_of_ongoing_calls = None
00493             self._restore_settings_load_missing()
00494 
00495     def _restore_settings_load_missing(self):
00496         # trigger_load of not yet loaded plugins
00497         plugins = self._restore_running_plugins_get_plugins()
00498         loading = []
00499         for instance_id_str, instance_id in plugins.items():
00500             if instance_id_str not in self._running_plugins.keys():
00501                 loading.append(instance_id)
00502         self._number_of_ongoing_calls = len(loading)
00503         if self._number_of_ongoing_calls > 0:
00504             qDebug('PluginManager.restore_settings() loading %d plugins' % self._number_of_ongoing_calls)
00505             for instance_id in loading:
00506                 self._load_plugin_load(instance_id, self._restore_settings_load_missing_callback)
00507         else:
00508             self._restore_settings_load_missing_callback()
00509 
00510     def _restore_settings_load_missing_callback(self, handler=None, exception=None):
00511         if handler is not None:
00512             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00513             self._load_plugin_completed(handler, exception)
00514         if self._number_of_ongoing_calls == 0:
00515             if handler is not None:
00516                 qDebug('PluginManager.restore_settings() all missing plugins loaded')
00517             self._number_of_ongoing_calls = None
00518             self._restore_settings_restore()
00519 
00520     def restore_settings_without_plugins(self, global_settings, perspective_settings):
00521         qDebug('PluginManager.restore_settings_without_plugins()')
00522         self._global_settings = global_settings.get_settings('pluginmanager')
00523         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00524         self._restore_settings_restore()
00525 
00526     def _restore_settings_restore(self):
00527         # trigger restore settings for all running plugins
00528         self._number_of_ongoing_calls = len(self._running_plugins)
00529         if self._number_of_ongoing_calls > 0:
00530             for info in self._running_plugins.values():
00531                 self._restore_plugin_settings(info['instance_id'], self._restore_settings_restore_callback)
00532         else:
00533             self._restore_settings_restore_callback()
00534 
00535     def _restore_settings_restore_callback(self, instance_id=None):
00536         if instance_id is not None:
00537             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00538         if self._number_of_ongoing_calls == 0:
00539             if instance_id is not None:
00540                 qDebug('PluginManager.restore_settings() all plugin settings restored')
00541             self._number_of_ongoing_calls = None
00542             # restore state of top-level widgets
00543             self.plugins_changed_signal.emit()


qt_gui
Author(s): Dirk Thomas
autogenerated on Thu Jun 6 2019 18:07:34