← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~openlp-core/openlp/python3-productive into lp:openlp

 

Andreas Preikschat has proposed merging lp:~openlp-core/openlp/python3-productive into lp:openlp.

Requested reviews:
  Tim Bentley (trb143)

For more details, see:
https://code.launchpad.net/~openlp-core/openlp/python3-productive/+merge/181632

Hello,

- changes required to run openlp with python3
- python3 does not have a buffer type, however, it is said that the "the memoryview API is similar but not exactly the same as that of buffer" [1], that is why I removed the check (we do not know if we get a memoryview object)
- ICU is now not required on linux and mac
- constructors

To review this run:
    2to3 --write --nobackups --no-diffs -x next print *
    sh scripts/generate_resources.sh


[1] http://docs.python.org/2/library/2to3.html#fixers
-- 
https://code.launchpad.net/~openlp-core/openlp/python3-productive/+merge/181632
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp.py'
--- openlp.py	2013-07-18 19:28:35 +0000
+++ openlp.py	2013-08-22 18:47:39 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
 
@@ -27,15 +27,7 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 
-import sip
 import sys
-sip.setapi(u'QDate', 2)
-sip.setapi(u'QDateTime', 2)
-sip.setapi(u'QString', 2)
-sip.setapi(u'QTextStream', 2)
-sip.setapi(u'QTime', 2)
-sip.setapi(u'QUrl', 2)
-sip.setapi(u'QVariant', 2)
 
 from openlp.core import main
 

=== modified file 'openlp/__init__.py'
--- openlp/__init__.py	2013-07-18 19:28:35 +0000
+++ openlp/__init__.py	2013-08-22 18:47:39 +0000
@@ -30,7 +30,7 @@
 The :mod:`openlp` module contains all the project produced OpenLP functionality
 """
 
-import core
-import plugins
+import openlp.core
+import openlp.plugins
 
 __all__ = [u'core', u'plugins']

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2013-06-03 17:19:42 +0000
+++ openlp/core/lib/__init__.py	2013-08-22 18:47:39 +0000
@@ -121,20 +121,19 @@
     if not os.path.isfile(text_file):
         return False
     file_handle = None
-    content_string = None
+    content = None
     try:
         file_handle = open(text_file, u'r')
         if not file_handle.read(3) == '\xEF\xBB\xBF':
             # no BOM was found
             file_handle.seek(0)
         content = file_handle.read()
-        content_string = content.decode(u'utf-8')
     except (IOError, UnicodeError):
         log.exception(u'Failed to open text file %s' % text_file)
     finally:
         if file_handle:
             file_handle.close()
-    return content_string
+    return content
 
 
 def str_to_bool(string_value):
@@ -186,7 +185,7 @@
     image.save(buffie, "PNG")
     log.debug(u'image_to_byte - end')
     # convert to base64 encoding so does not get missed!
-    return byte_array.toBase64()
+    return bytes(byte_array.toBase64()).decode('utf-8')
 
 
 def create_thumb(image_path, thumb_path, return_icon=True, size=None):

=== modified file 'openlp/core/lib/dockwidget.py'
--- openlp/core/lib/dockwidget.py	2013-04-24 19:05:34 +0000
+++ openlp/core/lib/dockwidget.py	2013-08-22 18:47:39 +0000
@@ -49,7 +49,7 @@
         Initialise the DockWidget
         """
         log.debug(u'Initialise the %s widget' % name)
-        QtGui.QDockWidget.__init__(self, parent)
+        super(OpenLPDockWidget, self).__init__(parent)
         if name:
             self.setObjectName(name)
         if icon:

=== modified file 'openlp/core/lib/formattingtags.py'
--- openlp/core/lib/formattingtags.py	2013-06-30 18:36:52 +0000
+++ openlp/core/lib/formattingtags.py	2013-08-22 18:47:39 +0000
@@ -62,9 +62,6 @@
                 # Remove key 'temporary' from tags. It is not needed to be saved.
                 if u'temporary' in tag:
                     del tag[u'temporary']
-                for element in tag:
-                    if isinstance(tag[element], unicode):
-                        tag[element] = tag[element].encode('utf8')
         # Formatting Tags were also known as display tags.
         Settings().setValue(u'formattingTags/html_tags', json.dumps(tags) if tags else u'')
 
@@ -156,15 +153,10 @@
             u'end html': u'', u'protected': True, u'temporary': False})
         FormattingTags.add_html_tags(base_tags)
         FormattingTags.add_html_tags(temporary_tags)
-        # Formatting Tags were also known as display tags.
         user_expands_string = str(Settings().value(u'formattingTags/html_tags'))
+        # If we have some user ones added them as well
         if user_expands_string:
             user_tags = json.loads(user_expands_string)
-            for tag in user_tags:
-                for element in tag:
-                    if isinstance(tag[element], str):
-                        tag[element] = tag[element].decode('utf8')
-            # If we have some user ones added them as well
             FormattingTags.add_html_tags(user_tags)
 
     @staticmethod

=== modified file 'openlp/core/lib/imagemanager.py'
--- openlp/core/lib/imagemanager.py	2013-06-30 05:35:57 +0000
+++ openlp/core/lib/imagemanager.py	2013-08-22 18:47:39 +0000
@@ -56,7 +56,7 @@
         ``manager``
             The image manager.
         """
-        QtCore.QThread.__init__(self, None)
+        super(ImageThread, self).__init__(None)
         self.image_manager = manager
 
     def run(self):
@@ -183,7 +183,7 @@
         """
         Constructor for the image manager.
         """
-        QtCore.QObject.__init__(self)
+        super(ImageManager, self).__init__()
         Registry().register(u'image_manager', self)
         current_screen = ScreenList().current
         self.width = current_screen[u'size'].width()

=== modified file 'openlp/core/lib/listwidgetwithdnd.py'
--- openlp/core/lib/listwidgetwithdnd.py	2013-03-19 22:00:50 +0000
+++ openlp/core/lib/listwidgetwithdnd.py	2013-08-22 18:47:39 +0000
@@ -44,7 +44,7 @@
         """
         Initialise the list widget
         """
-        QtGui.QListWidget.__init__(self, parent)
+        super(ListWidgetWithDnD, self).__init__(parent)
         self.mimeDataText = name
         assert(self.mimeDataText)
 

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-06-24 16:54:23 +0000
+++ openlp/core/lib/mediamanageritem.py	2013-08-22 18:47:39 +0000
@@ -82,7 +82,7 @@
         """
         Constructor to create the media manager item.
         """
-        QtGui.QWidget.__init__(self)
+        super(MediaManagerItem, self).__init__()
         self.hide()
         self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
         self.plugin = plugin

=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py	2013-07-19 13:57:19 +0000
+++ openlp/core/lib/plugin.py	2013-08-22 18:47:39 +0000
@@ -128,7 +128,7 @@
 
             class MyPlugin(Plugin):
                 def __init__(self):
-                    Plugin.__init__(self, u'MyPlugin', version=u'0.1')
+                    super(MyPlugin, self).__init__('MyPlugin', version=u'0.1')
 
         ``name``
             Defaults to *None*. The name of the plugin.
@@ -146,7 +146,7 @@
             Defaults to *None*, which means that the same version number is used as OpenLP's version number.
         """
         log.debug(u'Plugin %s initialised' % name)
-        QtCore.QObject.__init__(self)
+        super(Plugin, self).__init__()
         self.name = name
         self.text_strings = {}
         self.set_plugin_text_strings()

=== modified file 'openlp/core/lib/searchedit.py'
--- openlp/core/lib/searchedit.py	2013-04-24 19:05:34 +0000
+++ openlp/core/lib/searchedit.py	2013-08-22 18:47:39 +0000
@@ -46,7 +46,7 @@
         """
         Constructor.
         """
-        QtGui.QLineEdit.__init__(self, parent)
+        super(SearchEdit, self).__init__(parent)
         self._current_search_type = -1
         self.clear_button = QtGui.QToolButton(self)
         self.clear_button.setIcon(build_icon(u':/system/clear_shortcut.png'))

=== modified file 'openlp/core/lib/settingstab.py'
--- openlp/core/lib/settingstab.py	2013-04-24 20:47:30 +0000
+++ openlp/core/lib/settingstab.py	2013-08-22 18:47:39 +0000
@@ -52,7 +52,7 @@
         ``visible_title``
             The title of the tab, which is usually displayed on the tab.
         """
-        QtGui.QWidget.__init__(self, parent)
+        super(SettingsTab, self).__init__(parent)
         self.tab_title = title
         self.tab_title_visible = visible_title
         self.settings_section = self.tab_title.lower()

=== modified file 'openlp/core/lib/spelltextedit.py'
--- openlp/core/lib/spelltextedit.py	2013-03-07 09:01:42 +0000
+++ openlp/core/lib/spelltextedit.py	2013-08-22 18:47:39 +0000
@@ -60,7 +60,7 @@
         Constructor.
         """
         global ENCHANT_AVAILABLE
-        QtGui.QPlainTextEdit.__init__(self, parent)
+        super(SpellTextEdit, self).__init__(parent)
         self.formatting_tags_allowed = formatting_tags_allowed
         # Default dictionary based on the current locale.
         if ENCHANT_AVAILABLE:
@@ -177,7 +177,7 @@
         """
         Constructor
         """
-        QtGui.QSyntaxHighlighter.__init__(self, *args)
+        super(Highlighter, self).__init__(*args)
         self.spelling_dictionary = None
 
     def highlightBlock(self, text):
@@ -205,5 +205,5 @@
         """
         Constructor
         """
-        QtGui.QAction.__init__(self, *args)
+        super(SpellAction, self).__init__(*args)
         self.triggered.connect(lambda x: self.correct.emit(self.text()))

=== modified file 'openlp/core/lib/theme.py'
--- openlp/core/lib/theme.py	2013-03-01 09:20:26 +0000
+++ openlp/core/lib/theme.py	2013-08-22 18:47:39 +0000
@@ -473,7 +473,7 @@
         Pull out the XML string formatted for human consumption
         """
         self._build_xml_from_attrs()
-        return self.theme_xml.toprettyxml(indent=u'    ', newl=u'\n', encoding=u'utf-8')
+        return self.theme_xml.toprettyxml(indent='    ', newl='\n', encoding='utf-8')
 
     def parse(self, xml):
         """

=== modified file 'openlp/core/lib/toolbar.py'
--- openlp/core/lib/toolbar.py	2013-03-07 08:05:43 +0000
+++ openlp/core/lib/toolbar.py	2013-08-22 18:47:39 +0000
@@ -47,7 +47,7 @@
         """
         Initialise the toolbar.
         """
-        QtGui.QToolBar.__init__(self, parent)
+        super(OpenLPToolbar, self).__init__(parent)
         # useful to be able to reuse button icons...
         self.setIconSize(QtCore.QSize(20, 20))
         self.actions = {}

=== modified file 'openlp/core/lib/treewidgetwithdnd.py'
--- openlp/core/lib/treewidgetwithdnd.py	2013-03-23 07:07:06 +0000
+++ openlp/core/lib/treewidgetwithdnd.py	2013-08-22 18:47:39 +0000
@@ -44,7 +44,7 @@
         """
         Initialise the tree widget
         """
-        QtGui.QTreeWidget.__init__(self, parent)
+        super(TreeWidgetWithDnD, self).__init__(parent)
         self.mimeDataText = name
         self.allow_internal_dnd = False
         self.header().close()

=== modified file 'openlp/core/ui/aboutform.py'
--- openlp/core/ui/aboutform.py	2013-03-05 13:55:50 +0000
+++ openlp/core/ui/aboutform.py	2013-08-22 18:47:39 +0000
@@ -46,7 +46,7 @@
         """
         Do some initialisation stuff
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(AboutForm, self).__init__(parent)
         application_version = get_application_version()
         self.setupUi(self)
         about_text = self.about_text_edit.toPlainText()

=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py	2013-03-16 16:59:10 +0000
+++ openlp/core/ui/advancedtab.py	2013-08-22 18:47:39 +0000
@@ -57,14 +57,14 @@
         self.data_exists = False
         self.icon_path = u':/system/system_settings.png'
         advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced')
-        SettingsTab.__init__(self, parent, u'Advanced', advanced_translated)
+        super(AdvancedTab, self).__init__(parent, u'Advanced', advanced_translated)
 
     def setupUi(self):
         """
         Configure the UI elements for the tab.
         """
         self.setObjectName(u'AdvancedTab')
-        SettingsTab.setupUi(self)
+        super(AdvancedTab, self).setupUi()
         self.ui_group_box = QtGui.QGroupBox(self.left_column)
         self.ui_group_box.setObjectName(u'ui_group_box')
         self.ui_layout = QtGui.QFormLayout(self.ui_group_box)

=== modified file 'openlp/core/ui/exceptionform.py'
--- openlp/core/ui/exceptionform.py	2013-07-21 14:13:44 +0000
+++ openlp/core/ui/exceptionform.py	2013-08-22 18:47:39 +0000
@@ -107,7 +107,7 @@
         """
         Constructor.
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(ExceptionForm, self).__init__(self.main_window)
         self.setupUi(self)
         self.settings_section = u'crashreport'
 
@@ -276,4 +276,4 @@
             self._main_window = Registry().get(u'main_window')
         return self._main_window
 
-    main_window = property(_get_main_window)
\ No newline at end of file
+    main_window = property(_get_main_window)

=== modified file 'openlp/core/ui/filerenameform.py'
--- openlp/core/ui/filerenameform.py	2013-03-01 11:12:23 +0000
+++ openlp/core/ui/filerenameform.py	2013-08-22 18:47:39 +0000
@@ -45,7 +45,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(FileRenameForm, self).__init__(Registry().get(u'main_window'))
         self.setupUi(self)
 
     def exec_(self, copy=False):

