← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/bootstrap into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/bootstrap into lp:openlp.

Requested reviews:
  Raoul Snyman (raoul-snyman)

For more details, see:
https://code.launchpad.net/~trb143/openlp/bootstrap/+merge/150622

Implementation of a two phase bootstrap.

Maniwindow initialisation has been cleaned up and functions moved batch into their own classes.

Some minor code cleanups as well.

Cleanup the tests for PluginManager tests fixed but 2 are not relevant as we have moved to use the Registry.
Tests commented out for now.

Reinstate servicemanagertest as this now no longer starts the plugins when initialising mainwindow. 
-- 
https://code.launchpad.net/~trb143/openlp/bootstrap/+merge/150622
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2013-02-16 12:30:16 +0000
+++ openlp/core/__init__.py	2013-02-26 17:28:26 +0000
@@ -136,6 +136,8 @@
         self.processEvents()
         # start the main app window
         self.main_window = MainWindow()
+        Registry().execute(u'bootstrap_initialise')
+        Registry().execute(u'bootstrap_post_set_up')
         self.main_window.show()
         if show_splash:
             # now kill the splashscreen

=== modified file 'openlp/core/lib/pluginmanager.py'
--- openlp/core/lib/pluginmanager.py	2013-02-17 12:57:52 +0000
+++ openlp/core/lib/pluginmanager.py	2013-02-26 17:28:26 +0000
@@ -54,11 +54,37 @@
         """
         log.info(u'Plugin manager Initialising')
         Registry().register(u'plugin_manager', self)
+        Registry().register_function(u'bootstrap_initialise', self.bootstrap_initialise)
         self.base_path = os.path.abspath(AppLocation.get_directory(AppLocation.PluginsDir))
         log.debug(u'Base path %s ', self.base_path)
         self.plugins = []
         log.info(u'Plugin manager Initialised')
 
+    def bootstrap_initialise(self):
+        """
+        Bootstrap all the plugin manager functions
+        """
+        log.info(u'bootstrap_initialise')
+        self.find_plugins()
+        # hook methods have to happen after find_plugins. Find plugins needs
+        # the controllers hence the hooks have moved from setupUI() to here
+        # Find and insert settings tabs
+        log.info(u'hook settings')
+        self.hook_settings_tabs()
+        # Find and insert media manager items
+        log.info(u'hook media')
+        self.hook_media_manager()
+        # Call the hook method to pull in import menus.
+        log.info(u'hook menus')
+        self.hook_import_menu()
+        # Call the hook method to pull in export menus.
+        self.hook_export_menu()
+        # Call the hook method to pull in tools menus.
+        self.hook_tools_menu()
+        # Call the initialise method to setup plugins.
+        log.info(u'initialise plugins')
+        self.initialise_plugins()
+
     def find_plugins(self):
         """
         Scan a directory for objects inheriting from the ``Plugin`` class.
@@ -118,56 +144,44 @@
             if plugin.status is not PluginStatus.Disabled:
                 plugin.createMediaManagerItem()
 
-    def hook_settings_tabs(self, settings_form=None):
+    def hook_settings_tabs(self):
         """
         Loop through all the plugins. If a plugin has a valid settings tab
         item, add it to the settings tab.
         Tabs are set for all plugins not just Active ones
 
-        ``settings_form``
-            Defaults to *None*. The settings form to add tabs to.
         """
         for plugin in self.plugins:
             if plugin.status is not PluginStatus.Disabled:
-                plugin.createSettingsTab(settings_form)
-        if settings_form:
-            settings_form.plugins = self.plugins
+                plugin.createSettingsTab(self.settings_form)
 
-    def hook_import_menu(self, import_menu):
+    def hook_import_menu(self):
         """
         Loop through all the plugins and give them an opportunity to add an
         item to the import menu.
 
-        ``import_menu``
-            The Import menu.
         """
         for plugin in self.plugins:
             if plugin.status is not PluginStatus.Disabled:
-                plugin.addImportMenuItem(import_menu)
+                plugin.addImportMenuItem(self.main_window.file_import_menu)
 
-    def hook_export_menu(self, export_menu):
+    def hook_export_menu(self):
         """
         Loop through all the plugins and give them an opportunity to add an
         item to the export menu.
-
-        ``export_menu``
-            The Export menu.
         """
         for plugin in self.plugins:
             if plugin.status is not PluginStatus.Disabled:
-                plugin.addExportMenuItem(export_menu)
+                plugin.addExportMenuItem(self.main_window.file_export_menu)
 
-    def hook_tools_menu(self, tools_menu):
+    def hook_tools_menu(self):
         """
         Loop through all the plugins and give them an opportunity to add an
         item to the tools menu.
-
-        ``tools_menu``
-            The Tools menu.
         """
         for plugin in self.plugins:
             if plugin.status is not PluginStatus.Disabled:
-                plugin.addToolsMenuItem(tools_menu)
+                plugin.addToolsMenuItem(self.main_window.tools_menu)
 
     def initialise_plugins(self):
         """
@@ -211,3 +225,23 @@
             if plugin.isActive():
                 plugin.new_service_created()
 
+    def _get_settings_form(self):
+        """
+        Adds the plugin manager to the class dynamically
+        """
+        if not hasattr(self, u'_settings_form'):
+            self._settings_form = Registry().get(u'settings_form')
+        return self._settings_form
+
+    settings_form = property(_get_settings_form)
+
+    def _get_main_window(self):
+        """
+        Adds the main window to the class dynamically
+        """
+        if not hasattr(self, u'_main_window'):
+            self._main_window = Registry().get(u'main_window')
+        return self._main_window
+
+    main_window = property(_get_main_window)
+

=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2013-02-07 08:42:17 +0000
+++ openlp/core/lib/renderer.py	2013-02-26 17:28:26 +0000
@@ -662,4 +662,3 @@
         return self._theme_manager
 
     theme_manager = property(_get_theme_manager)
-

=== modified file 'openlp/core/lib/settingstab.py'
--- openlp/core/lib/settingstab.py	2013-02-02 21:16:42 +0000
+++ openlp/core/lib/settingstab.py	2013-02-26 17:28:26 +0000
@@ -123,7 +123,7 @@
         """
         self.load()
 
-    def postSetUp(self, postUpdate=False):
+    def post_set_up(self, postUpdate=False):
         """
         Changes which need to be made after setup of application
 

=== modified file 'openlp/core/ui/generaltab.py'
--- openlp/core/ui/generaltab.py	2013-02-09 17:13:27 +0000
+++ openlp/core/ui/generaltab.py	2013-02-26 17:28:26 +0000
@@ -308,9 +308,9 @@
         settings.setValue(u'audio repeat list', self.repeatListCheckBox.isChecked())
         settings.endGroup()
         # On save update the screens as well
-        self.postSetUp(True)
+        self.post_set_up(True)
 
-    def postSetUp(self, postUpdate=False):
+    def post_set_up(self, postUpdate=False):
         """
         Apply settings after settings tab has loaded and most of the
         system so must be delayed

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2013-02-20 07:02:48 +0000
+++ openlp/core/ui/mainwindow.py	2013-02-26 17:28:26 +0000
@@ -105,13 +105,13 @@
         self.controlSplitter.setObjectName(u'controlSplitter')
         self.mainContentLayout.addWidget(self.controlSplitter)
         # Create slide controllers
-        self.previewController = SlideController(self)
-        self.liveController = SlideController(self, True)
+        self.preview_controller = SlideController(self)
+        self.live_controller = SlideController(self, True)
         previewVisible = Settings().value(u'user interface/preview panel')
-        self.previewController.panel.setVisible(previewVisible)
+        self.preview_controller.panel.setVisible(previewVisible)
         liveVisible = Settings().value(u'user interface/live panel')
         panelLocked = Settings().value(u'user interface/lock panel')
-        self.liveController.panel.setVisible(liveVisible)
+        self.live_controller.panel.setVisible(liveVisible)
         # Create menu
         self.menuBar = QtGui.QMenuBar(main_window)
         self.menuBar.setObjectName(u'menuBar')
@@ -119,18 +119,18 @@
         self.fileMenu.setObjectName(u'fileMenu')
         self.recentFilesMenu = QtGui.QMenu(self.fileMenu)
         self.recentFilesMenu.setObjectName(u'recentFilesMenu')
-        self.fileImportMenu = QtGui.QMenu(self.fileMenu)
-        self.fileImportMenu.setObjectName(u'fileImportMenu')
-        self.fileExportMenu = QtGui.QMenu(self.fileMenu)
-        self.fileExportMenu.setObjectName(u'fileExportMenu')
+        self.file_import_menu = QtGui.QMenu(self.fileMenu)
+        self.file_import_menu.setObjectName(u'file_import_menu')
+        self.file_export_menu = QtGui.QMenu(self.fileMenu)
+        self.file_export_menu.setObjectName(u'file_export_menu')
         # View Menu
         self.viewMenu = QtGui.QMenu(self.menuBar)
         self.viewMenu.setObjectName(u'viewMenu')
         self.viewModeMenu = QtGui.QMenu(self.viewMenu)
         self.viewModeMenu.setObjectName(u'viewModeMenu')
         # Tools Menu
-        self.toolsMenu = QtGui.QMenu(self.menuBar)
-        self.toolsMenu.setObjectName(u'toolsMenu')
+        self.tools_menu = QtGui.QMenu(self.menuBar)
+        self.tools_menu.setObjectName(u'tools_menu')
         # Settings Menu
         self.settingsMenu = QtGui.QMenu(self.menuBar)
         self.settingsMenu.setObjectName(u'settingsMenu')
@@ -308,11 +308,13 @@
             can_shortcuts=True,
             category=UiStrings().Help, triggers=self.onOnlineHelpClicked)
         self.webSiteItem = create_action(main_window, u'webSiteItem', can_shortcuts=True, category=UiStrings().Help)
