← Back to team overview

openlp-core team mailing list archive

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

 

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

Requested reviews:
  Andreas Preikschat (googol)

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

This is big and may have some bugs in it like Powerpoint which I cannot test!

Remove the Receiver class and move over to either direct calls or the Registry.
Fix the Version code as it will not work with the registry directly.

Rename variables where possible for methods being used by the registry

Add more tests to the registry and debugging aids.

Fix 2 bugs in core which stopped the code working.
-- 
https://code.launchpad.net/~trb143/openlp/event_receiver_removal/+merge/147525
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2013-02-04 22:05:19 +0000
+++ openlp/core/__init__.py	2013-02-09 17:32:28 +0000
@@ -43,7 +43,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Settings, ScreenList, UiStrings, Registry, check_directory_exists
+from openlp.core.lib import Settings, ScreenList, UiStrings, Registry, check_directory_exists
 from openlp.core.resources import qInitResources
 from openlp.core.ui.mainwindow import MainWindow
 from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
@@ -150,16 +150,10 @@
         update_check = Settings().value(u'general/update check')
         if update_check:
             VersionThread(self.main_window).start()
-        Receiver.send_message(u'live_display_blank_check')
+        self.main_window.blank_check()
         self.main_window.app_startup()
         return self.exec_()
 
-    def close_splash_screen(self):
-        """
-        Close the splash screen when requested.
-        """
-        self.splash.close()
-
     def is_already_running(self):
         """
         Look to see if OpenLP is already running and ask if a 2nd copy
@@ -203,6 +197,7 @@
         """
         Wrapper to make ProcessEvents visible and named correctly
         """
+        log.debug(u'processing event flush')
         self.processEvents()
 
     def set_busy_cursor(self):

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2013-02-02 20:54:34 +0000
+++ openlp/core/lib/__init__.py	2013-02-09 17:32:28 +0000
@@ -387,7 +387,6 @@
 
 from registry import Registry
 from uistrings import UiStrings
-from eventreceiver import Receiver
 from screen import ScreenList
 from settings import Settings
 from listwidgetwithdnd import ListWidgetWithDnD

=== removed file 'openlp/core/lib/eventreceiver.py'
--- openlp/core/lib/eventreceiver.py	2013-02-03 17:42:31 +0000
+++ openlp/core/lib/eventreceiver.py	1970-01-01 00:00:00 +0000
@@ -1,253 +0,0 @@
-# -*- 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 event handling code for OpenLP
-"""
-import logging
-
-from PyQt4 import QtCore
-
-log = logging.getLogger(__name__)
-
-
-class EventReceiver(QtCore.QObject):
-    """
-    Class to allow events to be passed from different parts of the system. This
-    is a private class and should not be used directly but rather via the
-    Receiver class.
-
-    **Mainwindow related and generic signals**
-
-    ``mainwindow_status_text``
-        Changes the bottom status bar text on the mainwindow.
-
-    ``openlp_error_message``
-        Displays a standalone Error Message.
-
-    ``openlp_information_message``
-        Displays a standalone Information Message.
-
-    ``openlp_version_check``
-        Version has changed so pop up window.
-
-    ``openlp_stop_wizard``
-        Stops a wizard before completion.
-
-    **Setting related signals**
-
-    ``config_updated``
-        Informs components that the config has changed.
-
-    ``config_screen_changed``
-        The display monitor has been changed.
-
-    **Slidecontroller signals**
-
-    ``slidecontroller_{live|preview}_next``
-        Moves to the next slide.
-
-    ``slidecontroller_{live|preview}_next_noloop``
-        Moves to the next slide without auto advance.
-
-    ``slidecontroller_{live|preview}_previous``
-        Moves to the previous slide.
-
-    ``slidecontroller_{live|preview}_previous_noloop``
-        Moves to the previous slide, without auto advance.
-
-    ``slidecontroller_{live|preview}_set``
-        Moves to a specific slide, by index.
-
-    ``slidecontroller_{live|preview}_started``
-        Broadcasts that an item has been made live/previewed.
-
-    ``slidecontroller_{live|preview}_change``
-        Informs the slidecontroller that a slide change has occurred and to
-        update itself.
-
-    ``slidecontroller_{live|preview}_changed``
-        Broadcasts that the slidecontroller has changed the current slide.
-
-    ``slidecontroller_{live|preview}_blank``
-        Request that the output screen is blanked.
-
-    ``slidecontroller_{live|preview}_unblank``
-        Request that the output screen is unblanked.
-
-    ``slidecontroller_live_spin_delay``
-        Pushes out the loop delay.
-
-    ``slidecontroller_update_slide_limits``
-        Updates the slide_limits variable from the saved settings.
-
-    ``slidecontroller_live_stop_loop``
-        Stop the loop on the main display.
-
-    **Display signals**
-
-    ``update_display_css``
-        CSS has been updated which needs to be changed on the main display.
-
-    **Live Display signals**
-
-    ``live_display_hide``
-        Hide the live display.
-
-    ``live_display_show``
-        Return the live display.
-
-    ``live_display_active``
-        The live display has been made active.
-
-    ``live_display_blank_check``
-        Check to see if the blank display message is required.
-
-    **Theme related singlas**
-
-    ``theme_update_list``
-        send out message with new themes.
-
-    ``theme_update_global``
-        Tell the components we have a new global theme.
-
-    **Plugin specific signals**
-
-    ``{plugin}_start``
-        Requests a plugin to start a external program. Path and file have to
-        be provided in the message.
-
-    ``{plugin}_first``
-        Requests a plugin to handle a first event.
-
-    ``{plugin}_previous``
-        Requests a plugin to handle a previous event.
-
-    ``{plugin}_next``
-        Requests a plugin to handle a next event.
-
-    ``{plugin}_last``
-        Requests a plugin to handle a last event.
-
-    ``{plugin}_slide``
-        Requests a plugin to handle a go to specific slide event.
-
-    ``{plugin}_stop``
-        Requests a plugin to handle a stop event.
-
-    ``{plugin}_blank``
-        Requests a plugin to handle a blank screen event.
-
-    ``{plugin}_unblank``
-        Requests a plugin to handle an unblank screen event.
-
-    ``{plugin}_load_list``
-        Tells the the plugin to reload the media manager list.
-
-    ``{plugin}_preview``
-        Tells the plugin it's item can be previewed.
-
-    ``{plugin}_add_service_item``
-        Ask the plugin to push the selected items to the service item.
-
-    ``{plugin}_service_load``
-        Ask the plugin to process an individual service item after it has been
-        loaded.
-
-    ``{plugin}_config_updated``
-        The config has changed so tell the plugin about it.
-
-    ``alerts_text``
-        Displays an alert message.
-
-    ``bibles_nobook``
-        Attempt to find book resulted in no match.
-
-    ``remotes_poll_request``
-        Waits for openlp to do something "interesting" and sends a
-        ``remotes_poll_response`` signal when it does.
-
-    """
-    def __init__(self):
-        """
-        Initialise the event receiver, calling the parent constructor.
-        """
-        QtCore.QObject.__init__(self)
-
-    def send_message(self, event, msg=None):
-        """
-        Emit a Qt signal.
-
-        ``event``
-            The event to that was sent.
-
-        ``msg``
-            Defaults to *None*. The message to send with the event.
-        """
-        log.debug(u'Event %s passed with payload %s' % (event, msg))
-        self.emit(QtCore.SIGNAL(event), msg)
-
-
-class Receiver(object):
-    """
-    Class to allow events to be passed from different parts of the system. This
-    is a static wrapper around the ``EventReceiver`` class. As there is only
-    one instance of it in the system the Qt4 signal/slot architecture can send
-    messages across the system.
-
-    To send a message:
-       ``Receiver.send_message(u'<<Message ID>>', data)``
-
-    To receive a Message
-        ``QtCore.QObject.connect(
-            Receiver.get_receiver(),
-            QtCore.SIGNAL(u'<<Message ID>>'),
-            <<ACTION>>
-        )``
-    """
-    __eventreceiver__ = EventReceiver()
-
-    @staticmethod
-    def send_message(event, msg=None):
-        """
-        Sends a message to the messaging system.
-
-        ``event``
-            The event to send.
-
-        ``msg``
-            Defaults to *None*. The message to send with the event.
-        """
-        Receiver.__eventreceiver__.send_message(event, msg)
-
-    @staticmethod
-    def get_receiver():
-        """
-        Get the global ``__eventreceiver__`` instance.
-        """
-        return Receiver.__eventreceiver__

=== modified file 'openlp/core/lib/imagemanager.py'
--- openlp/core/lib/imagemanager.py	2013-02-05 08:05:28 +0000
+++ openlp/core/lib/imagemanager.py	2013-02-09 17:32:28 +0000
@@ -39,7 +39,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, Registry, ScreenList, resize_image, image_to_byte
+from openlp.core.lib import Registry, ScreenList, resize_image, image_to_byte
 
 log = logging.getLogger(__name__)
 
@@ -200,7 +200,7 @@
         self.image_thread = ImageThread(self)
         self._conversion_queue = PriorityQueue()
         self.stop_manager = False
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.process_updates)
+        Registry().register_function(u'config_updated', self.process_updates)
 
     def update_display(self):
         """

=== modified file 'openlp/core/lib/listwidgetwithdnd.py'
--- openlp/core/lib/listwidgetwithdnd.py	2013-02-01 19:58:18 +0000
+++ openlp/core/lib/listwidgetwithdnd.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver
+from openlp.core.lib import Registry
 
 
 class ListWidgetWithDnD(QtGui.QListWidget):
@@ -54,8 +54,7 @@
         """
         self.setAcceptDrops(True)
         self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_dnd' % self.mimeDataText),
-            self.parent().loadFile)
+        Registry().register_function((u'%s_dnd' % self.mimeDataText), self.parent().loadFile)
 
     def mouseMoveEvent(self, event):
         """
@@ -112,6 +111,6 @@
                     listing = os.listdir(localFile)
                     for file in listing:
                         files.append(os.path.join(localFile, file))
-            Receiver.send_message(u'%s_dnd' % self.mimeDataText, files)
+            Registry().execute(u'%s_dnd' % self.mimeDataText, files)
         else:
             event.ignore()

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-02-03 19:23:12 +0000
+++ openlp/core/lib/mediamanageritem.py	2013-02-09 17:32:28 +0000
@@ -35,7 +35,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, Receiver, ListWidgetWithDnD, \
+from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, ListWidgetWithDnD, \
     ServiceItemContext, Settings, Registry, UiStrings, build_icon, translate
 from openlp.core.lib.searchedit import SearchEdit
 from openlp.core.lib.ui import create_widget_action, critical_error_message_box
@@ -116,8 +116,7 @@
         self.setupUi()
         self.retranslateUi()
         self.autoSelectId = -1
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_service_load' % self.plugin.name),
-            self.serviceLoad)
+        Registry().register_function(u'%s_service_load' % self.plugin.name, self.serviceLoad)
 
     def requiredIcons(self):
         """

=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py	2013-02-03 19:23:12 +0000
+++ openlp/core/lib/plugin.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, Settings, Registry, UiStrings
+from openlp.core.lib import Settings, Registry, UiStrings
 from openlp.core.utils import get_application_version
 
 log = logging.getLogger(__name__)
@@ -171,10 +171,8 @@
             default_settings[u'%s/%s files' % (name, name)] = []
         # Add settings to the dict of all settings.
         Settings.extend_default_settings(default_settings)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_add_service_item' % self.name),
-            self.processAddServiceEvent)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_config_updated' % self.name),
-            self.configUpdated)
+        Registry().register_function(u'%s_add_service_item' % self.name, self.processAddServiceEvent)
+        Registry().register_function(u'%s_config_updated' % self.name, self.config_update)
 
     def checkPreConditions(self):
         """
@@ -403,7 +401,7 @@
         """
         return u''
 
-    def configUpdated(self):
+    def config_update(self):
         """
         The plugin's config has changed
         """

=== modified file 'openlp/core/lib/registry.py'
--- openlp/core/lib/registry.py	2013-02-02 21:16:42 +0000
+++ openlp/core/lib/registry.py	2013-02-09 17:32:28 +0000
@@ -59,15 +59,19 @@
         log.info(u'Registry Initialising')
         registry = cls()
         registry.service_list = {}
-        registry.running_under_test = False
+        registry.functions_list = {}
+        registry.running_under_test = True
         # Allow the tests to remove Registry entries but not the live system
-        if u'nosetest' in sys.argv[0]:
-            registry.running_under_test = True
+        if u'openlp.py' in sys.argv[0]:
+            registry.running_under_test = False
         return registry
 
     def get(self, key):
         """
         Extracts the registry value from the list based on the key passed in
+
+        ``key``
+            The service to be retrieved.
         """
         if key in self.service_list:
             return self.service_list[key]
@@ -78,6 +82,12 @@
     def register(self, key, reference):
         """
         Registers a component against a key.
+
+        ``key``
+            The service to be created this is usually a major class like "renderer" or "main_window" .
+
+        ``reference``
+            The service address to be saved.
         """
         if key in self.service_list:
             log.error(u'Duplicate service exception %s' % key)
@@ -88,7 +98,10 @@
     def remove(self, key):
         """
         Removes the registry value from the list based on the key passed in
-        (Only valid and active for testing framework)
+        (Only valid and active for testing framework).
+
+        ``key``
+            The service to be deleted.
         """
         if self.running_under_test is False:
             log.error(u'Invalid Method call for key %s' % key)
@@ -96,3 +109,65 @@
             return
         if key in self.service_list:
             del self.service_list[key]
+
+    def register_function(self, event, function):
+        """
+        Register a function and a handler to be called later
+
+        ``event``
+            The function description like "config_updated" or "live_display_hide" where a number of places in the
+            code will/may need to respond to a single action and the caller does not need to understand or know about
+            the recipients.
+
+        ``function``
+            The function to be called when the event happens.
+        """
+        if not self.functions_list.has_key(event):
+            self.functions_list[event] = [function]
+        else:
+            self.functions_list[event].append(function)
+
+    def remove_function(self, event, function):
+        """
+        Register a function and a handler to be called later
+
+        ``event``
+            The function description..
+
+        ``function``
+            The function to be called when the event happens.
+        """
+        if self.running_under_test is False:
+            log.error(u'Invalid Method call for key %s' % event)
+            raise KeyError(u'Invalid Method call for key %s' % event)
+            return
+        if event in self.functions_list:
+            self.functions_list[event].remove(function)
+
+    def execute(self, event, *args, **kwargs):
+        """
+        Execute all the handlers registered passing the data to the handler and returning results
+
+        ``event``
+            The function to be processed
+
+        ``*args``
+            Parameters to be passed to the function.
+
+        ``*kwargs``
+            Parameters to be passed to the function.
+        """
+        results = []
+        if event in self.functions_list:
+            for function in self.functions_list[event]:
+                try:
+                    result = function(*args, **kwargs)
+                    if result:
+                        results.append(result)
+                except TypeError:
+                    # Who has called me can help in debugging
+                    import inspect
+                    log.debug(inspect.currentframe().f_back.f_locals)
+                    log.exception(u'Exception for function %s', function)
+        return results
+

=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2013-02-05 08:05:28 +0000
+++ openlp/core/lib/renderer.py	2013-02-09 17:32:28 +0000
@@ -31,8 +31,8 @@
 
 from PyQt4 import QtGui, QtCore, QtWebKit
 
-from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Receiver, Registry, ScreenList, \
-    ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css
+from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Registry, ScreenList, ServiceItem, \
+    expand_tags, build_lyrics_format_css, build_lyrics_outline_css
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.ui import MainDisplay
 
@@ -80,7 +80,7 @@
         self.display.setup()
         self._theme_dimensions = {}
         self._calculate_default()
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.set_global_theme)
+        Registry().register_function(u'theme_update_global', self.set_global_theme)
         self.web = QtWebKit.QWebView()
         self.web.setVisible(False)
         self.web_frame = self.web.page().mainFrame()
@@ -602,7 +602,7 @@
                 previous_raw = u''
                 # Stop here as the theme line count was requested.
                 if self.force_page:
-                    Receiver.send_message(u'theme_line_count', index + 1)
+                    Registry().execute(u'theme_line_count', index + 1)
                     break
             else:
                 continue

=== modified file 'openlp/core/lib/screen.py'
--- openlp/core/lib/screen.py	2013-02-04 21:39:44 +0000
+++ openlp/core/lib/screen.py	2013-02-09 17:32:28 +0000
@@ -35,7 +35,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, translate
+from openlp.core.lib import Registry, translate
 
 log = logging.getLogger(__name__)
 
@@ -100,7 +100,7 @@
                 if screen == self.override:
                     self.override = copy.deepcopy(newScreen)
                     self.set_override_display()
-                Receiver.send_message(u'config_screen_changed')
+                Registry().execute(u'config_screen_changed')
                 break
 
     def screen_count_changed(self, changed_screen=-1):
@@ -128,7 +128,7 @@
         # We do not want to send this message at start up.
         if changed_screen != -1:
             # Reload setting tabs to apply possible changes.
