← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/bug-1097898 into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/bug-1097898 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #1097898 in OpenLP: "Exiting liveview with Alt-F4 causes OpenLP to become unstable"
  https://bugs.launchpad.net/openlp/+bug/1097898

For more details, see:
https://code.launchpad.net/~trb143/openlp/bug-1097898/+merge/144582

This code is for review but it is not ready for merging
It needs good testing as it changes the internals of the code.

Introduce the use of a Registry singleton and register components against it.
Add code the classes to use the registry instead of passing objects.
Clean up API's to remove passing objects when the Registry is done.

To Do.
Testing and code reviews

-- 
https://code.launchpad.net/~trb143/openlp/bug-1097898/+merge/144582
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/bug-1097898 into lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2013-01-23 20:30:59 +0000
+++ openlp/core/__init__.py	2013-01-23 20:36:22 +0000
@@ -43,7 +43,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Settings, check_directory_exists, ScreenList, UiStrings
+from openlp.core.lib import Receiver, Settings, check_directory_exists, ScreenList, UiStrings, Registry
 from openlp.core.resources import qInitResources
 from openlp.core.ui.mainwindow import MainWindow
 from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
@@ -284,6 +284,7 @@
     else:
         app.setApplicationName(u'OpenLP')
         set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
+    registry = Registry.create()
     app.setApplicationVersion(get_application_version()[u'version'])
     # Instance check
     if not options.testing:

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2013-01-23 20:30:59 +0000
+++ openlp/core/lib/__init__.py	2013-01-23 20:36:22 +0000
@@ -386,6 +386,7 @@
             u'Locale list separator: start') % (stringlist[0], merged)
 
 
+from registry import Registry
 from uistrings import UiStrings
 from eventreceiver import Receiver
 from screen import ScreenList

=== modified file 'openlp/core/lib/imagemanager.py'
--- openlp/core/lib/imagemanager.py	2013-01-10 23:07:48 +0000
+++ openlp/core/lib/imagemanager.py	2013-01-23 20:36:22 +0000
@@ -39,7 +39,8 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import resize_image, image_to_byte, Receiver, ScreenList
+from openlp.core.lib import resize_image, image_to_byte, Receiver, Registry
+from openlp.core.ui import ScreenList
 
 log = logging.getLogger(__name__)
 
@@ -182,6 +183,7 @@
 
     def __init__(self):
         QtCore.QObject.__init__(self)
+        Registry().register(u'image_manager', self)
         currentScreen = ScreenList().current
         self.width = currentScreen[u'size'].width()
         self.height = currentScreen[u'size'].height()

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-01-18 18:50:46 +0000
+++ openlp/core/lib/mediamanageritem.py	2013-01-23 20:36:22 +0000
@@ -35,8 +35,8 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, translate, \
-    Receiver, ListWidgetWithDnD, ServiceItemContext, Settings, UiStrings
+from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, build_icon, translate, Receiver, \
+    ListWidgetWithDnD, ServiceItemContext, Settings, Registry, UiStrings
 from openlp.core.lib.searchedit import SearchEdit
 from openlp.core.lib.ui import create_widget_action, critical_error_message_box
 
@@ -99,6 +99,7 @@
         self.plugin = plugin
         visible_title = self.plugin.getString(StringContent.VisibleName)
         self.title = unicode(visible_title[u'title'])
+        Registry().register(self.title, self)
         self.settingsSection = self.plugin.name
         self.icon = None
         if icon:
@@ -617,3 +618,73 @@
         Performs a plugin specific search for items containing ``string``
         """
         raise NotImplementedError(u'Plugin.search needs to be defined by the plugin')
+
+    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)
+
+    def _get_renderer(self):
+        """
+        Adds the Renderer to the class dynamically
+        """
+        if not hasattr(self, u'_renderer'):
+            self._renderer = Registry().get(u'renderer')
+        return self._renderer
+
+    renderer = property(_get_renderer)
+
+    def _get_live_controller(self):
+        """
+        Adds the live controller to the class dynamically
+        """
+        if not hasattr(self, u'_live_controller'):
+            self._live_controller = Registry().get(u'live_controller')
+        return self._live_controller
+
+    live_controller = property(_get_live_controller)
+
+    def _get_preview_controller(self):
+        """
+        Adds the preview controller to the class dynamically
+        """
+        if not hasattr(self, u'_preview_controller'):
+            self._preview_controller = Registry().get(u'preview_controller')
+        return self._preview_controller
+
+    preview_controller = property(_get_preview_controller)
+
+    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)
+
+    def _get_media_controller(self):
+        """
+        Adds the media controller to the class dynamically
+        """
+        if not hasattr(self, u'_media_controller'):
+            self._media_controller = Registry().get(u'media_controller')
+        return self._media_controller
+
+    media_controller = property(_get_media_controller)
+
+    def _get_service_manager(self):
+        """
+        Adds the plugin manager to the class dynamically
+        """
+        if not hasattr(self, u'_service_manager'):
+            self._service_manager = Registry().get(u'service_manager')
+        return self._service_manager
+
+    service_manager = property(_get_service_manager)
\ No newline at end of file

=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py	2013-01-18 20:35:30 +0000
+++ openlp/core/lib/plugin.py	2013-01-23 20:36:22 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, Settings, UiStrings
+from openlp.core.lib import Receiver, Settings, Registry, UiStrings
 from openlp.core.utils import get_application_version
 
 log = logging.getLogger(__name__)
@@ -167,13 +167,6 @@
         self.status = PluginStatus.Inactive
         self.previewController = plugin_helpers[u'preview']
         self.liveController = plugin_helpers[u'live']
-        self.renderer = plugin_helpers[u'renderer']
-        self.serviceManager = plugin_helpers[u'service']
-        self.settingsForm = plugin_helpers[u'settings form']
-        self.mediaDock = plugin_helpers[u'toolbox']
-        self.pluginManager = plugin_helpers[u'pluginmanager']
-        self.formParent = plugin_helpers[u'formparent']
-        self.mediaController = plugin_helpers[u'mediacontroller']
         # Add the default status to the default settings.
         default_settings[name + u'/status'] = PluginStatus.Inactive
         default_settings[name + u'/last directory'] = u''
@@ -228,7 +221,7 @@
         you need, and return it for integration into OpenLP.
         """
         if self.mediaItemClass:
-            self.mediaItem = self.mediaItemClass(self.mediaDock.media_dock, self, self.icon)
+            self.mediaItem = self.mediaItemClass(self.main_window.mediaDockManager.media_dock, self, self.icon)
 
     def addImportMenuItem(self, importMenu):
         """
@@ -298,14 +291,14 @@
         """
         if self.mediaItem:
             self.mediaItem.initialise()
-            self.mediaDock.insert_dock(self.mediaItem, self.icon, self.weight)
+            self.main_window.mediaDockManager.insert_dock(self.mediaItem, self.icon, self.weight)
 
     def finalise(self):
         """
         Called by the plugin Manager to cleanup things.
         """
         if self.mediaItem:
-            self.mediaDock.remove_dock(self.mediaItem)
+            self.main_window.mediaDockManager.remove_dock(self.mediaItem)
 
     def appStartup(self):
         """
@@ -421,3 +414,14 @@
         The plugin's config has changed
         """
         pass
+
+    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/pluginmanager.py'
--- openlp/core/lib/pluginmanager.py	2012-12-29 20:56:56 +0000
+++ openlp/core/lib/pluginmanager.py	2013-01-23 20:36:22 +0000
@@ -33,7 +33,7 @@
 import sys
 import logging
 
-from openlp.core.lib import Plugin, PluginStatus
+from openlp.core.lib import Plugin, PluginStatus, Registry
 
 log = logging.getLogger(__name__)
 
@@ -43,13 +43,6 @@
     and executes all the hooks, as and when necessary.
     """
     log.info(u'Plugin manager loaded')
-    __instance__ = None
-    @staticmethod
-    def get_instance():
-        """
-        Obtain a single instance of class.
-        """
-        return PluginManager.__instance__
 
     def __init__(self, plugin_dir):
         """