=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py	2013-07-03 20:20:12 +0000
+++ openlp/core/ui/firsttimeform.py	2013-08-22 18:47:39 +0000
@@ -29,20 +29,20 @@
 """
 This module contains the first time wizard.
 """
-import io
 import logging
 import os
 import sys
 import time
-import urllib
-import urllib2
+import urllib.request
+import urllib.parse
+import urllib.error
 from tempfile import gettempdir
 from ConfigParser import SafeConfigParser
 
 from PyQt4 import QtCore, QtGui
 
 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 openlp.core.utils import AppLocation, get_web_page
 from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
 
 log = logging.getLogger(__name__)
@@ -67,7 +67,7 @@
             filename = config.get(u'theme_%s' % theme, u'filename')
             screenshot = config.get(u'theme_%s' % theme, u'screenshot')
             urllib.urlretrieve(u'%s%s' % (self.parent().web, screenshot),
-                os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp', screenshot))
+                os.path.join(gettempdir(), u'openlp', screenshot))
             item = QtGui.QListWidgetItem(title, self.parent().themes_list_widget)
             item.setData(QtCore.Qt.UserRole, filename)
             item.setCheckState(QtCore.Qt.Unchecked)
@@ -93,7 +93,7 @@
         self.web_access = get_web_page(u'%s%s' % (self.web, u'download.cfg'))
         if self.web_access:
             files = self.web_access.read()
-            self.config.readfp(io.BytesIO(files))
+            self.config.read_string(files.decode())
         self.update_screen_list_combo()
         self.was_download_cancelled = False
         self.theme_screenshot_thread = None
@@ -115,7 +115,7 @@
         Set up display at start of theme edit.
         """
         self.restart()
-        check_directory_exists(os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
+        check_directory_exists(os.path.join(gettempdir(), u'openlp'))
         self.no_internet_finish_button.setVisible(False)
         # Check if this is a re-run of the wizard.
         self.has_run_wizard = Settings().value(u'core/has run wizard')
@@ -124,8 +124,8 @@
             songs = self.config.get(u'songs', u'languages')
             songs = songs.split(u',')
             for song in songs:
-                title = unicode(self.config.get(u'songs_%s' % song, u'title'), u'utf8')
-                filename = unicode(self.config.get(u'songs_%s' % song, u'filename'), u'utf8')
+                title = self.config.get(u'songs_%s' % song, u'title')
+                filename = self.config.get(u'songs_%s' % song, u'filename')
                 item = QtGui.QListWidgetItem(title, self.songs_list_widget)
                 item.setData(QtCore.Qt.UserRole, filename)
                 item.setCheckState(QtCore.Qt.Unchecked)
@@ -133,13 +133,13 @@
             bible_languages = self.config.get(u'bibles', u'languages')
             bible_languages = bible_languages.split(u',')
             for lang in bible_languages:
-                language = unicode(self.config.get(u'bibles_%s' % lang, u'title'), u'utf8')
+                language = self.config.get(u'bibles_%s' % lang, u'title')
                 langItem = QtGui.QTreeWidgetItem(self.bibles_tree_widget, [language])
                 bibles = self.config.get(u'bibles_%s' % lang, u'translations')
                 bibles = bibles.split(u',')
                 for bible in bibles:
-                    title = unicode(self.config.get(u'bible_%s' % bible, u'title'), u'utf8')
-                    filename = unicode(self.config.get(u'bible_%s' % bible, u'filename'))
+                    title = self.config.get(u'bible_%s' % bible, u'title')
+                    filename = self.config.get(u'bible_%s' % bible, u'filename')
                     item = QtGui.QTreeWidgetItem(langItem, [title])
                     item.setData(0, QtCore.Qt.UserRole, filename)
                     item.setCheckState(0, QtCore.Qt.Unchecked)
@@ -292,8 +292,7 @@
                 item = self.themes_list_widget.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(gettempdir(), u'openlp', screenshot)))
 
     def _getFileSize(self, url):
         """
@@ -302,9 +301,9 @@
         ``url``
             The URL of the file we want to download.
         """
-        site = urllib.urlopen(url)
+        site = urllib.request.urlopen(url)
         meta = site.info()
-        return int(meta.getheaders("Content-Length")[0])
+        return int(meta.get("Content-Length"))
 
     def _download_progress(self, count, block_size):
         """
@@ -426,8 +425,7 @@
         self._set_plugin_status(self.alert_check_box, u'alerts/status')
         if self.web_access:
             # Build directories for downloads
-            songs_destination = os.path.join(
-                unicode(gettempdir(), get_filesystem_encoding()), u'openlp')
+            songs_destination = os.path.join(gettempdir(), u'openlp')
             bibles_destination = AppLocation.get_section_data_path(u'bibles')
             themes_destination = AppLocation.get_section_data_path(u'themes')
             # Download songs

=== modified file 'openlp/core/ui/firsttimelanguageform.py'
--- openlp/core/ui/firsttimelanguageform.py	2013-04-18 17:45:14 +0000
+++ openlp/core/ui/firsttimelanguageform.py	2013-08-22 18:47:39 +0000
@@ -44,7 +44,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(FirstTimeLanguageForm, self).__init__(parent)
         self.setupUi(self)
         self.qmList = LanguageManager.get_qm_list()
         self.language_combo_box.addItem(u'Autodetect')

=== modified file 'openlp/core/ui/formattingtagform.py'
--- openlp/core/ui/formattingtagform.py	2013-07-19 15:51:47 +0000
+++ openlp/core/ui/formattingtagform.py	2013-08-22 18:47:39 +0000
@@ -46,7 +46,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(FormattingTagForm, self).__init__(parent)
         self.setupUi(self)
         self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
         self.new_push_button.clicked.connect(self.on_new_clicked)

=== modified file 'openlp/core/ui/generaltab.py'
--- openlp/core/ui/generaltab.py	2013-07-11 20:54:30 +0000
+++ openlp/core/ui/generaltab.py	2013-08-22 18:47:39 +0000
@@ -49,14 +49,14 @@
         self.screens = ScreenList()
         self.icon_path = u':/icon/openlp-logo-16x16.png'
         general_translated = translate('OpenLP.GeneralTab', 'General')
-        SettingsTab.__init__(self, parent, u'Core', general_translated)
+        super(GeneralTab, self).__init__(parent, u'Core', general_translated)
 
     def setupUi(self):
         """
         Create the user interface for the general settings tab
         """
         self.setObjectName(u'GeneralTab')
-        SettingsTab.setupUi(self)
+        super(GeneralTab, self).setupUi()
         self.tab_layout.setStretch(1, 1)
         # Monitors
         self.monitor_group_box = QtGui.QGroupBox(self.left_column)

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2013-07-05 18:41:49 +0000
+++ openlp/core/ui/maindisplay.py	2013-08-22 18:47:39 +0000
@@ -65,11 +65,11 @@
         Constructor
         """
         if live:
-            QtGui.QGraphicsView.__init__(self)
+            super(Display, self).__init__()
             # Overwrite the parent() method.
             self.parent = lambda: parent
         else:
-            QtGui.QGraphicsView.__init__(self, parent)
+            super(Display, self).__init__(parent)
         self.is_live = live
         self.controller = controller
         self.screen = {}
@@ -126,7 +126,7 @@
         """
         Constructor
         """
-        Display.__init__(self, parent, live, controller)
+        super(MainDisplay, self).__init__(parent, live, controller)
         self.screens = ScreenList()
         self.rebuild_css = False
         self.hide_mode = None
@@ -536,7 +536,7 @@
             The parent widget.
         """
         log.debug(u'AudioPlayer Initialisation started')
-        QtCore.QObject.__init__(self, parent)
+        super(AudioPlayer, self).__init__(parent)
         self.currentIndex = -1
         self.playlist = []
         self.repeat = False

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2013-07-19 15:36:45 +0000
+++ openlp/core/ui/mainwindow.py	2013-08-22 18:47:39 +0000
@@ -47,8 +47,7 @@
 from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
     MediaDockManager, ShortcutListForm, FormattingTagForm
 from openlp.core.ui.media import MediaController
-from openlp.core.utils import AppLocation, LanguageManager, add_actions, get_application_version, \
-    get_filesystem_encoding
+from openlp.core.utils import AppLocation, LanguageManager, add_actions, get_application_version
 from openlp.core.utils.actions import ActionList, CategoryOrder
 from openlp.core.ui.firsttimeform import FirstTimeForm
 
@@ -476,7 +475,7 @@
         """
         This constructor sets up the interface, the various managers, and the plugins.
         """
-        QtGui.QMainWindow.__init__(self)
+        super(MainWindow, self).__init__()
         Registry().register(u'main_window', self)
         self.clipboard = self.application.clipboard()
         self.arguments = self.application.args
@@ -903,7 +902,7 @@
             # Make sure it's a .conf file.
         if not export_file_name.endswith(u'conf'):
             export_file_name += u'.conf'
-        temp_file = os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp', u'exportConf.tmp')
+        temp_file = os.path.join(gettempdir(), u'openlp', u'exportConf.tmp')
         self.save_settings()
         setting_sections = []
         # Add main sections.

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2013-06-20 18:42:45 +0000
+++ openlp/core/ui/media/mediacontroller.py	2013-08-22 18:47:39 +0000
@@ -53,7 +53,7 @@
         """
         Constructor
         """
-        QtGui.QSlider.__init__(self, direction)
+        super(MediaSlider, self).__init__(direction)
         self.manager = manager
         self.controller = controller
 

=== modified file 'openlp/core/ui/media/phononplayer.py'
--- openlp/core/ui/media/phononplayer.py	2013-03-23 07:45:08 +0000
+++ openlp/core/ui/media/phononplayer.py	2013-08-22 18:47:39 +0000
@@ -87,7 +87,7 @@
         """
         Constructor
         """
-        MediaPlayer.__init__(self, parent, u'phonon')
+        super(PhononPlayer, self).__init__(parent, u'phonon')
         self.original_name = u'Phonon'
         self.display_name = u'&Phonon'
         self.parent = parent

=== modified file 'openlp/core/ui/media/playertab.py'
--- openlp/core/ui/media/playertab.py	2013-03-17 20:00:39 +0000
+++ openlp/core/ui/media/playertab.py	2013-08-22 18:47:39 +0000
@@ -55,18 +55,18 @@
         """
         Constructor
         """
-        self.media_players = self.media_controller.media_players
+        self.media_players = Registry().get('media_controller').media_players
         self.saved_used_players = None
         self.icon_path = u':/media/multimedia-player.png'
         player_translated = translate('OpenLP.PlayerTab', 'Players')
-        SettingsTab.__init__(self, parent, u'Players', player_translated)
+        super(PlayerTab, self).__init__(parent, u'Players', player_translated)
 
     def setupUi(self):
         """
         Set up the UI
         """
         self.setObjectName(u'MediaTab')
-        SettingsTab.setupUi(self)
+        super(PlayerTab, self).setupUi()
         self.background_color_group_box = QtGui.QGroupBox(self.left_column)
         self.background_color_group_box.setObjectName(u'background_color_group_box')
         self.form_layout = QtGui.QFormLayout(self.background_color_group_box)

=== modified file 'openlp/core/ui/media/vlcplayer.py'
--- openlp/core/ui/media/vlcplayer.py	2013-03-23 07:28:24 +0000
+++ openlp/core/ui/media/vlcplayer.py	2013-08-22 18:47:39 +0000
@@ -58,10 +58,12 @@
 
 if VLC_AVAILABLE:
     try:
-        VERSION = vlc.libvlc_get_version()
+        VERSION = vlc.libvlc_get_version().decode('UTF-8')
     except:
         VERSION = u'0.0.0'
-    if LooseVersion(VERSION) < LooseVersion('1.1.0'):
+    # LooseVersion does not work when a string contains letter and digits (e. g. 2.0.5 Twoflower).
+    # http://bugs.python.org/issue14894
+    if LooseVersion(VERSION.split()[0]) < LooseVersion('1.1.0'):
         VLC_AVAILABLE = False
         log.debug(u'VLC could not be loaded, because the vlc version is too old: %s' % VERSION)
 
@@ -96,15 +98,14 @@
 
 class VlcPlayer(MediaPlayer):
     """
-    A specialised version of the MediaPlayer class, which provides a VLC
-    display.
+    A specialised version of the MediaPlayer class, which provides a VLC display.
     """
 
     def __init__(self, parent):
         """
         Constructor
         """
-        MediaPlayer.__init__(self, parent, u'vlc')
+        super(VlcPlayer, self).__init__(parent, u'vlc')
         self.original_name = u'VLC'
         self.display_name = u'&VLC'
         self.parent = parent

=== modified file 'openlp/core/ui/media/webkitplayer.py'
--- openlp/core/ui/media/webkitplayer.py	2013-06-23 17:22:44 +0000
+++ openlp/core/ui/media/webkitplayer.py	2013-08-22 18:47:39 +0000
@@ -213,7 +213,7 @@
         """
         Constructor
         """
-        MediaPlayer.__init__(self, parent, u'webkit')
+        super(WebkitPlayer, self).__init__(parent, u'webkit')
         self.original_name = u'WebKit'
         self.display_name = u'&WebKit'
         self.parent = parent

=== modified file 'openlp/core/ui/pluginform.py'
--- openlp/core/ui/pluginform.py	2013-06-24 16:54:23 +0000
+++ openlp/core/ui/pluginform.py	2013-08-22 18:47:39 +0000
@@ -48,7 +48,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(PluginForm, self).__init__(parent)
         self.activePlugin = None
         self.programaticChange = False
         self.setupUi(self)