-            Receiver.send_message(u'config_screen_changed')
+            Registry().execute(u'config_screen_changed')
 
     def get_screen_list(self):
         """

=== modified file 'openlp/core/lib/ui.py'
--- openlp/core/lib/ui.py	2013-02-05 08:05:28 +0000
+++ openlp/core/lib/ui.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, UiStrings, build_icon, translate
+from openlp.core.lib import Registry, UiStrings, build_icon, translate
 from openlp.core.utils.actions import ActionList
 
 
@@ -135,8 +135,7 @@
         return QtGui.QMessageBox.critical(parent, UiStrings().Error, message,
             QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
     data = {u'message': message}
-    data[u'title'] = title if title else UiStrings().Error
-    return Receiver.send_message(u'openlp_error_message', data)
+    return Registry().get(u'main_window').error_message(title if title else UiStrings().Error, message)
 
 
 def create_horizontal_adjusting_combo_box(parent, name):

=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/advancedtab.py	2013-02-09 17:32:28 +0000
@@ -36,7 +36,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate, build_icon
+from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate, build_icon
 from openlp.core.utils import AppLocation, format_time, get_images_filter
 from openlp.core.lib import SlideLimits
 
@@ -397,22 +397,19 @@
         if not os.path.exists(self.current_data_path):
             log.error(u'Data path not found %s' % self.current_data_path)
             answer = QtGui.QMessageBox.critical(self,
-                translate('OpenLP.AdvancedTab',
-                'Data Directory Error'),
-                translate('OpenLP.AdvancedTab',
-                'OpenLP data directory was not found\n\n%s\n\n'
+                translate('OpenLP.AdvancedTab', 'Data Directory Error'),
+                translate('OpenLP.AdvancedTab', 'OpenLP data directory was not found\n\n%s\n\n'
                 'This data directory was previously changed from the OpenLP '
                 'default location.  If the new location was on removable '
                 'media, that media needs to be made available.\n\n'
-                'Click "No" to stop loading OpenLP. allowing you to fix '
-                'the the problem.\n\n'
+                'Click "No" to stop loading OpenLP. allowing you to fix the the problem.\n\n'
                 'Click "Yes" to reset the data directory to the default '
                 'location.').replace('%s', self.current_data_path),
                 QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
                 QtGui.QMessageBox.No)
             if answer == QtGui.QMessageBox.No:
                 log.info(u'User requested termination')
-                Receiver.send_message(u'cleanup')
+                self.main_window.clean_up()
                 sys.exit()
             # Set data location to default.
             settings.remove(u'advanced/data path')
@@ -455,9 +452,9 @@
         settings.setValue(u'slide limits', self.slide_limits)
         settings.endGroup()
         if self.display_changed:
-            Receiver.send_message(u'config_screen_changed')
+            Registry().execute(u'config_screen_changed')
             self.display_changed = False
-        Receiver.send_message(u'slidecontroller_update_slide_limits')
+        Registry().execute(u'slidecontroller_update_slide_limits')
 
     def cancel(self):
         """
@@ -573,7 +570,7 @@
         # Check if data already exists here.
         self.check_data_overwrite(new_data_path)
         # Save the new location.
-        Receiver.send_message(u'set_new_data_path', new_data_path)
+        self.main_window.set_new_data_path(new_data_path)
         self.new_data_directory_edit.setText(new_data_path)
         self.data_directory_cancel_button.show()
 
@@ -594,7 +591,7 @@
                 return
             self.check_data_overwrite(new_data_path)
             # Save the new location.
-            Receiver.send_message(u'set_new_data_path', new_data_path)
+            self.main_window.set_new_data_path(new_data_path)
             self.new_data_directory_edit.setText(os.path.abspath(new_data_path))
             self.data_directory_cancel_button.show()
         else:
@@ -605,8 +602,7 @@
         """
         Copy existing data when you change your data directory.
         """
-        Receiver.send_message(u'set_copy_data',
-            self.data_directory_copy_check_box.isChecked())
+        self.main_window.set_copy_data(self.data_directory_copy_check_box.isChecked())
         if self.data_exists:
             if self.data_directory_copy_check_box.isChecked():
                 self.new_data_directory_has_files_label.show()
@@ -645,8 +641,8 @@
         """
         self.new_data_directory_edit.clear()
         self.data_directory_copy_check_box.setChecked(False)
-        Receiver.send_message(u'set_new_data_path', u'')
-        Receiver.send_message(u'set_copy_data', False)
+        self.main_window.set_new_data_path(None)
+        self.main_window.set_copy_data(False)
         self.data_directory_copy_check_box.hide()
         self.data_directory_cancel_button.hide()
         self.new_data_directory_has_files_label.hide()

=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/firsttimeform.py	2013-02-09 17:32:28 +0000
@@ -41,7 +41,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import PluginStatus, Receiver, Settings, Registry, build_icon, check_directory_exists, translate
+from openlp.core.lib import PluginStatus, Settings, Registry, build_icon, check_directory_exists, translate
 from openlp.core.utils import AppLocation, get_web_page, get_filesystem_encoding
 from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
 
@@ -95,7 +95,7 @@
         if self.webAccess:
             files = self.webAccess.read()
             self.config.readfp(io.BytesIO(files))
-        self.updateScreenListCombo()
+        self.update_screen_list_combo()
         self.was_download_cancelled = False
         self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading %s...')
         QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL('clicked()'),
@@ -103,8 +103,7 @@
         QtCore.QObject.connect(self.noInternetFinishButton, QtCore.SIGNAL('clicked()'),
             self.onNoInternetFinishButtonClicked)
         QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'),
-            self.updateScreenListCombo)
+        Registry().register_function(u'config_screen_changed', self.update_screen_list_combo)
 
     def exec_(self):
         """
@@ -228,7 +227,7 @@
             self._postWizard()
             self.application.set_normal_cursor()
 
-    def updateScreenListCombo(self):
+    def update_screen_list_combo(self):
         """
         The user changed screen resolution or enabled/disabled more screens, so
         we need to update the combo box.
@@ -296,8 +295,8 @@
                 item = self.themesListWidget.item(index)
                 if item.data(QtCore.Qt.UserRole) == filename:
                     break
-            item.setIcon(build_icon(os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp',
-                screenshot)))
+            item.setIcon(build_icon(os.path.join(unicode(gettempdir(),
+                    get_filesystem_encoding()), u'openlp', screenshot)))
 
     def _getFileSize(self, url):
         """

=== modified file 'openlp/core/ui/generaltab.py'
--- openlp/core/ui/generaltab.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/generaltab.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Settings, SettingsTab, ScreenList, UiStrings, translate
+from openlp.core.lib import Registry, Settings, SettingsTab, ScreenList, UiStrings, translate
 
 log = logging.getLogger(__name__)
 
@@ -199,7 +199,7 @@
         QtCore.QObject.connect(self.customXValueEdit, QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
         QtCore.QObject.connect(self.monitorComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onDisplayChanged)
         # Reload the tab, as the screen resolution/count may have changed.
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.load)
+        Registry().register_function(u'config_screen_changed', self.load)
         # Remove for now
         self.usernameLabel.setVisible(False)
         self.usernameEdit.setVisible(False)
@@ -315,7 +315,7 @@
         Apply settings after settings tab has loaded and most of the
         system so must be delayed
         """
-        Receiver.send_message(u'slidecontroller_live_spin_delay', self.timeoutSpinBox.value())
+        Registry().execute(u'slidecontroller_live_spin_delay', self.timeoutSpinBox.value())
         # Do not continue on start up.
         if not postUpdate:
             return
@@ -331,7 +331,7 @@
         else:
             self.screens.reset_current_display()
         if self.display_changed:
-            Receiver.send_message(u'config_screen_changed')
+            Registry().execute(u'config_screen_changed')
         self.display_changed = False
 
     def onOverrideRadioButtonPressed(self, checked):

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/maindisplay.py	2013-02-09 17:32:28 +0000
@@ -42,7 +42,7 @@
 from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
 from PyQt4.phonon import Phonon
 
-from openlp.core.lib import Receiver, ServiceItem, Settings, ImageSource, Registry, build_html, expand_tags, \
+from openlp.core.lib import ServiceItem, Settings, ImageSource, Registry, build_html, expand_tags, \
     image_to_byte, translate
 from openlp.core.lib.theme import BackgroundType
 
@@ -158,10 +158,10 @@
         self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
         self.setTransparency(False)
         if self.isLive:
-            QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_display_hide'), self.hideDisplay)
-            QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_display_show'), self.showDisplay)
-            QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'update_display_css'), self.cssChanged)
-            QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configChanged)
+            Registry().register_function(u'live_display_hide', self.hide_display)
+            Registry().register_function(u'live_display_show', self.show_display)
+            Registry().register_function(u'update_display_css', self.css_changed)
+            Registry().register_function(u'config_updated', self.config_changed)
 
     def setTransparency(self, enabled):
         """
@@ -174,13 +174,13 @@
         self.setAttribute(QtCore.Qt.WA_TranslucentBackground, enabled)
         self.repaint()
 
-    def cssChanged(self):
+    def css_changed(self):
         """
         We may need to rebuild the CSS on the live display.
         """
         self.rebuildCSS = True
 
-    def configChanged(self):
+    def config_changed(self):
         """
         Call the plugins to rebuild the Live display CSS as the screen has
         not been rebuild on exit of config.
@@ -362,7 +362,7 @@
         # if was hidden keep it hidden
         if self.isLive:
             if self.hideMode:
-                self.hideDisplay(self.hideMode)
+                self.hide_display(self.hideMode)
             else:
                 # Single screen active
                 if self.screens.display_count == 1:
@@ -387,11 +387,11 @@
         if self.override:
             # We have an video override so allow it to be stopped.
             if u'video' in self.override:
-                Receiver.send_message(u'video_background_replaced')
+                Registry().execute(u'video_background_replaced')
                 self.override = {}
             # We have a different theme.
             elif self.override[u'theme'] != serviceItem.themedata.background_filename:
-                Receiver.send_message(u'live_theme_changed')
+                Registry().execute(u'live_theme_changed')
                 self.override = {}
             else:
                 # replace the background
@@ -417,9 +417,9 @@
         # if was hidden keep it hidden
         if self.hideMode and self.isLive and not serviceItem.is_media():
             if Settings().value(u'general/auto unblank'):
-                Receiver.send_message(u'slidecontroller_live_unblank')
+                Registry().execute(u'slidecontroller_live_unblank')
             else:
-                self.hideDisplay(self.hideMode)
+                self.hide_display(self.hideMode)
         self.__hideMouse()
 
     def footer(self, text):
@@ -430,12 +430,12 @@
         js = u'show_footer(\'' + text.replace(u'\\', u'\\\\').replace(u'\'', u'\\\'') + u'\')'
         self.frame.evaluateJavaScript(js)
 
-    def hideDisplay(self, mode=HideMode.Screen):
+    def hide_display(self, mode=HideMode.Screen):
         """
         Hide the display by making all layers transparent
         Store the images so they can be replaced when required
         """
-        log.debug(u'hideDisplay mode = %d', mode)
+        log.debug(u'hide_display mode = %d', mode)
         if self.screens.display_count == 1:
             # Only make visible if setting enabled.
             if not Settings().value(u'general/display on monitor'):
@@ -453,13 +453,13 @@
                 self.webView.setVisible(True)
         self.hideMode = mode
 
-    def showDisplay(self):
+    def show_display(self):
         """
         Show the stored layers so the screen reappears as it was
         originally.
         Make the stored images None to release memory.
         """
-        log.debug(u'showDisplay')
+        log.debug(u'show_display')
         if self.screens.display_count == 1:
             # Only make visible if setting enabled.
             if not Settings().value(u'general/display on monitor'):
@@ -470,7 +470,7 @@
         self.hideMode = None
         # Trigger actions when display is active again.
         if self.isLive:
-            Receiver.send_message(u'live_display_active')
+            Registry().execute(u'live_display_active')
 
     def __hideMouse(self):
         """

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2013-02-05 08:10:50 +0000
+++ openlp/core/ui/mainwindow.py	2013-02-09 17:32:28 +0000
@@ -41,7 +41,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, Receiver, ImageManager, PluginStatus, Registry, \
+from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, Registry, \
     Settings, ScreenList, build_icon, check_directory_exists, translate
 from openlp.core.lib.ui import UiStrings, create_action
 from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
@@ -484,6 +484,8 @@
         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
         plugin_path = AppLocation.get_directory(AppLocation.PluginsDir)
         self.plugin_manager = PluginManager(plugin_path)
@@ -497,8 +499,8 @@
         # Once settings are loaded update the menu with the recent files.
         self.updateRecentFilesMenu()
         self.pluginForm = PluginForm(self)
-        self.newDataPath = u''
-        self.copyData = False
+        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)
@@ -528,25 +530,13 @@
         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)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.defaultThemeChanged)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_version_check'), self.versionNotice)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_display_blank_check'), self.blankCheck)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mainwindow_status_text'),
-            self.showStatusMessage)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cleanup'), self.clean_up)
         # Media Manager
         QtCore.QObject.connect(self.mediaToolBox, QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
         self.application.set_busy_cursor()
         # Simple message boxes
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_error_message'), self.onErrorMessage)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_information_message'),
-            self.onInformationMessage)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'set_new_data_path'), self.setNewDataPath)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'set_copy_data'), self.setCopyData)
-        # warning cyclic dependency
-        # renderer needs to call ThemeManager and
-        # ThemeManager needs to call Renderer
+        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)
@@ -582,8 +572,6 @@
         # Once all components are initialised load the Themes
         log.info(u'Load Themes')
         self.themeManagerContents.load_themes(True)
-        # Hide/show the theme combobox on the service manager
-        self.serviceManagerContents.theme_change()
         # Reset the cursor
         self.application.set_normal_cursor()
 
@@ -603,16 +591,15 @@
         if widget:
             widget.onFocus()
 
-    def versionNotice(self, version):
+    def version_notice(self, version):
         """
         Notifies the user that a newer version of OpenLP is available.
-        Triggered by delay thread.
+        Triggered by delay thread and cannot display popup.
         """
+        log.debug(u'version_notice')
         version_text = translate('OpenLP.MainWindow', 'Version %s of OpenLP is now available for download (you are '
             'currently running version %s). \n\nYou can download the latest version from http://openlp.org/.')
-        QtGui.QMessageBox.question(self,
-            translate('OpenLP.MainWindow', 'OpenLP Version Updated'),
-                version_text % (version, get_application_version()[u'full']))
+        self.version_text = version_text % (version, get_application_version()[u'full'])
 
     def show(self):
         """
@@ -632,6 +619,7 @@
             self.serviceManagerContents.load_file(filename)
         elif Settings().value(self.generalSettingsSection + u'/auto open'):
             self.serviceManagerContents.load_Last_file()
+        self.timer_version_id = self.startTimer(1000)
         view_mode = Settings().value(u'%s/view mode' % self.generalSettingsSection)
         if view_mode == u'default':
             self.modeDefaultItem.setChecked(True)
@@ -699,15 +687,15 @@
                     self.activePlugin.app_startup()
                 else:
                     self.activePlugin.toggleStatus(PluginStatus.Inactive)
-        self.themeManagerContents.configUpdated()
+        self.themeManagerContents.config_updated()
         self.themeManagerContents.load_themes(True)
-        Receiver.send_message(u'theme_update_global', self.themeManagerContents.global_theme)
+        Registry().execute(u'theme_update_global', self.themeManagerContents.global_theme)
         # Check if any Bibles downloaded.  If there are, they will be
         # processed.
-        Receiver.send_message(u'bibles_load_list', True)
+        Registry().execute(u'bibles_load_list', True)
         self.application.set_normal_cursor()
 
-    def blankCheck(self):
+    def blank_check(self):
         """
         Check and display message if screen blank on setup.
         """
@@ -718,26 +706,44 @@
                 QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Main Display Blanked'),
                     translate('OpenLP.MainWindow', 'The Main Display has been blanked out'))
 
-    def onErrorMessage(self, data):
+    def error_message(self, title, message):
         """
         Display an error message
+
+        ``title``
+            The title of the warning box.
+
+        ``message``
+            The message to be displayed.
         """
-        self.application.close_splash_screen()
-        QtGui.QMessageBox.critical(self, data[u'title'], data[u'message'])
+        self.application.splash.close()
+        QtGui.QMessageBox.critical(self, title, message)
 
-    def warning_message(self, message):
+    def warning_message(self, title, message):
         """
         Display a warning message
+
+        ``title``
+            The title of the warning box.
+
+        ``message``
+            The message to be displayed.
         """
-        self.application.close_splash_screen()
-        QtGui.QMessageBox.warning(self, message[u'title'], message[u'message'])
+        self.application.splash.close()
+        QtGui.QMessageBox.warning(self, title, message)
 
-    def onInformationMessage(self, data):
+    def information_message(self, title, message):
         """
         Display an informational message