@@ -60,7 +53,7 @@
             The directory to search for plugins.
         """
         log.info(u'Plugin manager Initialising')
-        PluginManager.__instance__ = self
+        Registry().register(u'plugin_manager', self)
         if not plugin_dir in sys.path:
             log.debug(u'Inserting %s into sys.path', plugin_dir)
             sys.path.insert(0, plugin_dir)

=== added file 'openlp/core/lib/registry.py'
--- openlp/core/lib/registry.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/registry.py	2013-01-23 20:36:22 +0000
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann                         #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+Provide Registry Services
+"""
+import logging
+
+log = logging.getLogger(__name__)
+
+class Registry(object):
+    """
+    This is the Component Registry.  It is a singleton object and is used to provide a
+    look up service for common objects.
+    """
+    log.info(u'Registry loaded')
+    __instance__ = None
+
+    def __new__(cls):
+        if not cls.__instance__:
+            cls.__instance__ = object.__new__(cls)
+        return cls.__instance__
+
+    @classmethod
+    def create(cls):
+        """
+        The constructor for the component registry providing a single registry of objects.
+        """
+        log.info(u'Registry Initialising')
+        registry = cls()
+        registry.service_list = {}
+        return registry
+
+    def get(self, key):
+        """
+        Extracts the registry value from the list based on the key passed in
+        """
+        if key in self.service_list:
+            return self.service_list[key]
+        else:
+            log.error(u'Service %s not found in list' % key)
+            return None
+
+    def register(self, key, reference):
+        """
+        Registers a component against a key.
+        """
+        if key in self.service_list:
+            log.error(u'Duplicate service exception %s' % key)
+            raise Exception(u'Duplicate service exception %s' % key)
+        else:
+            self.service_list[key] = reference

=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2013-01-10 23:07:48 +0000
+++ openlp/core/lib/renderer.py	2013-01-23 20:36:22 +0000
@@ -32,7 +32,7 @@
 from PyQt4 import QtGui, QtCore, QtWebKit
 
 from openlp.core.lib import ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
-    ItemCapabilities, FormattingTags, ImageSource, ScreenList
+    ItemCapabilities, FormattingTags, ImageSource, Registry, ScreenList
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.ui import MainDisplay
 
@@ -57,7 +57,7 @@
     """
     log.info(u'Renderer Loaded')
 
-    def __init__(self, image_manager, theme_manager):
+    def __init__(self):
         """
         Initialise the renderer.
 
@@ -69,15 +69,14 @@
             The theme_manager instance, used to get the current theme details.
         """
         log.debug(u'Initialisation started')
-        self.theme_manager = theme_manager
-        self.image_manager = image_manager
         self.screens = ScreenList()
+        Registry().register(u'renderer', self)
         self.theme_level = ThemeLevel.Global
         self.global_theme_name = u''
         self.service_theme_name = u''
         self.item_theme_name = u''
         self.force_page = False
-        self.display = MainDisplay(None, self.image_manager, False, self)
+        self.display = MainDisplay(None, False, self)
         self.display.setup()
         self._theme_dimensions = {}
         self._calculate_default()
@@ -94,7 +93,7 @@
         self._calculate_default()
         if self.display:
             self.display.close()
-        self.display = MainDisplay(None, self.image_manager, False, self)
+        self.display = MainDisplay(None, False, self)
         self.display.setup()
         self._theme_dimensions = {}
 
@@ -236,7 +235,6 @@
             serviceItem.add_from_text(VERSE_FOR_LINE_COUNT)
         else:
             serviceItem.add_from_text(VERSE)
-        serviceItem.renderer = self
         serviceItem.raw_footer = FOOTER
         # if No file do not update cache
         if theme_data.background_filename:
@@ -644,3 +642,23 @@
         # this parse we are to be wordy
         line = line.replace(u'\n', u' ')
         return line.split(u' ')
+
+    def _get_image_manager(self):
+        """
+        Adds the image manager to the class dynamically
+        """
+        if not hasattr(self, u'_image_manager'):
+            self._image_manager = Registry().get(u'image_manager')
+        return self._image_manager
+
+    image_manager = property(_get_image_manager)
+
+    def _get_theme_manager(self):
+        """
+        Adds the theme manager to the class dynamically
+        """
+        if not hasattr(self, u'_theme_manager'):
+            self._theme_manager = Registry().get(u'theme_manager')
+        return self._theme_manager
+
+    theme_manager = property(_get_theme_manager)
\ No newline at end of file

=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2013-01-21 19:47:53 +0000
+++ openlp/core/lib/serviceitem.py	2013-01-23 20:36:22 +0000
@@ -39,7 +39,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource, Settings
+from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource, Settings, Registry
 
 log = logging.getLogger(__name__)
 
@@ -148,7 +148,6 @@
             The plugin that this service item belongs to.
         """
         if plugin:
-            self.renderer = plugin.renderer
             self.name = plugin.name
         self.title = u''
         self.shortname = u''
@@ -293,7 +292,7 @@
             self.image_border = background
         self.service_item_type = ServiceItemType.Image
         self._raw_frames.append({u'title': title, u'path': path})
-        self.renderer.image_manager.addImage(path, ImageSource.ImagePlugin, self.image_border)
+        self.image_manager.addImage(path, ImageSource.ImagePlugin, self.image_border)
         self._new_item()
 
     def add_from_text(self, raw_slide, verse_tag=None):
@@ -644,3 +643,23 @@
                     type = frame[u'title'].split(u'.')[-1]
                     if type.lower() not in suffix_list:
                         self.is_valid = False
+
+    def _get_renderer(self):
+        """
+        Adds the Renderer to the class dynamically
+        """
+        if not hasattr(self, u'_renderer'):
+            self._renderer = Registry().get(u'renderer')
+        return self._renderer
+
+    renderer = property(_get_renderer)
+
+    def _get_image_manager(self):
+        """
+        Adds the image manager to the class dynamically
+        """
+        if not hasattr(self, u'_image_manager'):
+            self._image_manager = Registry().get(u'image_manager')
+        return self._image_manager
+
+    image_manager = property(_get_image_manager)
\ No newline at end of file

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2013-01-10 23:07:48 +0000
+++ openlp/core/ui/maindisplay.py	2013-01-23 20:36:22 +0000
@@ -38,8 +38,8 @@
 from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
 from PyQt4.phonon import Phonon
 
-from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, translate, PluginManager, expand_tags,\
-    Settings, ImageSource
+from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, translate, expand_tags,\
+    Settings, ImageSource, Registry
 from openlp.core.lib.theme import BackgroundType
 
 from openlp.core.lib import ScreenList
@@ -66,7 +66,6 @@
         self.isLive = live
         self.controller = controller
         self.screen = {}
-        self.plugins = PluginManager.get_instance().plugins
         # FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with
         # OpenGL. Only white blank screen is shown on the 2nd monitor all the
         # time. We need to investigate more how to use OpenGL properly on Mac OS
@@ -116,9 +115,8 @@
     """
     This is the display screen as a specialized class from the Display class
     """
-    def __init__(self, parent, imageManager, live, controller):
+    def __init__(self, parent, live, controller):
         Display.__init__(self, parent, live, controller)
-        self.imageManager = imageManager
         self.screens = ScreenList()
         self.rebuildCSS = False
         self.hideMode = None
@@ -173,8 +171,8 @@
         Call the plugins to rebuild the Live display CSS as the screen has
         not been rebuild on exit of config.
         """
-        if self.rebuildCSS and self.plugins:
-            for plugin in self.plugins:
+        if self.rebuildCSS and self.plugin_manager.plugins:
+            for plugin in self.plugin_manager.plugins:
                 plugin.refreshCss(self.frame)
         self.rebuildCSS = False
 
@@ -213,8 +211,8 @@
                 splash_image)
             serviceItem = ServiceItem()
             serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
-            self.webView.setHtml(build_html(serviceItem, self.screen,
-                self.isLive, None, plugins=self.plugins))
+            self.webView.setHtml(build_html(serviceItem, self.screen, self.isLive, None,
+                plugins=self.plugin_manager.plugins))
             self.__hideMouse()
         log.debug(u'Finished MainDisplay setup')
 
@@ -280,7 +278,7 @@
         """
         API for replacement backgrounds so Images are added directly to cache.
         """
-        self.imageManager.addImage(path, ImageSource.ImagePlugin, background)
+        self.image_manager.addImage(path, ImageSource.ImagePlugin, background)
         if not hasattr(self, u'serviceItem'):
             return False
         self.override[u'image'] = path
@@ -302,7 +300,7 @@
             re-added to the image manager.
         """
         log.debug(u'image to display')
-        image = self.imageManager.getImageBytes(path, ImageSource.ImagePlugin)
+        image = self.image_manager.getImageBytes(path, ImageSource.ImagePlugin)
         self.controller.mediaController.media_reset(self.controller)
         self.displayImage(image)
 