=== modified file 'openlp/core/ui/printserviceform.py'
--- openlp/core/ui/printserviceform.py	2013-03-07 10:25:27 +0000
+++ openlp/core/ui/printserviceform.py	2013-08-22 18:47:39 +0000
@@ -118,7 +118,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(PrintServiceForm, self).__init__(Registry().get('main_window'))
         self.printer = QtGui.QPrinter()
         self.print_dialog = QtGui.QPrintDialog(self.printer, self)
         self.document = QtGui.QTextDocument()
@@ -183,7 +183,7 @@
             self._add_element(
                 u'span', translate('OpenLP.ServiceManager', 'Custom Service Notes: '), div, classId=u'customNotesTitle')
             self._add_element(u'span', cgi.escape(self.footer_text_edit.toPlainText()), div, classId=u'customNotesText')
-        self.document.setHtml(html.tostring(html_data))
+        self.document.setHtml(html.tostring(html_data).decode())
         self.preview_widget.updatePreview()
 
     def _add_preview_item(self, body, item, index):

=== modified file 'openlp/core/ui/serviceitemeditform.py'
--- openlp/core/ui/serviceitemeditform.py	2013-03-05 13:55:50 +0000
+++ openlp/core/ui/serviceitemeditform.py	2013-08-22 18:47:39 +0000
@@ -43,7 +43,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(ServiceItemEditForm, self).__init__(Registry().get(u'main_window'))
         self.setupUi(self)
         self.item_list = []
         self.list_widget.currentRowChanged.connect(self.on_current_row_changed)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2013-07-06 10:27:08 +0000
+++ openlp/core/ui/servicemanager.py	2013-08-22 18:47:39 +0000
@@ -30,7 +30,7 @@
 The service manager sets up, loads, saves and manages services.
 """
 import cgi
-import cPickle
+import pickle
 import logging
 import os
 import shutil
@@ -61,7 +61,7 @@
         """
         Constructor
         """
-        QtGui.QTreeWidget.__init__(self, parent)
+        super(ServiceManagerList, self).__init__(parent)
         self.serviceManager = serviceManager
 
     def keyPressEvent(self, event):
@@ -295,7 +295,7 @@
         """
         Sets up the service manager, toolbars, list view, et al.
         """
-        QtGui.QWidget.__init__(self, parent)
+        super(ServiceManager, self).__init__(parent)
         self.active = build_icon(u':/media/auto-start_active.png')
         self.inactive = build_icon(u':/media/auto-start_inactive.png')
         Registry().register(u'service_manager', self)
@@ -522,11 +522,11 @@
         self.main_window.increment_progress_bar()
         try:
             zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, allow_zip_64)
-            # First we add service contents. We save ALL file_names into ZIP using UTF-8.
-            zip_file.writestr(service_file_name.encode(u'utf-8'), service_content)
+            # First we add service contents..
+            zip_file.writestr(service_file_name, service_content)
             # Finally add all the listed media files.
             for write_from in write_list:
-                zip_file.write(write_from, write_from.encode(u'utf-8'))
+                zip_file.write(write_from, write_from)
             for audio_from, audio_to in audio_files:
                 if audio_from.startswith(u'audio'):
                     # When items are saved, they get new unique_identifier. Let's copy the file to the new location.
@@ -537,7 +537,7 @@
                 check_directory_exists(save_path)
                 if not os.path.exists(save_file):
                     shutil.copy(audio_from, save_file)
-                zip_file.write(audio_from, audio_to.encode(u'utf-8'))
+                zip_file.write(audio_from, audio_to)
         except IOError:
             log.exception(u'Failed to save service to disk: %s', temp_file_name)
             self.main_window.error_message(translate(u'OpenLP.ServiceManager', u'Error Saving File'),
@@ -594,7 +594,7 @@
             zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED,
                 True)
             # First we add service contents.
-            zip_file.writestr(service_file_name.encode(u'utf-8'), service_content)
+            zip_file.writestr(service_file_name, service_content)
         except IOError:
             log.exception(u'Failed to save service to disk: %s', temp_file_name)
             self.main_window.error_message(translate(u'OpenLP.ServiceManager', u'Error Saving File'),
@@ -686,14 +686,13 @@
             zip_file = zipfile.ZipFile(file_name)
             for zip_info in zip_file.infolist():
                 try:
-                    ucsfile = zip_info.filename.decode(u'utf-8')
+                    ucs_file = zip_info.filename
                 except UnicodeDecodeError:
-                    log.exception(u'file_name "%s" is not valid UTF-8' %
-                        zip_info.file_name.decode(u'utf-8', u'replace'))
+                    log.exception(u'file_name "%s" is not valid UTF-8' % zip_info.file_name)
                     critical_error_message_box(message=translate('OpenLP.ServiceManager',
                         'File is not a valid service.\n The content encoding is not UTF-8.'))
                     continue
-                osfile = ucsfile.replace(u'/', os.path.sep)
+                osfile = ucs_file.replace(u'/', os.path.sep)
                 if not osfile.startswith(u'audio'):
                     osfile = os.path.split(osfile)[1]
                 log.debug(u'Extract file: %s', osfile)

=== modified file 'openlp/core/ui/servicenoteform.py'
--- openlp/core/ui/servicenoteform.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/servicenoteform.py	2013-08-22 18:47:39 +0000
@@ -43,7 +43,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(ServiceNoteForm, self).__init__(Registry().get(u'main_window'))
         self.setupUi()
         self.retranslateUi()
 

=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py	2013-03-29 07:48:55 +0000
+++ openlp/core/ui/settingsform.py	2013-08-22 18:47:39 +0000
@@ -51,7 +51,7 @@
         """
         Registry().register(u'settings_form', self)
         Registry().register_function(u'bootstrap_post_set_up', self.post_set_up)
-        QtGui.QDialog.__init__(self, parent)
+        super(SettingsForm, self).__init__(parent)
         self.processes = []
         self.setupUi(self)
 

=== modified file 'openlp/core/ui/shortcutlistdialog.py'
--- openlp/core/ui/shortcutlistdialog.py	2013-03-07 08:05:43 +0000
+++ openlp/core/ui/shortcutlistdialog.py	2013-08-22 18:47:39 +0000
@@ -43,7 +43,7 @@
         """
         Constructor
         """
-        QtGui.QPushButton.__init__(self, *args)
+        super(CaptureShortcutButton, self).__init__(*args)
         self.setCheckable(True)
 
     def keyPressEvent(self, event):

=== modified file 'openlp/core/ui/shortcutlistform.py'
--- openlp/core/ui/shortcutlistform.py	2013-04-28 18:22:36 +0000
+++ openlp/core/ui/shortcutlistform.py	2013-08-22 18:47:39 +0000
@@ -52,7 +52,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(ShortcutListForm, self).__init__(parent)
         self.setupUi(self)
         self.changedActions = {}
         self.action_list = ActionList.get_instance()

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2013-07-05 18:39:31 +0000
+++ openlp/core/ui/slidecontroller.py	2013-08-22 18:47:39 +0000
@@ -65,7 +65,7 @@
         """
         Set up the general Controller.
         """
-        QtGui.QWidget.__init__(self, parent)
+        super(DisplayController, self).__init__(parent)
         self.is_live = is_live
         self.display = None
         self.controller_type = DisplayControllerType.Plugin
@@ -90,7 +90,7 @@
         """
         Set up the Slide Controller.
         """
-        DisplayController.__init__(self, parent, is_live)
+        super(SlideController, self).__init__(parent, is_live)
         Registry().register_function(u'bootstrap_post_set_up', self.screen_size_changed)
         self.screens = ScreenList()
         try:

=== modified file 'openlp/core/ui/splashscreen.py'
--- openlp/core/ui/splashscreen.py	2013-02-04 21:22:12 +0000
+++ openlp/core/ui/splashscreen.py	2013-08-22 18:47:39 +0000
@@ -41,7 +41,7 @@
         """
         Constructor
         """
-        QtGui.QSplashScreen.__init__(self)
+        super(SplashScreen, self).__init__()
         self.setupUi()
 
     def setupUi(self):

=== modified file 'openlp/core/ui/starttimeform.py'
--- openlp/core/ui/starttimeform.py	2013-03-01 09:20:26 +0000
+++ openlp/core/ui/starttimeform.py	2013-08-22 18:47:39 +0000
@@ -45,7 +45,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, self.main_window)
+        super(StartTimeForm, self).__init__(Registry().get(u'main_window'))
         self.setupUi(self)
 
     def exec_(self):

=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py	2013-07-26 20:17:51 +0000
+++ openlp/core/ui/themeform.py	2013-08-22 18:47:39 +0000
@@ -58,7 +58,7 @@
         ``parent``
             The QWidget-derived parent of the wizard.
         """
-        QtGui.QWizard.__init__(self, parent)
+        super(ThemeForm, self).__init__(parent)
         self.setupUi(self)
         self.registerFields()
         self.updateThemeAllowed = True

=== modified file 'openlp/core/ui/themelayoutform.py'
--- openlp/core/ui/themelayoutform.py	2013-02-01 21:34:23 +0000
+++ openlp/core/ui/themelayoutform.py	2013-08-22 18:47:39 +0000
@@ -42,7 +42,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(ThemeLayoutForm, self).__init__(parent)
         self.setupUi(self)
 
     def exec_(self, image):

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2013-06-24 16:54:23 +0000
+++ openlp/core/ui/thememanager.py	2013-08-22 18:47:39 +0000
@@ -57,7 +57,7 @@
         """
         Constructor
         """
-        QtGui.QWidget.__init__(self, parent)
+        super(ThemeManager, self).__init__(parent)
         Registry().register(u'theme_manager', self)
         Registry().register_function(u'bootstrap_initialise', self.load_first_time_themes)
         Registry().register_function(u'bootstrap_post_set_up', self._push_themes)
@@ -514,23 +514,17 @@
                 else:
                     abort_import = False
                 for name in theme_zip.namelist():
-                    try:
-                        uname = unicode(name, u'utf-8')
-                    except UnicodeDecodeError:
-                        log.exception(u'Theme file contains non utf-8 filename "%s"' %
-                            name.decode(u'utf-8', u'replace'))
-                        raise Exception(u'validation')
-                    uname = uname.replace(u'/', os.path.sep)
-                    split_name = uname.split(os.path.sep)
+                    name = name.replace(u'/', os.path.sep)
+                    split_name = name.split(os.path.sep)
                     if split_name[-1] == u'' or len(split_name) == 1:
                         # is directory or preview file
                         continue
-                    full_name = os.path.join(directory, uname)
+                    full_name = os.path.join(directory, name)
                     check_directory_exists(os.path.dirname(full_name))
-                    if os.path.splitext(uname)[1].lower() == u'.xml':
+                    if os.path.splitext(name)[1].lower() == u'.xml':
                         file_xml = unicode(theme_zip.read(name), u'utf-8')
                         out_file = open(full_name, u'w')
-                        out_file.write(file_xml.encode(u'utf-8'))
+                        out_file.write(file_xml)
                     else:
                         out_file = open(full_name, u'wb')
                         out_file.write(theme_zip.read(name))
@@ -637,7 +631,7 @@
         out_file = None
         try:
             out_file = open(theme_file, u'w')
-            out_file.write(theme_pretty_xml)
+            out_file.write(theme_pretty_xml.decode('UTF-8'))
         except IOError:
             log.exception(u'Saving theme to file failed')
         finally:

=== modified file 'openlp/core/ui/themestab.py'
--- openlp/core/ui/themestab.py	2013-04-24 19:05:34 +0000
+++ openlp/core/ui/themestab.py	2013-08-22 18:47:39 +0000
@@ -48,14 +48,14 @@
         """
         self.icon_path = u':/themes/theme_new.png'
         theme_translated = translate('OpenLP.ThemesTab', 'Themes')
-        SettingsTab.__init__(self, parent, u'Themes', theme_translated)
+        super(ThemesTab, self).__init__(parent, u'Themes', theme_translated)
 
     def setupUi(self):
         """
         Set up the UI
         """
         self.setObjectName(u'ThemesTab')
-        SettingsTab.setupUi(self)
+        super(ThemesTab, self).setupUi()
         self.global_group_box = QtGui.QGroupBox(self.left_column)
         self.global_group_box.setObjectName(u'global_group_box')
         self.global_group_box_layout = QtGui.QVBoxLayout(self.global_group_box)

=== modified file 'openlp/core/ui/wizard.py'
--- openlp/core/ui/wizard.py	2013-06-24 16:54:23 +0000
+++ openlp/core/ui/wizard.py	2013-08-22 18:47:39 +0000
@@ -96,7 +96,7 @@
         """
         Constructor
         """
-        QtGui.QWizard.__init__(self, parent)
+        super(OpenLPWizard, self).__init__(parent)
         self.plugin = plugin
         self.with_progress_page = add_progress_page
         self.setObjectName(name)

=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py	2013-07-13 16:33:32 +0000
+++ openlp/core/utils/__init__.py	2013-08-22 18:47:39 +0000
@@ -38,7 +38,6 @@
 from subprocess import Popen, PIPE
 import sys
 import urllib2
-import icu
 
 from PyQt4 import QtGui, QtCore
 
@@ -107,6 +106,7 @@
         # Get the revision of this tree.
         bzr = Popen((u'bzr', u'revno'), stdout=PIPE)
         tree_revision, error = bzr.communicate()
+        tree_revision = tree_revision.decode()
         code = bzr.wait()
         if code != 0:
             raise Exception(u'Error running bzr log')