+
+        ``title``
+            The title of the warning box.
+
+        ``message``
+            The message to be displayed.
         """
-        self.application.close_splash_screen()
-        QtGui.QMessageBox.information(self, data[u'title'], data[u'message'])
+        self.application.splash.close()
+        QtGui.QMessageBox.information(self, title, message)
 
     def onHelpWebSiteClicked(self):
         """
@@ -1003,12 +1009,12 @@
         self.setPreviewPanelVisibility(preview)
         self.setLivePanelVisibility(live)
 
-    def screenChanged(self):
+    def screen_changed(self):
         """
         The screen has changed so we have to update components such as the
         renderer.
         """
-        log.debug(u'screenChanged')
+        log.debug(u'screen_changed')
         self.application.set_busy_cursor()
         self.imageManager.update_display()
         self.renderer.update_display()
@@ -1081,14 +1087,12 @@
             # Save settings
             self.saveSettings()
         # Check if we need to change the data directory
-        if self.newDataPath:
+        if self.new_data_path:
             self.changeDataDirectory()
         # Close down the display
         if self.liveController.display:
             self.liveController.display.close()
             self.liveController.display = None
-        # Allow the main process to exit
-        self.application = None
 
     def serviceChanged(self, reset=False, serviceName=None):
         """
@@ -1129,13 +1133,13 @@
             title = u'%s - %s' % (self.mainTitle, fileName)
         self.setWindowTitle(title)
 
-    def showStatusMessage(self, message):
+    def show_status_message(self, message):
         """
         Show a message in the status bar
         """
         self.statusBar.showMessage(message)
 
-    def defaultThemeChanged(self, theme):
+    def default_theme_changed(self, theme):
         """
         Update the default theme indicator in the status bar
         """
@@ -1338,34 +1342,45 @@
             self.timer_id = 0
             self.loadProgressBar.hide()
             self.application.process_events()
+        if event.timerId() == self.timer_version_id:
+            self.timer_version_id = 0
+            # Has the thread passed some data to be displayed so display it and stop all waiting
+            if hasattr(self, u'version_text'):
+                QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Version Updated'),
+                    self.version_text)
+            else:
+                # the thread has not confirmed it is running or it has not yet sent any data so lets keep waiting
+                if not hasattr(self,u'version_update_running') or self.version_update_running:
+                    self.timer_version_id = self.startTimer(1000)
+            self.application.process_events()
 
-    def setNewDataPath(self, new_data_path):
+    def set_new_data_path(self, new_data_path):
         """
         Set the new data path
         """
-        self.newDataPath = new_data_path
+        self.new_data_path = new_data_path
 
-    def setCopyData(self, copy_data):
+    def set_copy_data(self, copy_data):
         """
         Set the flag to copy the data
         """
-        self.copyData = copy_data
+        self.copy_data = copy_data
 
     def changeDataDirectory(self):
         """
         Change the data directory.
         """
-        log.info(u'Changing data path to %s' % self.newDataPath)
+        log.info(u'Changing data path to %s' % self.new_data_path)
         old_data_path = unicode(AppLocation.get_data_path())
         # Copy OpenLP data to new location if requested.
         self.application.set_busy_cursor()
-        if self.copyData:
+        if self.copy_data:
             log.info(u'Copying data to new path')
             try:
                 self.showStatusMessage(
                     translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - %s '
-                    '- Please wait for copy to finish').replace('%s', self.newDataPath))
-                dir_util.copy_tree(old_data_path, self.newDataPath)
+                    '- Please wait for copy to finish').replace('%s', self.new_data_path))
+                dir_util.copy_tree(old_data_path, self.new_data_path)
                 log.info(u'Copy sucessful')
             except (IOError, os.error, DistutilsFileError), why:
                 self.application.set_normal_cursor()
@@ -1379,9 +1394,9 @@
             log.info(u'No data copy requested')
         # Change the location of data directory in config file.
         settings = QtCore.QSettings()
-        settings.setValue(u'advanced/data path', self.newDataPath)
+        settings.setValue(u'advanced/data path', self.new_data_path)
         # Check if the new data path is our default.
-        if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir):
+        if self.new_data_path == AppLocation.get_directory(AppLocation.DataDir):
             settings.remove(u'advanced/data path')
         self.application.set_normal_cursor()
 

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/media/mediacontroller.py	2013-02-09 17:32:28 +0000
@@ -35,7 +35,7 @@
 import datetime
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, Receiver, Settings, Registry, UiStrings, translate
+from openlp.core.lib import OpenLPToolbar, Settings, Registry, UiStrings, translate
 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
@@ -107,21 +107,19 @@
         self.timer.setInterval(200)
         # Signals
         self.timer.timeout.connect(self.media_state)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPlay'), self.media_play_msg)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPause'), self.media_pause_msg)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackStop'), self.media_stop_msg)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'seekSlider'), self.media_seek_msg)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'volumeSlider'), self.media_volume_msg)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_hide'), self.media_hide)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_blank'), self.media_blank)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_unblank'), self.media_unblank)
+        Registry().register_function(u'playbackPlay', self.media_play_msg)
+        Registry().register_function(u'playbackPause', self.media_pause_msg)
+        Registry().register_function(u'playbackStop', self.media_stop_msg)
+        Registry().register_function(u'seekSlider', self.media_seek_msg)
+        Registry().register_function(u'volumeSlider', self.media_volume_msg)
+        Registry().register_function(u'media_hide', self.media_hide)
+        Registry().register_function(u'media_blank', self.media_blank)
+        Registry().register_function(u'media_unblank', self.media_unblank)
         # Signals for background video
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_hide'), self.media_hide)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_unblank'), self.media_unblank)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_media_rebuild'),
-            self._set_active_players)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_suffixes'),
-            self._generate_extensions_lists)
+        Registry().register_function(u'songs_hide', self.media_hide)
+        Registry().register_function(u'songs_unblank', self.media_unblank)
+        Registry().register_function(u'mediaitem_media_rebuild', self._set_active_players)
+        Registry().register_function(u'mediaitem_suffixes', self._generate_extensions_lists)
 
     def _set_active_players(self):
         """
@@ -694,7 +692,7 @@
         hide_mode = msg[2]
         if not isLive:
             return
-        Receiver.send_message(u'live_display_hide', hide_mode)
+        Registry().execute(u'live_display_hide', hide_mode)
         controller = self.mainWindow.liveController
         display = self._define_display(controller)
         if self.currentMediaPlayer[controller.controllerType].state == MediaState.Playing:
@@ -709,7 +707,7 @@
             First element is not relevant in this context
             Second element is the boolean for Live indication
         """
-        Receiver.send_message(u'live_display_show')
+        Registry().execute(u'live_display_show')
         isLive = msg[1]
         if not isLive:
             return

=== modified file 'openlp/core/ui/media/playertab.py'
--- openlp/core/ui/media/playertab.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/media/playertab.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 """
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate
+from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate
 from openlp.core.lib.ui import create_button
 from openlp.core.ui.media import get_media_players, set_media_players
 
@@ -229,8 +229,8 @@
             player_string_changed = True
         if player_string_changed:
             self.service_manager.reset_supported_suffixes()
-            Receiver.send_message(u'mediaitem_media_rebuild')
-            Receiver.send_message(u'config_screen_changed')
+            Registry().execute(u'mediaitem_media_rebuild')
+            Registry().execute(u'config_screen_changed')
 
     def postSetUp(self, postUpdate=False):
         """

=== modified file 'openlp/core/ui/printserviceform.py'
--- openlp/core/ui/printserviceform.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/printserviceform.py	2013-02-09 17:32:28 +0000
@@ -36,7 +36,7 @@
 from PyQt4 import QtCore, QtGui
 from lxml import html
 
-from openlp.core.lib import Receiver, Settings, UiStrings, Registry, translate, get_text_file_string
+from openlp.core.lib import Settings, UiStrings, Registry, translate, get_text_file_string
 from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
 from openlp.core.utils import AppLocation
 
@@ -408,7 +408,7 @@
             return
         for item in self.service_manager.serviceItems:
             # Trigger Audit requests
-            Receiver.send_message(u'print_service_started', [item[u'service_item']])
+            Registry().register_function(u'print_service_started', [item[u'service_item']])
 
     def _get_service_manager(self):
         """

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2013-02-07 18:00:40 +0000
+++ openlp/core/ui/servicemanager.py	2013-02-09 17:32:28 +0000
@@ -42,7 +42,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, ItemCapabilities, Settings, PluginStatus, Registry, \
+from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, Settings, PluginStatus, Registry, \
     UiStrings, build_icon, translate, str_to_bool, check_directory_exists
 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
@@ -210,11 +210,10 @@
             self.collapsed)
         QtCore.QObject.connect(self.service_manager_list, QtCore.SIGNAL(u'itemExpanded(QTreeWidgetItem*)'),
             self.expanded)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.update_theme_list)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'),
-            self.regenerate_service_Items)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.theme_change)
+        Registry().register_function(u'theme_update_list', self.update_theme_list)
+        Registry().register_function(u'config_updated', self.config_updated)
+        Registry().register_function(u'config_screen_changed', self.regenerate_service_Items)
+        Registry().register_function(u'theme_update_global', self.theme_change)
         # Last little bits of setting up
         self.service_theme = Settings().value(self.main_window.serviceManagerSettingsSection + u'/service theme')
         self.servicePath = AppLocation.get_section_data_path(u'servicemanager')
@@ -555,10 +554,9 @@
                 zip_file.write(audio_from, audio_to.encode(u'utf-8'))
         except IOError:
             log.exception(u'Failed to save service to disk: %s', temp_file_name)
-            Receiver.send_message(u'openlp_error_message', {
-                u'title': translate(u'OpenLP.ServiceManager', u'Error Saving File'),
-                u'message': translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
-            })
+            self.main_window.error_message(translate(u'OpenLP.ServiceManager', u'Error Saving File'),
+                translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
+            )
             success = False
         finally:
             if zip_file:
@@ -613,10 +611,9 @@
             zip_file.writestr(service_file_name.encode(u'utf-8'), service_content)
         except IOError:
             log.exception(u'Failed to save service to disk: %s', temp_file_name)
-            Receiver.send_message(u'openlp_error_message', {
-                u'title': translate(u'OpenLP.ServiceManager', u'Error Saving File'),
-                u'message': translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
-            })
+            self.main_window.error_message(translate(u'OpenLP.ServiceManager', u'Error Saving File'),
+                translate(u'OpenLP.ServiceManager', u'There was an error saving your file.')
+            )
             success = False
         finally:
             if zip_file:
@@ -736,7 +733,7 @@
                     service_item.validate_item(self.suffixes)
                     self.load_item_unique_identifier = 0
                     if service_item.is_capable(ItemCapabilities.OnLoadUpdate):
-                        Receiver.send_message(u'%s_service_load' % service_item.name.lower(), service_item)
+                        Registry().execute(u'%s_service_load' % service_item.name.lower(), service_item)
                     # if the item has been processed
                     if service_item.unique_identifier == self.load_item_unique_identifier:
                         service_item.edit_id = int(self.load_item_edit_id)
@@ -1237,13 +1234,13 @@
         """
         Set the theme for the current service.
         """
-        log.debug(u'ontheme_combo_box_selected')
+        log.debug(u'on_theme_combo_box_selected')
         self.service_theme = self.theme_combo_box.currentText()
         self.renderer.set_service_theme(self.service_theme)
         Settings().setValue(self.main_window.serviceManagerSettingsSection + u'/service theme', self.service_theme)
         self.regenerate_service_Items(True)
 
-    def theme_change(self):
+    def theme_change(self, global_theme):
         """
         The theme may have changed in the settings dialog so make
         sure the theme combo box is in the correct state.
@@ -1439,7 +1436,7 @@
         Saves the current text item as a custom slide
         """
         item = self.find_service_item()[0]
-        Receiver.send_message(u'custom_create_from_service', self.service_items[item][u'service_item'])
+        Registry().execute(u'custom_create_from_service', self.service_items[item][u'service_item'])
 
     def find_service_item(self):
         """
@@ -1526,7 +1523,7 @@
                             replace = True
                     else:
                         self.drop_position = self._get_parent_item_data(item)
-                Receiver.send_message(u'%s_add_service_item' % plugin, replace)
+                Registry().execute(u'%s_add_service_item' % plugin, replace)
 
     def update_theme_list(self, theme_list):
         """

=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/settingsform.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import Receiver, PluginStatus, Registry, build_icon
+from openlp.core.lib import PluginStatus, Registry, build_icon
 from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
 from openlp.core.ui.media import PlayerTab
 from settingsdialog import Ui_SettingsDialog
@@ -107,7 +107,7 @@
         for tabIndex in range(self.stackedLayout.count()):
             self.stackedLayout.widget(tabIndex).save()
         # Must go after all settings are save
-        Receiver.send_message(u'config_updated')
+        Registry().execute(u'config_updated')
         return QtGui.QDialog.accept(self)
 
     def reject(self):