@@ -383,17 +381,18 @@
                 self.override = {}
             else:
                 # replace the background
-                background = self.imageManager.getImageBytes(self.override[u'image'], ImageSource.ImagePlugin)
+                background = self.image_manager.getImageBytes(self.override[u'image'], ImageSource.ImagePlugin)
         self.setTransparency(self.serviceItem.themedata.background_type ==
             BackgroundType.to_string(BackgroundType.Transparent))
         if self.serviceItem.themedata.background_filename:
-            self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes(
+            self.serviceItem.bg_image_bytes = self.image_manager.getImageBytes(
                 self.serviceItem.themedata.background_filename,ImageSource.Theme)
         if image_path:
-            image_bytes = self.imageManager.getImageBytes(image_path, ImageSource.ImagePlugin)
+            image_bytes = self.image_manager.getImageBytes(image_path, ImageSource.ImagePlugin)
         else:
             image_bytes = None
-        html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes, self.plugins)
+        html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes,
+            plugins=self.plugin_manager.plugins)
         log.debug(u'buildHtml - pre setHtml')
         self.webView.setHtml(html)
         log.debug(u'buildHtml - post setHtml')
@@ -468,6 +467,26 @@
             self.setCursor(QtCore.Qt.ArrowCursor)
             self.frame.evaluateJavaScript('document.body.style.cursor = "auto"')
 
+    def _get_plugin_manager(self):
+        """
+        Adds the Renderer 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)
+
+    def _get_image_manager(self):
+        """
+        Adds the image manager to the class dynamically
+        """
+        if not hasattr(self, u'_image_manager'):
+            self._image_manager = Registry().get(u'image_manager')
+        return self._image_manager
+
+    image_manager = property(_get_image_manager)
+
 
 class AudioPlayer(QtCore.QObject):
     """
@@ -591,3 +610,4 @@
     #@todo is this used?
     def connectSlot(self, signal, slot):
         QtCore.QObject.connect(self.mediaObject, signal, slot)
+

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2013-01-18 21:24:25 +0000
+++ openlp/core/ui/mainwindow.py	2013-01-23 20:36:22 +0000
@@ -40,9 +40,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, PluginManager, Receiver, translate, ImageManager, \
-    PluginStatus, ScreenList, UiStrings
-from openlp.core.lib.ui import create_action
-from openlp.core.lib import Settings
+    PluginStatus, Registry, Settings, ScreenList
+from openlp.core.lib.ui import UiStrings, create_action
 from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
     MediaDockManager, ShortcutListForm, FormattingTagForm
 from openlp.core.ui.media import MediaController
@@ -456,6 +455,7 @@
         plugins.
         """
         QtGui.QMainWindow.__init__(self)
+        Registry().register(u'main_window', self)
         self.application = application
         self.clipboard = self.application.clipboard()
         self.arguments = self.application.args
@@ -475,7 +475,7 @@
         self.serviceNotSaved = False
         self.aboutForm = AboutForm(self)
         self.mediaController = MediaController(self)
-        self.settingsForm = SettingsForm(self, self)
+        self.settingsForm = SettingsForm(self)
         self.formattingTagForm = FormattingTagForm(self)
         self.shortcutForm = ShortcutListForm(self)
         self.recentFiles = []
@@ -543,7 +543,7 @@
         # warning cyclic dependency
         # renderer needs to call ThemeManager and
         # ThemeManager needs to call Renderer
-        self.renderer = Renderer(self.imageManager, self.themeManagerContents)
+        self.renderer = Renderer()
         # Define the media Dock Manager
         self.mediaDockManager = MediaDockManager(self.mediaToolBox)
         log.info(u'Load Plugins')

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2013-01-20 12:23:22 +0000
+++ openlp/core/ui/media/mediacontroller.py	2013-01-23 20:36:22 +0000
@@ -32,7 +32,7 @@
 import datetime
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings, UiStrings
+from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings, Registry, UiStrings
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
 from openlp.core.ui.media.mediaplayer import MediaPlayer
@@ -88,6 +88,7 @@
     """
     def __init__(self, parent):
         self.mainWindow = parent
+        Registry().register(u'media_controller', self)
         self.mediaPlayers = {}
         self.displayControllers = {}
         self.currentMediaPlayer = {}
@@ -130,14 +131,14 @@
                 for item in player.audio_extensions_list:
                     if not item in self.audio_extensions_list:
                         self.audio_extensions_list.append(item)
-                        self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:])
+                        self.service_manager.supportedSuffixes(item[2:])
         self.video_extensions_list = []
         for player in self.mediaPlayers.values():
             if player.isActive:
                 for item in player.video_extensions_list:
                     if item not in self.video_extensions_list:
                         self.video_extensions_list.extend(item)
-                        self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:])
+                        self.service_manager.supportedSuffixes(item[2:])
 
     def register_players(self, player):
         """
@@ -729,3 +730,13 @@
         if controller.isLive:
             return controller.display
         return controller.previewDisplay
+
+    def _get_service_manager(self):
+        """
+        Adds the plugin manager to the class dynamically
+        """
+        if not hasattr(self, u'_service_manager'):
+            self._service_manager = Registry().get(u'service_manager')
+        return self._service_manager
+
+    service_manager = property(_get_service_manager)
\ No newline at end of file

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2013-01-21 19:47:53 +0000
+++ openlp/core/ui/servicemanager.py	2013-01-23 20:36:22 +0000
@@ -39,8 +39,8 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, \
-    translate, str_to_bool, check_directory_exists, Settings, PluginStatus, UiStrings
+from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, ItemCapabilities, SettingsManager, \
+    translate, str_to_bool, check_directory_exists, Settings, PluginStatus, Registry, UiStrings
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
 from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
@@ -105,6 +105,7 @@
         QtGui.QWidget.__init__(self, parent)
         self.active = build_icon(QtGui.QImage(u':/media/auto-start_active.png'))
         self.inactive = build_icon(QtGui.QImage(u':/media/auto-start_inactive.png'))
+        Registry().register(u'service_manager', self)
         self.mainwindow = mainwindow
         self.serviceItems = []
         self.suffixes = []
@@ -313,8 +314,7 @@
         Setter for service file.
         """
         self._fileName = unicode(fileName)
-        self.mainwindow.setServiceModified(self.isModified(),
-            self.shortFileName())
+        self.mainwindow.setServiceModified(self.isModified(), self.shortFileName())
         Settings().setValue(u'servicemanager/last file', fileName)
         self._saveLite = self._fileName.endswith(u'.oszl')
 
@@ -384,8 +384,8 @@
         if not loadFile:
             fileName = QtGui.QFileDialog.getOpenFileName(self.mainwindow,
                 translate('OpenLP.ServiceManager', 'Open File'),
-                Settings().value(self.mainwindow.serviceManagerSettingsSection + u'/last directory'),
-                translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)'))
+                    SettingsManager.get_last_dir(self.mainwindow.serviceManagerSettingsSection),
+                    translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)'))
             if not fileName:
                 return False
         else:
@@ -699,7 +699,6 @@
                 for item in items:
                     self.mainwindow.incrementProgressBar()
                     serviceItem = ServiceItem()
-                    serviceItem.renderer = self.mainwindow.renderer
                     if self._saveLite:
                         serviceItem.set_from_service(item)
                     else:
@@ -802,13 +801,13 @@
                 self.autoStartAction.setText(translate('OpenLP.ServiceManager', '&Auto Start - active'))
                 self.autoStartAction.setIcon(self.active)
         if serviceItem[u'service_item'].is_text():
-            for plugin in self.mainwindow.pluginManager.plugins:
+            for plugin in self.plugin_manager.plugins:
                 if plugin.name == u'custom' and plugin.status == PluginStatus.Active:
                     self.create_custom_action.setVisible(True)
                     break
         self.themeMenu.menuAction().setVisible(False)
         # Set up the theme menu.
-        if serviceItem[u'service_item'].is_text() and self.mainwindow.renderer.theme_level == ThemeLevel.Song:
+        if serviceItem[u'service_item'].is_text() and self.renderer.theme_level == ThemeLevel.Song:
             self.themeMenu.menuAction().setVisible(True)
             # The service item does not have a theme, check the "Default".
             if serviceItem[u'service_item'].theme is None:
@@ -1193,7 +1192,7 @@
         """
         log.debug(u'onThemeComboBoxSelected')
         self.service_theme = self.themeComboBox.currentText()
-        self.mainwindow.renderer.set_service_theme(self.service_theme)
+        self.renderer.set_service_theme(self.service_theme)
         Settings().setValue(self.mainwindow.serviceManagerSettingsSection + u'/service theme', self.service_theme)
         self.regenerateServiceItems(True)
 
@@ -1203,7 +1202,7 @@
         sure the theme combo box is in the correct state.
         """
         log.debug(u'themeChange')
-        visible = self.mainwindow.renderer.theme_level == ThemeLevel.Global
+        visible = self.renderer.theme_level == ThemeLevel.Global
         self.themeLabel.setVisible(visible)
         self.themeComboBox.setVisible(visible)
 
@@ -1266,7 +1265,7 @@
                 newItem.merge(item[u'service_item'])
                 item[u'service_item'] = newItem
                 self.repaintServiceList(itemcount + 1, 0)
-                self.mainwindow.liveController.replaceServiceManagerItem(newItem)
+                self.live_controller.replaceServiceManagerItem(newItem)
                 self.setModified()
 
     def addServiceItem(self, item, rebuild=False, expand=None, replace=False, repaint=True, selected=False):
@@ -1288,7 +1287,7 @@
             item.merge(self.serviceItems[sitem][u'service_item'])
             self.serviceItems[sitem][u'service_item'] = item
             self.repaintServiceList(sitem, child)
-            self.mainwindow.liveController.replaceServiceManagerItem(item)
+            self.live_controller.replaceServiceManagerItem(item)
         else:
             item.render()
             # nothing selected for dnd
@@ -1311,7 +1310,7 @@
                 self.repaintServiceList(self.dropPosition, -1)
             # if rebuilding list make sure live is fixed.
             if rebuild:
-                self.mainwindow.liveController.replaceServiceManagerItem(item)
+                self.live_controller.replaceServiceManagerItem(item)
         self.dropPosition = 0
         self.setModified()
 
@@ -1322,8 +1321,7 @@
         Receiver.send_message(u'cursor_busy')
         item, child = self.findServiceItem()
         if self.serviceItems[item][u'service_item'].is_valid:
-            self.mainwindow.previewController.addServiceManagerItem(
-                self.serviceItems[item][u'service_item'], child)
+            self.preview_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], child)
         else:
             critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
                 translate('OpenLP.ServiceManager',
@@ -1363,16 +1361,15 @@
             child = row
         Receiver.send_message(u'cursor_busy')
         if self.serviceItems[item][u'service_item'].is_valid:
-            self.mainwindow.liveController.addServiceManagerItem(
-                self.serviceItems[item][u'service_item'], child)
+            self.live_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], child)
             if Settings().value(self.mainwindow.generalSettingsSection + u'/auto preview'):
                 item += 1
                 if self.serviceItems and item < len(self.serviceItems) and \
                         self.serviceItems[item][u'service_item'].is_capable(ItemCapabilities.CanPreview):
-                    self.mainwindow.previewController.addServiceManagerItem(self.serviceItems[item][u'service_item'], 0)
+                    self.preview_controller.addServiceManagerItem(self.serviceItems[item][u'service_item'], 0)
                     next_item = self.serviceManagerList.topLevelItem(item)
                     self.serviceManagerList.setCurrentItem(next_item)
-                    self.mainwindow.liveController.previewListWidget.setFocus()
+                    self.live_controller.previewListWidget.setFocus()
         else:
             critical_error_message_box(translate('OpenLP.ServiceManager', 'Missing Display Handler'),
                 translate('OpenLP.ServiceManager',
@@ -1516,7 +1513,7 @@
             themeGroup.addAction(create_widget_action(self.themeMenu, theme, text=theme, checked=False,
                 triggers=self.onThemeChangeAction))
         find_and_set_in_combo_box(self.themeComboBox, self.service_theme)
-        self.mainwindow.renderer.set_service_theme(self.service_theme)
+        self.renderer.set_service_theme(self.service_theme)
         self.regenerateServiceItems()
 
     def onThemeChangeAction(self):
@@ -1541,3 +1538,43 @@
         """
         settingDialog = PrintServiceForm(self.mainwindow, self)
         settingDialog.exec_()
+
+    def _get_renderer(self):
+        """
+        Adds the Renderer to the class dynamically
+        """
+        if not hasattr(self, u'_renderer'):
+            self._renderer = Registry().get(u'renderer')
+        return self._renderer
+
+    renderer = property(_get_renderer)
+
+    def _get_live_controller(self):
+        """
+        Adds the live controller to the class dynamically
+        """
+        if not hasattr(self, u'_live_controller'):
+            self._live_controller = Registry().get(u'live_controller')
+        return self._live_controller
+
+    live_controller = property(_get_live_controller)
+
+    def _get_preview_controller(self):
+        """
+        Adds the preview controller to the class dynamically
+        """
+        if not hasattr(self, u'_preview_controller'):
+            self._preview_controller = Registry().get(u'preview_controller')
+        return self._preview_controller
+
+    preview_controller = property(_get_preview_controller)
+
+    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)
\ No newline at end of file

=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py	2013-01-18 23:31:02 +0000
+++ openlp/core/ui/settingsform.py	2013-01-23 20:36:22 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import Receiver, build_icon, PluginStatus
+from openlp.core.lib import Receiver, build_icon, PluginStatus, Registry
 from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
 from openlp.core.ui.media import PlayerTab
 from settingsdialog import Ui_SettingsDialog
@@ -44,21 +44,21 @@
     """
     Provide the form to manipulate the settings for OpenLP
     """
-    def __init__(self, mainWindow, parent=None):
+    def __init__(self, parent=None):
         """
         Initialise the settings form
         """
-        self.mainWindow = mainWindow
+        Registry().register(u'settings_form', self)
         QtGui.QDialog.__init__(self, parent)
         self.setupUi(self)
         # General tab
         self.generalTab = GeneralTab(self)
         # Themes tab
-        self.themesTab = ThemesTab(self, mainWindow)
+        self.themesTab = ThemesTab(self, self.main_window)
         # Advanced tab
         self.advancedTab = AdvancedTab(self)
         # Advanced tab
-        self.playerTab = PlayerTab(self, mainWindow)
+        self.playerTab = PlayerTab(self, self.main_window)
 
     def exec_(self):
         # load all the settings
@@ -142,3 +142,13 @@
         if self.resetSuffixes:
             self.mainWindow.serviceManagerContents.resetSupportedSuffixes()
             self.resetSuffixes = False
+
+    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)
\ No newline at end of file

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2013-01-21 19:47:53 +0000
+++ openlp/core/ui/slidecontroller.py	2013-01-23 20:36:22 +0000
@@ -35,10 +35,9 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, translate, build_icon, build_html, \
-    PluginManager, ServiceItem, ImageSource, SlideLimits, ServiceItemAction, Settings, ScreenList, UiStrings
-from openlp.core.lib.ui import create_action
-from openlp.core.lib import SlideLimits, ServiceItemAction
-from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
+    ServiceItem, ImageSource, SlideLimits, ServiceItemAction, Settings, Registry, UiStrings
+from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList, DisplayControllerType
+from openlp.core.lib.ui import UiStrings, create_action
 from openlp.core.utils.actions import ActionList, CategoryOrder
 
 log = logging.getLogger(__name__)
@@ -83,8 +82,6 @@
             self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height())
         except ZeroDivisionError:
             self.ratio = 1
-        self.imageManager = self.parent().imageManager
-        self.mediaController = self.parent().mediaController
         self.loopList = [
             u'playSlidesMenu',
             u'loopSeparator',
@@ -110,6 +107,7 @@
         # Type label for the top of the slide controller
         self.typeLabel = QtGui.QLabel(self.panel)
         if self.isLive:
+            Registry().register(u'live_controller', self)
             self.typeLabel.setText(UiStrings().Live)
             self.split = 1
             self.typePrefix = u'live'
@@ -118,6 +116,7 @@
             self.category = UiStrings().LiveToolbar
             ActionList.get_instance().add_category(unicode(self.category), CategoryOrder.standardToolbar)
         else:
+            Registry().register(u'preview_controller', self)
             self.typeLabel.setText(UiStrings().Preview)
             self.split = 0
             self.typePrefix = u'preview'
@@ -231,7 +230,7 @@
                 tooltip=translate('OpenLP.SlideController', 'Edit and reload song preview.'), triggers=self.onEditSong)
         self.controllerLayout.addWidget(self.toolbar)
         # Build the Media Toolbar
-        self.mediaController.register_controller(self)
+        self.media_controller.register_controller(self)
         if self.isLive:
             # Build the Song Toolbar
             self.songMenu = QtGui.QToolButton(self.toolbar)
@@ -354,8 +353,7 @@
             self.setLiveHotkeys(self)
             self.__addActionsToWidget(self.previewListWidget)
         else:
-            self.previewListWidget.addActions(
-                [self.nextItem, self.previousItem])
+            self.previewListWidget.addActions([self.nextItem, self.previousItem])
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix), self.onStopLoop)
         QtCore.QObject.connect(Receiver.get_receiver(),
@@ -450,7 +448,7 @@
 
     def liveEscape(self):
         self.display.setVisible(False)
-        self.mediaController.media_stop(self)
+        self.media_controller.media_stop(self)
 
     def toggleDisplay(self, action):
         """
@@ -507,7 +505,7 @@
         # rebuild display as screen size changed
         if self.display:
             self.display.close()
-        self.display = MainDisplay(self, self.imageManager, self.isLive, self)
+        self.display = MainDisplay(self, self.isLive, self)
         self.display.setup()
         if self.isLive:
             self.__addActionsToWidget(self.display)
@@ -517,13 +515,13 @@
             self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height())
         except ZeroDivisionError:
             self.ratio = 1
-        self.mediaController.setup_display(self.display, False)
+        self.media_controller.setup_display(self.display, False)
         self.previewSizeChanged()
         self.previewDisplay.setup()
         serviceItem = ServiceItem()
         self.previewDisplay.webView.setHtml(build_html(serviceItem, self.previewDisplay.screen, None, self.isLive,
-            plugins=PluginManager.get_instance().plugins))
-        self.mediaController.setup_display(self.previewDisplay,True)
+            plugins=self.plugin_manager.plugins))
+        self.media_controller.setup_display(self.previewDisplay,True)
         if self.serviceItem:
             self.refreshServiceItem()
 