@@ -117,7 +117,7 @@
         code = bzr.wait()
         if code != 0:
             raise Exception(u'Error running bzr tags')
-        tags = output.splitlines()
+        tags = map(bytes.decode, output.splitlines())
         if not tags:
             tag_version = u'0.0.0'
             tag_revision = u'0'
@@ -196,7 +196,7 @@
         req.add_header(u'User-Agent', u'OpenLP/%s' % current_version[u'full'])
         remote_version = None
         try:
-            remote_version = unicode(urllib2.urlopen(req, None).read()).strip()
+            remote_version = unicode(urllib2.urlopen(req, None).read().decode()).strip()
         except IOError:
             log.exception(u'Failed to download the latest OpenLP version file')
         if remote_version:
@@ -239,7 +239,7 @@
     global IMAGES_FILTER
     if not IMAGES_FILTER:
         log.debug(u'Generating images filter.')
-        formats = map(unicode, QtGui.QImageReader.supportedImageFormats())
+        formats = list(map(bytes.decode, map(bytes, QtGui.QImageReader.supportedImageFormats())))
         visible_formats = u'(*.%s)' % u'; *.'.join(formats)
         actual_formats = u'(*.%s)' % u' *.'.join(formats)
         IMAGES_FILTER = u'%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats)
@@ -393,16 +393,22 @@
 def get_locale_key(string):
     """
     Creates a key for case insensitive, locale aware string sorting.
+
+    ``string``
+        The corresponding string.
     """
     string = string.lower()
     # For Python 3 on platforms other than Windows ICU is not necessary. In those cases locale.strxfrm(str) can be used.
-    global ICU_COLLATOR
-    if ICU_COLLATOR is None:
-        from languagemanager import LanguageManager
-        locale = LanguageManager.get_language()
-        icu_locale = icu.Locale(locale)
-        ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
-    return ICU_COLLATOR.getSortKey(string)
+    if os.name == 'nt':
+        global ICU_COLLATOR
+        if ICU_COLLATOR is None:
+            import icu
+            from languagemanager import LanguageManager
+            language = LanguageManager.get_language()
+            icu_locale = icu.Locale(language)
+            ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
+        return ICU_COLLATOR.getSortKey(string)
+    return locale.strxfrm(string).encode()
 
 
 def get_natural_key(string):
@@ -412,9 +418,10 @@
     """
     key = DIGITS_OR_NONDIGITS.findall(string)
     key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
-    # Python 3 does not support comparision of different types anymore. So make sure, that we do not compare str and int.
-    #if string[0].isdigit():
-    #    return [''] + key
+    # Python 3 does not support comparision of different types anymore. So make sure, that we do not compare str
+    # and int.
+    if string[0].isdigit():
+        return [b''] + key
     return key
 
 

=== modified file 'openlp/core/utils/actions.py'
--- openlp/core/utils/actions.py	2013-03-07 11:20:57 +0000
+++ openlp/core/utils/actions.py	2013-08-22 18:47:39 +0000
@@ -103,12 +103,6 @@
             self.index += 1
             return self.actions[self.index - 1][1]
 
-    def next(self):
-        """
-        Python 2 "next" method.
-        """
-        return self.__next__()
-
     def has_key(self, key):
         """
         Implement the has_key() method to make this class a dictionary type
@@ -167,12 +161,6 @@
                 return category
         raise KeyError(u'Category "%s" does not exist.' % key)
 
-    def __contains__(self, item):
-        """
-        Implement the __contains__() method to make this class like a dictionary
-        """
-        return self.has_key(item)
-
     def __len__(self):
         """
         Implement the __len__() method to make this class like a dictionary
@@ -196,12 +184,6 @@
             self.index += 1
             return self.categories[self.index - 1]
 
-    def next(self):
-        """
-        Python 2 "next" method for iterator.
-        """
-        return self.__next__()
-
     def has_key(self, key):
         """
         Implement the has_key() method to make this class like a dictionary

=== modified file 'openlp/core/utils/applocation.py'
--- openlp/core/utils/applocation.py	2013-07-06 19:21:21 +0000
+++ openlp/core/utils/applocation.py	2013-08-22 18:47:39 +0000
@@ -143,20 +143,19 @@
     """
     Return a path based on which OS and environment we are running in.
     """
-    encoding = sys.getfilesystemencoding()
     if sys.platform == u'win32':
         if dir_type == AppLocation.DataDir:
-            return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), u'openlp', u'data')
+            return os.path.join(unicode(os.getenv(u'APPDATA')), u'openlp', u'data')
         elif dir_type == AppLocation.LanguageDir:
             return os.path.split(openlp.__file__)[0]
-        return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), u'openlp')
+        return os.path.join(unicode(os.getenv(u'APPDATA')), u'openlp')
     elif sys.platform == u'darwin':
         if dir_type == AppLocation.DataDir:
-            return os.path.join(unicode(os.getenv(u'HOME'), encoding),
+            return os.path.join(unicode(os.getenv(u'HOME')),
                                 u'Library', u'Application Support', u'openlp', u'Data')
         elif dir_type == AppLocation.LanguageDir:
             return os.path.split(openlp.__file__)[0]
-        return os.path.join(unicode(os.getenv(u'HOME'), encoding), u'Library', u'Application Support', u'openlp')
+        return os.path.join(unicode(os.getenv(u'HOME')), u'Library', u'Application Support', u'openlp')
     else:
         if dir_type == AppLocation.LanguageDir:
             for prefix in [u'/usr/local', u'/usr']:
@@ -166,10 +165,10 @@
             return os.path.join(u'/usr', u'share', u'openlp')
         if XDG_BASE_AVAILABLE:
             if dir_type == AppLocation.DataDir:
-                return os.path.join(unicode(BaseDirectory.xdg_data_home, encoding), u'openlp')
+                return os.path.join(unicode(BaseDirectory.xdg_data_home), u'openlp')
             elif dir_type == AppLocation.CacheDir:
-                return os.path.join(unicode(BaseDirectory.xdg_cache_home, encoding), u'openlp')
+                return os.path.join(unicode(BaseDirectory.xdg_cache_home), u'openlp')
         if dir_type == AppLocation.DataDir:
-            return os.path.join(unicode(os.getenv(u'HOME'), encoding), u'.openlp', u'data')
-        return os.path.join(unicode(os.getenv(u'HOME'), encoding), u'.openlp')
+            return os.path.join(unicode(os.getenv(u'HOME')), u'.openlp', u'data')
+        return os.path.join(unicode(os.getenv(u'HOME')), u'.openlp')
 

=== modified file 'openlp/plugins/alerts/alertsplugin.py'
--- openlp/plugins/alerts/alertsplugin.py	2013-04-18 17:17:00 +0000
+++ openlp/plugins/alerts/alertsplugin.py	2013-08-22 18:47:39 +0000
@@ -129,7 +129,7 @@
     log.info(u'Alerts Plugin loaded')
 
     def __init__(self):
-        Plugin.__init__(self, u'alerts', __default_settings__, settings_tab_class=AlertsTab)
+        super(AlertsPlugin, self).__init__(u'alerts', __default_settings__, settings_tab_class=AlertsTab)
         self.weight = -3
         self.icon_path = u':/plugins/plugin_alerts.png'
         self.icon = build_icon(self.icon_path)
@@ -153,7 +153,7 @@
 
     def initialise(self):
         log.info(u'Alerts Initialising')
-        Plugin.initialise(self)
+        super(AlertsPlugin, self).initialise()
         self.tools_alert_item.setVisible(True)
         action_list = ActionList.get_instance()
         action_list.add_action(self.tools_alert_item, UiStrings().Tools)
@@ -164,7 +164,7 @@
         """
         log.info(u'Alerts Finalising')
         self.manager.finalise()
-        Plugin.finalise(self)
+        super(AlertsPlugin, self).finalise()
         self.tools_alert_item.setVisible(False)
         action_list = ActionList.get_instance()
         action_list.remove_action(self.tools_alert_item, u'Tools')

=== modified file 'openlp/plugins/alerts/forms/__init__.py'
--- openlp/plugins/alerts/forms/__init__.py	2013-04-18 17:17:00 +0000
+++ openlp/plugins/alerts/forms/__init__.py	2013-08-22 18:47:39 +0000
@@ -41,7 +41,7 @@
     class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
 
         def __init__(self, parent=None):
-            QtGui.QDialog.__init__(self, parent)
+            super(AuthorsForm, self).__init__(parent)
             self.setupUi(self)
 
 This allows OpenLP to use ``self.object`` for all the GUI elements while keeping them separate from the functionality,

=== modified file 'openlp/plugins/alerts/forms/alertform.py'
--- openlp/plugins/alerts/forms/alertform.py	2013-04-18 17:17:00 +0000
+++ openlp/plugins/alerts/forms/alertform.py	2013-08-22 18:47:39 +0000
@@ -46,6 +46,7 @@
         self.manager = plugin.manager
         self.plugin = plugin
         self.item_id = None
+        # TODO: Use Registry()
         super(AlertForm, self).__init__(self.plugin.main_window)
         self.setupUi(self)
         self.display_button.clicked.connect(self.on_display_clicked)

=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
--- openlp/plugins/alerts/lib/alertsmanager.py	2013-04-20 20:34:46 +0000
+++ openlp/plugins/alerts/lib/alertsmanager.py	2013-08-22 18:47:39 +0000
@@ -48,7 +48,7 @@
     log.info(u'Alert Manager loaded')
 
     def __init__(self, parent):
-        QtCore.QObject.__init__(self, parent)
+        super(AlertsManager, self).__init__(parent)
         Registry().register(u'alerts_manager', self)
         self.timer_id = 0
         self.alert_list = []

=== modified file 'openlp/plugins/alerts/lib/alertstab.py'
--- openlp/plugins/alerts/lib/alertstab.py	2013-03-16 20:52:59 +0000
+++ openlp/plugins/alerts/lib/alertstab.py	2013-08-22 18:47:39 +0000
@@ -38,11 +38,11 @@
     AlertsTab is the alerts settings tab in the settings dialog.
     """
     def __init__(self, parent, name, visible_title, icon_path):
-        SettingsTab.__init__(self, parent, name, visible_title, icon_path)
+        super(AlertsTab, self).__init__(parent, name, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'AlertsTab')
-        SettingsTab.setupUi(self)
+        super(AlertsTab, self).setupUi()
         self.font_group_box = QtGui.QGroupBox(self.left_column)
         self.font_group_box.setObjectName(u'font_group_box')
         self.font_layout = QtGui.QFormLayout(self.font_group_box)

=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py	2013-04-18 17:45:14 +0000
+++ openlp/plugins/bibles/bibleplugin.py	2013-08-22 18:47:39 +0000
@@ -69,7 +69,7 @@
     log.info(u'Bible Plugin loaded')
 
     def __init__(self):
-        Plugin.__init__(self, u'bibles', __default_settings__, BibleMediaItem, BiblesTab)
+        super(BiblePlugin, self).__init__(u'bibles', __default_settings__, BibleMediaItem, BiblesTab)
         self.weight = -9
         self.icon_path = u':/plugins/plugin_bibles.png'
         self.icon = build_icon(self.icon_path)

=== modified file 'openlp/plugins/bibles/forms/__init__.py'
--- openlp/plugins/bibles/forms/__init__.py	2013-04-18 17:45:14 +0000
+++ openlp/plugins/bibles/forms/__init__.py	2013-08-22 18:47:39 +0000
@@ -42,7 +42,7 @@
     class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
 
         def __init__(self, parent, manager, bible_plugin):
-            QtGui.QWizard.__init__(self, parent)
+            super(BibleImportForm, self).__init__(parent)
             self.setupUi(self)
 
 This allows OpenLP to use ``self.object`` for all the GUI elements while keeping them separate from the functionality,

=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
--- openlp/plugins/bibles/forms/bibleimportform.py	2013-04-25 17:58:37 +0000
+++ openlp/plugins/bibles/forms/bibleimportform.py	2013-08-22 18:47:39 +0000
@@ -78,13 +78,14 @@
         """
         self.manager = manager
         self.web_bible_list = {}
-        OpenLPWizard.__init__(self, parent, bible_plugin, u'bibleImportWizard', u':/wizards/wizard_importbible.bmp')
+        super(BibleImportForm, self).__init__(
+            parent, bible_plugin, u'bibleImportWizard', u':/wizards/wizard_importbible.bmp')
 
     def setupUi(self, image):
         """
         Set up the UI for the bible wizard.
         """
-        OpenLPWizard.setupUi(self, image)
+        super(BibleImportForm, self).setupUi(image)
         self.formatComboBox.currentIndexChanged.connect(self.onCurrentIndexChanged)
 
     def onCurrentIndexChanged(self, index):
@@ -515,7 +516,7 @@
         """
         Prepare the UI for the import.
         """
-        OpenLPWizard.pre_wizard(self)
+        super(BibleImportForm, self).pre_wizard()
         bible_type = self.field(u'source_format')
         if bible_type == BibleFormat.WebDownload:
             self.progress_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Registering Bible...'))

=== modified file 'openlp/plugins/bibles/forms/bibleupgradeform.py'
--- openlp/plugins/bibles/forms/bibleupgradeform.py	2013-04-25 17:58:37 +0000
+++ openlp/plugins/bibles/forms/bibleupgradeform.py	2013-08-22 18:47:39 +0000
@@ -39,7 +39,7 @@
 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
+from openlp.core.utils import AppLocation, delete_file
 from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB
 from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract
 
@@ -71,17 +71,18 @@
         self.suffix = u'.sqlite'
         self.settings_section = u'bibles'
         self.path = AppLocation.get_section_data_path(self.settings_section)
-        self.temp_dir = os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp')
+        self.temp_dir = os.path.join(gettempdir(), u'openlp')
         self.files = self.manager.old_bible_databases
         self.success = {}
         self.new_bibles = {}
-        OpenLPWizard.__init__(self, parent, bible_plugin, u'bibleUpgradeWizard', u':/wizards/wizard_importbible.bmp')
+        super(BibleUpgradeForm, self).__init__(
+            parent, bible_plugin, u'bibleUpgradeWizard', u':/wizards/wizard_importbible.bmp')
 
     def setupUi(self, image):
         """
         Set up the UI for the bible wizard.
         """
-        OpenLPWizard.setupUi(self, image)
+        super(BibleUpgradeForm, self).setupUi(image)
         Registry().execute(u'openlp_stop_wizard', self.stop_import)
 
     def stop_import(self):
@@ -333,7 +334,7 @@
         """
         Prepare the UI for the upgrade.
         """
-        OpenLPWizard.pre_wizard(self)
+        super(BibleUpgradeForm, self).pre_wizard()
         self.progress_label.setText(translate('BiblesPlugin.UpgradeWizardForm', 'Starting upgrade...'))
         self.application.process_events()
 
@@ -559,4 +560,4 @@
             self.progress_label.setText(translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade failed.'))
         # Remove temp directory.
         shutil.rmtree(self.temp_dir, True)
-        OpenLPWizard.post_wizard(self)
+        super(BibleUpgradeForm, self).post_wizard()

=== modified file 'openlp/plugins/bibles/forms/booknameform.py'
--- openlp/plugins/bibles/forms/booknameform.py	2013-04-18 17:45:14 +0000
+++ openlp/plugins/bibles/forms/booknameform.py	2013-08-22 18:47:39 +0000
@@ -56,7 +56,7 @@
         """
         Constructor
         """
-        QDialog.__init__(self, parent)
+        super(BookNameForm, self).__init__(parent)
         self.setupUi(self)
         self.custom_signals()
         self.book_names = BibleStrings().BookNames

=== modified file 'openlp/plugins/bibles/forms/editbibleform.py'
--- openlp/plugins/bibles/forms/editbibleform.py	2013-06-24 16:54:23 +0000
+++ openlp/plugins/bibles/forms/editbibleform.py	2013-08-22 18:47:39 +0000
@@ -51,7 +51,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(EditBibleForm, self).__init__(parent)
         self.media_item = media_item
         self.book_names = BibleStrings().BookNames
         self.setupUi(self)

=== modified file 'openlp/plugins/bibles/forms/languageform.py'
--- openlp/plugins/bibles/forms/languageform.py	2013-07-18 19:28:35 +0000
+++ openlp/plugins/bibles/forms/languageform.py	2013-08-22 18:47:39 +0000
@@ -54,7 +54,7 @@
         """
         Constructor
         """
-        QDialog.__init__(self, parent)
+        super(LanguageForm, self).__init__(parent)
         self.setupUi(self)
 
     def exec_(self, bible_name):

=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
--- openlp/plugins/bibles/lib/biblestab.py	2013-03-25 07:27:54 +0000
+++ openlp/plugins/bibles/lib/biblestab.py	2013-08-22 18:47:39 +0000
@@ -49,11 +49,11 @@
         self.paragraph_style = True
         self.show_new_chapters = False
         self.display_style = 0
-        SettingsTab.__init__(self, parent, title, visible_title, icon_path)
+        super(BiblesTab, self).__init__(parent, title, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'BiblesTab')
-        SettingsTab.setupUi(self)
+        super(BiblesTab, self).setupUi()
         self.verse_display_group_box = QtGui.QGroupBox(self.left_column)
         self.verse_display_group_box.setObjectName(u'verse_display_group_box')
         self.verse_display_layout = QtGui.QFormLayout(self.verse_display_group_box)

=== modified file 'openlp/plugins/custom/customplugin.py'
--- openlp/plugins/custom/customplugin.py	2013-03-19 19:43:22 +0000
+++ openlp/plugins/custom/customplugin.py	2013-08-22 18:47:39 +0000
@@ -61,7 +61,7 @@
     log.info(u'Custom Plugin loaded')
 
     def __init__(self):
-        Plugin.__init__(self, u'custom', __default_settings__, CustomMediaItem, CustomTab)
+        super(CustomPlugin, self).__init__(u'custom', __default_settings__, CustomMediaItem, CustomTab)
         self.weight = -5
         self.manager = Manager(u'custom', init_schema)
         self.icon_path = u':/plugins/plugin_custom.png'

=== modified file 'openlp/plugins/custom/lib/customtab.py'
--- openlp/plugins/custom/lib/customtab.py	2013-03-17 09:21:18 +0000
+++ openlp/plugins/custom/lib/customtab.py	2013-08-22 18:47:39 +0000
@@ -41,11 +41,11 @@
     CustomTab is the Custom settings tab in the settings dialog.
     """
     def __init__(self, parent, title, visible_title, icon_path):
-        SettingsTab.__init__(self, parent, title, visible_title, icon_path)
+        super(CustomTab, self).__init__(parent, title, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'CustomTab')
-        SettingsTab.setupUi(self)
+        super(CustomTab, self).setupUi()
         self.custom_mode_group_box = QtGui.QGroupBox(self.left_column)
         self.custom_mode_group_box.setObjectName(u'custom_mode_group_box')
         self.custom_mode_layout = QtGui.QFormLayout(self.custom_mode_group_box)
@@ -97,4 +97,4 @@
         settings.endGroup()
         if self.tab_visited:
             self.settings_form.register_post_process(u'custom_config_updated')
-        self.tab_visited = False
\ No newline at end of file
+        self.tab_visited = False

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2013-05-19 07:35:07 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2013-08-22 18:47:39 +0000
@@ -57,7 +57,7 @@
 
     def __init__(self, parent, plugin):
         self.icon_path = u'custom/custom'
-        MediaManagerItem.__init__(self, parent, plugin)
+        super(CustomMediaItem, self).__init__(parent, plugin)
         self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager)
         self.single_service_item = False
         self.quick_preview_allowed = True