=== modified file 'openlp/core/ui/shortcutlistform.py'
--- openlp/core/ui/shortcutlistform.py	2013-02-03 17:42:31 +0000
+++ openlp/core/ui/shortcutlistform.py	2013-02-09 17:32:28 +0000
@@ -438,12 +438,11 @@
                 if changing_action.shortcutContext() in [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
                     is_valid = False
         if not is_valid:
-            self.main_window.warning_message( {
-                u'title': translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
-                u'message': translate('OpenLP.ShortcutListDialog',
-                    'The shortcut "%s" is already assigned to another action, '
-                    'please use a different shortcut.') % key_sequence.toString()
-            })
+            self.main_window.warning_message( translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
+                translate('OpenLP.ShortcutListDialog',
+                    'The shortcut "%s" is already assigned to another action, please use a different shortcut.') %
+                    key_sequence.toString()
+            )
         return is_valid
 
     def _actionShortcuts(self, action):

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2013-02-05 08:10:50 +0000
+++ openlp/core/ui/slidecontroller.py	2013-02-09 17:32:28 +0000
@@ -27,7 +27,7 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 """
-The :mod:`slidecontroller` module contains argubly the most important part of OpenLP - the slide controller
+The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller
 """
 import os
 import logging
@@ -36,7 +36,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \
+from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \
     ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate
 from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
 from openlp.core.lib.ui import create_action
@@ -66,7 +66,7 @@
         """
         sender = self.sender().objectName() if self.sender().objectName() else self.sender().text()
         controller = self
-        Receiver.send_message('%s' % sender, [controller, args])
+        Registry().execute('%s' % sender, [controller, args])
 
 
 class SlideController(DisplayController):
@@ -107,7 +107,7 @@
         self.selectedRow = 0
         self.serviceItem = None
         self.slide_limits = None
-        self.updateSlideLimits()
+        self.update_slide_limits()
         self.panel = QtGui.QWidget(parent.controlSplitter)
         self.slideList = {}
         # Layout for holding panel
@@ -169,13 +169,13 @@
             text=translate('OpenLP.SlideController', 'Previous Slide'), icon=u':/slides/slide_previous.png',
             tooltip=translate('OpenLP.SlideController', 'Move to previous.'),
             shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp], context=QtCore.Qt.WidgetWithChildrenShortcut,
-            category=self.category, triggers=self.onSlideSelectedPrevious)
+            category=self.category, triggers=self.on_slide_selected_previous)
         self.toolbar.addAction(self.previousItem)
         self.nextItem = create_action(self, u'nextItem_' + self.typePrefix,
             text=translate('OpenLP.SlideController', 'Next Slide'), icon=u':/slides/slide_next.png',
             tooltip=translate('OpenLP.SlideController', 'Move to next.'),
             shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown], context=QtCore.Qt.WidgetWithChildrenShortcut,
-            category=self.category, triggers=self.onSlideSelectedNextAction)
+            category=self.category, triggers=self.on_slide_selected_next_action)
         self.toolbar.addAction(self.nextItem)
         self.toolbar.addSeparator()
         self.controllerType = DisplayControllerType.Preview
@@ -362,10 +362,8 @@
         # Signals
         QtCore.QObject.connect(self.previewListWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
         if self.isLive:
-            QtCore.QObject.connect(Receiver.get_receiver(),
-                QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), self.receiveSpinDelay)
-            QtCore.QObject.connect(Receiver.get_receiver(),
-                QtCore.SIGNAL(u'slidecontroller_toggle_display'), self.toggleDisplay)
+            Registry().register_function(u'slidecontroller_live_spin_delay', self.receive_spin_delay)
+            Registry().register_function(u'slidecontroller_toggle_display', self.toggle_display)
             self.toolbar.setWidgetVisible(self.loopList, False)
             self.toolbar.setWidgetVisible(self.wideMenu, False)
         else:
@@ -377,22 +375,14 @@
             self.__addActionsToWidget(self.previewListWidget)
         else:
             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(),
-            QtCore.SIGNAL(u'slidecontroller_%s_next' % self.typePrefix), self.onSlideSelectedNext)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_%s_previous' % self.typePrefix), self.onSlideSelectedPrevious)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_%s_change' % self.typePrefix), self.onSlideChange)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_%s_set' % self.typePrefix), self.onSlideSelectedIndex)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_%s_blank' % self.typePrefix), self.onSlideBlank)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix), self.onSlideUnblank)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'slidecontroller_update_slide_limits'), self.updateSlideLimits)
+        Registry().register_function(u'slidecontroller_%s_stop_loop' % self.typePrefix, self.on_stop_loop)
+        Registry().register_function(u'slidecontroller_%s_next' % self.typePrefix, self.on_slide_selected_next)
+        Registry().register_function(u'slidecontroller_%s_previous' % self.typePrefix, self.on_slide_selected_previous)
+        Registry().register_function(u'slidecontroller_%s_change' % self.typePrefix, self.on_slide_change)
+        Registry().register_function(u'slidecontroller_%s_set' % self.typePrefix, self.on_slide_selected_index)
+        Registry().register_function(u'slidecontroller_%s_blank' % self.typePrefix, self.on_slide_blank)
+        Registry().register_function(u'slidecontroller_%s_unblank' % self.typePrefix, self.on_slide_unblank)
+        Registry().register_function(u'slidecontroller_update_slide_limits', self.update_slide_limits)
 
     def _slideShortcutActivated(self):
         """
@@ -479,7 +469,7 @@
         self.display.setVisible(False)
         self.media_controller.media_stop(self)
 
-    def toggleDisplay(self, action):
+    def toggle_display(self, action):
         """
         Toggle the display settings triggered from remote messages.
         """
@@ -618,13 +608,13 @@
         self.__updatePreviewSelection(slide_no)
         self.slideSelected()
 
-    def receiveSpinDelay(self, value):
+    def receive_spin_delay(self, value):
         """
         Adjusts the value of the ``delaySpinBox`` to the given one.
         """
         self.delaySpinBox.setValue(int(value))
 
-    def updateSlideLimits(self):
+    def update_slide_limits(self):
         """
         Updates the Slide Limits variable from the settings.
         """
@@ -750,14 +740,13 @@
         Display the slide number passed
         """
         log.debug(u'processManagerItem live = %s' % self.isLive)
-        self.onStopLoop()
+        self.on_stop_loop()
         old_item = self.serviceItem
         # take a copy not a link to the servicemanager copy.
         self.serviceItem = copy.copy(serviceItem)
         if old_item and self.isLive and old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
             self._resetBlank()
-        Receiver.send_message(u'%s_start' % serviceItem.name.lower(),
-            [serviceItem, self.isLive, self.hideMode(), slideno])
+        Registry().execute(u'%s_start' % serviceItem.name.lower(), [serviceItem, self.isLive, self.hideMode(), slideno])
         self.slideList = {}
         width = self.parent().controlSplitter.sizes()[self.split]
         self.previewListWidget.clear()
@@ -853,10 +842,10 @@
             # However opening a new item of the same type will automatically
             # close the previous, so make sure we don't close the new one.
             if old_item.is_command() and not serviceItem.is_command():
-                Receiver.send_message(u'%s_stop' % old_item.name.lower(), [old_item, self.isLive])
+                Registry().execute(u'%s_stop' % old_item.name.lower(), [old_item, self.isLive])
             if old_item.is_media() and not serviceItem.is_media():
                 self.onMediaClose()
-        Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix, [serviceItem])
+        Registry().execute(u'slidecontroller_%s_started' % self.typePrefix, [serviceItem])
 
     def __updatePreviewSelection(self, slideno):
         """
@@ -869,7 +858,7 @@
             self.__checkUpdateSelectedSlide(slideno)
 
     # Screen event methods
-    def onSlideSelectedIndex(self, message):
+    def on_slide_selected_index(self, message):
         """
         Go to the requested slide
         """
@@ -877,7 +866,7 @@
         if not self.serviceItem:
             return
         if self.serviceItem.is_command():
-            Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive, index])
+            Registry().execute(u'%s_slide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive, index])
             self.updatePreview()
         else:
             self.__checkUpdateSelectedSlide(index)
@@ -898,17 +887,17 @@
             elif display_type == u'blanked':
                 self.onBlankDisplay(True)
             else:
-                Receiver.send_message(u'live_display_show')
+                Registry().execute(u'live_display_show')
         else:
             self.liveEscape()
 
-    def onSlideBlank(self):
+    def on_slide_blank(self):
         """
         Handle the slidecontroller blank event
         """
         self.onBlankDisplay(True)
 
-    def onSlideUnblank(self):
+    def on_slide_unblank(self):
         """
         Handle the slidecontroller unblank event
         """
@@ -980,18 +969,18 @@
         if self.serviceItem is not None:
             if hide_mode:
                 if not self.serviceItem.is_command():
-                    Receiver.send_message(u'live_display_hide', hide_mode)
-                Receiver.send_message(u'%s_blank' % self.serviceItem.name.lower(),
+                    Registry().execute(u'live_display_hide', hide_mode)
+                Registry().execute(u'%s_blank' % self.serviceItem.name.lower(),
                     [self.serviceItem, self.isLive, hide_mode])
             else:
                 if not self.serviceItem.is_command():
-                    Receiver.send_message(u'live_display_show')
-                Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+                    Registry().execute(u'live_display_show')
+                Registry().execute(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
         else:
             if hide_mode:
-                Receiver.send_message(u'live_display_hide', hide_mode)
+                Registry().execute(u'live_display_hide', hide_mode)
             else:
-                Receiver.send_message(u'live_display_show')
+                Registry().execute(u'live_display_show')
 
     def hidePlugin(self, hide):
         """
@@ -1000,17 +989,17 @@
         log.debug(u'hidePlugin %s ', hide)
         if self.serviceItem is not None:
             if hide:
-                Receiver.send_message(u'live_display_hide', HideMode.Screen)
-                Receiver.send_message(u'%s_hide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+                Registry().execute(u'live_display_hide', HideMode.Screen)
+                Registry().execute(u'%s_hide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
             else:
                 if not self.serviceItem.is_command():
-                    Receiver.send_message(u'live_display_show')
-                Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+                    Registry().execute(u'live_display_show')
+                Registry().execute(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
         else:
             if hide:
-                Receiver.send_message(u'live_display_hide', HideMode.Screen)
+                Registry().execute(u'live_display_hide', HideMode.Screen)
             else:
-                Receiver.send_message(u'live_display_show')
+                Registry().execute(u'live_display_show')
 
     def onSlideSelected(self):
         """
@@ -1028,7 +1017,7 @@
         if -1 < row < self.previewListWidget.rowCount():
             if self.serviceItem.is_command():
                 if self.isLive and not start:
-                    Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
+                    Registry().execute(u'%s_slide' % self.serviceItem.name.lower(),
                         [self.serviceItem, self.isLive, row])
             else:
                 to_display = self.serviceItem.get_rendered_frame(row)
@@ -1044,16 +1033,16 @@
             self.updatePreview()
             self.selectedRow = row
             self.__checkUpdateSelectedSlide(row)
-        Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row)
+        Registry().execute(u'slidecontroller_%s_changed' % self.typePrefix, row)
         self.display.setFocus()
 
-    def onSlideChange(self, row):
+    def on_slide_change(self, row):
         """
         The slide has been changed. Update the slidecontroller accordingly
         """
         self.__checkUpdateSelectedSlide(row)
         self.updatePreview()
-        Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row)
+        Registry().execute(u'slidecontroller_%s_changed' % self.typePrefix, row)
 
     def updatePreview(self):
         """
@@ -1079,20 +1068,20 @@
         winimg = QtGui.QPixmap.grabWindow(winid, rect.x(), rect.y(), rect.width(), rect.height())
         self.slidePreview.setPixmap(winimg)
 
-    def onSlideSelectedNextAction(self, checked):
+    def on_slide_selected_next_action(self, checked):
         """
         Wrapper function from create_action so we can throw away the
         incorrect parameter
         """
-        self.onSlideSelectedNext()
+        self.on_slide_selected_next()
 
-    def onSlideSelectedNext(self, wrap=None):
+    def on_slide_selected_next(self, wrap=None):
         """
         Go to the next slide.
         """
         if not self.serviceItem:
             return
-        Receiver.send_message(u'%s_next' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+        Registry().execute(u'%s_next' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
         if self.serviceItem.is_command() and self.isLive:
             self.updatePreview()
         else:
@@ -1113,13 +1102,13 @@
             self.__checkUpdateSelectedSlide(row)
             self.slideSelected()
 
-    def onSlideSelectedPrevious(self):
+    def on_slide_selected_previous(self):
         """
         Go to the previous slide.
         """
         if not self.serviceItem:
             return
-        Receiver.send_message(u'%s_previous' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+        Registry().execute(u'%s_previous' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
         if self.serviceItem.is_command() and self.isLive:
             self.updatePreview()
         else:
@@ -1152,7 +1141,7 @@
         if hide_mode is None and (self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked()):
             self.onStartLoop()
         else:
-            self.onStopLoop()
+            self.on_stop_loop()
 
     def onStartLoop(self):
         """
@@ -1161,7 +1150,7 @@
         if self.previewListWidget.rowCount() > 1:
             self.timer_id = self.startTimer(int(self.delaySpinBox.value()) * 1000)
 
-    def onStopLoop(self):
+    def on_stop_loop(self):
         """
         Stop the timer loop running
         """
@@ -1233,7 +1222,7 @@
         If the timer event is for this window select next slide
         """
         if event.timerId() == self.timer_id:
-            self.onSlideSelectedNext(self.playSlidesLoop.isChecked())
+            self.on_slide_selected_next(self.playSlidesLoop.isChecked())
 
     def onEditSong(self):
         """
@@ -1259,7 +1248,7 @@
             # Live and Preview have issues if we have video or presentations
             # playing in both at the same time.
             if self.serviceItem.is_command():
-                Receiver.send_message(u'%s_stop' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
+                Registry().execute(u'%s_stop' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
             if self.serviceItem.is_media():
                 self.onMediaClose()
             self.onGoLive()

=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/themeform.py	2013-02-09 17:32:28 +0000
@@ -34,7 +34,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, UiStrings, Registry, translate
+from openlp.core.lib import UiStrings, Registry, translate
 from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui import ThemeLayoutForm
@@ -88,7 +88,7 @@
         QtCore.QObject.connect(self.footerPositionCheckBox, QtCore.SIGNAL(u'stateChanged(int)'),
             self.onFooterPositionCheckBoxStateChanged)
         QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_line_count'), self.updateLinesText)
+        Registry().register_function(u'theme_line_count', self.updateLinesText)
         QtCore.QObject.connect(self.mainSizeSpinBox, QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines)
         QtCore.QObject.connect(self.lineSpacingSpinBox, QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines)
         QtCore.QObject.connect(self.outlineSizeSpinBox, QtCore.SIGNAL(u'valueChanged(int)'), self.calculateLines)

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/thememanager.py	2013-02-09 17:32:28 +0000
@@ -38,7 +38,7 @@
 from xml.etree.ElementTree import ElementTree, XML
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import ImageSource, OpenLPToolbar, Receiver, Registry, SettingsManager, Settings, UiStrings, \
+from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, SettingsManager, Settings, UiStrings, \
     get_text_file_string, build_icon, translate, check_item_selected, check_directory_exists, create_thumb, \
     validate_thumb
 from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType
@@ -125,18 +125,17 @@
         self.global_action = create_widget_action(self.menu,
             text=translate('OpenLP.ThemeManager', 'Set As &Global Default'),
             icon=u':/general/general_export.png',
-            triggers=self.changeGlobalFromScreen)
+            triggers=self.change_global_from_screen)
         self.exportAction = create_widget_action(self.menu,
             text=translate('OpenLP.ThemeManager', '&Export Theme'),
             icon=u':/general/general_export.png', triggers=self.on_export_theme)
         # Signals
         QtCore.QObject.connect(self.theme_list_widget,
-            QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.changeGlobalFromScreen)
+            QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.change_global_from_screen)
         QtCore.QObject.connect(self.theme_list_widget,
             QtCore.SIGNAL(u'currentItemChanged(QListWidgetItem *, QListWidgetItem *)'), self.check_list_state)
-        QtCore.QObject.connect(Receiver.get_receiver(),
-            QtCore.SIGNAL(u'theme_update_global'), self.change_global_from_tab)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
+        Registry().register_function(u'theme_update_global', self.change_global_from_tab)
+        Registry().register_function(u'config_updated', self.config_updated)
         # Variables
         self.theme_list = []
         self.path = AppLocation.get_section_data_path(self.settingsSection)
@@ -166,6 +165,7 @@
         """
         Triggered when Config dialog is updated.
         """
+        log.debug(u'config_updated')
         self.global_theme = Settings().value(self.settingsSection + u'/global theme')
 
     def check_list_state(self, item):
@@ -215,15 +215,14 @@
             if theme_name == new_name:
                 name = translate('OpenLP.ThemeManager', '%s (default)') % new_name
                 self.theme_list_widget.item(count).setText(name)
-                self.deleteToolbarAction.setVisible(
-                    item not in self.theme_list_widget.selectedItems())
+                self.deleteToolbarAction.setVisible(item not in self.theme_list_widget.selectedItems())
 
-    def changeGlobalFromScreen(self, index=-1):
+    def change_global_from_screen(self, index=-1):
         """
         Change the global theme when a theme is double clicked upon in the
         Theme Manager list
         """
-        log.debug(u'changeGlobalFromScreen %s', index)
+        log.debug(u'change_global_from_screen %s', index)
         selected_row = self.theme_list_widget.currentRow()
         for count in range(0, self.theme_list_widget.count()):
             item = self.theme_list_widget.item(count)
@@ -237,7 +236,7 @@
                 name = translate('OpenLP.ThemeManager', '%s (default)') % self.global_theme
                 self.theme_list_widget.item(count).setText(name)
                 Settings().setValue(self.settingsSection + u'/global theme', self.global_theme)
-                Receiver.send_message(u'theme_update_global', self.global_theme)
+                Registry().execute(u'theme_update_global', self.global_theme)
                 self._push_themes()
 
     def onAddTheme(self):
@@ -464,12 +463,13 @@
         """
         Notify listeners that the theme list has been updated
         """
-        Receiver.send_message(u'theme_update_list', self.get_themes())
+        Registry().execute(u'theme_update_list', self.get_themes())
 
     def get_themes(self):
         """
         Return the list of loaded themes
         """
+        log.debug(u'get themes')
         return self.theme_list
 
     def get_theme_data(self, theme_name):
@@ -479,7 +479,7 @@
         ``theme_name``
             Name of the theme to load from file
         """
-        log.debug(u'getthemedata for theme %s', theme_name)
+        log.debug(u'get theme data for theme %s', theme_name)
         xml_file = os.path.join(self.path, unicode(theme_name), unicode(theme_name) + u'.xml')
         xml = get_text_file_string(xml_file)
         if not xml:
@@ -687,6 +687,7 @@
         """
         Called to update the themes' preview images.
         """
+        log.debug('update_preview_images')
         self.main_window.displayProgressBar(len(self.theme_list))
         for theme in self.theme_list:
             self.main_window.incrementProgressBar()

=== modified file 'openlp/core/ui/themestab.py'
--- openlp/core/ui/themestab.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/themestab.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 """
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Settings, SettingsTab, UiStrings, translate
+from openlp.core.lib import Registry, Settings, SettingsTab, UiStrings, translate
 from openlp.core.lib.theme import ThemeLevel
 from openlp.core.lib.ui import find_and_set_in_combo_box
 
@@ -104,7 +104,7 @@
         QtCore.QObject.connect(self.GlobalLevelRadioButton, QtCore.SIGNAL(u'clicked()'),
             self.onGlobalLevelButtonClicked)
         QtCore.QObject.connect(self.DefaultComboBox, QtCore.SIGNAL(u'activated(int)'), self.onDefaultComboBoxChanged)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
+        Registry().register_function(u'theme_update_list', self.update_theme_list)
 
     def retranslateUi(self):
         """
@@ -153,13 +153,13 @@
         settings.endGroup()
         self.renderer.set_global_theme(self.global_theme)
         self.renderer.set_theme_level(self.theme_level)
-        Receiver.send_message(u'theme_update_global', self.global_theme)
+        Registry().execute(u'theme_update_global', self.global_theme)
 
     def postSetUp(self):
         """
         After setting things up...
         """
-        Receiver.send_message(u'theme_update_global', self.global_theme)
+        Registry().execute(u'theme_update_global', self.global_theme)
 
     def onSongLevelButtonClicked(self):
         """
@@ -187,7 +187,7 @@
         self.renderer.set_global_theme(self.global_theme)
         self.__previewGlobalTheme()
 
-    def updateThemeList(self, theme_list):
+    def update_theme_list(self, theme_list):
         """
         Called from ThemeManager when the Themes have changed.
 

=== modified file 'openlp/core/ui/wizard.py'
--- openlp/core/ui/wizard.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/wizard.py	2013-02-09 17:32:28 +0000
@@ -34,7 +34,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Registry, Settings, UiStrings, build_icon, translate
+from openlp.core.lib import Registry, Settings, UiStrings, build_icon, translate
 from openlp.core.lib.ui import add_welcome_page
 
 log = logging.getLogger(__name__)
@@ -173,7 +173,7 @@
         """
         log.debug(u'Wizard cancelled by user.')
         if self.currentPage() == self.progressPage:
-            Receiver.send_message(u'openlp_stop_wizard')
+            Registry().execute(u'openlp_stop_wizard')
         self.done(QtGui.QDialog.Rejected)
 
     def onCurrentIdChanged(self, pageId):

=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py	2013-02-03 19:23:12 +0000
+++ openlp/core/utils/__init__.py	2013-02-09 17:32:28 +0000
@@ -51,7 +51,7 @@
         XDG_BASE_AVAILABLE = False
 
 import openlp
-from openlp.core.lib import Receiver, translate, check_directory_exists
+from openlp.core.lib import translate, check_directory_exists
 
 log = logging.getLogger(__name__)
 APPLICATION_VERSION = {}
@@ -72,11 +72,11 @@
         Run the thread.
         """
         self.sleep(1)
+        log.debug(u'Version thread - run')
         app_version = get_application_version()
         version = check_latest_version(app_version)
         if LooseVersion(str(version)) > LooseVersion(str(app_version[u'full'])):
-            Receiver.send_message(u'openlp_version_check', u'%s' % version)
-
+            Registry().execute(u'openlp_version_check', u'%s' % version)
 
 class AppLocation(object):
     """
@@ -288,6 +288,8 @@
     this_test = datetime.now().date()
     settings.setValue(u'last version test', this_test)
     settings.endGroup()
+    # Tell the main window whether there will ever be data to display
+    Registry().get(u'main_window').version_update_running = last_test != this_test
     if last_test != this_test:
         if current_version[u'build']:
             req = urllib2.Request(u'http://www.openlp.org/files/nightly_version.txt')

=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
--- openlp/plugins/alerts/lib/alertsmanager.py	2013-01-16 21:03:01 +0000
+++ openlp/plugins/alerts/lib/alertsmanager.py	2013-02-09 17:32:28 +0000
@@ -35,7 +35,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, translate
+from openlp.core.lib import Registry, translate
 
 log = logging.getLogger(__name__)
 
@@ -49,19 +49,19 @@
         QtCore.QObject.__init__(self, parent)
         self.screen = None
         self.timer_id = 0
-        self.alertList = []
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_display_active'), self.generateAlert)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'alerts_text'), self.onAlertText)
+        self.alert_list = []
+        Registry().register_function(u'live_display_active', self.generate_alert)
+        Registry().register_function(u'alerts_text', self.alert_text)
 
-    def onAlertText(self, message):
+    def alert_text(self, message):
         """
         Called via a alerts_text event. Message is single element array
         containing text
         """
         if message:
-            self.displayAlert(message[0])
+            self.display_alert(message[0])
 
-    def displayAlert(self, text=u''):
+    def display_alert(self, text=u''):
         """
         Called from the Alert Tab to display an alert
 
@@ -70,22 +70,22 @@
         """
         log.debug(u'display alert called %s' % text)
         if text:
-            self.alertList.append(text)
+            self.alert_list.append(text)
             if self.timer_id != 0:
-                Receiver.send_message(u'mainwindow_status_text',
+                self.main_window.show_status_message(
                     translate('AlertsPlugin.AlertsManager', 'Alert message created and displayed.'))
                 return
-            Receiver.send_message(u'mainwindow_status_text', u'')
-            self.generateAlert()
+            self.main_window.show_status_message(u'')
+            self.generate_alert()
 
-    def generateAlert(self):
+    def generate_alert(self):
         """
         Format and request the Alert and start the timer
         """
         log.debug(u'Generate Alert called')
-        if not self.alertList:
+        if not self.alert_list:
             return
-        text = self.alertList.pop(0)
+        text = self.alert_list.pop(0)
         alertTab = self.parent().settingsTab
         self.parent().liveController.display.alert(text, alertTab.location)
         # Check to see if we have a timer running.
@@ -106,4 +106,14 @@
             self.parent().liveController.display.alert(u'', alertTab.location)
         self.killTimer(self.timer_id)
         self.timer_id = 0
-        self.generateAlert()
+        self.generate_alert()
+
+    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/plugins/alerts/lib/alertstab.py'
--- openlp/plugins/alerts/lib/alertstab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/alerts/lib/alertstab.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate
+from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate
 from openlp.core.lib.ui import create_valign_selection_widgets
 
 class AlertsTab(SettingsTab):
@@ -174,7 +174,7 @@
         settings.setValue(u'location', self.location)
         settings.endGroup()
         if self.changed:
-            Receiver.send_message(u'update_display_css')
+            Registry().execute(u'update_display_css')
         self.changed = False
 
     def updateDisplay(self):

=== modified file 'openlp/plugins/bibles/forms/bibleupgradeform.py'
--- openlp/plugins/bibles/forms/bibleupgradeform.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/bibles/forms/bibleupgradeform.py	2013-02-09 17:32:28 +0000
@@ -36,7 +36,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, Settings, UiStrings, translate, check_directory_exists
+from openlp.core.lib import Registry, Settings, UiStrings, translate, check_directory_exists
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
 from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
@@ -82,7 +82,7 @@
         Set up the UI for the bible wizard.
         """
         OpenLPWizard.setupUi(self, image)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
+        Registry().execute(u'openlp_stop_wizard', self.stop_import)
 
     def stop_import(self):
         """

=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
--- openlp/plugins/bibles/lib/biblestab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/bibles/lib/biblestab.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, SettingsTab, Settings, UiStrings, translate
+from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate
 from openlp.core.lib.ui import find_and_set_in_combo_box
 from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \
     get_reference_separator, LanguageSelection
@@ -168,7 +168,7 @@
             self.onEndSeparatorLineEditEdited)
         QtCore.QObject.connect(self.endSeparatorLineEdit, QtCore.SIGNAL(u'editingFinished()'),
             self.onEndSeparatorLineEditFinished)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
+        Registry().register_function(u'theme_update_list', self.update_theme_list)
         QtCore.QObject.connect(self.languageSelectionComboBox, QtCore.SIGNAL(u'activated(int)'),
             self.onLanguageSelectionComboBoxChanged)
 
@@ -406,10 +406,10 @@
         else:
             settings.remove(u'end separator')
         update_reference_separators()
-        Receiver.send_message(u'bibles_load_list')
+        Registry().execute(u'bibles_load_list')
         settings.endGroup()
 
-    def updateThemeList(self, theme_list):
+    def update_theme_list(self, theme_list):
         """
         Called from ThemeManager when the Themes have changed.
 

=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/bibles/lib/db.py	2013-02-09 17:32:28 +0000
@@ -38,7 +38,7 @@
 from sqlalchemy.orm import class_mapper, mapper, relation
 from sqlalchemy.orm.exc import UnmappedClassError
 
-from openlp.core.lib import Receiver, Registry, translate
+from openlp.core.lib import Registry, translate
 from openlp.core.lib.db import BaseModel, init_db, Manager
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.utils import AppLocation, clean_filename
@@ -160,7 +160,7 @@
         if u'path' in kwargs:
             self.path = kwargs[u'path']
         self.wizard = None
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
+        Registry().execute(u'openlp_stop_wizard', self.stop_import)
 
     def stop_import(self):
         """

=== modified file 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/http.py	2013-02-05 06:54:55 +0000
+++ openlp/plugins/bibles/lib/http.py	2013-02-09 17:32:28 +0000
@@ -234,10 +234,8 @@
         soup = get_soup_for_bible_ref(
             u'http://www.biblegateway.com/passage/?%s' % url_params,
             pre_parse_regex=r'<meta name.*?/>', pre_parse_substitute='', cleaner=cleaner)
-        self.application.process_events()
         if not soup:
             return None
-        self.application.process_events()
         div = soup.find('div', 'result-text-style-normal')
         self._clean_soup(div)
         span_list = div.findAll('span', 'text')
@@ -296,6 +294,16 @@
                 books.append(book.contents[0])
         return books
 
+    def _get_application(self):
+        """
+        Adds the openlp to the class dynamically
+        """
+        if not hasattr(self, u'_application'):
+            self._application = Registry().get(u'application')
+        return self._application
+
+    application = property(_get_application)
+
 
 class BSExtract(object):
     """
@@ -457,6 +465,16 @@
             books.append(book.contents[0])
         return books
 
+    def _get_application(self):
+        """
+        Adds the openlp to the class dynamically
+        """
+        if not hasattr(self, u'_application'):
+            self._application = Registry().get(u'application')
+        return self._application
+
+    application = property(_get_application)
+
 
 class HTTPBible(BibleDB):
     log.info(u'%s HTTPBible loaded', __name__)

=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/bibles/lib/manager.py	2013-02-09 17:32:28 +0000
@@ -30,7 +30,7 @@
 import logging
 import os
 
-from openlp.core.lib import Receiver, SettingsManager, Settings, translate
+from openlp.core.lib import Registry, SettingsManager, Settings, translate
 from openlp.core.utils import AppLocation, delete_file
 from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection
 from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
@@ -304,12 +304,12 @@
         log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
         if not bible:
             if show_error:
-                Receiver.send_message(u'openlp_information_message', {
-                    u'title': translate('BiblesPlugin.BibleManager', 'No Bibles Available'),
-                    u'message': translate('BiblesPlugin.BibleManager',
+                self.main_window.information_message(
+                    translate('BiblesPlugin.BibleManager', 'No Bibles Available'),
+                    translate('BiblesPlugin.BibleManager',
                         'There are no Bibles currently installed. Please use the '
                         'Import Wizard to install one or more Bibles.')
-                    })
+                    )
             return None
         language_selection = self.get_language_selection(bible)
         reflist = parse_reference(versetext, self.db_cache[bible],
@@ -322,14 +322,11 @@
                     u'verse': get_reference_separator(u'sep_v_display'),
                     u'range': get_reference_separator(u'sep_r_display'),
                     u'list': get_reference_separator(u'sep_l_display')}
-                Receiver.send_message(u'openlp_information_message', {
-                    u'title': translate('BiblesPlugin.BibleManager',
-                    'Scripture Reference Error'),
-                    u'message': translate('BiblesPlugin.BibleManager',
-                    'Your scripture reference is either not supported by '
+                self.main_window.information_message(
+                    translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'),
+                    translate('BiblesPlugin.BibleManager', 'Your scripture reference is either not supported by '
                     'OpenLP or is invalid. Please make sure your reference '
-                    'conforms to one of the following patterns or consult the '
-                    'manual:\n\n'
+                    'conforms to one of the following patterns or consult the manual:\n\n'
                     'Book Chapter\n'
                     'Book Chapter%(range)sChapter\n'
                     'Book Chapter%(verse)sVerse%(range)sVerse\n'
@@ -339,9 +336,8 @@
                     '%(verse)sVerse%(range)sVerse\n'
                     'Book Chapter%(verse)sVerse%(range)sChapter%(verse)sVerse',
                     'Please pay attention to the appended "s" of the wildcards '
-                    'and refrain from translating the words inside the '
-                    'names in the brackets.') % reference_seperators
-                    })
+                    'and refrain from translating the words inside the names in the brackets.') % reference_seperators
+                    )
             return None
 
     def get_language_selection(self, bible):
@@ -380,36 +376,33 @@
         """
         log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text)
         if not bible:
-            Receiver.send_message(u'openlp_information_message', {
-                u'title': translate('BiblesPlugin.BibleManager', 'No Bibles Available'),
-                u'message': translate('BiblesPlugin.BibleManager',
-                    'There are no Bibles currently installed. Please use the '
-                    'Import Wizard to install one or more Bibles.')
-                })
+            self.main_window.information_message(
+                translate('BiblesPlugin.BibleManager', 'No Bibles Available'),
+                translate('BiblesPlugin.BibleManager',
+                    'There are no Bibles currently installed. Please use the Import Wizard to install one or more'
+                    ' Bibles.')
+                )
             return None
         # Check if the bible or second_bible is a web bible.
-        webbible = self.db_cache[bible].get_object(BibleMeta,
-            u'download_source')
+        webbible = self.db_cache[bible].get_object(BibleMeta, u'download_source')
         second_webbible = u''
         if second_bible:
-            second_webbible = self.db_cache[second_bible].get_object(BibleMeta,
-                u'download_source')
+            second_webbible = self.db_cache[second_bible].get_object(BibleMeta, u'download_source')
         if webbible or second_webbible:
-            Receiver.send_message(u'openlp_information_message', {
-                u'title': translate('BiblesPlugin.BibleManager', 'Web Bible cannot be used'),
-                u'message': translate('BiblesPlugin.BibleManager', 'Text Search is not available with Web Bibles.')
-                })
+            self.main_window.information_message(
+                translate('BiblesPlugin.BibleManager', 'Web Bible cannot be used'),
+                translate('BiblesPlugin.BibleManager', 'Text Search is not available with Web Bibles.')
+                )
             return None
         if text:
             return self.db_cache[bible].verse_search(text)
         else:
-            Receiver.send_message(u'openlp_information_message', {
-                u'title': translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'),
-                u'message': translate('BiblesPlugin.BibleManager', 'You did not enter a search keyword.\n'
-                    'You can separate different keywords by a space to '
-                    'search for all of your keywords and you can separate '
+            self.main_window.information_message(
+                translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'),
+                translate('BiblesPlugin.BibleManager', 'You did not enter a search keyword.\nYou can separate '
+                    'different keywords by a space to search for all of your keywords and you can separate '
                     'them by a comma to search for one of them.')
-                })
+                )
             return None
 
     def save_meta_data(self, bible, version, copyright, permissions,
@@ -460,6 +453,16 @@
         for bible in self.db_cache:
             self.db_cache[bible].finalise()
 
+    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)
+
 BibleFormat.set_availability(BibleFormat.OpenLP1, HAS_OPENLP1)
 
 __all__ = [u'BibleFormat']

=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \
+from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \
     create_separated_list, translate
 from openlp.core.lib.searchedit import SearchEdit
 from openlp.core.lib.ui import set_case_insensitive_completer, create_horizontal_adjusting_combo_box, \
@@ -70,7 +70,8 @@
         self.search_results = {}
         self.second_search_results = {}
         self.checkSearchResult()
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles)
+        Registry().register_function(u'bibles_load_list', self.reload_bibles)
+        Registry().register_function(u'config_updated', self.config_update)
 
     def __checkSecondBible(self, bible, second_bible):
         """
@@ -246,7 +247,6 @@
         # Buttons
         QtCore.QObject.connect(self.advancedSearchButton, QtCore.SIGNAL(u'clicked()'), self.onAdvancedSearchButton)
         QtCore.QObject.connect(self.quickSearchButton, QtCore.SIGNAL(u'clicked()'), self.onQuickSearchButton)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated)
         # Other stuff
         QtCore.QObject.connect(self.quickSearchEdit, QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton)
         QtCore.QObject.connect(self.searchTabBar, QtCore.SIGNAL(u'currentChanged(int)'),
@@ -258,8 +258,8 @@
         else:
             self.advancedBookComboBox.setFocus()
 
-    def configUpdated(self):
-        log.debug(u'configUpdated')
+    def config_update(self):
+        log.debug(u'config_update')
         if Settings().value(self.settingsSection + u'/second bibles'):
             self.advancedSecondLabel.setVisible(True)
             self.advancedSecondComboBox.setVisible(True)
@@ -313,7 +313,7 @@
                 translate('BiblesPlugin.MediaItem', 'Search Text...'))
         ])
         self.quickSearchEdit.setCurrentSearchType(Settings().value(u'%s/last search type' % self.settingsSection))
-        self.configUpdated()
+        self.config_update()
         log.debug(u'bible manager initialise complete')
 
     def loadBibles(self):
@@ -343,7 +343,7 @@
         bible = Settings().value(self.settingsSection + u'/quick bible')
         find_and_set_in_combo_box(self.quickVersionComboBox, bible)
 
-    def reloadBibles(self, process=False):
+    def reload_bibles(self, process=False):
         log.debug(u'Reloading Bibles')
         self.plugin.manager.reload_bibles()
         self.loadBibles()
@@ -471,7 +471,7 @@
             self.import_wizard = BibleImportForm(self, self.plugin.manager, self.plugin)
         # If the import was not cancelled then reload.
         if self.import_wizard.exec_():
-            self.reloadBibles()
+            self.reload_bibles()
 
     def onEditClick(self):
         if self.quickTab.isVisible():
@@ -482,7 +482,7 @@
             self.editBibleForm = EditBibleForm(self, self.main_window, self.plugin.manager)
             self.editBibleForm.loadBible(bible)
             if self.editBibleForm.exec_():
-                self.reloadBibles()
+                self.reload_bibles()
 
     def onDeleteClick(self):
         if self.quickTab.isVisible():
@@ -497,7 +497,7 @@
                 QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
                 return
             self.plugin.manager.delete_bible(bible)
-            self.reloadBibles()
+            self.reload_bibles()
 
     def onSearchTabBarCurrentChanged(self, index):
         if index == 0:

=== modified file 'openlp/plugins/custom/forms/editcustomform.py'
--- openlp/plugins/custom/forms/editcustomform.py	2013-01-31 22:01:41 +0000
+++ openlp/plugins/custom/forms/editcustomform.py	2013-02-09 17:32:28 +0000
@@ -31,9 +31,8 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, translate
-from openlp.core.lib.ui import critical_error_message_box, \
-    find_and_set_in_combo_box
+from openlp.core.lib import Registry, translate
+from openlp.core.lib.ui import critical_error_message_box, find_and_set_in_combo_box
 from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser
 from openlp.plugins.custom.lib.db import CustomSlide
 from editcustomdialog import Ui_CustomEditDialog
@@ -65,9 +64,9 @@
         self.editAllButton.clicked.connect(self.on_edit_all_button_clicked)
         self.slideListView.currentRowChanged.connect(self.on_current_row_changed)
         self.slideListView.doubleClicked.connect(self.on_edit_button_clicked)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
+        Registry().register_function(u'theme_update_list', self.load_themes)
 
-    def loadThemes(self, theme_list):
+    def load_themes(self, theme_list):
         """
         Load a list of themes into the themes combo box.
 