@@ -773,9 +771,9 @@
                 else:
                     # If current slide set background to image
                     if framenumber == slideno:
-                        self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes(frame[u'path'],
+                        self.serviceItem.bg_image_bytes = self.image_manager.getImageBytes(frame[u'path'],
                             ImageSource.ImagePlugin)
-                    image = self.imageManager.getImage(frame[u'path'], ImageSource.ImagePlugin)
+                    image = self.image_manager.getImage(frame[u'path'], ImageSource.ImagePlugin)
                     label.setPixmap(QtGui.QPixmap.fromImage(image))
                 self.previewListWidget.setCellWidget(framenumber, 0, label)
                 slideHeight = width * (1 / self.ratio)
@@ -1223,7 +1221,7 @@
         Respond to the arrival of a media service item
         """
         log.debug(u'SlideController onMediaStart')
-        self.mediaController.video(self.controllerType, item, self.hideMode())
+        self.media_controller.video(self.controllerType, item, self.hideMode())
         if not self.isLive:
             self.previewDisplay.show()
             self.slidePreview.hide()
@@ -1233,7 +1231,7 @@
         Respond to a request to close the Video
         """
         log.debug(u'SlideController onMediaClose')
-        self.mediaController.media_reset(self)
+        self.media_controller.media_reset(self)
         self.previewDisplay.hide()
         self.slidePreview.show()
 
@@ -1279,3 +1277,34 @@
     def onTrackTriggered(self):
         action = self.sender()
         self.display.audioPlayer.goTo(action.data())
+
+    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)
+
+    def _get_image_manager(self):
+        """
+        Adds the image manager to the class dynamically
+        """
+        if not hasattr(self, u'_image_manager'):
+            self._image_manager = Registry().get(u'image_manager')
+        return self._image_manager
+
+    image_manager = property(_get_image_manager)
+
+    def _get_media_controller(self):
+        """
+        Adds the media controller to the class dynamically
+        """
+        if not hasattr(self, u'_media_controller'):
+            self._media_controller = Registry().get(u'media_controller')
+        return self._media_controller
+
+    media_controller = property(_get_media_controller)
+

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2013-01-17 22:14:06 +0000
+++ openlp/core/ui/thememanager.py	2013-01-23 20:36:22 +0000
@@ -37,7 +37,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, Receiver, SettingsManager, translate, \
-    check_item_selected, check_directory_exists, create_thumb, validate_thumb, ImageSource, Settings, UiStrings
+    check_item_selected, check_directory_exists, create_thumb, validate_thumb, ImageSource, Settings, Registry, \
+    UiStrings
 from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType
 from openlp.core.lib.ui import critical_error_message_box, create_widget_action
 from openlp.core.theme import Theme
@@ -52,6 +53,7 @@
     """
     def __init__(self, mainwindow, parent=None):
         QtGui.QWidget.__init__(self, parent)
+        Registry().register(u'theme_manager', self)
         self.mainwindow = mainwindow
         self.settingsSection = u'themes'
         self.themeForm = ThemeForm(self)
@@ -261,11 +263,10 @@
                     old_theme_data = self.getThemeData(old_theme_name)
                     self.cloneThemeData(old_theme_data, new_theme_name)
                     self.deleteTheme(old_theme_name)
-                    for plugin in self.mainwindow.pluginManager.plugins:
+                    for plugin in self.plugin_manager.plugins:
                         if plugin.usesTheme(old_theme_name):
                             plugin.renameTheme(old_theme_name, new_theme_name)
-                    self.mainwindow.renderer.update_theme(
-                        new_theme_name, old_theme_name)
+                    self.renderer.update_theme(new_theme_name, old_theme_name)
                     self.loadThemes()
 
     def onCopyTheme(self):
@@ -312,7 +313,7 @@
             self.themeForm.theme = theme
             self.themeForm.exec_(True)
             self.oldBackgroundImage = None
-            self.mainwindow.renderer.update_theme(theme.theme_name)
+            self.renderer.update_theme(theme.theme_name)
             self.loadThemes()
 
     def onDeleteTheme(self):
@@ -327,7 +328,7 @@
             row = self.themeListWidget.row(item)
             self.themeListWidget.takeItem(row)
             self.deleteTheme(theme)
-            self.mainwindow.renderer.update_theme(theme, only_delete=True)
+            self.renderer.update_theme(theme, only_delete=True)
             # As we do not reload the themes, push out the change. Reload the
             # list as the internal lists and events need to be triggered.
             self._pushThemes()
@@ -631,9 +632,9 @@
         """
         self._writeTheme(theme, image_from, image_to)
         if theme.background_type == BackgroundType.to_string(BackgroundType.Image):
-            self.mainwindow.imageManager.updateImageBorder(theme.background_filename,
+            self.image_manager.updateImageBorder(theme.background_filename,
                 ImageSource.Theme, QtGui.QColor(theme.background_border_color))
-            self.mainwindow.imageManager.processUpdates()
+            self.image_manager.processUpdates()
 
     def _writeTheme(self, theme, image_from, image_to):
         """
@@ -698,7 +699,7 @@
             Flag to tell message lines per page need to be generated.
         """
         log.debug(u'generateImage \n%s ', theme_data)
-        return self.mainwindow.renderer.generate_preview(theme_data, forcePage)
+        return self.renderer.generate_preview(theme_data, forcePage)
 
     def getPreviewImage(self, theme):
         """
@@ -747,7 +748,7 @@
                 return False
             # check for use in the system else where.
             if testPlugin:
-                for plugin in self.mainwindow.pluginManager.plugins:
+                for plugin in self.plugin_manager.plugins:
                     if plugin.usesTheme(theme):
                         critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'),
                             translate('OpenLP.ThemeManager', 'Theme %s is used in the %s plugin.') %
@@ -805,3 +806,32 @@
         new_theme.display_vertical_align = vAlignCorrection
         return new_theme.extract_xml()
 
+    def _get_renderer(self):
+        """
+        Adds the Renderer to the class dynamically
+        """
+        if not hasattr(self, u'_renderer'):
+            self._renderer = Registry().get(u'renderer')
+        return self._renderer
+
+    renderer = property(_get_renderer)
+
+    def _get_image_manager(self):
+        """
+        Adds the image manager to the class dynamically
+        """
+        if not hasattr(self, u'_image_manager'):
+            self._image_manager = Registry().get(u'image_manager')
+        return self._image_manager
+
+    image_manager = property(_get_image_manager)
+
+    def _get_plugin_manager(self):
+        """
+        Adds the Renderer 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)
\ No newline at end of file