=== modified file 'openlp/plugins/images/forms/__init__.py'
--- openlp/plugins/images/forms/__init__.py	2013-04-19 19:03:16 +0000
+++ openlp/plugins/images/forms/__init__.py	2013-08-22 18:47:39 +0000
@@ -41,7 +41,7 @@
     class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
 
         def __init__(self, parent=None):
-            QtGui.QDialog.__init__(self, parent)
+            super(AuthorsForm, self).__init__(parent)
             self.setupUi(self)
 
 This allows OpenLP to use ``self.object`` for all the GUI elements while keeping them separate from the functionality,

=== modified file 'openlp/plugins/images/forms/addgroupform.py'
--- openlp/plugins/images/forms/addgroupform.py	2013-04-19 19:43:17 +0000
+++ openlp/plugins/images/forms/addgroupform.py	2013-08-22 18:47:39 +0000
@@ -42,7 +42,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(AddGroupForm, self).__init__(parent)
         self.setupUi(self)
 
     def exec_(self, clear=True, show_top_level_group=False, selected_group=None):

=== modified file 'openlp/plugins/images/forms/choosegroupform.py'
--- openlp/plugins/images/forms/choosegroupform.py	2013-05-14 14:57:37 +0000
+++ openlp/plugins/images/forms/choosegroupform.py	2013-08-22 18:47:39 +0000
@@ -40,7 +40,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(ChooseGroupForm, self).__init__(parent)
         self.setupUi(self)
 
     def exec_(self, selected_group=None):

=== modified file 'openlp/plugins/images/imageplugin.py'
--- openlp/plugins/images/imageplugin.py	2013-04-19 19:03:16 +0000
+++ openlp/plugins/images/imageplugin.py	2013-08-22 18:47:39 +0000
@@ -48,7 +48,7 @@
     log.info(u'Image Plugin loaded')
 
     def __init__(self):
-        Plugin.__init__(self, u'images', __default_settings__, ImageMediaItem, ImageTab)
+        super(ImagePlugin, self).__init__(u'images', __default_settings__, ImageMediaItem, ImageTab)
         self.manager = Manager(u'images', init_schema)
         self.weight = -7
         self.icon_path = u':/plugins/plugin_images.png'

=== modified file 'openlp/plugins/images/lib/imagetab.py'
--- openlp/plugins/images/lib/imagetab.py	2013-03-26 09:47:05 +0000
+++ openlp/plugins/images/lib/imagetab.py	2013-08-22 18:47:39 +0000
@@ -37,11 +37,11 @@
     ImageTab is the images settings tab in the settings dialog.
     """
     def __init__(self, parent, name, visible_title, icon_path):
-        SettingsTab.__init__(self, parent, name, visible_title, icon_path)
+        super(ImageTab, self).__init__(parent, name, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'ImagesTab')
-        SettingsTab.setupUi(self)
+        super(ImageTab, self).setupUi()
         self.background_color_group_box = QtGui.QGroupBox(self.left_column)
         self.background_color_group_box.setObjectName(u'background_color_group_box')
         self.form_layout = QtGui.QFormLayout(self.background_color_group_box)

=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py	2013-06-16 19:42:50 +0000
+++ openlp/plugins/images/lib/mediaitem.py	2013-08-22 18:47:39 +0000
@@ -52,7 +52,7 @@
 
     def __init__(self, parent, plugin):
         self.icon_path = u'images/image'
-        MediaManagerItem.__init__(self, parent, plugin)
+        super(ImageMediaItem, self).__init__(parent, plugin)
         self.quick_preview_allowed = True
         self.has_search = True
         self.manager = plugin.manager

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2013-05-25 05:54:25 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2013-08-22 18:47:39 +0000
@@ -60,7 +60,7 @@
         self.icon_path = u'images/image'
         self.background = False
         self.automatic = u''
-        MediaManagerItem.__init__(self, parent, plugin)
+        super(MediaMediaItem, self).__init__(parent, plugin)
         self.single_service_item = False
         self.has_search = True
         self.media_object = None

=== modified file 'openlp/plugins/media/lib/mediatab.py'
--- openlp/plugins/media/lib/mediatab.py	2013-03-17 09:21:18 +0000
+++ openlp/plugins/media/lib/mediatab.py	2013-08-22 18:47:39 +0000
@@ -46,11 +46,11 @@
     """
     def __init__(self, parent, title, visible_title, icon_path):
         self.parent = parent
-        SettingsTab.__init__(self, parent, title, visible_title, icon_path)
+        super(MediaTab, self).__init__(parent, title, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'MediaTab')
-        SettingsTab.setupUi(self)
+        super(MediaTab, self).setupUi()
         self.advanced_group_box = QtGui.QGroupBox(self.left_column)
         self.advanced_group_box.setObjectName(u'advanced_group_box')
         self.advanced_layout = QtGui.QVBoxLayout(self.advanced_group_box)

=== modified file 'openlp/plugins/media/mediaplugin.py'
--- openlp/plugins/media/mediaplugin.py	2013-04-19 19:15:12 +0000
+++ openlp/plugins/media/mediaplugin.py	2013-08-22 18:47:39 +0000
@@ -49,7 +49,7 @@
     log.info(u'%s MediaPlugin loaded', __name__)
 
     def __init__(self):
-        Plugin.__init__(self, u'media', __default_settings__, MediaMediaItem)
+        super(MediaPlugin, self).__init__(u'media', __default_settings__, MediaMediaItem)
         self.weight = -6
         self.icon_path = u':/plugins/plugin_media.png'
         self.icon = build_icon(self.icon_path)

=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py	2013-04-20 09:02:45 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py	2013-08-22 18:47:39 +0000
@@ -78,7 +78,7 @@
         Initialise the class
         """
         log.debug(u'Initialising')
-        PresentationController.__init__(self, plugin, u'Impress', ImpressDocument)
+        super(ImpressController, self).__init__(plugin, u'Impress', ImpressDocument)
         self.supports = [u'odp']
         self.also_supports = [u'ppt', u'pps', u'pptx', u'ppsx']
         self.process = None
@@ -208,7 +208,7 @@
         Constructor, store information about the file and initialise.
         """
         log.debug(u'Init Presentation OpenOffice')
-        PresentationDocument.__init__(self, controller, presentation)
+        super(ImpressDocument, self).__init__(controller, presentation)
         self.document = None
         self.presentation = None
         self.control = None

=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py	2013-04-19 18:52:39 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py	2013-08-22 18:47:39 +0000
@@ -58,7 +58,7 @@
         Initialise the class
         """
         log.debug(u'Initialising')
-        PresentationController.__init__(self, plugin, u'Powerpoint', PowerpointDocument)
+        super(PowerpointController, self).__init__(plugin, u'Powerpoint', PowerpointDocument)
         self.supports = [u'ppt', u'pps', u'pptx', u'ppsx']
         self.process = None
 
@@ -114,7 +114,7 @@
         Constructor, store information about the file and initialise.
         """
         log.debug(u'Init Presentation Powerpoint')
-        PresentationDocument.__init__(self, controller, presentation)
+        super(PowerpointDocument, self).__init__(controller, presentation)
         self.presentation = None
 
     def load_presentation(self):

=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py	2013-04-19 18:52:39 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py	2013-08-22 18:47:39 +0000
@@ -54,7 +54,7 @@
         """
         log.debug(u'Initialising')
         self.process = None
-        PresentationController.__init__(self, plugin, u'Powerpoint Viewer', PptviewDocument)
+        super(PptviewController, self).__init__(plugin, u'Powerpoint Viewer', PptviewDocument)
         self.supports = [u'ppt', u'pps', u'pptx', u'ppsx']
 
     def check_available(self):
@@ -109,7 +109,7 @@
         Constructor, store information about the file and initialise.
         """
         log.debug(u'Init Presentation PowerPoint')