@@ -191,7 +190,7 @@
         """
         log.debug(u'onPreview')
         if self.saveCustom():
-            Receiver.send_message(u'custom_preview')
+            Registry().execute(u'custom_preview')
 
     def updateSlideList(self, slides, edit_all=False):
         """

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -32,7 +32,7 @@
 from PyQt4 import QtCore, QtGui
 from sqlalchemy.sql import or_, func, and_
 
-from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, ServiceItemContext, Settings, PluginStatus, \
+from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, Settings, PluginStatus,\
     UiStrings, check_item_selected, translate
 from openlp.plugins.custom.forms import EditCustomForm
 from openlp.plugins.custom.lib import CustomXMLParser, CustomXMLBuilder
@@ -73,11 +73,10 @@
         QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'cleared()'), self.onClearTextButtonClick)
         QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'searchTypeChanged(int)'),
             self.onSearchTextButtonClicked)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_load_list'), self.loadList)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_create_from_service'),
-            self.create_from_service_item)
+        Registry().register_function(u'custom_load_list', self.loadList)
+        Registry().register_function(u'custom_preview', self.onPreviewClick)
+        Registry().register_function(u'config_updated', self.config_updated)
+        Registry().register_function(u'custom_create_from_service', self.create_from_service_item)
 
     def config_updated(self):
         self.add_custom_from_service = Settings().value(self.settingsSection + u'/add custom from service')
@@ -280,7 +279,7 @@
         self.plugin.manager.save_object(custom)
         self.onSearchTextButtonClicked()
         if item.name.lower() == u'custom':
-            Receiver.send_message(u'service_item_update', u'%s:%s:%s' % (custom.id, item.unique_identifier, False))
+            Registry().execute(u'service_item_update', u'%s:%s:%s' % (custom.id, item.unique_identifier, False))
 
     def onClearTextButtonClick(self):
         """

=== modified file 'openlp/plugins/images/imageplugin.py'
--- openlp/plugins/images/imageplugin.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/images/imageplugin.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 
 import logging
 
-from openlp.core.lib import Plugin, StringContent, Receiver, ImageSource, Settings, build_icon, translate
+from openlp.core.lib import Plugin, StringContent, Registry, ImageSource, Settings, build_icon, translate
 from openlp.plugins.images.lib import ImageMediaItem, ImageTab
 
 log = logging.getLogger(__name__)
@@ -50,7 +50,7 @@
         self.weight = -7
         self.iconPath = u':/plugins/plugin_images.png'
         self.icon = build_icon(self.iconPath)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'image_updated'), self.image_updated)
+        Registry().execute(u'image_updated', self.image_updated)
 
     def about(self):
         about_text = translate('ImagePlugin', '<strong>Image Plugin</strong>'

=== modified file 'openlp/plugins/images/lib/imagetab.py'
--- openlp/plugins/images/lib/imagetab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/images/lib/imagetab.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate
+from openlp.core.lib import SettingsTab, Registry, Settings, UiStrings, translate
 
 class ImageTab(SettingsTab):
     """
@@ -91,5 +91,5 @@
         settings.setValue(u'background color', self.bg_color)
         settings.endGroup()
         if self.initial_color != self.bg_color:
-            Receiver.send_message(u'image_updated')
+            Registry().execute(u'image_updated')
 

=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/images/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -32,7 +32,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import MediaManagerItem, ItemCapabilities, Receiver, SettingsManager, ServiceItemContext, \
+from openlp.core.lib import MediaManagerItem, ItemCapabilities, Registry, SettingsManager, ServiceItemContext, \
     Settings, UiStrings, build_icon, check_item_selected, check_directory_exists, create_thumb, translate, \
     validate_thumb
 from openlp.core.lib.ui import critical_error_message_box
@@ -51,7 +51,7 @@
         MediaManagerItem.__init__(self, parent, plugin, icon)
         self.quickPreviewAllowed = True
         self.hasSearch = True
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged)
+        Registry().register_function(u'live_theme_changed', self.live_theme_changed)
         # Allow DnD from the desktop
         self.listView.activateDnD()
 
@@ -194,7 +194,7 @@
         self.resetAction.setVisible(False)
         self.live_controller.display.resetImage()
 
-    def liveThemeChanged(self):
+    def live_theme_changed(self):
         """
         Triggered by the change of theme in the slide controller
         """

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -32,7 +32,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import ItemCapabilities, MediaManagerItem,MediaType, Receiver, ServiceItem, ServiceItemContext, \
+from openlp.core.lib import ItemCapabilities, MediaManagerItem,MediaType, Registry, ServiceItem, ServiceItemContext, \
     Settings, UiStrings, build_icon, check_item_selected, check_directory_exists, translate
 from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
 from openlp.core.ui import DisplayController, Display, DisplayControllerType
@@ -71,10 +71,9 @@
         self.displayController.previewDisplay.screen = {u'size':self.displayController.previewDisplay.geometry()}
         self.displayController.previewDisplay.setup()
         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)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.displaySetup)
+        Registry().register_function(u'video_background_replaced', self.video_background_replaced)
+        Registry().register_function(u'mediaitem_media_rebuild', self.rebuild_players)
+        Registry().register_function(u'config_screen_changed', self.display_setup)
         # Allow DnD from the desktop
         self.listView.activateDnD()
 
@@ -133,7 +132,7 @@
         self.media_controller.media_reset(self.live_controller)
         self.resetAction.setVisible(False)
 
-    def videobackgroundReplaced(self):
+    def video_background_replaced(self):
         """
         Triggered by main display on change of serviceitem.
         """
@@ -214,7 +213,7 @@
             u' '.join(self.media_controller.video_extensions_list),
             u' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles)
 
-    def displaySetup(self):
+    def display_setup(self):
         self.media_controller.setup_display(self.displayController.previewDisplay, False)
 
     def populateDisplayTypes(self):

=== modified file 'openlp/plugins/media/lib/mediatab.py'
--- openlp/plugins/media/lib/mediatab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/media/lib/mediatab.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import Receiver, Settings, SettingsTab, UiStrings, translate
+from openlp.core.lib import Registry, Settings, SettingsTab, UiStrings, translate
 
 class MediaQCheckBox(QtGui.QCheckBox):
     """
@@ -84,5 +84,5 @@
             Settings().setValue(setting_key, self.autoStartCheckBox.checkState())
         if override_changed:
             self.parent.reset_supported_suffixes()
-            Receiver.send_message(u'mediaitem_media_rebuild')
-            Receiver.send_message(u'mediaitem_suffixes')
+            Registry().execute(u'mediaitem_media_rebuild')
+            Registry().execute(u'mediaitem_suffixes')

=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -32,7 +32,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \
+from openlp.core.lib import MediaManagerItem, Registry, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \
     build_icon, check_item_selected, create_thumb, translate, validate_thumb
 from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
 from openlp.core.utils import locale_compare
@@ -60,9 +60,8 @@
         self.message_listener = MessageListener(self)
         self.hasSearch = True
         self.singleServiceItem = False
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_presentation_rebuild'),
-            self.populateDisplayTypes)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mediaitem_suffixes'), self.buildFileMaskString)
+        Registry().register_function(u'mediaitem_presentation_rebuild', self.populate_display_types)
+        Registry().register_function(u'mediaitem_suffixes', self.build_file_mask_string)
         # Allow DnD from the desktop
         self.listView.activateDnD()
 
@@ -74,7 +73,7 @@
         self.Automatic = translate('PresentationPlugin.MediaItem', 'Automatic')
         self.displayTypeLabel.setText(translate('PresentationPlugin.MediaItem', 'Present using:'))
 
-    def buildFileMaskString(self):
+    def build_file_mask_string(self):
         """
         Build the list of file extensions to be used in the Open file dialog
         """
@@ -122,9 +121,9 @@
         self.listView.setIconSize(QtCore.QSize(88, 50))
         files = Settings().value(self.settingsSection + u'/presentations files')
         self.loadList(files, True)
-        self.populateDisplayTypes()
+        self.populate_display_types()
 
-    def populateDisplayTypes(self):
+    def populate_display_types(self):
         """
         Load the combobox with the enabled presentation controllers,
         allowing user to select a specific app if settings allow

=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py	2013-02-04 21:26:27 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver
+from openlp.core.lib import Registry
 from openlp.core.ui import HideMode
 
 log = logging.getLogger(__name__)
@@ -71,7 +71,7 @@
         self.hide_mode = hide_mode
         if self.is_live:
             if hide_mode == HideMode.Screen:
-                Receiver.send_message(u'live_display_hide', HideMode.Screen)
+                Registry().execute(u'live_display_hide', HideMode.Screen)
                 self.stop()
             elif hide_mode == HideMode.Theme:
                 self.blank(hide_mode)
@@ -79,7 +79,7 @@
                 self.blank(hide_mode)
             else:
                 self.doc.start_presentation()
-                Receiver.send_message(u'live_display_hide', HideMode.Screen)
+                Registry().execute(u'live_display_hide', HideMode.Screen)
                 self.doc.slidenumber = 1
                 if slide_no > 1:
                     self.slide(slide_no)
@@ -236,7 +236,7 @@
                 return
             if not self.doc.is_active():
                 return
-            Receiver.send_message(u'live_display_hide', HideMode.Theme)
+            Registry().execute(u'live_display_hide', HideMode.Theme)
         elif hide_mode == HideMode.Blank:
             if not self.activate():
                 return
@@ -273,7 +273,7 @@
         if self.doc.slidenumber and self.doc.slidenumber != self.doc.get_slide_number():
             self.doc.goto_slide(self.doc.slidenumber)
         self.doc.unblank_screen()
-        Receiver.send_message(u'live_display_hide', HideMode.Screen)
+        Registry().execute(u'live_display_hide', HideMode.Screen)
 
     def poll(self):
         if not self.doc:
@@ -294,16 +294,16 @@
         self.preview_handler = Controller(False)
         self.live_handler = Controller(True)
         # messages are sent from core.ui.slidecontroller
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_start'), self.startup)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_stop'), self.shutdown)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_hide'), self.hide)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_first'), self.first)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_previous'), self.previous)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_next'), self.next)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_last'), self.last)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_slide'), self.slide)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_blank'), self.blank)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_unblank'), self.unblank)
+        Registry().register_function(u'presentations_start', self.startup)
+        Registry().register_function(u'presentations_stop', self.shutdown)
+        Registry().register_function(u'presentations_hide', self.hide)
+        Registry().register_function(u'presentations_first', self.first)
+        Registry().register_function(u'presentations_previous', self.previous)
+        Registry().register_function(u'presentations_next', self.next)
+        Registry().register_function(u'presentations_last', self.last)
+        Registry().register_function(u'presentations_slide', self.slide)
+        Registry().register_function(u'presentations_blank', self.blank)
+        Registry().register_function(u'presentations_unblank', self.unblank)
         self.timer = QtCore.QTimer()
         self.timer.setInterval(500)
         QtCore.QObject.connect(self.timer, QtCore.SIGNAL(u'timeout()'), self.timeout)

=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
--- openlp/plugins/presentations/lib/presentationcontroller.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/presentations/lib/presentationcontroller.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, Registry, Settings, check_directory_exists, create_thumb, validate_thumb
+from openlp.core.lib import Registry, Settings, check_directory_exists, create_thumb, validate_thumb
 from openlp.core.utils import AppLocation
 
 log = logging.getLogger(__name__)
@@ -274,7 +274,7 @@
             prefix = u'live'
         else:
             prefix = u'preview'
-        Receiver.send_message(u'slidecontroller_%s_change' % prefix, self.slidenumber - 1)
+        Registry().execute(u'slidecontroller_%s_change' % prefix, self.slidenumber - 1)
 
     def get_slide_text(self, slide_no):
         """

=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import Receiver, Settings, SettingsTab, UiStrings, translate
+from openlp.core.lib import Registry, Settings, SettingsTab, UiStrings, translate
 
 class PresentationTab(SettingsTab):
     """
@@ -130,8 +130,8 @@
             changed = True
         if changed:
             self.parent.reset_supported_suffixes()
-            Receiver.send_message(u'mediaitem_presentation_rebuild')
-            Receiver.send_message(u'mediaitem_suffixes')
+            Registry().execute(u'mediaitem_presentation_rebuild')
+            Registry().execute(u'mediaitem_suffixes')
 
     def tabVisible(self):
         """

=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py	2013-01-23 21:05:25 +0000
+++ openlp/plugins/presentations/presentationplugin.py	2013-02-09 17:32:28 +0000
@@ -37,8 +37,7 @@
 
 from openlp.core.lib import Plugin, StringContent, build_icon, translate
 from openlp.core.utils import AppLocation
-from openlp.plugins.presentations.lib import PresentationController, \
-    PresentationMediaItem, PresentationTab
+from openlp.plugins.presentations.lib import PresentationController, PresentationMediaItem, PresentationTab
 
 log = logging.getLogger(__name__)
 
@@ -91,7 +90,7 @@
                 except Exception:
                     log.warn(u'Failed to start controller process')
                     self.controllers[controller].available = False
-        self.mediaItem.buildFileMaskString()
+        self.mediaItem.build_file_mask_string()
 
     def finalise(self):
         """

=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
--- openlp/plugins/remotes/lib/httpserver.py	2013-02-04 21:27:50 +0000
+++ openlp/plugins/remotes/lib/httpserver.py	2013-02-09 17:32:28 +0000
@@ -123,7 +123,7 @@
 from PyQt4 import QtCore, QtNetwork
 from mako.template import Template
 
-from openlp.core.lib import Receiver, Settings, PluginStatus, StringContent
+from openlp.core.lib import Registry, Settings, PluginStatus, StringContent
 from openlp.core.utils import AppLocation, translate
 
 log = logging.getLogger(__name__)
@@ -175,10 +175,8 @@
         address = Settings().value(self.plugin.settingsSection + u'/ip address')
         self.server = QtNetwork.QTcpServer()
         self.server.listen(QtNetwork.QHostAddress(address), port)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_changed'),
-            self.slide_change)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_started'),
-            self.item_change)
+        Registry().register_function(u'slidecontroller_live_changed', self.slide_change)
+        Registry().register_function(u'slidecontroller_live_started', self.item_change)
         QtCore.QObject.connect(self.server, QtCore.SIGNAL(u'newConnection()'), self.new_connection)
         log.debug(u'TCP listening on port %d' % port)
 