=== modified file 'openlp/plugins/alerts/alertsplugin.py'
--- openlp/plugins/alerts/alertsplugin.py	2013-01-16 11:28:38 +0000
+++ openlp/plugins/alerts/alertsplugin.py	2013-01-23 20:36:22 +0000
@@ -151,7 +151,7 @@
             text=translate('AlertsPlugin', '&Alert'), icon=u':/plugins/plugin_alerts.png',
             statustip=translate('AlertsPlugin', 'Show an alert message.'),
             visible=False, shortcuts=[u'F7'], triggers=self.onAlertsTrigger)
-        self.serviceManager.mainwindow.toolsMenu.addAction(self.toolsAlertItem)
+        self.main_window.toolsMenu.addAction(self.toolsAlertItem)
 
     def initialise(self):
         log.info(u'Alerts Initialising')

=== modified file 'openlp/plugins/alerts/forms/alertform.py'
--- openlp/plugins/alerts/forms/alertform.py	2013-01-01 16:33:41 +0000
+++ openlp/plugins/alerts/forms/alertform.py	2013-01-23 20:36:22 +0000
@@ -45,7 +45,7 @@
         self.manager = plugin.manager
         self.plugin = plugin
         self.item_id = None
-        QtGui.QDialog.__init__(self, plugin.formParent)
+        QtGui.QDialog.__init__(self, self.plugin.main_window)
         self.setupUi(self)
         QtCore.QObject.connect(self.displayButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked)
         QtCore.QObject.connect(self.displayCloseButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayCloseClicked)

=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py	2013-01-20 12:23:22 +0000
+++ openlp/plugins/bibles/bibleplugin.py	2013-01-23 20:36:22 +0000
@@ -108,7 +108,7 @@
         """
         Plugin.appStartup(self)
         if self.manager.old_bible_databases:
-            if QtGui.QMessageBox.information(self.formParent,
+            if QtGui.QMessageBox.information(self.main_window,
                 translate('OpenLP', 'Information'),
                 translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your existing Bibles.\n'
                     'Should OpenLP upgrade now?'),
@@ -149,7 +149,7 @@
         Upgrade older bible databases.
         """
         if not hasattr(self, u'upgrade_wizard'):
-            self.upgrade_wizard = BibleUpgradeForm(self.formParent, self.manager, self)
+            self.upgrade_wizard = BibleUpgradeForm(self.main_window, self.manager, self)
         # If the import was not cancelled then reload.
         if self.upgrade_wizard.exec_():
             self.mediaItem.reloadBibles()

=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py	2013-01-21 23:39:10 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -479,7 +479,7 @@
         elif self.advancedTab.isVisible():
             bible = self.advancedVersionComboBox.currentText()
         if bible:
-            self.editBibleForm = EditBibleForm(self, self.plugin.formParent, self.plugin.manager)
+            self.editBibleForm = EditBibleForm(self, self.main_window, self.plugin.manager)
             self.editBibleForm.loadBible(bible)
             if self.editBibleForm.exec_():
                 self.reloadBibles()

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2013-01-11 00:19:11 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -57,7 +57,7 @@
     def __init__(self, parent, plugin, icon):
         self.IconPath = u'custom/custom'
         MediaManagerItem.__init__(self, parent, plugin, icon)
-        self.edit_custom_form = EditCustomForm(self, self.plugin.formParent, self.plugin.manager)
+        self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager)
         self.singleServiceItem = False
         self.quickPreviewAllowed = True
         self.hasSearch = True

=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py	2013-01-18 19:24:06 +0000
+++ openlp/plugins/images/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -100,22 +100,22 @@
             row_list = [item.row() for item in self.listView.selectedIndexes()]
             row_list.sort(reverse=True)
             Receiver.send_message(u'cursor_busy')
-            self.plugin.formParent.displayProgressBar(len(row_list))
+            self.main_window.displayProgressBar(len(row_list))
             for row in row_list:
                 text = self.listView.item(row)
                 if text:
                     delete_file(os.path.join(self.servicePath, text.text()))
                 self.listView.takeItem(row)
-                self.plugin.formParent.incrementProgressBar()
-            Settings().setValue(self.settingsSection + u'/images files', self.getFileList())
-            self.plugin.formParent.finishedProgressBar()
+                self.main_window.incrementProgressBar()
+            SettingsManager.setValue(self.settingsSection + u'/images files', self.getFileList())
+            self.main_window.finishedProgressBar()
             Receiver.send_message(u'cursor_normal')
         self.listView.blockSignals(False)
 
     def loadList(self, images, initialLoad=False):
         if not initialLoad:
             Receiver.send_message(u'cursor_busy')
-            self.plugin.formParent.displayProgressBar(len(images))
+            self.main_window.displayProgressBar(len(images))
         # Sort the images by its filename considering language specific
         # characters.
         images.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1])
@@ -135,9 +135,9 @@
             item_name.setData(QtCore.Qt.UserRole, imageFile)
             self.listView.addItem(item_name)
             if not initialLoad:
-                self.plugin.formParent.incrementProgressBar()
+                self.main_window.incrementProgressBar()
         if not initialLoad:
-            self.plugin.formParent.finishedProgressBar()
+            self.main_window.finishedProgressBar()
             Receiver.send_message(u'cursor_normal')
 
     def generateSlideData(self, service_item, item=None, xmlVersion=False,

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2013-01-20 12:23:22 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -64,14 +64,14 @@
         self.mediaObject = None
         self.displayController = DisplayController(parent)
         self.displayController.controllerLayout = QtGui.QVBoxLayout()
-        self.plugin.mediaController.register_controller(self.displayController)
-        self.plugin.mediaController.set_controls_visible(self.displayController, False)
+        self.media_controller.register_controller(self.displayController)
+        self.media_controller.set_controls_visible(self.displayController, False)
         self.displayController.previewDisplay = Display(self.displayController, False, self.displayController)
         self.displayController.previewDisplay.hide()
         self.displayController.previewDisplay.setGeometry(QtCore.QRect(0, 0, 300, 300))
         self.displayController.previewDisplay.screen = {u'size':self.displayController.previewDisplay.geometry()}
         self.displayController.previewDisplay.setup()
-        self.plugin.mediaController.setup_display(self.displayController.previewDisplay, False)
+        self.media_controller.setup_display(self.displayController.previewDisplay, False)
         QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'video_background_replaced'),
             self.videobackgroundReplaced)
         QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.rebuild_players)
@@ -131,7 +131,7 @@
         """
         Called to reset the Live background with the media selected,
         """
-        self.plugin.liveController.mediaController.media_reset(self.plugin.liveController)
+        self.live_controller.mediaController.media_reset(self.plugin.liveController)
         self.resetAction.setVisible(False)
 
     def videobackgroundReplaced(self):
@@ -154,7 +154,7 @@
                 service_item.shortname = service_item.title
                 (path, name) = os.path.split(filename)
                 service_item.add_from_command(path, name,CLAPPERBOARD)
