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 
00236         info = {
00237             'handler': handler,
00238             'instance_id': instance_id
00239         }
00240         self._running_plugins[str(instance_id)] = info
00241 
00242     def _load_plugin_restore(self, handler, exception):
00243         qDebug('PluginManager._load_plugin_restore()')
00244         self._load_plugin_completed(handler, exception)
00245         if exception is None:
00246             # restore settings after load
00247             self._restore_plugin_settings(handler.instance_id(), self._emit_load_plugin_completed)
00248 
00249     def _load_plugin_completed(self, handler, exception):
00250         instance_id = handler.instance_id()
00251         if exception is not None:
00252             if isinstance(exception, PluginLoadError):
00253                 qWarning('PluginManager._load_plugin() could not load plugin "%s": %s' % (instance_id.plugin_id, exception))
00254             else:
00255                 qCritical('PluginManager._load_plugin() could not load plugin "%s"%s' % (instance_id.plugin_id, (':\n%s' % traceback.format_exc() if exception != True else '')))
00256             self._remove_running_plugin(instance_id)
00257             # quit embed application
00258             if self._application_context.options.embed_plugin:
00259                 exit(-1)
00260             return
00261 
00262         qDebug('PluginManager._load_plugin(%s) successful' % str(instance_id))
00263 
00264         handler.close_signal.connect(self.unload_plugin)
00265         handler.reload_signal.connect(self.reload_plugin)
00266         handler.help_signal.connect(self._emit_plugin_help_signal)
00267 
00268     def _emit_plugin_help_signal(self, instance_id_str):
00269         instance_id = PluginInstanceId(instance_id=instance_id_str)
00270         plugin_descriptor = self._plugin_descriptors[instance_id.plugin_id]
00271         self.plugin_help_signal.emit(plugin_descriptor)
00272 
00273     def _restore_plugin_settings(self, instance_id, callback):
00274         if self._global_settings is not None and self._perspective_settings is not None:
00275             info = self._running_plugins[str(instance_id)]
00276             plugin_settings = self._global_settings.get_settings('plugin__' + instance_id.tidy_plugin_str())
00277             instance_settings = self._perspective_settings.get_settings('plugin__' + instance_id.tidy_str())
00278             handler = info['handler']
00279             handler.restore_settings(plugin_settings, instance_settings, callback)
00280         else:
00281             callback(instance_id)
00282 
00283     def _emit_load_plugin_completed(self, instance_id):
00284         qDebug('PluginManager._emit_load_plugin_completed()')
00285         # restore state of top-level widgets
00286         self.plugins_changed_signal.emit()
00287 
00288 
00289     @Slot(str)
00290     def unload_plugin(self, instance_id_str):
00291         # unloading a plugin with locked perspective or running standalone triggers close of application
00292         if self._application_context.options.lock_perspective or self._application_context.options.standalone_plugin:
00293             self._close_application_signal()
00294             return
00295         instance_id = PluginInstanceId(instance_id=instance_id_str)
00296         qDebug('PluginManager.unload_plugin(%s)' % str(instance_id))
00297         # save state of top-level widgets
00298         self.plugins_about_to_change_signal.emit()
00299         # save settings before shutdown and unloading
00300         self._save_plugin_settings(instance_id, self._unload_plugin_shutdown)
00301 
00302     def _save_plugin_settings(self, instance_id, callback):
00303         if self._global_settings is not None and self._perspective_settings is not None:
00304             info = self._running_plugins[str(instance_id)]
00305             plugin_settings = self._global_settings.get_settings('plugin__' + instance_id.tidy_plugin_str())
00306             instance_settings = self._perspective_settings.get_settings('plugin__' + instance_id.tidy_str())
00307             handler = info['handler']
00308             handler.save_settings(plugin_settings, instance_settings, callback)
00309         else:
00310             callback(instance_id)
00311 
00312     def _unload_plugin_shutdown(self, instance_id):
00313         qDebug('PluginManager._unload_plugin_shutdown(%s)' % str(instance_id))
00314         self._shutdown_plugin(instance_id, self._unload_plugin_unload)
00315 
00316     def _shutdown_plugin(self, instance_id, callback):
00317         # shutdown plugin before unloading
00318         info = self._running_plugins[str(instance_id)]
00319         handler = info['handler']
00320         handler.close_signal.disconnect(self.unload_plugin)
00321         handler.shutdown_plugin(callback)
00322 
00323     def _unload_plugin_unload(self, instance_id):
00324         qDebug('PluginManager._unload_plugin_unload(%s)' % str(instance_id))
00325         self._unload_plugin(instance_id, self._unload_plugin_completed)
00326 
00327     def _unload_plugin(self, instance_id, callback=None):
00328         # unload plugin
00329         info = self._running_plugins[str(instance_id)]
00330         handler = info['handler']
00331         handler.unload(callback)
00332 
00333     def _unload_plugin_completed(self, instance_id):
00334         qDebug('PluginManager._unload_plugin_completed(%s)' % str(instance_id))
00335         self._remove_running_plugin(instance_id)
00336 
00337     def _remove_running_plugin(self, instance_id):
00338         if self._plugin_menu is not None:
00339             self._plugin_menu.remove_instance(instance_id)
00340         info = self._running_plugins[str(instance_id)]
00341         self._running_plugins.pop(str(instance_id))
00342 
00343 
00344     @Slot(str)
00345     def reload_plugin(self, instance_id_str):
00346         instance_id = PluginInstanceId(instance_id=instance_id_str)
00347         qDebug('PluginManager.reload_plugin(%s)' % str(instance_id))
00348         # save state of top-level widgets
00349         self.plugins_about_to_change_signal.emit()
00350         self._reload_plugin_save(instance_id)
00351 
00352     def _reload_plugin_save(self, instance_id):
00353         # save settings before unloading
00354         self._save_plugin_settings(instance_id, self._reload_plugin_shutdown)
00355 
00356     def _reload_plugin_shutdown(self, instance_id):
00357         qDebug('PluginManager._reload_plugin_shutdown(%s)' % str(instance_id))
00358         self._shutdown_plugin(instance_id, self._reload_plugin_unload)
00359 
00360     def _reload_plugin_unload(self, instance_id):
00361         qDebug('PluginManager._reload_plugin_unload(%s)' % str(instance_id))
00362         self._unload_plugin(instance_id, self._reload_plugin_schedule_load)
00363 
00364     def _reload_plugin_schedule_load(self, instance_id):
00365         qDebug('PluginManager._reload_plugin_schedule_load(%s)' % str(instance_id))
00366         self._remove_running_plugin(instance_id)
00367         self._deferred_reload_plugin_signal.emit(str(instance_id))
00368 
00369     def _reload_plugin_load(self, instance_id_str):
00370         instance_id = PluginInstanceId(instance_id=instance_id_str)
00371         qDebug('PluginManager._reload_plugin_load(%s)' % str(instance_id))
00372         self._load_plugin_load(instance_id, self._reload_plugin_restore)
00373 
00374     def _reload_plugin_restore(self, handler, exception):
00375         qDebug('PluginManager._reload_plugin_restore()')
00376         self._load_plugin_completed(handler, exception)
00377         if exception is None:
00378             # restore settings after load
00379             self._restore_plugin_settings(handler.instance_id(), self._emit_load_plugin_completed)
00380 
00381 
00382     def save_settings(self, global_settings, perspective_settings):
00383         self._save_settings(global_settings, perspective_settings, self._save_settings_callback)
00384 
00385     def _save_settings(self, global_settings, perspective_settings, callback):
00386         qDebug('PluginManager.save_settings()')
00387         self._global_settings = global_settings.get_settings('pluginmanager')
00388         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00389         self._store_running_plugins()
00390         # trigger async call on all running plugins
00391         self._number_of_ongoing_calls = len(self._running_plugins)
00392         if self._number_of_ongoing_calls > 0:
00393             for info in self._running_plugins.values():
00394                 self._save_plugin_settings(info['instance_id'], callback)
00395         else:
00396             callback()
00397 
00398     def _store_running_plugins(self):
00399         if self._perspective_settings is not None:
00400             plugins = {}
00401             for info in self._running_plugins.values():
00402                 instance_id = info['instance_id']
00403                 plugin_id = instance_id.plugin_id
00404                 if plugin_id not in plugins:
00405                     plugins[plugin_id] = []
00406                 plugins[plugin_id].append(instance_id.serial_number)
00407             self._perspective_settings.set_value('running-plugins', plugins)
00408 
00409     def _save_settings_callback(self, instance_id=None):
00410         if instance_id is not None:
00411             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00412         if self._number_of_ongoing_calls == 0:
00413             qDebug('PluginManager.save_settings() completed')
00414             self._number_of_ongoing_calls = None
00415             self.save_settings_completed_signal.emit()
00416 
00417 
00418     def close_application(self, global_settings, perspective_settings):
00419         self._save_settings(global_settings, perspective_settings, self._close_application_save_callback)
00420 
00421     def _close_application_save_callback(self, instance_id=None):
00422         self._save_settings_callback(instance_id)
00423         if self._number_of_ongoing_calls is None:
00424             self._close_application_shutdown_plugins()
00425 
00426     def _close_application_shutdown_plugins(self):
00427         # trigger async call on all running plugins
00428         self._number_of_ongoing_calls = len(self._running_plugins)
00429         if self._number_of_ongoing_calls > 0:
00430             for info in self._running_plugins.values():
00431                 self._shutdown_plugin(info['instance_id'], self._close_application_shutdown_callback)
00432         else:
00433             self._close_application_shutdown_callback()
00434 
00435     def _close_application_shutdown_callback(self, instance_id=None):
00436         if instance_id is not None:
00437             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00438         if self._number_of_ongoing_calls == 0:
00439             qDebug('PluginManager.close_application() completed')
00440             self._number_of_ongoing_calls = None
00441             self._close_application_signal()
00442 
00443     def _close_application_signal(self):
00444         self._plugin_provider.shutdown()
00445         self.close_application_signal.emit()
00446 
00447 
00448     def restore_settings(self, global_settings, perspective_settings):
00449         qDebug('PluginManager.restore_settings()')
00450         self._global_settings = global_settings.get_settings('pluginmanager')
00451         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00452         self._restore_settings_save_obsolete()
00453 
00454     def _restore_settings_save_obsolete(self):
00455         # trigger shutdown of obsolete plugins
00456         plugins = self._restore_running_plugins_get_plugins()
00457         obsolete = []
00458         for instance_id in self._running_plugins.keys():
00459             if instance_id not in plugins.keys():
00460                 obsolete.append(PluginInstanceId(instance_id=instance_id))
00461         self._number_of_ongoing_calls = len(obsolete)
00462         if self._number_of_ongoing_calls > 0:
00463             qDebug('PluginManager.restore_settings() unloading %d obsolete plugins' % self._number_of_ongoing_calls)
00464             for instance_id in obsolete:
00465                 self._shutdown_plugin(instance_id, self._restore_settings_unload_obsolete)
00466         else:
00467             self._restore_settings_unload_obsolete_callback()
00468 
00469     def _restore_running_plugins_get_plugins(self):
00470         plugins = {}
00471         if self._perspective_settings is not None:
00472             data = self._perspective_settings.value('running-plugins', {})
00473             for plugin_id, serial_numbers in data.items():
00474                 for serial_number in serial_numbers:
00475                     instance_id = PluginInstanceId(plugin_id, serial_number)
00476                     plugins[str(instance_id)] = instance_id
00477         return plugins
00478 
00479     def _restore_settings_unload_obsolete(self, instance_id):
00480         # trigger unload of obsolete plugins
00481         self._unload_plugin(instance_id, self._restore_settings_unload_obsolete_callback)
00482 
00483     def _restore_settings_unload_obsolete_callback(self, instance_id=None):
00484         if instance_id is not None:
00485             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00486             self._remove_running_plugin(instance_id)
00487         if self._number_of_ongoing_calls == 0:
00488             if instance_id is not None:
00489                 qDebug('PluginManager.restore_settings() all obsolete plugins unloaded')
00490             self._number_of_ongoing_calls = None
00491             self._restore_settings_load_missing()
00492 
00493     def _restore_settings_load_missing(self):
00494         # trigger_load of not yet loaded plugins
00495         plugins = self._restore_running_plugins_get_plugins()
00496         loading = []
00497         for instance_id_str, instance_id in plugins.items():
00498             if instance_id_str not in self._running_plugins.keys():
00499                 loading.append(instance_id)
00500         self._number_of_ongoing_calls = len(loading)
00501         if self._number_of_ongoing_calls > 0:
00502             qDebug('PluginManager.restore_settings() loading %d plugins' % self._number_of_ongoing_calls)
00503             for instance_id in loading:
00504                 self._load_plugin_load(instance_id, self._restore_settings_load_missing_callback)
00505         else:
00506             self._restore_settings_load_missing_callback()
00507 
00508     def _restore_settings_load_missing_callback(self, handler=None, exception=None):
00509         if handler is not None:
00510             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00511             self._load_plugin_completed(handler, exception)
00512         if self._number_of_ongoing_calls == 0:
00513             if handler is not None:
00514                 qDebug('PluginManager.restore_settings() all missing plugins loaded')
00515             self._number_of_ongoing_calls = None
00516             self._restore_settings_restore()
00517 
00518     def restore_settings_without_plugins(self, global_settings, perspective_settings):
00519         qDebug('PluginManager.restore_settings_without_plugins()')
00520         self._global_settings = global_settings.get_settings('pluginmanager')
00521         self._perspective_settings = perspective_settings.get_settings('pluginmanager')
00522         self._restore_settings_restore()
00523 
00524     def _restore_settings_restore(self):
00525         # trigger restore settings for all running plugins
00526         self._number_of_ongoing_calls = len(self._running_plugins)
00527         if self._number_of_ongoing_calls > 0:
00528             for info in self._running_plugins.values():
00529                 self._restore_plugin_settings(info['instance_id'], self._restore_settings_restore_callback)
00530         else:
00531             self._restore_settings_restore_callback()
00532 
00533     def _restore_settings_restore_callback(self, instance_id=None):
00534         if instance_id is not None:
00535             self._number_of_ongoing_calls = self._number_of_ongoing_calls - 1
00536         if self._number_of_ongoing_calls == 0:
00537             if instance_id is not None:
00538                 qDebug('PluginManager.restore_settings() all plugin settings restored')
00539             self._number_of_ongoing_calls = None
00540             # restore state of top-level widgets
00541             self.plugins_changed_signal.emit()


qt_gui
Author(s): Dirk Thomas
autogenerated on Fri Aug 28 2015 12:15:40