@@ -406,7 +404,7 @@
         ``action``
             This is the action, either ``hide`` or ``show``.
         """
-        Receiver.send_message(u'slidecontroller_toggle_display', action)
+        Registry().execute(u'slidecontroller_toggle_display', action)
         return HttpResponse(json.dumps({u'results': {u'success': True}}),
             {u'Content-Type': u'application/json'})
 
@@ -421,7 +419,7 @@
             except KeyError, ValueError:
                 return HttpResponse(code=u'400 Bad Request')
             text = urllib.unquote(text)
-            Receiver.send_message(u'alerts_text', [text])
+            Registry().execute(u'alerts_text', [text])
             success = True
         else:
             success = False
@@ -471,9 +469,9 @@
                 log.info(data)
                 # This slot expects an int within a list.
                 id = data[u'request'][u'id']
-                Receiver.send_message(event, [id])
+                Registry().execute(event, [id])
             else:
-                Receiver.send_message(event)
+                Registry().execute(event)
             json_data = {u'results': {u'success': True}}
         return HttpResponse(json.dumps(json_data),
             {u'Content-Type': u'application/json'})
@@ -490,9 +488,9 @@
                 data = json.loads(self.url_params[u'data'][0])
             except KeyError, ValueError:
                 return HttpResponse(code=u'400 Bad Request')
-            Receiver.send_message(event, data[u'request'][u'id'])
+            Registry().execute(event, data[u'request'][u'id'])
         else:
-            Receiver.send_message(event)
+            Registry().execute(event)
         return HttpResponse(json.dumps({u'results': {u'success': True}}),
             {u'Content-Type': u'application/json'})
 

=== modified file 'openlp/plugins/remotes/lib/remotetab.py'
--- openlp/plugins/remotes/lib/remotetab.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/remotes/lib/remotetab.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtCore, QtGui, QtNetwork
 
-from openlp.core.lib import Settings, SettingsTab, Receiver, translate
+from openlp.core.lib import Registry, Settings, SettingsTab, translate
 
 
 ZERO_URL = u'0.0.0.0'
@@ -152,7 +152,7 @@
         Settings().setValue(self.settingsSection + u'/ip address', self.addressEdit.text())
         Settings().setValue(self.settingsSection + u'/twelve hour', self.twelveHour)
         if changed:
-            Receiver.send_message(u'remotes_config_updated')
+            Registry().register_function(u'remotes_config_updated')
 
     def onTwelveHourCheckBoxChanged(self, check_state):
         self.twelveHour = False

=== modified file 'openlp/plugins/remotes/remoteplugin.py'
--- openlp/plugins/remotes/remoteplugin.py	2013-01-23 21:05:25 +0000
+++ openlp/plugins/remotes/remoteplugin.py	2013-02-09 17:32:28 +0000
@@ -95,7 +95,7 @@
             u'title': translate('RemotePlugin', 'Remote', 'container title')
         }
 
-    def configUpdated(self):
+    def config_update(self):
         """
         Called when Config is changed to restart the server on new address or
         port

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2013-02-06 21:43:18 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2013-02-09 17:32:28 +0000
@@ -38,8 +38,8 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import PluginStatus, Receiver, MediaType, Registry, UiStrings, translate, create_separated_list, \
-    check_directory_exists
+from openlp.core.lib import Registry, PluginStatus, MediaType, translate, create_separated_list, \
+    check_directory_exists, UiStrings
 from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, \
     find_and_set_in_combo_box
 from openlp.core.utils import AppLocation
@@ -97,7 +97,7 @@
         QtCore.QObject.connect(self.audioRemoveButton, QtCore.SIGNAL(u'clicked()'), self.onAudioRemoveButtonClicked)
         QtCore.QObject.connect(self.audioRemoveAllButton, QtCore.SIGNAL(u'clicked()'),
             self.onAudioRemoveAllButtonClicked)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
+        Registry().register_function(u'theme_update_list', self.load_themes)
         self.previewButton = QtGui.QPushButton()
         self.previewButton.setObjectName(u'previewButton')
         self.previewButton.setText(UiStrings().SaveAndPreview)
@@ -169,7 +169,7 @@
             combo.setItemData(row, object.id)
         set_case_insensitive_completer(cache, combo)
 
-    def loadThemes(self, theme_list):
+    def load_themes(self, theme_list):
         """
         Load the themes into a combobox.
         """
@@ -699,7 +699,7 @@
         log.debug(u'onPreview')
         if button.objectName() == u'previewButton':
             self.saveSong(True)
-            Receiver.send_message(u'songs_preview')
+            Registry().execute(u'songs_preview')
 
     def onAudioAddFromFileButtonClicked(self):
         """

=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/songs/forms/songexportform.py	2013-02-09 17:32:28 +0000
@@ -34,7 +34,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, UiStrings, create_separated_list, build_icon, translate
+from openlp.core.lib import Registry, UiStrings, create_separated_list, build_icon, translate
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
 from openlp.plugins.songs.lib import natcmp
@@ -62,7 +62,7 @@
         """
         OpenLPWizard.__init__(self, parent, plugin, u'songExportWizard', u':/wizards/wizard_exportsong.bmp')
         self.stop_export_flag = False
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_export)
+        Registry().register_function(u'openlp_stop_wizard', self.stop_export)
 
     def stop_export(self):
         """

=== modified file 'openlp/plugins/songs/forms/songmaintenanceform.py'
--- openlp/plugins/songs/forms/songmaintenanceform.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/songs/forms/songmaintenanceform.py	2013-02-09 17:32:28 +0000
@@ -31,7 +31,7 @@
 from PyQt4 import QtGui, QtCore
 from sqlalchemy.sql import and_
 
-from openlp.core.lib import Receiver, UiStrings, translate
+from openlp.core.lib import Registry, UiStrings, translate
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm
 from openlp.plugins.songs.lib.db import Author, Book, Topic, Song
@@ -283,7 +283,7 @@
                 if self.manager.save_object(author):
                     self.resetAuthors()
                     if not self.fromSongEdit:
-                        Receiver.send_message(u'songs_load_list')
+                        Registry().execute(u'songs_load_list')
                 else:
                     critical_error_message_box(
                         message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.'))
@@ -378,7 +378,7 @@
         merge(dbObject)
         reset()
         if not self.fromSongEdit:
-            Receiver.send_message(u'songs_load_list')
+            Registry().execute(u'songs_load_list')
         self.application.set_normal_cursor()
 
     def mergeAuthors(self, oldAuthor):

=== modified file 'openlp/plugins/songs/lib/cclifileimport.py'
--- openlp/plugins/songs/lib/cclifileimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/cclifileimport.py	2013-02-09 17:32:28 +0000
@@ -95,7 +95,7 @@
                     self.logError(filename,
                         translate('SongsPlugin.CCLIFileImport', 'The file does not have a valid extension.'))
                     log.info(u'Extension %s is not valid', filename)
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
 
     def doImportUsrFile(self, textList):

=== modified file 'openlp/plugins/songs/lib/dreambeamimport.py'
--- openlp/plugins/songs/lib/dreambeamimport.py	2013-01-18 23:31:02 +0000
+++ openlp/plugins/songs/lib/dreambeamimport.py	2013-02-09 17:32:28 +0000
@@ -90,7 +90,7 @@
         if isinstance(self.importSource, list):
             self.importWizard.progressBar.setMaximum(len(self.importSource))
             for file in self.importSource:
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     return
                 self.setDefaults()
                 parser = etree.XMLParser(remove_blank_text=True)

=== modified file 'openlp/plugins/songs/lib/easyslidesimport.py'
--- openlp/plugins/songs/lib/easyslidesimport.py	2013-02-04 21:26:27 +0000
+++ openlp/plugins/songs/lib/easyslidesimport.py	2013-02-09 17:32:28 +0000
@@ -58,7 +58,7 @@
         song_xml = objectify.fromstring(xml)
         self.importWizard.progressBar.setMaximum(len(song_xml.Item))
         for song in song_xml.Item:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self._parseSong(song)
 

=== modified file 'openlp/plugins/songs/lib/ewimport.py'
--- openlp/plugins/songs/lib/ewimport.py	2013-02-04 17:47:02 +0000
+++ openlp/plugins/songs/lib/ewimport.py	2013-02-09 17:32:28 +0000
@@ -142,7 +142,7 @@
             rec_count = (rec_count + record_size) / record_size
             # Loop through each record within the current block
             for i in range(rec_count):
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     break
                 raw_record = db_file.read(record_size)
                 self.fields = self.recordStruct.unpack(raw_record)
@@ -216,7 +216,7 @@
                 if len(self.comments) > 5:
                     self.comments += unicode(translate('SongsPlugin.EasyWorshipSongImport',
                         '\n[above are Song Tags with notes imported from EasyWorship]'))
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     break
                 if not self.finish():
                     self.logError(self.importSource)

=== modified file 'openlp/plugins/songs/lib/foilpresenterimport.py'
--- openlp/plugins/songs/lib/foilpresenterimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/foilpresenterimport.py	2013-02-09 17:32:28 +0000
@@ -124,7 +124,7 @@
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         parser = etree.XMLParser(remove_blank_text=True)
         for file_path in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self.importWizard.incrementProgressBar(
                 WizardStrings.ImportingType % os.path.basename(file_path))

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2013-02-09 17:32:28 +0000
@@ -35,7 +35,8 @@
 from PyQt4 import QtCore, QtGui
 from sqlalchemy.sql import or_
 
-from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, PluginStatus, ServiceItemContext, Settings, \
+
+from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, Settings, \
     UiStrings, translate, check_item_selected, create_separated_list, check_directory_exists
 from openlp.core.lib.ui import create_widget_action
 from openlp.core.utils import AppLocation
@@ -99,9 +100,9 @@
             triggers=self.onSongMaintenanceClick)
         self.addSearchToToolBar()
         # Signals and slots
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_load_list'), self.onSongListLoad)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_preview'), self.onPreviewClick)
+        Registry().register_function(u'songs_load_list', self.on_song_list_load)
+        Registry().register_function(u'config_updated', self.config_update)
+        Registry().register_function(u'songs_preview', self.onPreviewClick)
         QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'cleared()'), self.onClearTextButtonClick)
         QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'searchTypeChanged(int)'),
             self.onSearchTextButtonClicked)
@@ -115,7 +116,7 @@
     def onFocus(self):
         self.searchTextEdit.setFocus()
 
-    def configUpdated(self):
+    def config_update(self):
         self.searchAsYouType = Settings().value(self.settingsSection + u'/search as type')
         self.updateServiceOnEdit = Settings().value(self.settingsSection + u'/update service on edit')
         self.addSongFromService = Settings().value(self.settingsSection + u'/add song from service',)
@@ -146,7 +147,7 @@
             UiStrings().Themes, UiStrings().SearchThemes)
         ])
         self.searchTextEdit.setCurrentSearchType(Settings().value(u'%s/last search type' % self.settingsSection))
-        self.configUpdated()
+        self.config_update()
 
     def onSearchTextButtonClicked(self):
         # Save the current search type to the configuration.
@@ -198,12 +199,12 @@
                 Song.search_lyrics.like(u'%' + clean_string(search_keywords) + u'%'),
                 Song.comments.like(u'%' + search_keywords.lower() + u'%')))
 
-    def onSongListLoad(self):
+    def on_song_list_load(self):
         """
         Handle the exit from the edit dialog and trigger remote updates
         of songs
         """
-        log.debug(u'onSongListLoad - start')
+        log.debug(u'on_song_list_load - start')
         # Called to redisplay the song list screen edit from a search
         # or from the exit of the Song edit dialog. If remote editing is active
         # Trigger it and clean up so it will not update again.
@@ -212,7 +213,7 @@
             item = self.buildServiceItem(self.editItem)
             self.service_manager.replace_service_item(item)
         self.onSearchTextButtonClicked()
-        log.debug(u'onSongListLoad - finished')
+        log.debug(u'on_song_list_load - finished')
 
     def displayResultsSong(self, searchresults):
         log.debug(u'display results Song')
@@ -293,7 +294,7 @@
             self.importWizard = SongImportForm(self, self.plugin)
         self.importWizard.exec_()
         # Run song load as list may have been cancelled but some songs loaded
-        Receiver.send_message(u'songs_load_list')
+        Registry().execute(u'songs_load_list')
 
     def onExportClick(self):
         if not hasattr(self, u'exportWizard'):
@@ -324,7 +325,7 @@
             self.editSongForm.loadSong(song_id, preview)
             if self.editSongForm.exec_() == QtGui.QDialog.Accepted:
                 self.autoSelectId = -1
-                self.onSongListLoad()
+                self.on_song_list_load()
                 self.remoteSong = song_id
                 self.remoteTriggered = True
                 item = self.buildServiceItem(remote=True)
@@ -345,7 +346,7 @@
             self.editSongForm.loadSong(item_id, False)
             self.editSongForm.exec_()
             self.autoSelectId = -1
-            self.onSongListLoad()
+            self.on_song_list_load()
         self.editItem = None
 
     def onDeleteClick(self):
@@ -397,7 +398,7 @@
             new_song.title = u'%s <%s>' % (new_song.title,
                 translate('SongsPlugin.MediaItem', 'copy', 'For song cloning'))
             self.plugin.manager.save_object(new_song)
-        self.onSongListLoad()
+        self.on_song_list_load()
 
     def generateSlideData(self, service_item, item=None, xmlVersion=False,
                 remote=False, context=ServiceItemContext.Service):

=== modified file 'openlp/plugins/songs/lib/mediashoutimport.py'
--- openlp/plugins/songs/lib/mediashoutimport.py	2013-01-18 23:31:02 +0000
+++ openlp/plugins/songs/lib/mediashoutimport.py	2013-02-09 17:32:28 +0000
@@ -66,7 +66,7 @@
         songs = cursor.fetchall()
         self.importWizard.progressBar.setMaximum(len(songs))
         for song in songs:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
             cursor.execute(u'SELECT Type, Number, Text FROM Verses '
                 u'WHERE Record = %s ORDER BY Type, Number' % song.Record)

=== modified file 'openlp/plugins/songs/lib/olp1import.py'
--- openlp/plugins/songs/lib/olp1import.py	2013-02-02 07:08:28 +0000
+++ openlp/plugins/songs/lib/olp1import.py	2013-02-09 17:32:28 +0000
@@ -110,7 +110,7 @@
         self.importWizard.progressBar.setMaximum(len(songs))
         for song in songs:
             self.setDefaults()
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
             song_id = song[0]
             self.title = song[1]
@@ -131,13 +131,13 @@
                 u'WHERE songid = %s' % song_id)
             author_ids = cursor.fetchall()
             for author_id in author_ids:
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     break
                 for author in authors:
                     if author[0] == author_id[0]:
                         self.parseAuthor(author[1])
                         break
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
             if db_has_tracks:
                 cursor.execute(u'-- types int, int')
@@ -146,14 +146,14 @@
                     u'WHERE songid = %s ORDER BY listindex' % song_id)
                 track_ids = cursor.fetchall()
                 for track_id, listindex in track_ids:
-                    if self.stopImportFlag:
+                    if self.stop_import_flag:
                         break
                     for track in tracks:
                         if track[0] == track_id:
                             media_file = self.expandMediaFile(track[1])
                             self.addMediaFile(media_file, listindex)
                             break
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
             if not self.finish():
                 self.logError(self.importSource)

=== modified file 'openlp/plugins/songs/lib/olpimport.py'
--- openlp/plugins/songs/lib/olpimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/olpimport.py	2013-02-09 17:32:28 +0000
@@ -225,6 +225,6 @@
                 progressDialog.setLabelText(WizardStrings.ImportingType % new_song.title)
             else:
                 self.importWizard.incrementProgressBar(WizardStrings.ImportingType % new_song.title)
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
         engine.dispose()

=== modified file 'openlp/plugins/songs/lib/oooimport.py'
--- openlp/plugins/songs/lib/oooimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/oooimport.py	2013-02-09 17:32:28 +0000
@@ -77,7 +77,7 @@
             return
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         for filename in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 break
             filename = unicode(filename)
             if os.path.isfile(filename):
@@ -189,7 +189,7 @@
         slides = doc.getDrawPages()
         text = u''
         for slide_no in range(slides.getCount()):
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 self.importWizard.incrementProgressBar(u'Import cancelled', 0)
                 return
             slide = slides.getByIndex(slide_no)

=== modified file 'openlp/plugins/songs/lib/openlyricsimport.py'
--- openlp/plugins/songs/lib/openlyricsimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/openlyricsimport.py	2013-02-09 17:32:28 +0000
@@ -63,7 +63,7 @@
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         parser = etree.XMLParser(remove_blank_text=True)
         for file_path in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self.importWizard.incrementProgressBar(WizardStrings.ImportingType % os.path.basename(file_path))
             try:

=== modified file 'openlp/plugins/songs/lib/opensongimport.py'
--- openlp/plugins/songs/lib/opensongimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/opensongimport.py	2013-02-09 17:32:28 +0000
@@ -113,7 +113,7 @@
     def doImport(self):
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         for filename in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             song_file = open(filename)
             self.doImportFile(song_file)

=== modified file 'openlp/plugins/songs/lib/powersongimport.py'
--- openlp/plugins/songs/lib/powersongimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/powersongimport.py	2013-02-09 17:32:28 +0000
@@ -106,7 +106,7 @@
             return
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         for file in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self.setDefaults()
             parse_error = False

=== modified file 'openlp/plugins/songs/lib/sofimport.py'
--- openlp/plugins/songs/lib/sofimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/sofimport.py	2013-02-09 17:32:28 +0000
@@ -100,7 +100,7 @@
         try:
             paragraphs = self.document.getText().createEnumeration()
             while paragraphs.hasMoreElements():
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     return
                 paragraph = paragraphs.nextElement()
                 if paragraph.supportsService("com.sun.star.text.Paragraph"):

=== modified file 'openlp/plugins/songs/lib/songbeamerimport.py'
--- openlp/plugins/songs/lib/songbeamerimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/songbeamerimport.py	2013-02-09 17:32:28 +0000
@@ -109,7 +109,7 @@
             return
         for file in self.importSource:
             # TODO: check that it is a valid SongBeamer file
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self.setDefaults()
             self.currentVerse = u''

=== modified file 'openlp/plugins/songs/lib/songimport.py'
--- openlp/plugins/songs/lib/songimport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/songimport.py	2013-02-09 17:32:28 +0000
@@ -34,7 +34,7 @@
 
 from PyQt4 import QtCore
 
-from openlp.core.lib import Receiver, translate, check_directory_exists
+from openlp.core.lib import Registry, translate, check_directory_exists
 from openlp.core.ui.wizard import WizardStrings
 from openlp.core.utils import AppLocation
 from openlp.plugins.songs.lib import clean_song, VerseType
@@ -81,9 +81,9 @@
         log.debug(self.importSource)
         self.importWizard = None
         self.song = None
-        self.stopImportFlag = False
+        self.stop_import_flag = False
         self.setDefaults()
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stopImport)
+        Registry().register_function(u'openlp_stop_wizard', self.stop_import)
 
     def setDefaults(self):
         """