-                if self.plugin.liveController.mediaController.video(DisplayControllerType.Live, service_item,
+                if self.live_controller.mediaController.video(DisplayControllerType.Live, service_item,
                         videoBehindText=True):
                     self.resetAction.setVisible(True)
                 else:
@@ -186,7 +186,7 @@
         # Only get start and end times if going to a service
         if context == ServiceItemContext.Service:
             # Start media and obtain the length
-            if not self.plugin.mediaController.media_length(service_item):
+            if not self.media_controller.media_length(service_item):
                 return False
         service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
         service_item.add_capability(ItemCapabilities.RequiresMedia)
@@ -212,11 +212,11 @@
         """
         self.populateDisplayTypes()
         self.onNewFileMasks = translate('MediaPlugin.MediaItem', 'Videos (%s);;Audio (%s);;%s (*)') % (
-            u' '.join(self.plugin.mediaController.video_extensions_list),
-            u' '.join(self.plugin.mediaController.audio_extensions_list), UiStrings().AllFiles)
+            u' '.join(self.media_controller.video_extensions_list),
+            u' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles)
 
     def displaySetup(self):
-        self.plugin.mediaController.setup_display(self.displayController.previewDisplay, False)
+        self.media_controller.setup_display(self.displayController.previewDisplay, False)
 
     def populateDisplayTypes(self):
         """
@@ -228,7 +228,7 @@
         self.displayTypeComboBox.blockSignals(True)
         self.displayTypeComboBox.clear()
         usedPlayers, overridePlayer = get_media_players()
-        mediaPlayers = self.plugin.mediaController.mediaPlayers
+        mediaPlayers = self.media_controller.mediaPlayers
         currentIndex = 0
         for player in usedPlayers:
             # load the drop down selection
@@ -270,7 +270,7 @@
             elif track_info.isFile():
                 filename = os.path.split(unicode(track))[1]
                 item_name = QtGui.QListWidgetItem(filename)
-                if u'*.%s' % (filename.split(u'.')[-1].lower()) in self.plugin.mediaController.audio_extensions_list:
+                if u'*.%s' % (filename.split(u'.')[-1].lower()) in self.media_controller.audio_extensions_list:
                     item_name.setIcon(AUDIO)
                 else:
                     item_name.setIcon(VIDEO)
@@ -288,9 +288,9 @@
         media.sort(cmp=locale_compare, key=lambda filename: os.path.split(unicode(filename))[1])
         ext = []
         if type == MediaType.Audio:
-            ext = self.plugin.mediaController.audio_extensions_list
+            ext = self.media_controller.audio_extensions_list
         else:
-            ext = self.plugin.mediaController.video_extensions_list
+            ext = self.media_controller.video_extensions_list
         ext = map(lambda x: x[1:], ext)
         media = filter(lambda x: os.path.splitext(x)[1] in ext, media)
         return media

=== modified file 'openlp/plugins/media/mediaplugin.py'
--- openlp/plugins/media/mediaplugin.py	2013-01-18 19:24:06 +0000
+++ openlp/plugins/media/mediaplugin.py	2013-01-23 20:36:22 +0000
@@ -31,7 +31,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings
+from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings, Registry
 from openlp.plugins.media.lib import MediaMediaItem, MediaTab
 
 log = logging.getLogger(__name__)
@@ -97,26 +97,26 @@
         Time to tidy up on exit
         """
         log.info(u'Media Finalising')
-        self.mediaController.finalise()
+        self.media_controller.finalise()
         Plugin.finalise(self)
 
     def getDisplayCss(self):
         """
         Add css style sheets to htmlbuilder
         """
-        return self.mediaController.get_media_display_css()
+        return self.media_controller.get_media_display_css()
 
     def getDisplayJavaScript(self):
         """
         Add javascript functions to htmlbuilder
         """
-        return self.mediaController.get_media_display_javascript()
+        return self.media_controller.get_media_display_javascript()
 
     def getDisplayHtml(self):
         """
         Add html code to htmlbuilder
         """
-        return self.mediaController.get_media_display_html()
+        return self.media_controller.get_media_display_html()
 
     def appStartup(self):
         """
@@ -129,7 +129,7 @@
         settings.beginGroup(self.settingsSection)
         if settings.contains(u'use phonon'):
             log.info(u'Found old Phonon setting')
-            players = self.mediaController.mediaPlayers.keys()
+            players = self.media_controller.mediaPlayers.keys()
             has_phonon = u'phonon' in players
             if settings.value(u'use phonon')  and has_phonon:
                 log.debug(u'Converting old setting to new setting')
@@ -137,8 +137,18 @@
                 if players:
                     new_players = [player for player in players if player != u'phonon']
                 new_players.insert(0, u'phonon')
-                self.mediaController.mediaPlayers[u'phonon'].isActive = True
+                self.media_controller.mediaPlayers[u'phonon'].isActive = True
                 settings.setValue(u'players', u','.join(new_players))
                 self.settingsTab.load()
             settings.remove(u'use phonon')
         settings.endGroup()
+
+    def _get_media_controller(self):
+        """
+        Adds the media controller to the class dynamically
+        """
+        if not hasattr(self, u'_media_controller'):
+            self._media_controller = Registry().get(u'media_controller')
+        return self._media_controller
+
+    media_controller = property(_get_media_controller)

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2013-01-18 19:24:06 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -153,13 +153,13 @@
         Receiver.send_message(u'cursor_busy')
         if not initialLoad:
             Receiver.send_message(u'cursor_busy')
-            self.plugin.formParent.displayProgressBar(len(files))
+            self.main_window.displayProgressBar(len(files))
         # Sort the presentations by its filename considering language specific characters.
         files.sort(cmp=locale_compare,
             key=lambda filename: os.path.split(unicode(filename))[1])
         for file in files:
             if not initialLoad:
-                self.plugin.formParent.incrementProgressBar()
+                self.main_window.incrementProgressBar()
             if currlist.count(file) > 0:
                 continue
             filename = os.path.split(unicode(file))[1]
@@ -208,7 +208,7 @@
                 self.listView.addItem(item_name)
         Receiver.send_message(u'cursor_normal')
         if not initialLoad:
-            self.plugin.formParent.finishedProgressBar()
+            self.main_window.finishedProgressBar()
             Receiver.send_message(u'cursor_normal')
 
     def onDeleteClick(self):
@@ -220,15 +220,15 @@
             row_list = [item.row() for item in items]
             row_list.sort(reverse=True)
             Receiver.send_message(u'cursor_busy')
-            self.plugin.formParent.displayProgressBar(len(row_list))
+            self.main_window.displayProgressBar(len(row_list))
             for item in items:
                 filepath = unicode(item.data(QtCore.Qt.UserRole))
                 for cidx in self.controllers:
                     doc = self.controllers[cidx].add_document(filepath)
                     doc.presentation_deleted()
                     doc.close_presentation()
-                self.plugin.formParent.incrementProgressBar()
-            self.plugin.formParent.finishedProgressBar()
+                self.main_window.incrementProgressBar()
+            self.main_window.finishedProgressBar()
             Receiver.send_message(u'cursor_normal')
             for row in row_list:
                 self.listView.takeItem(row)

=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py	2013-01-18 21:36:15 +0000
+++ openlp/plugins/presentations/presentationplugin.py	2013-01-23 20:36:22 +0000
@@ -111,7 +111,7 @@
         Create the Media Manager List
         """
         self.mediaItem = PresentationMediaItem(
-            self.mediaDock.media_dock, self, self.icon, self.controllers)
+            self.main_window.mediaDockManager.media_dock, self, self.icon, self.controllers)
 
     def registerControllers(self, controller):
         """

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2013-01-18 21:36:15 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2013-01-23 20:36:22 +0000
@@ -39,8 +39,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import PluginStatus, Receiver, MediaType, translate, create_separated_list, \
-    check_directory_exists, UiStrings
-from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, \
+    check_directory_exists, Registry, UiStrings
+from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, critical_error_message_box, \
     find_and_set_in_combo_box
 from openlp.core.utils import AppLocation
 from openlp.plugins.songs.forms import EditVerseForm, MediaFilesForm
@@ -88,8 +88,7 @@
             self.onVerseListViewClicked)
         QtCore.QObject.connect(self.verseOrderEdit, QtCore.SIGNAL(u'textChanged(QString)'),
             self.onVerseOrderTextChanged)