-        add_actions(self.fileImportMenu, (self.settingsImportItem, None, self.importThemeItem, self.importLanguageItem))
-        add_actions(self.fileExportMenu, (self.settingsExportItem, None, self.exportThemeItem, self.exportLanguageItem))
+        add_actions(self.file_import_menu, (self.settingsImportItem, None, self.importThemeItem,
+            self.importLanguageItem))
+        add_actions(self.file_export_menu, (self.settingsExportItem, None, self.exportThemeItem,
+            self.exportLanguageItem))
         add_actions(self.fileMenu, (self.fileNewItem, self.fileOpenItem,
             self.fileSaveItem, self.fileSaveAsItem, self.recentFilesMenu.menuAction(), None,
-            self.fileImportMenu.menuAction(), self.fileExportMenu.menuAction(), None, self.printServiceOrderItem,
+            self.file_import_menu.menuAction(), self.file_export_menu.menuAction(), None, self.printServiceOrderItem,
             self.fileExitItem))
         add_actions(self.viewModeMenu, (self.modeDefaultItem, self.modeSetupItem, self.modeLiveItem))
         add_actions(self.viewMenu, (self.viewModeMenu.menuAction(), None, self.viewMediaManagerItem,
@@ -329,16 +331,16 @@
         else:
             add_actions(self.settingsMenu, (self.settingsPluginListItem, self.settingsLanguageMenu.menuAction(), None,
                 self.formattingTagItem, self.settingsShortcutsItem, self.settingsConfigureItem))
-        add_actions(self.toolsMenu, (self.toolsAddToolItem, None))
-        add_actions(self.toolsMenu, (self.toolsOpenDataFolder, None))
-        add_actions(self.toolsMenu, (self.toolsFirstTimeWizard, None))
-        add_actions(self.toolsMenu, [self.updateThemeImages])
+        add_actions(self.tools_menu, (self.toolsAddToolItem, None))
+        add_actions(self.tools_menu, (self.toolsOpenDataFolder, None))
+        add_actions(self.tools_menu, (self.toolsFirstTimeWizard, None))
+        add_actions(self.tools_menu, [self.updateThemeImages])
         if os.name == u'nt':
             add_actions(self.helpMenu, (self.offlineHelpItem, self.onlineHelpItem, None, self.webSiteItem,
                 self.aboutItem))
         else:
             add_actions(self.helpMenu, (self.onlineHelpItem, None, self.webSiteItem, self.aboutItem))
-        add_actions(self.menuBar, (self.fileMenu.menuAction(), self.viewMenu.menuAction(), self.toolsMenu.menuAction(),
+        add_actions(self.menuBar, (self.fileMenu.menuAction(), self.viewMenu.menuAction(), self.tools_menu.menuAction(),
             self.settingsMenu.menuAction(), self.helpMenu.menuAction()))
         # Initialise the translation
         self.retranslateUi(main_window)
@@ -359,12 +361,12 @@
         mainWindow.mainTitle = UiStrings().OLPV2x
         mainWindow.setWindowTitle(mainWindow.mainTitle)
         self.fileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
-        self.fileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
-        self.fileExportMenu.setTitle(translate('OpenLP.MainWindow', '&Export'))
+        self.file_import_menu.setTitle(translate('OpenLP.MainWindow', '&Import'))
+        self.file_export_menu.setTitle(translate('OpenLP.MainWindow', '&Export'))
         self.recentFilesMenu.setTitle(translate('OpenLP.MainWindow', '&Recent Files'))
         self.viewMenu.setTitle(translate('OpenLP.MainWindow', '&View'))
         self.viewModeMenu.setTitle(translate('OpenLP.MainWindow', 'M&ode'))
-        self.toolsMenu.setTitle(translate('OpenLP.MainWindow', '&Tools'))
+        self.tools_menu.setTitle(translate('OpenLP.MainWindow', '&Tools'))
         self.settingsMenu.setTitle(translate('OpenLP.MainWindow', '&Settings'))
         self.settingsLanguageMenu.setTitle(translate('OpenLP.MainWindow', '&Language'))
         self.helpMenu.setTitle(translate('OpenLP.MainWindow', '&Help'))
@@ -478,102 +480,70 @@
         self.playersSettingsSection = u'players'
         self.displayTagsSection = u'displayTags'
         self.headerSection = u'SettingsImport'
+        self.recentFiles = []
+        self.timer_id = 0
+        self.timer_version_id = 0
+        self.new_data_path = None
+        self.copy_data = False
         Settings().set_up_default_values()
         Settings().remove_obsolete_settings()
         self.serviceNotSaved = False
         self.aboutForm = AboutForm(self)
-        self.mediaController = MediaController(self)
+        self.media_controller = MediaController(self)
         self.settingsForm = SettingsForm(self)
         self.formattingTagForm = FormattingTagForm(self)
         self.shortcutForm = ShortcutListForm(self)
-        self.recentFiles = []
-        self.timer_id = 0
-        self.timer_version_id = 0
         # Set up the path with plugins
         self.plugin_manager = PluginManager()
-        self.imageManager = ImageManager()
+        self.image_manager = ImageManager()
         # Set up the interface
         self.setupUi(self)
-        # Register the active media players and suffixes
-        self.mediaController.check_available_media_players()
+        # Define the media Dock Manager
+        self.mediaDockManager = MediaDockManager(self.mediaToolBox)
         # Load settings after setupUi so default UI sizes are overwritten
         self.loadSettings()
         # Once settings are loaded update the menu with the recent files.
         self.updateRecentFilesMenu()
         self.pluginForm = PluginForm(self)
-        self.new_data_path = None
-        self.copy_data = False
         # Set up signals and slots
-        QtCore.QObject.connect(self.importThemeItem, QtCore.SIGNAL(u'triggered()'),
-            self.themeManagerContents.on_import_theme)
-        QtCore.QObject.connect(self.exportThemeItem, QtCore.SIGNAL(u'triggered()'),
-            self.themeManagerContents.on_export_theme)
         QtCore.QObject.connect(self.mediaManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'),
-            self.viewMediaManagerItem.setChecked)
+                               self.viewMediaManagerItem.setChecked)
         QtCore.QObject.connect(self.serviceManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'),
-            self.viewServiceManagerItem.setChecked)
+                               self.viewServiceManagerItem.setChecked)
         QtCore.QObject.connect(self.themeManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'),
-            self.viewThemeManagerItem.setChecked)
-        QtCore.QObject.connect(self.webSiteItem, QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked)
-        QtCore.QObject.connect(self.toolsOpenDataFolder, QtCore.SIGNAL(u'triggered()'),
-            self.onToolsOpenDataFolderClicked)
-        QtCore.QObject.connect(self.toolsFirstTimeWizard, QtCore.SIGNAL(u'triggered()'), self.onFirstTimeWizardClicked)
-        QtCore.QObject.connect(self.updateThemeImages, QtCore.SIGNAL(u'triggered()'), self.onUpdateThemeImages)
-        QtCore.QObject.connect(self.formattingTagItem, QtCore.SIGNAL(u'triggered()'), self.onFormattingTagItemClicked)
-        QtCore.QObject.connect(self.settingsConfigureItem, QtCore.SIGNAL(u'triggered()'),
-            self.onSettingsConfigureItemClicked)
-        QtCore.QObject.connect(self.settingsShortcutsItem, QtCore.SIGNAL(u'triggered()'),
-            self.onSettingsShortcutsItemClicked)
-        QtCore.QObject.connect(self.settingsImportItem, QtCore.SIGNAL(u'triggered()'),
-            self.onSettingsImportItemClicked)
-        QtCore.QObject.connect(self.settingsExportItem, QtCore.SIGNAL(u'triggered()'), self.onSettingsExportItemClicked)
+                               self.viewThemeManagerItem.setChecked)
+        self.importThemeItem.triggered.connect(self.themeManagerContents.on_import_theme)
+        self.exportThemeItem.triggered.connect(self.themeManagerContents.on_export_theme)
+        self.webSiteItem.triggered.connect(self.onHelpWebSiteClicked)
+        self.toolsOpenDataFolder.triggered.connect(self.onToolsOpenDataFolderClicked)
+        self.toolsFirstTimeWizard.triggered.connect(self.onFirstTimeWizardClicked)
+        self.updateThemeImages.triggered.connect(self.onUpdateThemeImages)
+        self.formattingTagItem.triggered.connect(self.onFormattingTagItemClicked)
+        self.settingsConfigureItem.triggered.connect(self.onSettingsConfigureItemClicked)
+        self.settingsShortcutsItem.triggered.connect(self.onSettingsShortcutsItemClicked)
+        self.settingsImportItem.triggered.connect(self.onSettingsImportItemClicked)
+        self.settingsExportItem.triggered.connect(self.onSettingsExportItemClicked)
         # i18n set signals for languages
         self.languageGroup.triggered.connect(LanguageManager.set_language)
-        QtCore.QObject.connect(self.modeDefaultItem, QtCore.SIGNAL(u'triggered()'), self.onModeDefaultItemClicked)
-        QtCore.QObject.connect(self.modeSetupItem, QtCore.SIGNAL(u'triggered()'), self.onModeSetupItemClicked)
-        QtCore.QObject.connect(self.modeLiveItem, QtCore.SIGNAL(u'triggered()'), self.onModeLiveItemClicked)
+        self.modeDefaultItem.triggered.connect(self.onModeDefaultItemClicked)
+        self.modeSetupItem.triggered.connect(self.onModeSetupItemClicked)
+        self.modeLiveItem.triggered.connect(self.onModeLiveItemClicked)
         # Media Manager
-        QtCore.QObject.connect(self.mediaToolBox, QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
+        self.mediaToolBox.currentChanged.connect(self.onMediaToolBoxChanged)
         self.application.set_busy_cursor()
         # Simple message boxes
         Registry().register_function(u'theme_update_global', self.default_theme_changed)
         Registry().register_function(u'openlp_version_check', self.version_notice)
         Registry().register_function(u'config_screen_changed', self.screen_changed)
         self.renderer = Renderer()
-        # Define the media Dock Manager
-        self.mediaDockManager = MediaDockManager(self.mediaToolBox)
-        log.info(u'Load Plugins')
-        self.plugin_manager.find_plugins()
-        # hook methods have to happen after find_plugins. Find plugins needs
-        # the controllers hence the hooks have moved from setupUI() to here
-        # Find and insert settings tabs
-        log.info(u'hook settings')
-        self.plugin_manager.hook_settings_tabs(self.settingsForm)
-        # Find and insert media manager items
-        log.info(u'hook media')
-        self.plugin_manager.hook_media_manager()
-        # Call the hook method to pull in import menus.
-        log.info(u'hook menus')
-        self.plugin_manager.hook_import_menu(self.fileImportMenu)
-        # Call the hook method to pull in export menus.
-        self.plugin_manager.hook_export_menu(self.fileExportMenu)
-        # Call the hook method to pull in tools menus.
-        self.plugin_manager.hook_tools_menu(self.toolsMenu)
-        # Call the initialise method to setup plugins.
-        log.info(u'initialise plugins')
-        self.plugin_manager.initialise_plugins()
         # Create the displays as all necessary components are loaded.
-        self.previewController.screenSizeChanged()
-        self.liveController.screenSizeChanged()
+        self.preview_controller.screenSizeChanged()
+        self.live_controller.screenSizeChanged()
         log.info(u'Load data from Settings')
         if Settings().value(u'advanced/save current plugin'):
             savedPlugin = Settings().value(u'advanced/current media plugin')
             if savedPlugin != -1:
                 self.mediaToolBox.setCurrentIndex(savedPlugin)
-        self.settingsForm.postSetUp()
-        # Once all components are initialised load the Themes
-        log.info(u'Load Themes')
-        self.themeManagerContents.load_themes(True)
         # Reset the cursor
         self.application.set_normal_cursor()
 
@@ -608,8 +578,8 @@
         Show the main form, as well as the display form
         """
         QtGui.QWidget.show(self)
-        if self.liveController.display.isVisible():
-            self.liveController.display.setFocus()
+        if self.live_controller.display.isVisible():
+            self.live_controller.display.setFocus()
         self.activateWindow()
         if self.arguments:
             args = []
@@ -702,7 +672,7 @@
         Check and display message if screen blank on setup.
         """
         settings = Settings()
-        self.liveController.mainDisplaySetBackground()
+        self.live_controller.mainDisplaySetBackground()
         if settings.value(u'%s/screen blank' % self.generalSettingsSection):
             if settings.value(u'%s/blank warning' % self.generalSettingsSection):
                 QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Main Display Blanked'),
@@ -809,8 +779,8 @@
         """
         We need to make sure, that the SlidePreview's size is correct.
         """
-        self.previewController.previewSizeChanged()
-        self.liveController.previewSizeChanged()
+        self.preview_controller.previewSizeChanged()
+        self.live_controller.previewSizeChanged()
 
     def onSettingsShortcutsItemClicked(self):
         """
@@ -1018,10 +988,10 @@
         """
         log.debug(u'screen_changed')
         self.application.set_busy_cursor()
-        self.imageManager.update_display()
+        self.image_manager.update_display()
         self.renderer.update_display()
-        self.previewController.screenSizeChanged()
-        self.liveController.screenSizeChanged()
+        self.preview_controller.screenSizeChanged()
+        self.live_controller.screenSizeChanged()
         self.setFocus()
         self.activateWindow()
         self.application.set_normal_cursor()
@@ -1074,8 +1044,8 @@
         ``save_settings``
             Switch to prevent saving settings. Defaults to **True**.
         """
-        self.imageManager.stop_manager = True
-        while self.imageManager.image_thread.isRunning():
+        self.image_manager.stop_manager = True
+        while self.image_manager.image_thread.isRunning():
             time.sleep(0.1)
         # Clean temporary files used by services
         self.serviceManagerContents.clean_up()
@@ -1092,9 +1062,9 @@
         if self.new_data_path:
             self.changeDataDirectory()
         # Close down the display
-        if self.liveController.display:
-            self.liveController.display.close()
-            self.liveController.display = None
+        if self.live_controller.display:
+            self.live_controller.display.close()
+            self.live_controller.display = None
 
     def serviceChanged(self, reset=False, serviceName=None):
         """
@@ -1175,7 +1145,7 @@
                 True - Visible
                 False - Hidden
         """
-        self.previewController.panel.setVisible(visible)
+        self.preview_controller.panel.setVisible(visible)
         Settings().setValue(u'user interface/preview panel', visible)
         self.viewPreviewPanel.setChecked(visible)
 
@@ -1213,7 +1183,7 @@
                 True - Visible
                 False - Hidden
         """
-        self.liveController.panel.setVisible(visible)
+        self.live_controller.panel.setVisible(visible)
         Settings().setValue(u'user interface/live panel', visible)
         self.viewLivePanel.setChecked(visible)
 
@@ -1233,8 +1203,8 @@
         self.move(settings.value(u'main window position'))
         self.restoreGeometry(settings.value(u'main window geometry'))
         self.restoreState(settings.value(u'main window state'))
-        self.liveController.splitter.restoreState(settings.value(u'live splitter geometry'))
-        self.previewController.splitter.restoreState(settings.value(u'preview splitter geometry'))
+        self.live_controller.splitter.restoreState(settings.value(u'live splitter geometry'))
+        self.preview_controller.splitter.restoreState(settings.value(u'preview splitter geometry'))
         self.controlSplitter.restoreState(settings.value(u'main window splitter geometry'))
         settings.endGroup()
 
@@ -1254,8 +1224,8 @@
         settings.setValue(u'main window position', self.pos())
         settings.setValue(u'main window state', self.saveState())
         settings.setValue(u'main window geometry', self.saveGeometry())
-        settings.setValue(u'live splitter geometry', self.liveController.splitter.saveState())
-        settings.setValue(u'preview splitter geometry', self.previewController.splitter.saveState())
+        settings.setValue(u'live splitter geometry', self.live_controller.splitter.saveState())
+        settings.setValue(u'preview splitter geometry', self.preview_controller.splitter.saveState())
         settings.setValue(u'main window splitter geometry', self.controlSplitter.saveState())
         settings.endGroup()
 

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2013-02-07 08:42:17 +0000
+++ openlp/core/ui/media/mediacontroller.py	2013-02-26 17:28:26 +0000
@@ -99,6 +99,7 @@
         """
         self.mainWindow = parent
         Registry().register(u'media_controller', self)
+        Registry().register_function(u'bootstrap_initialise', self.check_available_media_players)
         self.mediaPlayers = {}
         self.displayControllers = {}
         self.currentMediaPlayer = {}

=== modified file 'openlp/core/ui/media/playertab.py'
--- openlp/core/ui/media/playertab.py	2013-02-07 08:42:17 +0000
+++ openlp/core/ui/media/playertab.py	2013-02-26 17:28:26 +0000
@@ -232,7 +232,7 @@
             Registry().execute(u'mediaitem_media_rebuild')
             Registry().execute(u'config_screen_changed')
 
-    def postSetUp(self, postUpdate=False):
+    def post_set_up(self):
         """
         Late setup for players as the MediaController has to be initialised
         first.

=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py	2013-02-07 08:42:17 +0000
+++ openlp/core/ui/settingsform.py	2013-02-26 17:28:26 +0000
@@ -50,6 +50,7 @@
         Initialise the settings form
         """
         Registry().register(u'settings_form', self)
+        Registry().register_function(u'bootstrap_post_set_up', self.post_set_up)
         QtGui.QDialog.__init__(self, parent)
         self.setupUi(self)
         # General tab
@@ -75,7 +76,7 @@
         self.insertTab(self.advancedTab, 2, PluginStatus.Active)
         self.insertTab(self.playerTab, 3, PluginStatus.Active)
         count = 4
-        for plugin in self.plugins:
+        for plugin in self.plugin_manager.plugins:
             if plugin.settingsTab:
                 self.insertTab(plugin.settingsTab, count, plugin.status)
                 count += 1
@@ -118,17 +119,17 @@
             self.stackedLayout.widget(tabIndex).cancel()
         return QtGui.QDialog.reject(self)
 
-    def postSetUp(self):
+    def post_set_up(self):
         """
         Run any post-setup code for the tabs on the form
         """
-        self.generalTab.postSetUp()
-        self.themesTab.postSetUp()
-        self.advancedTab.postSetUp()
-        self.playerTab.postSetUp()
-        for plugin in self.plugins:
+        self.generalTab.post_set_up()
+        self.themesTab.post_set_up()
+        self.advancedTab.post_set_up()
+        self.playerTab.post_set_up()
+        for plugin in self.plugin_manager.plugins:
             if plugin.settingsTab:
-                plugin.settingsTab.postSetUp()
+                plugin.settingsTab.post_set_up()
 
     def tabChanged(self, tabIndex):
         """
@@ -166,3 +167,13 @@
         return self._service_manager
 
     service_manager = property(_get_service_manager)
+
+    def _get_plugin_manager(self):
+        """
+        Adds the plugin manager to the class dynamically
+        """
+        if not hasattr(self, u'_plugin_manager'):
+            self._plugin_manager = Registry().get(u'plugin_manager')
+        return self._plugin_manager
+
+    plugin_manager = property(_get_plugin_manager)

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2013-02-16 13:24:56 +0000
+++ openlp/core/ui/thememanager.py	2013-02-26 17:28:26 +0000
@@ -60,6 +60,7 @@
         """
         QtGui.QWidget.__init__(self, parent)
         Registry().register(u'theme_manager', self)
+        Registry().register_function(u'bootstrap_initialise', self.load_first_time_themes)
         self.settingsSection = u'themes'
         self.themeForm = ThemeForm(self)
         self.fileRenameForm = FileRenameForm()
@@ -145,18 +146,6 @@
         # Last little bits of setting up
         self.config_updated()
 
-    def first_time(self):
-        """
-        Import new themes downloaded by the first time wizard
-        """
-        self.application.set_busy_cursor()
-        files = SettingsManager.get_files(self.settingsSection, u'.otz')
-        for theme_file in files:
-            theme_file = os.path.join(self.path, theme_file)
-            self.unzip_theme(theme_file, self.path)
-            delete_file(theme_file)
-        self.application.set_normal_cursor()
-
     def config_updated(self):
         """
         Triggered when Config dialog is updated.
@@ -410,9 +399,30 @@
         self.load_themes()
         self.application.set_normal_cursor()
 
-    def load_themes(self, first_time=False):
-        """
-        Loads the theme lists and triggers updates accross the whole system
+    def load_first_time_themes(self):
+        """
+        Imports any themes on start up and makes sure there is at least one theme
+        """
+        self.application.set_busy_cursor()
+        files = SettingsManager.get_files(self.settingsSection, u'.otz')
+        for theme_file in files:
+            theme_file = os.path.join(self.path, theme_file)
+            self.unzip_theme(theme_file, self.path)
+            delete_file(theme_file)
+        files = SettingsManager.get_files(self.settingsSection, u'.png')
+        # No themes have been found so create one
+        if not files:
+            theme = ThemeXML()
+            theme.theme_name = UiStrings().Default
+            self._write_theme(theme, None, None)
+            Settings().setValue(self.settingsSection + u'/global theme', theme.theme_name)
+            self.config_updated()
+        self.application.set_normal_cursor()
+        self.load_themes()
+
+    def load_themes(self):
+        """
+        Loads the theme lists and triggers updates across the whole system
         using direct calls or core functions and events for the plugins.
         The plugins will call back in to get the real list if they want it.
         """
@@ -420,18 +430,7 @@
         self.theme_list = []
         self.theme_list_widget.clear()
         files = SettingsManager.get_files(self.settingsSection, u'.png')
-        if first_time:
-            self.first_time()
-            files = SettingsManager.get_files(self.settingsSection, u'.png')
-            # No themes have been found so create one
-            if not files:
-                theme = ThemeXML()
-                theme.theme_name = UiStrings().Default
-                self._write_theme(theme, None, None)
-                Settings().setValue(self.settingsSection + u'/global theme', theme.theme_name)
-                self.config_updated()
-                files = SettingsManager.get_files(self.settingsSection, u'.png')
-        # Sort the themes by its name considering language specific
+          # Sort the themes by its name considering language specific
         files.sort(key=lambda file_name: unicode(file_name), cmp=locale_compare)
         # now process the file list of png files
         for name in files:

=== modified file 'openlp/core/ui/themestab.py'
--- openlp/core/ui/themestab.py	2013-02-07 11:33:47 +0000
+++ openlp/core/ui/themestab.py	2013-02-26 17:28:26 +0000
@@ -155,7 +155,7 @@
         self.renderer.set_theme_level(self.theme_level)
         Registry().execute(u'theme_update_global', self.global_theme)
 
-    def postSetUp(self):
+    def post_set_up(self):
         """
         After setting things up...
         """

=== modified file 'openlp/plugins/alerts/alertsplugin.py'
--- openlp/plugins/alerts/alertsplugin.py	2013-02-21 21:26:24 +0000
+++ openlp/plugins/alerts/alertsplugin.py	2013-02-26 17:28:26 +0000
@@ -151,7 +151,8 @@
             text=translate('AlertsPlugin', '&Alert'), icon=u':/plugins/plugin_alerts.png',
             statustip=translate('AlertsPlugin', 'Show an alert message.'),
             visible=False, can_shortcuts=True, triggers=self.onAlertsTrigger)
-        self.main_window.toolsMenu.addAction(self.toolsAlertItem)
+        self.main_window.tools_menu.addAction(self.toolsAlertItem)
+
 
     def initialise(self):
         log.info(u'Alerts Initialising')

=== modified file 'tests/functional/openlp_core_lib/test_pluginmanager.py'
--- tests/functional/openlp_core_lib/test_pluginmanager.py	2013-02-17 13:03:59 +0000
+++ tests/functional/openlp_core_lib/test_pluginmanager.py	2013-02-26 17:28:26 +0000
@@ -18,8 +18,15 @@
         """
         Some pre-test setup required.
         """
+        self.mocked_main_window = MagicMock()
+        self.mocked_main_window.file_import_menu.return_value = True
+        self.mocked_main_window.file_export_menu.return_value = True
+        self.mocked_main_window.file_export_menu.return_value = True
+        self.mocked_settings_form = MagicMock()
         Registry.create()
         Registry().register(u'service_list', MagicMock())
+        Registry().register(u'main_window', self.mocked_main_window)
+        Registry().register(u'settings_form', self.mocked_settings_form)
 
     def hook_media_manager_with_disabled_plugin_test(self):
         """
@@ -78,18 +85,17 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Disabled
-        mocked_settings_form = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_settings_tabs()
-        plugin_manager.hook_settings_tabs(mocked_settings_form)
+        plugin_manager.hook_settings_tabs()
 
         # THEN: The createSettingsTab() method should not have been called, but the plugins lists should be the same
         assert mocked_plugin.createSettingsTab.call_count == 0, \
             u'The createMediaManagerItem() method should not have been called.'
-        self.assertEqual(mocked_settings_form.plugins, plugin_manager.plugins,
-            u'The plugins on the settings form should be the same as the plugins in the plugin manager')
+        #self.assertEqual(self.mocked_settings_form.plugin_manager.plugins, plugin_manager.plugins,
+        #    u'The plugins on the settings form should be the same as the plugins in the plugin manager')
 
     def hook_settings_tabs_with_active_plugin_and_no_form_test(self):
         """
@@ -105,7 +111,7 @@
         plugin_manager.hook_settings_tabs()
 
         # THEN: The createSettingsTab() method should have been called
-        mocked_plugin.createSettingsTab.assert_called_with(None)
+        mocked_plugin.createSettingsTab.assert_called_with(self.mocked_settings_form)
 
     def hook_settings_tabs_with_active_plugin_and_mocked_form_test(self):
         """
@@ -114,17 +120,16 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Active
-        mocked_settings_form = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_settings_tabs()
-        plugin_manager.hook_settings_tabs(mocked_settings_form)
+        plugin_manager.hook_settings_tabs()
 
         # THEN: The createMediaManagerItem() method should have been called with the mocked settings form
-        mocked_plugin.createSettingsTab.assert_called_with(mocked_settings_form)
-        self.assertEqual(mocked_settings_form.plugins, plugin_manager.plugins,
-            u'The plugins on the settings form should be the same as the plugins in the plugin manager')
+        mocked_plugin.createSettingsTab.assert_called_with(self.mocked_settings_form)
+        #self.assertEqual(self.mocked_settings_form.plugins, plugin_manager.plugins,
+        #    u'The plugins on the settings form should be the same as the plugins in the plugin manager')
 
     def hook_import_menu_with_disabled_plugin_test(self):
         """
@@ -133,12 +138,11 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Disabled
-        mocked_import_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_import_menu()
-        plugin_manager.hook_import_menu(mocked_import_menu)
+        plugin_manager.hook_import_menu()
 
         # THEN: The createMediaManagerItem() method should have been called
         assert mocked_plugin.addImportMenuItem.call_count == 0, \
@@ -151,15 +155,14 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Active
-        mocked_import_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_import_menu()
-        plugin_manager.hook_import_menu(mocked_import_menu)
+        plugin_manager.hook_import_menu()
 
         # THEN: The addImportMenuItem() method should have been called
-        mocked_plugin.addImportMenuItem.assert_called_with(mocked_import_menu)
+        mocked_plugin.addImportMenuItem.assert_called_with(self.mocked_main_window.file_import_menu)
 
     def hook_export_menu_with_disabled_plugin_test(self):
         """
@@ -168,12 +171,11 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Disabled
-        mocked_export_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_export_menu()
-        plugin_manager.hook_export_menu(mocked_export_menu)
+        plugin_manager.hook_export_menu()
 
         # THEN: The addExportMenuItem() method should have been called
         assert mocked_plugin.addExportMenuItem.call_count == 0, \
@@ -186,15 +188,14 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Active
-        mocked_export_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_export_menu()
-        plugin_manager.hook_export_menu(mocked_export_menu)
+        plugin_manager.hook_export_menu()
 
         # THEN: The addExportMenuItem() method should have been called
-        mocked_plugin.addExportMenuItem.assert_called_with(mocked_export_menu)
+        mocked_plugin.addExportMenuItem.assert_called_with(self.mocked_main_window.file_export_menu)
 
     def hook_tools_menu_with_disabled_plugin_test(self):
         """
@@ -203,12 +204,11 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Disabled
-        mocked_tools_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_tools_menu()
-        plugin_manager.hook_tools_menu(mocked_tools_menu)
+        plugin_manager.hook_tools_menu()
 
         # THEN: The addToolsMenuItem() method should have been called
         assert mocked_plugin.addToolsMenuItem.call_count == 0, \
@@ -221,15 +221,14 @@
         # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active
         mocked_plugin = MagicMock()
         mocked_plugin.status = PluginStatus.Active
-        mocked_tools_menu = MagicMock()
         plugin_manager = PluginManager()
         plugin_manager.plugins = [mocked_plugin]
 
         # WHEN: We run hook_tools_menu()
-        plugin_manager.hook_tools_menu(mocked_tools_menu)
+        plugin_manager.hook_tools_menu()
 
         # THEN: The addToolsMenuItem() method should have been called
-        mocked_plugin.addToolsMenuItem.assert_called_with(mocked_tools_menu)
+        mocked_plugin.addToolsMenuItem.assert_called_with(self.mocked_main_window.tools_menu)
 
     def initialise_plugins_with_disabled_plugin_test(self):
         """

=== modified file 'tests/interfaces/openlp_core_ui/test_servicemanager.py'
--- tests/interfaces/openlp_core_ui/test_servicemanager.py	2013-02-18 19:34:36 +0000
+++ tests/interfaces/openlp_core_ui/test_servicemanager.py	2013-02-26 17:28:26 +0000
@@ -21,15 +21,15 @@
         self.app = QtGui.QApplication.instance()
         ScreenList.create(self.app.desktop())
         Registry().register(u'application', MagicMock())
-        #with patch(u'openlp.core.lib.PluginManager'):
-        #    self.main_window = MainWindow()
-        #self.service_manager = Registry().get(u'service_manager')
+        with patch(u'openlp.core.lib.PluginManager'):
+            self.main_window = MainWindow()
+        self.service_manager = Registry().get(u'service_manager')
 
     def tearDown(self):
         """
         Delete all the C++ objects at the end so that we don't have a segfault
         """
-        #del self.main_window
+        del self.main_window
         del self.app
 
     def basic_service_manager_test(self):
@@ -40,6 +40,5 @@
 
         # WHEN I have an empty display
         # THEN the count of items should be zero
-        #self.assertEqual(self.service_manager.service_manager_list.topLevelItemCount(), 0,
-        #    u'The service manager list should be empty ')
-        pass
+        self.assertEqual(self.service_manager.service_manager_list.topLevelItemCount(), 0,
+            u'The service manager list should be empty ')


Follow ups