@@ -133,12 +133,12 @@
             self.importWizard.errorSaveToButton.setVisible(True)
         self.importWizard.errorReportTextEdit.append(u'- %s (%s)' % (filepath, reason))
 
-    def stopImport(self):
+    def stop_import(self):
         """
         Sets the flag for importers to stop their import
         """
         log.debug(u'Stopping songs import')
-        self.stopImportFlag = True
+        self.stop_import_flag = True
 
     def register(self, import_wizard):
         self.importWizard = import_wizard

=== modified file 'openlp/plugins/songs/lib/songproimport.py'
--- openlp/plugins/songs/lib/songproimport.py	2013-02-04 17:47:02 +0000
+++ openlp/plugins/songs/lib/songproimport.py	2013-02-09 17:32:28 +0000
@@ -83,7 +83,7 @@
             tag = u''
             text = u''
             for file_line in songs_file:
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     break
                 file_line = unicode(file_line, u'cp1252')
                 file_text = file_line.rstrip()

=== modified file 'openlp/plugins/songs/lib/songshowplusimport.py'
--- openlp/plugins/songs/lib/songshowplusimport.py	2013-02-04 21:26:27 +0000
+++ openlp/plugins/songs/lib/songshowplusimport.py	2013-02-09 17:32:28 +0000
@@ -105,7 +105,7 @@
             return
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         for file in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             self.sspVerseOrderList = []
             other_count = 0

=== modified file 'openlp/plugins/songs/lib/sundayplusimport.py'
--- openlp/plugins/songs/lib/sundayplusimport.py	2013-02-06 21:43:18 +0000
+++ openlp/plugins/songs/lib/sundayplusimport.py	2013-02-09 17:32:28 +0000
@@ -66,7 +66,7 @@
     def doImport(self):
         self.importWizard.progressBar.setMaximum(len(self.importSource))
         for filename in self.importSource:
-            if self.stopImportFlag:
+            if self.stop_import_flag:
                 return
             song_file = open(filename)
             self.doImportFile(song_file)

=== modified file 'openlp/plugins/songs/lib/wowimport.py'
--- openlp/plugins/songs/lib/wowimport.py	2013-01-16 21:03:01 +0000
+++ openlp/plugins/songs/lib/wowimport.py	2013-02-09 17:32:28 +0000
@@ -108,7 +108,7 @@
         if isinstance(self.importSource, list):
             self.importWizard.progressBar.setMaximum(len(self.importSource))
             for source in self.importSource:
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     return
                 self.setDefaults()
                 song_data = open(source, 'rb')

=== modified file 'openlp/plugins/songs/lib/zionworximport.py'
--- openlp/plugins/songs/lib/zionworximport.py	2013-01-06 17:25:49 +0000
+++ openlp/plugins/songs/lib/zionworximport.py	2013-02-09 17:32:28 +0000
@@ -96,7 +96,7 @@
             log.info(u'%s records found in CSV file' % num_records)
             self.importWizard.progressBar.setMaximum(num_records)
             for index, record in enumerate(records, 1):
-                if self.stopImportFlag:
+                if self.stop_import_flag:
                     return
                 self.setDefaults()
                 try:

=== modified file 'openlp/plugins/songusage/forms/songusagedeleteform.py'
--- openlp/plugins/songusage/forms/songusagedeleteform.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/songusage/forms/songusagedeleteform.py	2013-02-09 17:32:28 +0000
@@ -29,7 +29,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Receiver, translate
+from openlp.core.lib import Registry, translate
 from openlp.plugins.songusage.lib.db import SongUsageItem
 from songusagedeletedialog import Ui_SongUsageDeleteDialog
 
@@ -57,11 +57,20 @@
             if ret == QtGui.QMessageBox.Yes:
                 deleteDate = self.deleteCalendar.selectedDate().toPyDate()
                 self.manager.delete_all_objects(SongUsageItem, SongUsageItem.usagedate <= deleteDate)
-                Receiver.send_message(u'openlp_information_message', {
-                    u'title': translate('SongUsagePlugin.SongUsageDeleteForm', 'Deletion Successful'),
-                    u'message': translate(
-                        'SongUsagePlugin.SongUsageDeleteForm', 'All requested data has been deleted successfully. ')}
+                self.main_window.information_message(
+                    translate('SongUsagePlugin.SongUsageDeleteForm', 'Deletion Successful'),
+                    translate(
+                        'SongUsagePlugin.SongUsageDeleteForm', 'All requested data has been deleted successfully. ')
                 )
                 self.accept()
         else:
             self.reject()
+    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/plugins/songusage/forms/songusagedetailform.py'
--- openlp/plugins/songusage/forms/songusagedetailform.py	2013-01-18 12:25:05 +0000
+++ openlp/plugins/songusage/forms/songusagedetailform.py	2013-02-09 17:32:28 +0000
@@ -33,7 +33,7 @@
 from PyQt4 import QtGui
 from sqlalchemy.sql import and_
 
-from openlp.core.lib import Receiver, Settings, translate, check_directory_exists
+from openlp.core.lib import Registry, Settings, translate, check_directory_exists
 from openlp.plugins.songusage.lib.db import SongUsageItem
 from songusagedetaildialog import Ui_SongUsageDetailDialog
 
@@ -81,11 +81,11 @@
         log.debug(u'accept')
         path = self.fileLineEdit.text()
         if not path:
-            Receiver.send_message(u'openlp_error_message', {
-                u'title': translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'),
-                u'message': translate(
-                'SongUsagePlugin.SongUsageDetailForm', 'You have not set a valid output location for your song usage '
-                    'report. Please select an existing path on your computer.')})
+            self.main_window.error_message(
+                translate('SongUsagePlugin.SongUsageDetailForm', 'Output Path Not Selected'),
+                translate('SongUsagePlugin.SongUsageDetailForm', 'You have not set a valid output location for your'
+                    ' song usage report. Please select an existing path on your computer.')
+            )
             return
         check_directory_exists(path)
         filename = translate('SongUsagePlugin.SongUsageDetailForm', 'usage_detail_%s_%s.txt') % (
@@ -108,13 +108,24 @@
                     instance.usagetime, instance.title, instance.copyright,
                     instance.ccl_number, instance.authors, instance.plugin_name, instance.source)
                 fileHandle.write(record.encode(u'utf-8'))
-            Receiver.send_message(u'openlp_information_message', {
-                u'title': translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation'),
-                u'message': translate('SongUsagePlugin.SongUsageDetailForm', 'Report \n%s \n'
-                    'has been successfully created. ') % outname})
+            self.main_window.information_message(
+                translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation'),
+                translate('SongUsagePlugin.SongUsageDetailForm', 'Report \n%s \n'
+                    'has been successfully created. ') % outname
+            )
         except IOError:
             log.exception(u'Failed to write out song usage records')
         finally:
             if fileHandle:
                 fileHandle.close()
         self.close()
+
+    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/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py	2013-02-05 08:05:28 +0000
+++ openlp/plugins/songusage/songusageplugin.py	2013-02-09 17:32:28 +0000
@@ -32,7 +32,7 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.lib import Plugin, Receiver, Settings, StringContent, build_icon, translate
+from openlp.core.lib import Plugin, Registry, Settings, StringContent, build_icon, translate
 from openlp.core.lib.db import Manager
 from openlp.core.lib.ui import create_action
 from openlp.core.utils.actions import ActionList
@@ -123,10 +123,8 @@
     def initialise(self):
         log.info(u'SongUsage Initialising')
         Plugin.initialise(self)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_started'),
-            self.displaySongUsage)
-        QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'print_service_started'),
-            self.printSongUsage)
+        Registry().register_function(u'slidecontroller_live_started', self.display_song_usage)
+        Registry().register_function(u'print_service_started', self.print_song_usage)
         self.songUsageActive = Settings().value(self.settingsSection + u'/active')
         # Set the button and checkbox state
         self.setButtonState()
@@ -185,13 +183,13 @@
         self.songUsageStatus.blockSignals(False)
 
 
-    def displaySongUsage(self, item):
+    def display_song_usage(self, item):
         """
         Song Usage for which has been displayed
         """
         self._add_song_usage(translate('SongUsagePlugin', 'display'), item)
 
-    def printSongUsage(self, item):
+    def print_song_usage(self, item):
         """
         Song Usage for which has been printed
         """

=== removed file 'tests/conftest.py'
--- tests/conftest.py	2012-06-22 14:14:53 +0000
+++ tests/conftest.py	1970-01-01 00:00:00 +0000
@@ -1,46 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2011 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan      #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
-# Meinert Jordan, Armin Köhler, Edwin Lunando, 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                                        #
-# --------------------------------------------------------------------------- #
-# 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                          #
-###############################################################################
-
-"""
-Configuration file for pytest framework.
-"""
-
-from openlp.core import main as openlp_main
-
-
-# Test function argument to make openlp gui instance persistent for all tests.
-# All test cases have to access the same instance. To allow create multiple
-# instances it would be necessary use diffrent configuraion and data files.
-# Created instance will use your OpenLP settings.
-def pytest_funcarg__openlpapp(request):
-    def setup():
-        return openlp_main(['--testing'])
-    def teardown(app):
-        pass
-    return request.cached_setup(setup=setup, teardown=teardown, scope='session')

=== modified file 'tests/functional/openlp_core_lib/test_registry.py'
--- tests/functional/openlp_core_lib/test_registry.py	2013-01-30 18:18:28 +0000
+++ tests/functional/openlp_core_lib/test_registry.py	2013-02-09 17:32:28 +0000
@@ -11,12 +11,12 @@
 
 class TestRegistry(TestCase):
 
-    def registry_basic_test(self):
+    def registry_service_test(self):
         """
         Test the registry creation and its usage
         """
         # GIVEN: A new registry
-        registry = Registry.create()
+        Registry.create()
 
         # WHEN: I add a component it should save it
         mock_1 = MagicMock()
@@ -46,3 +46,37 @@
             temp = Registry().get(u'test1')
         self.assertEqual(context.exception[0], u'Service test1 not found in list',
             u'KeyError exception should have been thrown for deleted service')
+
+    def registry_function_test(self):
+        """
+        Test the registry function creation and their usages
+        """
+        # GIVEN: An existing registry register a function
+        Registry.create()
+        Registry().register_function(u'test1', self.dummy_function_1)
+
+        # WHEN: I execute the function
+        return_value = Registry().execute(u'test1')
+
+        # THEN: I expect then function to have been called and a return given
+        self.assertEqual(return_value[0], u'function_1', u'A return value is provided and matches')
+
+        # WHEN: I execute the a function with the same reference and execute the function
+        Registry().register_function(u'test1', self.dummy_function_1)
+        return_value = Registry().execute(u'test1')
+
+        # THEN: I expect then function to have been called and a return given
+        self.assertEqual(return_value, [u'function_1', u'function_1'], u'A return value list is provided and matches')
+
+        # WHEN: I execute the a 2nd function with the different reference and execute the function
+        Registry().register_function(u'test2', self.dummy_function_2)
+        return_value = Registry().execute(u'test2')
+
+        # THEN: I expect then function to have been called and a return given
+        self.assertEqual(return_value[0], u'function_2', u'A return value is provided and matches')
+
+    def dummy_function_1(self):
+        return "function_1"
+
+    def dummy_function_2(self):
+        return "function_2"
\ No newline at end of file

=== modified file 'tests/interfaces/openlp_core_ui/test_servicenotedialog.py'
--- tests/interfaces/openlp_core_ui/test_servicenotedialog.py	2013-01-31 19:41:45 +0000
+++ tests/interfaces/openlp_core_ui/test_servicenotedialog.py	2013-02-09 17:32:28 +0000
@@ -14,7 +14,7 @@
         """
         Create the UI
         """
-        registry = Registry.create()
+        Registry.create()
         self.app = QtGui.QApplication([])
         self.main_window = QtGui.QMainWindow()
         Registry().register(u'main_window', self.main_window)
@@ -36,7 +36,7 @@
         self.form.text_edit.setPlainText(u'')
 
         # WHEN displaying the UI and pressing enter
-        with patch(u'PyQt4.QtGui.QDialog') as mocked_exec:
+        with patch(u'PyQt4.QtGui.QDialog.exec_'):
             self.form.exec_()
         okWidget = self.form.button_box.button(self.form.button_box.Save)
         QtTest.QTest.mouseClick(okWidget, QtCore.Qt.LeftButton)
@@ -47,7 +47,7 @@
         # WHEN displaying the UI, having set the text and pressing enter
         text = u'OpenLP is the best worship software'
         self.form.text_edit.setPlainText(text)
-        with patch(u'PyQt4.QtGui.QDialog') as mocked_exec:
+        with patch(u'PyQt4.QtGui.QDialog.exec_'):
             self.form.exec_()
         okWidget = self.form.button_box.button(self.form.button_box.Save)
         QtTest.QTest.mouseClick(okWidget, QtCore.Qt.LeftButton)
@@ -57,7 +57,7 @@
 
         # WHEN displaying the UI, having set the text and pressing enter
         self.form.text_edit.setPlainText(u'')
-        with patch(u'PyQt4.QtGui.QDialog') as mocked_exec:
+        with patch(u'PyQt4.QtGui.QDialog.exec_'):
             self.form.exec_()
             self.form.text_edit.setPlainText(text)
         okWidget = self.form.button_box.button(self.form.button_box.Save)

=== modified file 'tests/interfaces/openlp_core_ui/test_starttimedialog.py'
--- tests/interfaces/openlp_core_ui/test_starttimedialog.py	2013-02-04 21:22:12 +0000
+++ tests/interfaces/openlp_core_ui/test_starttimedialog.py	2013-02-09 17:32:28 +0000
@@ -14,7 +14,7 @@
         """
         Create the UI
         """
-        registry = Registry.create()
+        Registry.create()
         self.app = QtGui.QApplication([])
         self.main_window = QtGui.QMainWindow()
         Registry().register(u'main_window', self.main_window)
@@ -67,7 +67,7 @@
 
         # WHEN displaying the UI and pressing enter
         self.form.item = {u'service_item': mocked_serviceitem}
-        with patch(u'PyQt4.QtGui.QDialog') as mocked_exec:
+        with patch(u'PyQt4.QtGui.QDialog.exec_'):
             self.form.exec_()
         okWidget = self.form.button_box.button(self.form.button_box.Ok)
         QtTest.QTest.mouseClick(okWidget, QtCore.Qt.LeftButton)
@@ -80,7 +80,7 @@
 
         # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter
         self.form.item = {u'service_item': mocked_serviceitem}
-        with patch(u'PyQt4.QtGui.QDialog') as mocked_exec:
+        with patch(u'PyQt4.QtGui.QDialog.exec_'):
             self.form.exec_()
         self.form.minuteSpinBox.setValue(2)
         self.form.secondSpinBox.setValue(3)

=== removed file 'tests/run.py'
--- tests/run.py	2012-06-22 14:14:53 +0000
+++ tests/run.py	1970-01-01 00:00:00 +0000
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2011 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan      #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
-# Meinert Jordan, Armin Köhler, Edwin Lunando, 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                                        #
-# --------------------------------------------------------------------------- #
-# 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                          #
-###############################################################################
-
-"""
-This script is used to run set of automated tests of OpenLP. To start tests,
-simply run this script::
-
-    @:~$ ./run.py
-
-"""
-
-import os
-import sys
-
-TESTS_PATH = os.path.dirname(os.path.abspath(__file__))
-SRC_PATH = os.path.join(TESTS_PATH, '..')
-
-PYTEST_OPTIONS = [TESTS_PATH]
-
-# Extend python PATH with openlp source
-sys.path.insert(0, SRC_PATH)
-
-# Python testing framework
-# http://pytest.org
-import pytest
-
-
-def main():
-    print 'pytest options:', PYTEST_OPTIONS
-    pytest.main(PYTEST_OPTIONS)
-
-
-if __name__ == u'__main__':
-    main()

=== removed file 'tests/test_app.py'
--- tests/test_app.py	2012-12-08 08:40:41 +0000
+++ tests/test_app.py	1970-01-01 00:00:00 +0000
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2011 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan      #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
-# Meinert Jordan, Armin Köhler, Edwin Lunando, 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                                        #
-# --------------------------------------------------------------------------- #
-# 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                          #
-###############################################################################
-
-from openlp.core import OpenLP
-from openlp.core.ui.mainwindow import MainWindow
-
-
-def test_start_app(openlpapp):
-    assert type(openlpapp) == OpenLP
-    assert type(openlpapp.mainWindow) == MainWindow
-    assert unicode(openlpapp.mainWindow.windowTitle()) == u'OpenLP 2.1'


Follow ups