-        QtCore.QObject.connect(self.themeAddButton, QtCore.SIGNAL(u'clicked()'),
-            self.mediaitem.plugin.renderer.theme_manager.onAddTheme)
+        QtCore.QObject.connect(self.themeAddButton, QtCore.SIGNAL(u'clicked()'), self.theme_manager.onAddTheme)
         QtCore.QObject.connect(self.maintenanceButton, QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
         QtCore.QObject.connect(self.audioAddFromFileButton, QtCore.SIGNAL(u'clicked()'),
             self.onAudioAddFromFileButtonClicked)
@@ -909,3 +908,12 @@
         except:
             log.exception(u'Problem processing song Lyrics \n%s', sxml.dump_xml())
 
+    def _get_theme_manager(self):
+        """
+        Adds the theme manager to the class dynamically
+        """
+        if not hasattr(self, u'_theme_manager'):
+            self._theme_manager = Registry().get(u'theme_manager')
+        return self._theme_manager
+
+    theme_manager = property(_get_theme_manager)
\ No newline at end of file

=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2013-01-18 20:35:30 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2013-01-23 20:36:22 +0000
@@ -59,7 +59,7 @@
         ``plugin``
             The songs plugin.
         """
-        self.clipboard = plugin.formParent.clipboard
+        self.clipboard = self.main_window.clipboard
         OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp')
 
     def setupUi(self, image):

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2013-01-11 00:19:11 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2013-01-23 20:36:22 +0000
@@ -71,8 +71,7 @@
     def __init__(self, parent, plugin, icon):
         self.IconPath = u'songs/song'
         MediaManagerItem.__init__(self, parent, plugin, icon)
-        self.editSongForm = EditSongForm(self, self.plugin.formParent,
-            self.plugin.manager)
+        self.editSongForm = EditSongForm(self, self.main_window, self.plugin.manager)
         self.openLyrics = OpenLyrics(self.plugin.manager)
         self.singleServiceItem = False
         self.songMaintenanceForm = SongMaintenanceForm(self.plugin.manager, self)
@@ -373,7 +372,7 @@
                 QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
                 return
             Receiver.send_message(u'cursor_busy')
-            self.plugin.formParent.displayProgressBar(len(items))
+            self.main_window.displayProgressBar(len(items))
             for item in items:
                 item_id = item.data(QtCore.Qt.UserRole)
                 media_files = self.plugin.manager.get_all_objects(MediaFile, MediaFile.song_id == item_id)
@@ -389,8 +388,8 @@
                 except OSError:
                     log.exception(u'Could not remove directory: %s', save_path)
                 self.plugin.manager.delete_object(Song, item_id)
-                self.plugin.formParent.incrementProgressBar()
-            self.plugin.formParent.finishedProgressBar()
+                self.main_window.incrementProgressBar()
+            self.main_window.finishedProgressBar()
             Receiver.send_message(u'cursor_normal')
             self.onSearchTextButtonClicked()
 

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2013-01-18 21:36:15 +0000
+++ openlp/plugins/songs/songsplugin.py	2013-01-23 20:36:22 +0000
@@ -157,7 +157,7 @@
         if maxSongs == 0:
             return
         progressDialog = QtGui.QProgressDialog(translate('SongsPlugin', 'Reindexing songs...'), UiStrings().Cancel,
-            0, maxSongs, self.formParent)
+            0, maxSongs, self.main_window)
         progressDialog.setWindowTitle(translate('SongsPlugin', 'Reindexing songs'))
         progressDialog.setWindowModality(QtCore.Qt.WindowModal)
         songs = self.manager.get_all_objects(Song)
@@ -200,8 +200,7 @@
         ``newTheme``
             The new name the plugin should now use.
         """
-        songsUsingTheme = self.manager.get_all_objects(Song,
-            Song.theme_name == oldTheme)
+        songsUsingTheme = self.manager.get_all_objects(Song, Song.theme_name == oldTheme)
         for song in songsUsingTheme:
             song.theme_name = newTheme
             self.manager.save_object(song)
@@ -261,7 +260,7 @@
         if not song_dbs:
             return
         Receiver.send_message(u'openlp_process_events')
-        progress = QtGui.QProgressDialog(self.formParent)
+        progress = QtGui.QProgressDialog(self.main_window)
         progress.setWindowModality(QtCore.Qt.WindowModal)
         progress.setWindowTitle(translate('OpenLP.Ui', 'Importing Songs'))
         progress.setLabelText(translate('OpenLP.Ui', 'Starting import...'))

=== modified file 'openlp/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py	2013-01-18 12:25:05 +0000
+++ openlp/plugins/songusage/songusageplugin.py	2013-01-23 20:36:22 +0000
@@ -107,12 +107,12 @@
         self.songUsageMenu.addSeparator()
         self.songUsageMenu.addAction(self.songUsageReport)
         self.songUsageMenu.addAction(self.songUsageDelete)
-        self.songUsageActiveButton = QtGui.QToolButton(self.formParent.statusBar)
+        self.songUsageActiveButton = QtGui.QToolButton(self.main_window.statusBar)
         self.songUsageActiveButton.setCheckable(True)
         self.songUsageActiveButton.setAutoRaise(True)
         self.songUsageActiveButton.setStatusTip(translate('SongUsagePlugin', 'Toggle the tracking of song usage.'))
         self.songUsageActiveButton.setObjectName(u'songUsageActiveButton')
-        self.formParent.statusBar.insertPermanentWidget(1, self.songUsageActiveButton)
+        self.main_window.statusBar.insertPermanentWidget(1, self.songUsageActiveButton)
         self.songUsageActiveButton.hide()
         # Signals and slots
         QtCore.QObject.connect(self.songUsageStatus, QtCore.SIGNAL(u'visibilityChanged(bool)'),
@@ -134,8 +134,8 @@
         action_list.add_action(self.songUsageStatus, translate('SongUsagePlugin', 'Song Usage'))
         action_list.add_action(self.songUsageDelete, translate('SongUsagePlugin', 'Song Usage'))
         action_list.add_action(self.songUsageReport, translate('SongUsagePlugin', 'Song Usage'))
-        self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.formParent)
-        self.songUsageDetailForm = SongUsageDetailForm(self, self.formParent)
+        self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.main_window)
+        self.songUsageDetailForm = SongUsageDetailForm(self, self.main_window)
         self.songUsageMenu.menuAction().setVisible(True)
         self.songUsageActiveButton.show()
 

=== added file 'tests/functional/openlp_core_lib/test_registry.py'
--- tests/functional/openlp_core_lib/test_registry.py	1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_lib/test_registry.py	2013-01-23 20:36:22 +0000
@@ -0,0 +1,33 @@
+"""
+    Package to test the openlp.core.lib package.
+"""
+import os
+
+from unittest import TestCase
+from mock import MagicMock
+from openlp.core.lib import ServiceItem, Registry
+
+TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources'))
+
+class TestServiceItem(TestCase):
+
+    def registry_basic_test(self):
+        """
+        Test the Service Item basic test
+        """
+        # GIVEN: A new registry
+        registry = Registry.create()
+
+        # WHEN:A service item is created (without a plugin)
+        mock_1 = MagicMock()
+        Registry().register(u'test1', mock_1)
+
+        # THEN: we should be able retrieve the saved object
+        assert Registry().get(u'test1') == mock_1, u'The saved object can be retrieved'
+        #assert service_item.missing_frames() is True, u'There should not be any frames in the service item'
+
+        # THEN: We should get back a valid service item
+        try:
+            assert Registry().get(u'test2') == mock_1, u'This should not be fired'
+        except Exception, e:
+            pass
\ No newline at end of file

=== modified file 'tests/functional/openlp_core_lib/test_serviceitem.py'
--- tests/functional/openlp_core_lib/test_serviceitem.py	2013-01-20 20:53:58 +0000
+++ tests/functional/openlp_core_lib/test_serviceitem.py	2013-01-23 20:36:22 +0000
@@ -5,7 +5,7 @@
 
 from unittest import TestCase
 from mock import MagicMock
-from openlp.core.lib import ServiceItem
+from openlp.core.lib import ServiceItem, Registry
 
 VERSE = u'The Lord said to {r}Noah{/r}: \n'\
         'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
@@ -20,6 +20,17 @@
 
 class TestServiceItem(TestCase):
 
+    def setUp(self):
+        """
+        Set up the Registry
+        """
+        registry = Registry.create()
+        mocked_renderer =  MagicMock()
+        mocked_image_manager =  MagicMock()
+        mocked_renderer.format_slide.return_value = [VERSE]
+        Registry().register(u'renderer', mocked_renderer)
+        Registry().register(u'image_manager', mocked_image_manager)
+
     def serviceitem_basic_test(self):
         """
         Test the Service Item basic test
@@ -48,11 +59,6 @@
         assert service_item.is_valid is True, u'The new service item should be valid'
         assert service_item.missing_frames() is False, u'check frames loaded '
 
-        # GIVEN: A service item with text
-        mocked_renderer =  MagicMock()
-        mocked_renderer.format_slide.return_value = [VERSE]
-        service_item.renderer = mocked_renderer
-
         # WHEN: Render called
         assert len(service_item._display_frames) == 0, u'A blank Service Item with no display frames'
         service_item.render(True)
@@ -68,8 +74,6 @@
         # GIVEN: A new service item and a mocked renderer
         service_item = ServiceItem(None)
         service_item.name = u'test'
-        mocked_renderer =  MagicMock()
-        service_item.renderer = mocked_renderer
 
         # WHEN: adding image to a service item
         test_image = os.path.join(TESTPATH, u'church.jpg')
@@ -125,8 +129,6 @@
         # GIVEN: A new service item and a mocked renderer
         service_item = ServiceItem(None)
         service_item.name = u'test'
-        mocked_renderer =  MagicMock()
-        service_item.renderer = mocked_renderer
 
         # WHEN: adding image to a service item
         test_file = os.path.join(TESTPATH, u'church.jpg')