-        PresentationDocument.__init__(self, controller, presentation)
+        super(PptviewDocument, self).__init__(controller, presentation)
         self.presentation = None
         self.ppt_id = None
         self.blanked = False

=== modified file 'openlp/plugins/presentations/lib/pptviewlib/ppttest.py'
--- openlp/plugins/presentations/lib/pptviewlib/ppttest.py	2013-07-18 19:28:35 +0000
+++ openlp/plugins/presentations/lib/pptviewlib/ppttest.py	2013-08-22 18:47:39 +0000
@@ -37,7 +37,7 @@
     Standalone Test Harness for the pptviewlib library
     """
     def __init__(self, parent=None):
-        QtGui.QWidget.__init__(self, parent)
+        super(PPTViewer, self).__init__(parent)
         self.pptid = -1
         self.setWindowTitle(u'PowerPoint Viewer Test')
 

=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py	2013-04-19 18:52:39 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py	2013-08-22 18:47:39 +0000
@@ -42,7 +42,7 @@
         """
         self.parent = parent
         self.controllers = controllers
-        SettingsTab.__init__(self, parent, title, visible_title, icon_path)
+        super(PresentationTab, self).__init__(parent, title, visible_title, icon_path)
         self.activated = False
 
     def setupUi(self):
@@ -50,7 +50,7 @@
         Create the controls for the settings tab
         """
         self.setObjectName(u'PresentationTab')
-        SettingsTab.setupUi(self)
+        super(PresentationTab, self).setupUi()
         self.controllers_group_box = QtGui.QGroupBox(self.left_column)
         self.controllers_group_box.setObjectName(u'controllers_group_box')
         self.controllers_layout = QtGui.QVBoxLayout(self.controllers_group_box)

=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py	2013-05-24 20:17:47 +0000
+++ openlp/plugins/presentations/presentationplugin.py	2013-08-22 18:47:39 +0000
@@ -82,7 +82,7 @@
         Initialise the plugin. Determine which controllers are enabled are start their processes.
         """
         log.info(u'Presentations Initialising')
-        Plugin.initialise(self)
+        super(PresentationPlugin, self).initialise()
         for controller in self.controllers:
             if self.controllers[controller].enabled():
                 try:
@@ -103,7 +103,7 @@
             controller = self.controllers[key]
             if controller.enabled():
                 controller.kill()
-        Plugin.finalise(self)
+        super(PresentationPlugin, self).finalise()
 
     def create_media_manager_item(self):
         """

=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
--- openlp/plugins/remotes/lib/httpserver.py	2013-07-12 18:13:06 +0000
+++ openlp/plugins/remotes/lib/httpserver.py	2013-08-22 18:47:39 +0000
@@ -127,7 +127,7 @@
 from openlp.core.lib import Registry, Settings, PluginStatus, StringContent, image_to_byte
 from openlp.core.utils import AppLocation, translate
 
-from cherrypy._cpcompat import sha, ntob
+from hashlib import sha1
 
 log = logging.getLogger(__name__)
 
@@ -137,7 +137,7 @@
     Create an encrypted password for the given password.
     """
     log.debug("make_sha_hash")
-    return sha(ntob(password)).hexdigest()
+    return sha1(password.encode()).hexdigest()
 
 
 def fetch_password(username):
@@ -445,7 +445,7 @@
             u'display': self.live_controller.desktop_screen.isChecked()
         }
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': result})
+        return json.dumps({u'results': result}).encode()
 
     def main_poll(self):
         """
@@ -455,7 +455,7 @@
             u'slide_count': self.live_controller.slide_count
         }
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': result})
+        return json.dumps({u'results': result}).encode()
 
     def main_image(self):
         """
@@ -465,7 +465,7 @@
             u'slide_image': u'data:image/png;base64,' + str(image_to_byte(self.live_controller.slide_image))
         }
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': result})
+        return json.dumps({u'results': result}).encode()
 
     def display(self, action):
         """
@@ -477,7 +477,7 @@
         """
         self.live_controller.emit(QtCore.SIGNAL(u'slidecontroller_toggle_display'), action)
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': {u'success': True}})
+        return json.dumps({u'results': {u'success': True}}).encode()
 
     def alert(self):
         """
@@ -495,7 +495,7 @@
         else:
             success = False
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': {u'success': success}})
+        return json.dumps({u'results': {u'success': success}}).encode()
 
     def controller(self, display_type, action):
         """
@@ -543,7 +543,7 @@
                 self.live_controller.emit(QtCore.SIGNAL(event))
             json_data = {u'results': {u'success': True}}
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps(json_data)
+        return json.dumps(json_data).encode()
 
     def service(self, action):
         """
@@ -555,7 +555,7 @@
         event = u'servicemanager_%s' % action
         if action == u'list':
             cherrypy.response.headers['Content-Type'] = u'application/json'
-            return json.dumps({u'results': {u'items': self._get_service_items()}})
+            return json.dumps({u'results': {u'items': self._get_service_items()}}).encode()
         event += u'_item'
         if self.request_data:
             try:
@@ -566,7 +566,7 @@
         else:
             Registry().execute(event)
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': {u'success': True}})
+        return json.dumps({u'results': {u'success': True}}).encode()
 
     def plugin_info(self, action):
         """
@@ -582,7 +582,7 @@
                 if plugin.status == PluginStatus.Active and plugin.media_item and plugin.media_item.has_search:
                     searches.append([plugin.name, unicode(plugin.text_strings[StringContent.Name][u'plural'])])
             cherrypy.response.headers['Content-Type'] = u'application/json'
-            return json.dumps({u'results': {u'items': searches}})
+            return json.dumps({u'results': {u'items': searches}}).encode()
 
     def search(self, plugin_name):
         """
@@ -602,7 +602,7 @@
         else:
             results = []
         cherrypy.response.headers['Content-Type'] = u'application/json'
-        return json.dumps({u'results': {u'items': results}})
+        return json.dumps({u'results': {u'items': results}}).encode()
 
     def go_live(self, plugin_name):
         """
@@ -648,7 +648,7 @@
         Set the HTTP not found return code.
         """
         cherrypy.response.status = 404
-        cherrypy.response.body = ["<html><body>Sorry, an error occurred </body></html>"]
+        cherrypy.response.body = [b'<html><body>Sorry, an error occurred </body></html>']
 
     def _get_service_manager(self):
         """

=== modified file 'openlp/plugins/remotes/lib/remotetab.py'
--- openlp/plugins/remotes/lib/remotetab.py	2013-06-03 18:47:25 +0000
+++ openlp/plugins/remotes/lib/remotetab.py	2013-08-22 18:47:39 +0000
@@ -43,11 +43,11 @@
     RemoteTab is the Remotes settings tab in the settings dialog.
     """
     def __init__(self, parent, title, visible_title, icon_path):
-        SettingsTab.__init__(self, parent, title, visible_title, icon_path)
+        super(RemoteTab, self).__init__(parent, title, visible_title, icon_path)
 
     def setupUi(self):
         self.setObjectName(u'RemoteTab')
-        SettingsTab.setupUi(self)
+        super(RemoteTab, self).setupUi()
         self.server_settings_group_box = QtGui.QGroupBox(self.left_column)
         self.server_settings_group_box.setObjectName(u'server_settings_group_box')
         self.server_settings_layout = QtGui.QFormLayout(self.server_settings_group_box)

=== modified file 'openlp/plugins/remotes/remoteplugin.py'
--- openlp/plugins/remotes/remoteplugin.py	2013-03-30 06:56:28 +0000
+++ openlp/plugins/remotes/remoteplugin.py	2013-08-22 18:47:39 +0000
@@ -55,7 +55,7 @@
         """
         remotes constructor
         """
-        Plugin.__init__(self, u'remotes', __default_settings__, settings_tab_class=RemoteTab)
+        super(RemotesPlugin, self).__init__(u'remotes', __default_settings__, settings_tab_class=RemoteTab)
         self.icon_path = u':/plugins/plugin_remote.png'
         self.icon = build_icon(self.icon_path)
         self.weight = -1
@@ -66,7 +66,7 @@
         Initialise the remotes plugin, and start the http server
         """
         log.debug(u'initialise')
-        Plugin.initialise(self)
+        super(RemotesPlugin, self).initialise()
         self.server = HttpServer()
         self.server.start_server()
 
@@ -75,7 +75,7 @@
         Tidy up and close down the http server
         """
         log.debug(u'finalise')
-        Plugin.finalise(self)
+        super(RemotesPlugin, self).finalise()
         if self.server:
             self.server.close()
             self.server = None

=== modified file 'openlp/plugins/songs/forms/__init__.py'
--- openlp/plugins/songs/forms/__init__.py	2013-04-23 19:17:25 +0000
+++ openlp/plugins/songs/forms/__init__.py	2013-08-22 18:47:39 +0000
@@ -45,7 +45,7 @@
     class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
 
         def __init__(self, parent=None):
-            QtGui.QDialog.__init__(self, parent)
+            super(AuthorsForm, self).__init__(parent)
             self.setupUi(self)
 
 This allows OpenLP to use ``self.object`` for all the GUI elements while keeping

=== modified file 'openlp/plugins/songs/forms/authorsform.py'
--- openlp/plugins/songs/forms/authorsform.py	2013-03-08 08:14:39 +0000
+++ openlp/plugins/songs/forms/authorsform.py	2013-08-22 18:47:39 +0000
@@ -42,7 +42,7 @@
         """
         Set up the screen and common data
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(AuthorsForm, self).__init__(parent)
         self.setupUi(self)
         self.auto_display_name = False
         self.first_name_edit.textEdited.connect(self.on_first_name_edited)

=== modified file 'openlp/plugins/songs/forms/duplicatesongremovalform.py'
--- openlp/plugins/songs/forms/duplicatesongremovalform.py	2013-06-24 16:54:23 +0000
+++ openlp/plugins/songs/forms/duplicatesongremovalform.py	2013-08-22 18:47:39 +0000
@@ -67,8 +67,8 @@
         self.review_total_count = 0
         # Used to interrupt ongoing searches when cancel is clicked.
         self.break_search = False
-        OpenLPWizard.__init__(self, self.main_window, plugin, u'duplicateSongRemovalWizard',
-            u':/wizards/wizard_duplicateremoval.bmp', False)
+        super(DuplicateSongRemovalForm, self).__init__(Registry().get('main_window'),
+            plugin, u'duplicateSongRemovalWizard', u':/wizards/wizard_duplicateremoval.bmp', False)
         self.setMinimumWidth(730)
 
     def custom_signals(self):
@@ -269,7 +269,7 @@
             else:
                 self.proceed_to_next_review()
                 return False
-        return OpenLPWizard.validateCurrentPage(self)
+        return super(DuplicateSongRemovalForm, self).validateCurrentPage()
 
     def remove_button_clicked(self, song_review_widget):
         """
@@ -312,7 +312,7 @@
                 self.review_scroll_area_layout.removeItem(item)
         # Process next set of duplicates.
         self.process_current_duplicate_entry()
-    
+
     def process_current_duplicate_entry(self):
         """
         Update the review counter in the wizard header, add song widgets for
@@ -359,4 +359,5 @@
                 self._application = Registry().get(u'application')
             return self._application
 
-    application = property(_get_application)
\ No newline at end of file
+    application = property(_get_application)
+

=== modified file 'openlp/plugins/songs/forms/editsongdialog.py'
--- openlp/plugins/songs/forms/editsongdialog.py	2013-06-16 17:28:44 +0000
+++ openlp/plugins/songs/forms/editsongdialog.py	2013-08-22 18:47:39 +0000
@@ -355,7 +355,7 @@
         """
         Constructor
         """
-        QtGui.QTableWidget.__init__(self, parent)
+        super(SingleColumnTableWidget, self).__init__(parent)
         self.horizontalHeader().setVisible(False)
         self.setColumnCount(1)
 

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2013-07-22 20:27:51 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2013-08-22 18:47:39 +0000
@@ -387,9 +387,6 @@
         # lazy xml migration for now
         self.verse_list_widget.clear()
         self.verse_list_widget.setRowCount(0)
-        # This is just because occasionally the lyrics come back as a "buffer"
-        if isinstance(self.song.lyrics, buffer):
-            self.song.lyrics = unicode(self.song.lyrics)
         verse_tags_translated = False
         if self.song.lyrics.startswith(u'<?xml version='):
             songXML = SongXML()

=== modified file 'openlp/plugins/songs/forms/editverseform.py'
--- openlp/plugins/songs/forms/editverseform.py	2013-03-14 22:22:18 +0000
+++ openlp/plugins/songs/forms/editverseform.py	2013-08-22 18:47:39 +0000
@@ -48,7 +48,7 @@
         """
         Constructor
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(EditVerseForm, self).__init__(parent)
         self.setupUi(self)
         self.verse_text_edit.customContextMenuRequested.connect(self.context_menu)
         self.insert_button.clicked.connect(self.on_insert_button_clicked)

=== modified file 'openlp/plugins/songs/forms/mediafilesform.py'
--- openlp/plugins/songs/forms/mediafilesform.py	2013-03-14 22:22:18 +0000
+++ openlp/plugins/songs/forms/mediafilesform.py	2013-08-22 18:47:39 +0000
@@ -44,7 +44,7 @@
     log.info(u'%s MediaFilesForm loaded', __name__)
 
     def __init__(self, parent):
-        QtGui.QDialog.__init__(self)
+        super(MediaFilesForm, self).__init__()
         self.setupUi(self)
 
     def populateFiles(self, files):

=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py	2013-04-25 17:58:37 +0000
+++ openlp/plugins/songs/forms/songexportform.py	2013-08-22 18:47:39 +0000
@@ -60,7 +60,7 @@
         ``plugin``
             The songs plugin.
         """
-        OpenLPWizard.__init__(self, parent, plugin, u'song_export_wizard', u':/wizards/wizard_exportsong.bmp')
+        super(SongExportForm, self).__init__(parent, plugin, u'song_export_wizard', u':/wizards/wizard_exportsong.bmp')
         self.stop_export_flag = False
         Registry().register_function(u'openlp_stop_wizard', self.stop_export)
 
@@ -75,7 +75,7 @@
         """
         Set up the song wizard UI.
         """
-        OpenLPWizard.setupUi(self, image)
+        super(SongExportForm, self).setupUi(image)
 
     def custom_signals(self):
         """
@@ -239,7 +239,7 @@
         """
         Perform pre export tasks.
         """
-        OpenLPWizard.pre_wizard(self)
+        super(SongExportForm, self).pre_wizard()
         self.progress_label.setText(translate('SongsPlugin.ExportWizardForm', 'Starting export...'))
         self.application.process_events()
 

=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2013-06-27 08:30:34 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2013-08-22 18:47:39 +0000
@@ -60,15 +60,15 @@
         ``plugin``
             The songs plugin.
         """
+        super(SongImportForm, self).__init__(parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp')
         self.clipboard = self.main_window.clipboard
-        OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp')
 
     def setupUi(self, image):
         """
         Set up the song wizard UI.
         """
         self.format_widgets = dict([(song_format, {}) for song_format in SongFormat.get_format_list()])
-        OpenLPWizard.setupUi(self, image)
+        super(SongImportForm, self).setupUi(image)
         self.current_format = SongFormat.OpenLyrics
         self.format_stack.setCurrentIndex(self.current_format)
         self.format_combo_box.currentIndexChanged.connect(self.onCurrentIndexChanged)
@@ -329,7 +329,7 @@
         """
         Perform pre import tasks
         """
-        OpenLPWizard.pre_wizard(self)
+        super(SongImportForm, self).pre_wizard()
         self.progress_label.setText(WizardStrings.StartingImport)
         self.application.process_events()
 

=== modified file 'openlp/plugins/songs/forms/songreviewwidget.py'
--- openlp/plugins/songs/forms/songreviewwidget.py	2013-04-09 21:32:19 +0000
+++ openlp/plugins/songs/forms/songreviewwidget.py	2013-08-22 18:47:39 +0000
@@ -64,7 +64,7 @@
         ``song``
             The Song which this SongReviewWidget should represent.
         """
-        QtGui.QWidget.__init__(self, parent)
+        super(SongReviewWidget, self).__init__(parent)
         self.song = song
         self.setupUi()
         self.retranslateUi()

=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py	2013-06-14 20:20:26 +0000
+++ openlp/plugins/songs/lib/__init__.py	2013-08-22 18:47:39 +0000
@@ -395,12 +395,6 @@
     """
     from xml import SongXML
 
-    if isinstance(song.title, buffer):
-        song.title = unicode(song.title)
-    if isinstance(song.alternate_title, buffer):
-        song.alternate_title = unicode(song.alternate_title)
-    if isinstance(song.lyrics, buffer):
-        song.lyrics = unicode(song.lyrics)
     if song.title:
         song.title = clean_title(song.title)
     else:

=== modified file 'openlp/plugins/songs/lib/db.py'
--- openlp/plugins/songs/lib/db.py	2013-03-31 10:31:54 +0000
+++ openlp/plugins/songs/lib/db.py	2013-08-22 18:47:39 +0000
@@ -68,7 +68,7 @@
     Song model
     """
     def __init__(self):
-        self.sort_key = ()
+        self.sort_key = []
 
     @reconstructor
     def init_on_load(self):

=== modified file 'openlp/plugins/songs/lib/dreambeamimport.py'
--- openlp/plugins/songs/lib/dreambeamimport.py	2013-03-07 08:05:43 +0000
+++ openlp/plugins/songs/lib/dreambeamimport.py	2013-08-22 18:47:39 +0000
@@ -100,12 +100,11 @@
                     log.exception(u'XML syntax error in file %s' % file)
                     self.logError(file, SongStrings.XMLSyntaxError)
                     continue
-                xml = unicode(etree.tostring(parsed_file))
+                xml = etree.tostring(parsed_file).decode()
                 song_xml = objectify.fromstring(xml)
                 if song_xml.tag != u'DreamSong':
-                    self.logError(file, unicode(
-                        translate('SongsPlugin.DreamBeamImport',
-                            ('Invalid DreamBeam song file. Missing DreamSong tag.'))))
+                    self.logError(file,
+                        translate('SongsPlugin.DreamBeamImport', 'Invalid DreamBeam song file. Missing DreamSong tag.'))
                     continue
                 if hasattr(song_xml, u'Version'):
                     self.version = float(song_xml.Version.text)

=== modified file 'openlp/plugins/songs/lib/easyslidesimport.py'
--- openlp/plugins/songs/lib/easyslidesimport.py	2013-03-07 08:05:43 +0000
+++ openlp/plugins/songs/lib/easyslidesimport.py	2013-08-22 18:47:39 +0000
@@ -54,7 +54,7 @@
         log.info(u'Importing EasySlides XML file %s', self.import_source)
         parser = etree.XMLParser(remove_blank_text=True)
         parsed_file = etree.parse(self.import_source, parser)
-        xml = unicode(etree.tostring(parsed_file))
+        xml = etree.tostring(parsed_file).decode()
         song_xml = objectify.fromstring(xml)
         self.import_wizard.progress_bar.setMaximum(len(song_xml.Item))
         for song in song_xml.Item:

=== modified file 'openlp/plugins/songs/lib/ewimport.py'
--- openlp/plugins/songs/lib/ewimport.py	2013-07-06 14:40:49 +0000
+++ openlp/plugins/songs/lib/ewimport.py	2013-08-22 18:47:39 +0000
@@ -274,7 +274,7 @@
             return None
         # Format the field depending on the field type
         if field_desc.field_type == FieldType.String:
-            return field.rstrip('\0').decode(self.encoding)
+            return field.rstrip('\0')
         elif field_desc.field_type == FieldType.Int16:
             return field ^ 0x8000
         elif field_desc.field_type == FieldType.Int32:

=== modified file 'openlp/plugins/songs/lib/foilpresenterimport.py'
--- openlp/plugins/songs/lib/foilpresenterimport.py	2013-07-24 20:04:49 +0000
+++ openlp/plugins/songs/lib/foilpresenterimport.py	2013-08-22 18:47:39 +0000
@@ -127,11 +127,10 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            self.import_wizard.increment_progress_bar(
-                WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
             try:
                 parsed_file = etree.parse(file_path, parser)
-                xml = unicode(etree.tostring(parsed_file))
+                xml = etree.tostring(parsed_file).decode()
                 self.FoilPresenter.xml_to_song(xml)
             except etree.XMLSyntaxError:
                 self.logError(file_path, SongStrings.XMLSyntaxError)

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2013-06-14 20:20:26 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2013-08-22 18:47:39 +0000
@@ -71,7 +71,7 @@
 
     def __init__(self, parent, plugin):
         self.icon_path = u'songs/song'
-        MediaManagerItem.__init__(self, parent, plugin)
+        super(SongMediaItem, self).__init__(parent, plugin)
         self.single_service_item = False
         # Holds information about whether the edit is remotely triggered and which Song is required.
         self.remote_song = -1

=== modified file 'openlp/plugins/songs/lib/openlyricsexport.py'
--- openlp/plugins/songs/lib/openlyricsexport.py	2013-06-24 16:54:23 +0000
+++ openlp/plugins/songs/lib/openlyricsexport.py	2013-08-22 18:47:39 +0000
@@ -71,14 +71,14 @@
             self.parent.increment_progress_bar(translate('SongsPlugin.OpenLyricsExport', 'Exporting "%s"...') %
                 song.title)
             xml = openLyrics.song_to_xml(song)
-            tree = etree.ElementTree(etree.fromstring(xml))
+            tree = etree.ElementTree(etree.fromstring(xml.encode()))
             filename = u'%s (%s)' % (song.title, u', '.join([author.display_name for author in song.authors]))
             filename = clean_filename(filename)
             # Ensure the filename isn't too long for some filesystems
             filename = u'%s.xml' % filename[0:250 - len(self.save_path)]
             # Pass a file object, because lxml does not cope with some special
             # characters in the path (see lp:757673 and lp:744337).
-            tree.write(open(os.path.join(self.save_path, filename), u'w'),
+            tree.write(open(os.path.join(self.save_path, filename), u'wb'),
                 encoding=u'utf-8', xml_declaration=True, pretty_print=True)
         return True
 

=== modified file 'openlp/plugins/songs/lib/openlyricsimport.py'
--- openlp/plugins/songs/lib/openlyricsimport.py	2013-03-08 08:14:39 +0000
+++ openlp/plugins/songs/lib/openlyricsimport.py	2013-08-22 18:47:39 +0000
@@ -70,7 +70,7 @@
                 # Pass a file object, because lxml does not cope with some
                 # special characters in the path (see lp:757673 and lp:744337).
                 parsed_file = etree.parse(open(file_path, u'r'), parser)
-                xml = unicode(etree.tostring(parsed_file))
+                xml = etree.tostring(parsed_file).decode()
                 self.openLyrics.xml_to_song(xml)
             except etree.XMLSyntaxError:
                 log.exception(u'XML syntax error in file %s' % file_path)

=== modified file 'openlp/plugins/songs/lib/songshowplusimport.py'
--- openlp/plugins/songs/lib/songshowplusimport.py	2013-03-31 10:13:56 +0000
+++ openlp/plugins/songs/lib/songshowplusimport.py	2013-08-22 18:47:39 +0000
@@ -27,7 +27,7 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 """
-The :mod:`songshowplusimport` module provides the functionality for importing 
+The :mod:`songshowplusimport` module provides the functionality for importing
 SongShow Plus songs into the OpenLP database.
 """
 import os
@@ -132,43 +132,41 @@
                 else:
                     length_descriptor, = struct.unpack("B", song_data.read(1))
                 log.debug(length_descriptor_size)
-                data = song_data.read(length_descriptor)
+                data = song_data.read(length_descriptor).decode()
                 if block_key == TITLE:
-                    self.title = unicode(data, u'cp1252')
+                    self.title = data
                 elif block_key == AUTHOR:
                     authors = data.split(" / ")
                     for author in authors:
                         if author.find(",") !=-1:
                             authorParts = author.split(", ")
                             author = authorParts[1] + " " + authorParts[0]
-                        self.parse_author(unicode(author, u'cp1252'))
+                        self.parse_author(author)
                 elif block_key == COPYRIGHT:
-                    self.addCopyright(unicode(data, u'cp1252'))
+                    self.addCopyright(data)
                 elif block_key == CCLI_NO:
                     self.ccliNumber = int(data)
                 elif block_key == VERSE:
-                    self.addVerse(unicode(data, u'cp1252'), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no))
+                    self.addVerse(data, "%s%s" % (VerseType.tags[VerseType.Verse], verse_no))
                 elif block_key == CHORUS:
-                    self.addVerse(unicode(data, u'cp1252'), "%s%s" % (VerseType.tags[VerseType.Chorus], verse_no))
+                    self.addVerse(data, "%s%s" % (VerseType.tags[VerseType.Chorus], verse_no))
                 elif block_key == BRIDGE:
-                    self.addVerse(unicode(data, u'cp1252'), "%s%s" % (VerseType.tags[VerseType.Bridge], verse_no))
+                    self.addVerse(data, "%s%s" % (VerseType.tags[VerseType.Bridge], verse_no))
                 elif block_key == TOPIC:
-                    self.topics.append(unicode(data, u'cp1252'))
+                    self.topics.append(data)
                 elif block_key == COMMENTS:
-                    self.comments = unicode(data, u'cp1252')
+                    self.comments = data
                 elif block_key == VERSE_ORDER:
                     verse_tag = self.to_openlp_verse_tag(data, True)
                     if verse_tag:
-                        if not isinstance(verse_tag, unicode):
-                            verse_tag = unicode(verse_tag, u'cp1252')
                         self.ssp_verse_order_list.append(verse_tag)
                 elif block_key == SONG_BOOK:
-                    self.songBookName = unicode(data, u'cp1252')
+                    self.songBookName = data
                 elif block_key == SONG_NUMBER:
                     self.songNumber = ord(data)
                 elif block_key == CUSTOM_VERSE:
                     verse_tag = self.to_openlp_verse_tag(verse_name)
-                    self.addVerse(unicode(data, u'cp1252'), verse_tag)
+                    self.addVerse(data, verse_tag)
                 else:
                     log.debug("Unrecognised blockKey: %s, data: %s" % (block_key, data))
                     song_data.seek(next_block_starts)

=== modified file 'openlp/plugins/songs/lib/songstab.py'
--- openlp/plugins/songs/lib/songstab.py	2013-03-17 09:21:18 +0000
+++ openlp/plugins/songs/lib/songstab.py	2013-08-22 18:47:39 +0000
@@ -41,7 +41,7 @@
         Set up the configuration tab UI.
         """
         self.setObjectName(u'SongsTab')
-        SettingsTab.setupUi(self)
+        super(SongsTab, self).setupUi()
         self.mode_group_box = QtGui.QGroupBox(self.left_column)
         self.mode_group_box.setObjectName(u'mode_group_box')
         self.mode_layout = QtGui.QVBoxLayout(self.mode_group_box)

=== modified file 'openlp/plugins/songs/lib/xml.py'
--- openlp/plugins/songs/lib/xml.py	2013-02-24 18:13:50 +0000
+++ openlp/plugins/songs/lib/xml.py	2013-08-22 18:47:39 +0000
@@ -340,7 +340,7 @@
                 # Do not add the break attribute to the last lines element.
                 if index < len(optional_verses) - 1:
                     lines_element.set(u'break', u'optional')
-        return self._extract_xml(song_xml)
+        return self._extract_xml(song_xml).decode()
 
     def _get_missing_tags(self, text):
         """
@@ -592,8 +592,10 @@
             found_tags.append(openlp_tag)
         existing_tag_ids = [tag[u'start tag'] for tag in FormattingTags.get_html_tags()]
         new_tags = [tag for tag in found_tags if tag[u'start tag'] not in existing_tag_ids]
-        FormattingTags.add_html_tags(new_tags)
-        FormattingTags.save_html_tags()
+        # Do not save an empty list.
+        if new_tags:
+            FormattingTags.add_html_tags(new_tags)
+            FormattingTags.save_html_tags()
 
     def _process_lines_mixed_content(self, element, newlines=True):
         """
@@ -820,7 +822,7 @@
     VerseError = 2
 
     def __init__(self, type, log_message, display_message):
-        Exception.__init__(self)
+        super(OpenLyricsError, self).__init__()
         self.type = type
         self.log_message = log_message
         self.display_message = display_message

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2013-06-11 05:31:11 +0000
+++ openlp/plugins/songs/songsplugin.py	2013-08-22 18:47:39 +0000
@@ -41,7 +41,6 @@
 from openlp.core.lib import Plugin, StringContent, UiStrings, build_icon, translate
 from openlp.core.lib.db import Manager
 from openlp.core.lib.ui import create_action
-from openlp.core.utils import get_filesystem_encoding
 from openlp.core.utils.actions import ActionList
 from openlp.plugins.songs.lib import clean_song, upgrade
 from openlp.plugins.songs.lib.db import init_schema, Song
@@ -81,7 +80,7 @@
         """
         Create and set up the Songs plugin.
         """
-        Plugin.__init__(self, u'songs', __default_settings__, SongMediaItem, SongsTab)
+        super(SongsPlugin, self).__init__(u'songs', __default_settings__, SongMediaItem, SongsTab)
         self.manager = Manager(u'songs', init_schema, upgrade_mod=upgrade)
         self.weight = -10
         self.icon_path = u':/plugins/plugin_songs.png'
@@ -95,7 +94,7 @@
 
     def initialise(self):
         log.info(u'Songs Initialising')
-        Plugin.initialise(self)
+        super(SongsPlugin, self).initialise()
         self.song_import_item.setVisible(True)
         self.song_export_item.setVisible(True)
         self.tools_reindex_item.setVisible(True)
@@ -263,7 +262,7 @@
         self.application.process_events()
         self.on_tools_reindex_item_triggered()
         self.application.process_events()
-        db_dir = unicode(os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
+        db_dir = os.path.join(gettempdir(), u'openlp')
         if not os.path.exists(db_dir):
             return
         song_dbs = []
@@ -309,7 +308,7 @@
         action_list.remove_action(self.song_export_item, UiStrings().Export)
         action_list.remove_action(self.tools_reindex_item, UiStrings().Tools)
         action_list.remove_action(self.tools_find_duplicates, UiStrings().Tools)
-        Plugin.finalise(self)
+        super(SongsPlugin, self).finalise()
 
     def new_service_created(self):
         """

=== modified file 'openlp/plugins/songusage/forms/songusagedeleteform.py'
--- openlp/plugins/songusage/forms/songusagedeleteform.py	2013-02-16 10:38:02 +0000
+++ openlp/plugins/songusage/forms/songusagedeleteform.py	2013-08-22 18:47:39 +0000
@@ -43,7 +43,7 @@
         Constructor
         """
         self.manager = manager
-        QtGui.QDialog.__init__(self, parent)
+        super(SongUsageDeleteForm, self).__init__(parent)
         self.setupUi(self)
         self.button_box.clicked.connect(self.on_button_box_clicked)
 

=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
--- openlp/plugins/songusage/forms/songusagedetailform.py	2013-03-19 19:43:22 +0000
+++ openlp/plugins/songusage/forms/songusagedetailform.py	2013-08-22 18:47:39 +0000
@@ -50,7 +50,7 @@
         """
         Initialise the form
         """
-        QtGui.QDialog.__init__(self, parent)
+        super(SongUsageDetailForm, self).__init__(parent)
         self.plugin = plugin
         self.setupUi(self)
 

=== modified file 'openlp/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py	2013-04-19 18:52:39 +0000
+++ openlp/plugins/songusage/songusageplugin.py	2013-08-22 18:47:39 +0000
@@ -60,7 +60,7 @@
     log.info(u'SongUsage Plugin loaded')
 
     def __init__(self):
-        Plugin.__init__(self, u'songusage', __default_settings__)
+        super(SongUsagePlugin, self).__init__(u'songusage', __default_settings__)
         self.manager = Manager(u'songusage', init_schema, upgrade_mod=upgrade)
         self.weight = -4
         self.icon = build_icon(u':/plugins/plugin_songusage.png')
@@ -122,7 +122,7 @@
 
     def initialise(self):
         log.info(u'SongUsage Initialising')
-        Plugin.initialise(self)
+        super(SongUsagePlugin, self).initialise()
         Registry().register_function(u'slidecontroller_live_started', self.display_song_usage)
         Registry().register_function(u'print_service_started', self.print_song_usage)
         self.song_usage_active = Settings().value(self.settings_section + u'/active')
@@ -143,7 +143,7 @@
         """
         log.info(u'Plugin Finalise')
         self.manager.finalise()
-        Plugin.finalise(self)
+        super(SongUsagePlugin, self).finalise()
         self.song_usage_menu.menuAction().setVisible(False)
         action_list = ActionList.get_instance()
         action_list.remove_action(self.song_usage_status, translate('SongUsagePlugin', 'Song Usage'))

=== modified file 'scripts/generate_resources.sh'
--- scripts/generate_resources.sh	2013-03-29 12:19:40 +0000
+++ scripts/generate_resources.sh	2013-08-22 18:47:39 +0000
@@ -44,7 +44,7 @@
 mv openlp/core/resources.py openlp/core/resources.py.old
 
 # Create the new data from the updated qrc
-pyrcc4 -o openlp/core/resources.py.new resources/images/openlp-2.qrc
+pyrcc4 -py3 -o openlp/core/resources.py.new resources/images/openlp-2.qrc
 
 # Remove patch breaking lines
 cat openlp/core/resources.py.new | sed '/# Created: /d;/#      by: /d' > openlp/core/resources.py

=== modified file 'tests/functional/openlp_core_lib/test_image_manager.py'
--- tests/functional/openlp_core_lib/test_image_manager.py	2013-03-12 08:19:47 +0000
+++ tests/functional/openlp_core_lib/test_image_manager.py	2013-08-22 18:47:39 +0000
@@ -46,11 +46,11 @@
         # WHEN: The image bytes are requested.
         byte_array = self.image_manager.get_image_bytes(TEST_PATH, u'church.jpg')
 
-        # THEN: Type should be a byte array.
-        self.assertEqual(isinstance(byte_array, QtCore.QByteArray), True, u'The returned object should be a QByteArray')
+        # THEN: Type should be a str.
+        self.assertEqual(isinstance(byte_array, str), True, u'The returned object should be a str')
 
         # WHEN the image is retrieved has not been loaded
         # THEN a KeyError is thrown
         with self.assertRaises(KeyError) as context:
             self.image_manager.get_image(TEST_PATH, u'church1.jpg')
-        self.assertNotEquals(context.exception[0], u'', u'KeyError exception should have been thrown for missing image')
+        self.assertNotEquals(context.exception, u'', u'KeyError exception should have been thrown for missing image')

=== modified file 'tests/functional/openlp_core_lib/test_lib.py'
--- tests/functional/openlp_core_lib/test_lib.py	2013-06-23 15:29:16 +0000
+++ tests/functional/openlp_core_lib/test_lib.py	2013-08-22 18:47:39 +0000
@@ -187,7 +187,7 @@
         """
         Test the get_text_file_string() method when a read error happens
         """
-        with patch(u'openlp.core.lib.os.path.isfile') as mocked_isfile, patch(u'__builtin__.open') as mocked_open:
+        with patch(u'openlp.core.lib.os.path.isfile') as mocked_isfile, patch(u'builtins.open') as mocked_open:
             # GIVEN: A mocked-out open() which raises an exception and isfile returns True
             filename = u'testfile.txt'
             mocked_isfile.return_value = True

=== modified file 'tests/functional/openlp_core_lib/test_registry.py'
--- tests/functional/openlp_core_lib/test_registry.py	2013-02-17 07:54:43 +0000
+++ tests/functional/openlp_core_lib/test_registry.py	2013-08-22 18:47:39 +0000
@@ -31,14 +31,14 @@
         # THEN  and I will get an exception
         with self.assertRaises(KeyError) as context:
             Registry().register(u'test1', mock_1)
-        self.assertEqual(context.exception[0], u'Duplicate service exception test1',
+        self.assertEqual(context.exception.args[0], u'Duplicate service exception test1',
             u'KeyError exception should have been thrown for duplicate service')
 
         # WHEN I try to get back a non existent component
         # THEN I will get an exception
         with self.assertRaises(KeyError) as context:
             temp = Registry().get(u'test2')
-        self.assertEqual(context.exception[0], u'Service test2 not found in list',
+        self.assertEqual(context.exception.args[0], u'Service test2 not found in list',
             u'KeyError exception should have been thrown for missing service')
 
         # WHEN I try to replace a component I should be allowed (testing only)
@@ -46,7 +46,7 @@
         # THEN I will get an exception
         with self.assertRaises(KeyError) as context:
             temp = Registry().get(u'test1')
-        self.assertEqual(context.exception[0], u'Service test1 not found in list',
+        self.assertEqual(context.exception.args[0], u'Service test1 not found in list',
             u'KeyError exception should have been thrown for deleted service')
 
     def registry_function_test(self):
@@ -81,4 +81,5 @@
         return "function_1"
 
     def dummy_function_2(self):
-        return "function_2"
\ No newline at end of file
+        return "function_2"
+

=== modified file 'tests/functional/openlp_core_lib/test_serviceitem.py'
--- tests/functional/openlp_core_lib/test_serviceitem.py	2013-07-05 07:47:09 +0000
+++ tests/functional/openlp_core_lib/test_serviceitem.py	2013-08-22 18:47:39 +0000
@@ -2,6 +2,7 @@
     Package to test the openlp.core.lib package.
 """
 import os
+
 from unittest import TestCase
 from mock import MagicMock, patch
 

=== modified file 'tests/functional/openlp_core_utils/test_utils.py'
--- tests/functional/openlp_core_utils/test_utils.py	2013-04-15 15:43:18 +0000
+++ tests/functional/openlp_core_utils/test_utils.py	2013-08-22 18:47:39 +0000
@@ -105,14 +105,33 @@
         # THEN: The file name should be cleaned.
         assert result == wanted_name, u'The file name should not contain any special characters.'
 
-    def get_locale_key_test(self):
-        """
-        Test the get_locale_key(string) function
-        """
-        with patch(u'openlp.core.utils.languagemanager.LanguageManager.get_language') as mocked_get_language:
-            # GIVEN: The language is German
-            # 0x00C3 (A with diaresis) should be sorted as "A". 0x00DF (sharp s) should be sorted as "ss".
-            mocked_get_language.return_value = u'de'
+    def get_locale_key_windows_test(self):
+        """
+        Test the get_locale_key(string) function
+        """
+        with patch(u'openlp.core.utils.languagemanager.LanguageManager.get_language') as mocked_get_language,  \
+                patch(u'openlp.core.utils.os') as mocked_os:
+            # GIVEN: The language is German
+            # 0x00C3 (A with diaresis) should be sorted as "A". 0x00DF (sharp s) should be sorted as "ss".
+            mocked_get_language.return_value = u'de'
+            mocked_os.name = u'nt'
+            unsorted_list = [u'Auszug', u'Aushang', u'\u00C4u\u00DFerung']
+            # WHEN: We sort the list and use get_locale_key() to generate the sorting keys
+            # THEN: We get a properly sorted list
+            test_passes = sorted(unsorted_list, key=get_locale_key) == [u'Aushang', u'\u00C4u\u00DFerung', u'Auszug']
+            assert test_passes, u'Strings should be sorted properly'
+
+    def get_locale_key_linux_test(self):
+
+        """
+        Test the get_locale_key(string) function
+        """
+        with patch(u'openlp.core.utils.languagemanager.LanguageManager.get_language') as mocked_get_language,  \
+                patch(u'openlp.core.utils.os.name') as mocked_os:
+            # GIVEN: The language is German
+            # 0x00C3 (A with diaresis) should be sorted as "A". 0x00DF (sharp s) should be sorted as "ss".
+            mocked_get_language.return_value = u'de'
+            mocked_os.name = u'linux'
             unsorted_list = [u'Auszug', u'Aushang', u'\u00C4u\u00DFerung']
             # WHEN: We sort the list and use get_locale_key() to generate the sorting keys
             # THEN: We get a properly sorted list


Follow ups