← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~phill-ridout/openlp/bug1135392_2.0 into lp:openlp

 

Phill has proposed merging lp:~phill-ridout/openlp/bug1135392_2.0 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #1135392 in OpenLP: "Catch all error trap in editsongform.py, _processLyrics"
  https://bugs.launchpad.net/openlp/+bug/1135392

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/bug1135392_2.0/+merge/151618

Reraise the error so that we can catch the original cause and hopefully solve some bugs.
-- 
https://code.launchpad.net/~phill-ridout/openlp/bug1135392_2.0/+merge/151618
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/bug1135392_2.0 into lp:openlp.
=== modified file 'copyright.txt'
=== modified file 'openlp.py'
=== modified file 'openlp/.version'
--- openlp/.version	2013-01-08 20:44:56 +0000
+++ openlp/.version	2013-03-04 21:19:34 +0000
@@ -1,1 +1,5 @@
+<<<<<<< TREE
 2.1.0-bzr2141
+=======
+2.0.1
+>>>>>>> MERGE-SOURCE

=== modified file 'openlp/__init__.py'
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2013-03-01 17:45:17 +0000
+++ openlp/core/__init__.py	2013-03-04 21:19:34 +0000
@@ -284,10 +284,19 @@
         application.setApplicationName(u'OpenLPPortable')
         Settings.setDefaultFormat(Settings.IniFormat)
         # Get location OpenLPPortable.ini
+<<<<<<< TREE
         application_path = AppLocation.get_directory(AppLocation.AppDir)
         set_up_logging(os.path.abspath(os.path.join(application_path, u'..', u'..', u'Other')))
         log.info(u'Running portable')
         portable_settings_file = os.path.abspath(os.path.join(application_path, u'..', u'..', u'Data', u'OpenLP.ini'))
+=======
+        app_path = AppLocation.get_directory(AppLocation.AppDir)
+        set_up_logging(os.path.abspath(os.path.join(app_path, u'..',
+            u'..', u'Other')))
+        log.info(u'Running portable')
+        portable_settings_file = os.path.abspath(os.path.join(app_path, u'..',
+            u'..', u'Data', u'OpenLP.ini'))
+>>>>>>> MERGE-SOURCE
         # Make this our settings file
         log.info(u'INI file: %s', portable_settings_file)
         Settings.set_filename(portable_settings_file)
@@ -300,11 +309,17 @@
         portable_settings.setValue(u'advanced/is portable', True)
         portable_settings.sync()
     else:
+<<<<<<< TREE
         application.setApplicationName(u'OpenLP')
         set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
     Registry.create()
     Registry().register(u'application', application)
     application.setApplicationVersion(get_application_version()[u'version'])
+=======
+        set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
+        app.setApplicationName(u'OpenLP')
+    app.setApplicationVersion(get_application_version()[u'version'])
+>>>>>>> MERGE-SOURCE
     # Instance check
     if application.is_already_running():
         sys.exit()

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2013-03-01 17:45:17 +0000
+++ openlp/core/lib/__init__.py	2013-03-04 21:19:34 +0000
@@ -338,18 +338,35 @@
     return text
 
 
+<<<<<<< TREE
 def check_directory_exists(directory, do_not_log=False):
+=======
+def check_directory_exists(dir, do_not_log=False):
+>>>>>>> MERGE-SOURCE
     """
     Check a theme directory exists and if not create it
 
+<<<<<<< TREE
     ``directory``
         The directory to make sure exists
 
     ``do_not_log``
         To not log anything. This is need for the start up, when the log isn't ready.
+=======
+    ``dir``
+        Theme directory to make sure exists
+
+    ``do_not_log``
+        To not log anything. This is need for the start up, when the log isn't ready.
+>>>>>>> MERGE-SOURCE
     """
+<<<<<<< TREE
     if not do_not_log:
         log.debug(u'check_directory_exists %s' % directory)
+=======
+    if not do_not_log:
+        log.debug(u'check_directory_exists %s' % dir)
+>>>>>>> MERGE-SOURCE
     try:
         if not os.path.exists(directory):
             os.makedirs(directory)

=== modified file 'openlp/core/lib/db.py'
=== modified file 'openlp/core/lib/dockwidget.py'
=== added file 'openlp/core/lib/eventreceiver.py.OTHER'
--- openlp/core/lib/eventreceiver.py.OTHER	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/eventreceiver.py.OTHER	2013-03-04 21:19:34 +0000
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky                                             #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+Provide event handling code for OpenLP
+"""
+import logging
+
+from PyQt4 import QtCore
+
+log = logging.getLogger(__name__)
+
+class EventReceiver(QtCore.QObject):
+    """
+    Class to allow events to be passed from different parts of the system. This
+    is a private class and should not be used directly but rather via the
+    Receiver class.
+
+    **Mainwindow related and generic signals**
+
+    ``mainwindow_status_text``
+        Changes the bottom status bar text on the mainwindow.
+
+    ``openlp_warning_message``
+        Displays a standalone Warning Message.
+
+    ``openlp_error_message``
+        Displays a standalone Error Message.
+
+    ``openlp_information_message``
+        Displays a standalone Information Message.
+
+    ``cursor_busy``
+        Makes the cursor got to a busy form.
+
+    ``cursor_normal``
+        Resets the cursor to default.
+
+    ``openlp_process_events``
+        Requests the Application to flush the events queue.
+
+    ``openlp_version_check``
+        Version has changed so pop up window.
+
+    ``openlp_stop_wizard``
+        Stops a wizard before completion.
+
+    **Setting related signals**
+
+    ``config_updated``
+        Informs components that the config has changed.
+
+    ``config_screen_changed``
+        The display monitor has been changed.
+
+    **Slidecontroller signals**
+
+    ``slidecontroller_{live|preview}_next``
+        Moves to the next slide.
+
+    ``slidecontroller_{live|preview}_next_noloop``
+        Moves to the next slide without auto advance.
+
+    ``slidecontroller_{live|preview}_previous``
+        Moves to the previous slide.
+
+    ``slidecontroller_{live|preview}_previous_noloop``
+        Moves to the previous slide, without auto advance.
+
+    ``slidecontroller_{live|preview}_set``
+        Moves to a specific slide, by index.
+
+    ``slidecontroller_{live|preview}_started``
+        Broadcasts that an item has been made live/previewed.
+
+    ``slidecontroller_{live|preview}_change``
+        Informs the slidecontroller that a slide change has occurred and to
+        update itself.
+
+    ``slidecontroller_{live|preview}_changed``
+        Broadcasts that the slidecontroller has changed the current slide.
+
+    ``slidecontroller_{live|preview}_blank``
+        Request that the output screen is blanked.
+
+    ``slidecontroller_{live|preview}_unblank``
+        Request that the output screen is unblanked.
+
+    ``slidecontroller_live_spin_delay``
+        Pushes out the loop delay.
+
+    ``slidecontroller_update_slide_limits``
+        Updates the slide_limits variable from the saved settings.
+
+    ``slidecontroller_live_stop_loop``
+        Stop the loop on the main display.
+
+
+    **Servicemanager related signals**
+
+    ``servicemanager_new_service``
+        A new service is being loaded or created.
+
+    ``servicemanager_previous_item``
+        Display the previous item in the service.
+
+    ``servicemanager_preview_live``
+        Requests a Preview item from the Service Manager to update live and add
+        a new item to the preview panel.
+
+    ``servicemanager_next_item``
+        Display the next item in the service.
+
+    ``servicemanager_set_item``
+        Go live on a specific item, by index.
+
+    ``service_item_update``
+        Passes back to the service manager the service item after it has been
+        processed by the plugin.
+
+    **Display signals**
+
+    ``update_display_css``
+        CSS has been updated which needs to be changed on the main display.
+
+    **Live Display signals**
+
+    ``live_display_hide``
+        Hide the live display.
+
+    ``live_display_show``
+        Return the live display.
+
+    ``live_display_active``
+        The live display has been made active.
+
+    ``live_display_blank_check``
+        Check to see if the blank display message is required.
+
+    **Theme related singlas**
+
+    ``theme_update_list``
+        send out message with new themes.
+
+    ``theme_update_global``
+        Tell the components we have a new global theme.
+
+    **Plugin specific signals**
+
+    ``{plugin}_start``
+        Requests a plugin to start a external program. Path and file have to
+        be provided in the message.
+
+    ``{plugin}_first``
+        Requests a plugin to handle a first event.
+
+    ``{plugin}_previous``
+        Requests a plugin to handle a previous event.
+
+    ``{plugin}_next``
+        Requests a plugin to handle a next event.
+
+    ``{plugin}_last``
+        Requests a plugin to handle a last event.
+
+    ``{plugin}_slide``
+        Requests a plugin to handle a go to specific slide event.
+
+    ``{plugin}_stop``
+        Requests a plugin to handle a stop event.
+
+    ``{plugin}_blank``
+        Requests a plugin to handle a blank screen event.
+
+    ``{plugin}_unblank``
+        Requests a plugin to handle an unblank screen event.
+
+    ``{plugin}_edit``
+        Requests a plugin edit a database item with the key as the payload.
+
+    ``{plugin}_edit_clear``
+        Editing has been completed.
+
+    ``{plugin}_load_list``
+        Tells the the plugin to reload the media manager list.
+
+    ``{plugin}_preview``
+        Tells the plugin it's item can be previewed.
+
+    ``{plugin}_add_service_item``
+        Ask the plugin to push the selected items to the service item.
+
+    ``{plugin}_service_load``
+        Ask the plugin to process an individual service item after it has been
+        loaded.
+
+    ``{plugin}_config_updated``
+        The config has changed so tell the plugin about it.
+
+    ``alerts_text``
+        Displays an alert message.
+
+    ``bibles_nobook``
+        Attempt to find book resulted in no match.
+
+    ``remotes_poll_request``
+        Waits for openlp to do something "interesting" and sends a
+        ``remotes_poll_response`` signal when it does.
+
+    """
+    def __init__(self):
+        """
+        Initialise the event receiver, calling the parent constructor.
+        """
+        QtCore.QObject.__init__(self)
+
+    def send_message(self, event, msg=None):
+        """
+        Emit a Qt signal.
+
+        ``event``
+            The event to that was sent.
+
+        ``msg``
+            Defaults to *None*. The message to send with the event.
+        """
+        log.debug(u'Event %s passed with payload %s' % (event, msg))
+        self.emit(QtCore.SIGNAL(event), msg)
+
+
+class Receiver(object):
+    """
+    Class to allow events to be passed from different parts of the system. This
+    is a static wrapper around the ``EventReceiver`` class. As there is only
+    one instance of it in the system the Qt4 signal/slot architecture can send
+    messages across the system.
+
+    To send a message:
+       ``Receiver.send_message(u'<<Message ID>>', data)``
+
+    To receive a Message
+        ``QtCore.QObject.connect(
+            Receiver.get_receiver(),
+            QtCore.SIGNAL(u'<<Message ID>>'),
+            <<ACTION>>
+        )``
+    """
+    __eventreceiver__ = EventReceiver()
+
+    @staticmethod
+    def send_message(event, msg=None):
+        """
+        Sends a message to the messaging system.
+
+        ``event``
+            The event to send.
+
+        ``msg``
+            Defaults to *None*. The message to send with the event.
+        """
+        Receiver.__eventreceiver__.send_message(event, msg)
+
+    @staticmethod
+    def get_receiver():
+        """
+        Get the global ``__eventreceiver__`` instance.
+        """
+        return Receiver.__eventreceiver__

=== modified file 'openlp/core/lib/formattingtags.py'
=== modified file 'openlp/core/lib/htmlbuilder.py'
=== modified file 'openlp/core/lib/imagemanager.py'
=== modified file 'openlp/core/lib/listwidgetwithdnd.py'
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2013-02-19 09:56:36 +0000
+++ openlp/core/lib/mediamanageritem.py	2013-03-04 21:19:34 +0000
@@ -330,9 +330,18 @@
         """
         Add a file to the list widget to make it available for showing
         """
+<<<<<<< TREE
         files = QtGui.QFileDialog.getOpenFileNames(self, self.onNewPrompt,
             Settings().value(self.settingsSection + u'/last directory'), self.onNewFileMasks)
         log.info(u'New files(s) %s', files)
+=======
+        files = QtGui.QFileDialog.getOpenFileNames(
+            self, self.onNewPrompt,
+            SettingsManager.get_last_dir(self.settingsSection),
+            self.onNewFileMasks)
+        files =  map(unicode, files)
+        log.info(u'New files(s) %s', unicode(files))
+>>>>>>> MERGE-SOURCE
         if files:
             self.application.set_busy_cursor()
             self.validateAndLoad(files)

=== modified file 'openlp/core/lib/plugin.py'
=== modified file 'openlp/core/lib/pluginmanager.py'
=== modified file 'openlp/core/lib/renderer.py'
=== modified file 'openlp/core/lib/screen.py'
=== modified file 'openlp/core/lib/searchedit.py'
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py	2013-02-16 18:24:31 +0000
+++ openlp/core/lib/serviceitem.py	2013-03-04 21:19:34 +0000
@@ -37,9 +37,17 @@
 import os
 import uuid
 
+<<<<<<< TREE
 from PyQt4 import QtGui
 
 from openlp.core.lib import ImageSource, Settings, Registry, build_icon, clean_tags, expand_tags, translate
+=======
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, \
+    ImageSource
+from openlp.core.lib.settings import Settings
+>>>>>>> MERGE-SOURCE
 
 log = logging.getLogger(__name__)
 
@@ -419,6 +427,7 @@
             for slide in serviceitem[u'serviceitem'][u'data']:
                 self._raw_frames.append(slide)
         elif self.service_item_type == ServiceItemType.Image:
+<<<<<<< TREE
             settingsSection = serviceitem[u'serviceitem'][u'header'][u'name']
             background = QtGui.QColor(Settings().value(settingsSection + u'/background color'))
             if path:
@@ -429,6 +438,14 @@
             else:
                 for text_image in serviceitem[u'serviceitem'][u'data']:
                     self.add_from_image(text_image[u'path'], text_image[u'title'], background)
+=======
+            settingsSection = serviceitem[u'serviceitem'][u'header'][u'name']
+            background = QtGui.QColor(Settings().value(settingsSection
+                + u'/background color', QtCore.QVariant(u'#000000')))
+            for text_image in serviceitem[u'serviceitem'][u'data']:
+                filename = os.path.join(path, text_image)
+                self.add_from_image(filename, text_image, background)
+>>>>>>> MERGE-SOURCE
         elif self.service_item_type == ServiceItemType.Command:
             for text_image in serviceitem[u'serviceitem'][u'data']:
                 if path:

=== added file 'openlp/core/lib/settings.py'
--- openlp/core/lib/settings.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/settings.py	2013-03-04 21:19:34 +0000
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky                                             #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+The :mod:``settings`` module provides a thin wrapper for QSettings, which OpenLP
+uses to manage settings persistence.
+"""
+
+import logging
+
+from PyQt4 import QtCore
+
+log = logging.getLogger()
+
+class Settings(QtCore.QSettings):
+    """
+    Class to wrap QSettings.
+
+    * Exposes all the methods of QSettings.
+    * Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to
+      ``IniFormat``, and the path to the Ini file is set using ``setFilename``,
+      then the Settings constructor (without any arguments) will create a Settings
+      object for accessing settings stored in that Ini file.
+    """
+
+    __filePath = u''
+
+    @staticmethod
+    def setFilename(iniFile):
+        """
+        Sets the complete path to an Ini file to be used by Settings objects.
+
+        Does not affect existing Settings objects.
+        """
+        Settings.__filePath = iniFile
+
+    def __init__(self, *args):
+        if not args and Settings.__filePath and (Settings.defaultFormat() ==
+            Settings.IniFormat):
+            QtCore.QSettings.__init__(self, Settings.__filePath,
+                Settings.IniFormat)
+        else:
+            QtCore.QSettings.__init__(self, *args)

=== renamed file 'openlp/core/lib/settings.py' => 'openlp/core/lib/settings.py.moved'
=== added file 'openlp/core/lib/settingsmanager.py.OTHER'
--- openlp/core/lib/settingsmanager.py.OTHER	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/settingsmanager.py.OTHER	2013-03-04 21:19:34 +0000
@@ -0,0 +1,168 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky                                             #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+Provide handling for persisting OpenLP settings.  OpenLP uses QSettings to
+manage settings persistence.  QSettings provides a single API for saving and
+retrieving settings from the application but writes to disk in an OS dependant
+format.
+"""
+import os
+
+from PyQt4 import QtCore
+
+from openlp.core.lib.settings import Settings
+from openlp.core.utils import AppLocation
+
+class SettingsManager(object):
+    """
+    Class to provide helper functions for the loading and saving of application
+    settings.
+    """
+
+    @staticmethod
+    def get_last_dir(section, num=None):
+        """
+        Read the last directory used for plugin.
+
+        ``section``
+            The section of code calling the method. This is used in the
+            settings key.
+
+        ``num``
+            Defaults to *None*. A further qualifier.
+        """
+        if num:
+            name = u'last directory %d' % num
+        else:
+            name = u'last directory'
+        last_dir = unicode(Settings().value(
+            section + u'/' + name, QtCore.QVariant(u'')).toString())
+        return last_dir
+
+    @staticmethod
+    def set_last_dir(section, directory, num=None):
+        """
+        Save the last directory used for plugin.
+
+        ``section``
+            The section of code calling the method. This is used in the
+            settings key.
+
+        ``directory``
+            The directory being stored in the settings.
+
+        ``num``
+            Defaults to *None*. A further qualifier.
+        """
+        if num:
+            name = u'last directory %d' % num
+        else:
+            name = u'last directory'
+        Settings().setValue(
+            section + u'/' + name, QtCore.QVariant(directory))
+
+    @staticmethod
+    def set_list(section, name, list):
+        """
+        Save a list to application settings.
+
+        ``section``
+            The section of the settings to store this list.
+
+        ``name``
+            The name of the list to save.
+
+        ``list``
+            The list of values to save.
+        """
+        settings = Settings()
+        settings.beginGroup(section)
+        old_count = settings.value(
+            u'%s count' % name, QtCore.QVariant(0)).toInt()[0]
+        new_count = len(list)
+        settings.setValue(u'%s count' % name, QtCore.QVariant(new_count))
+        for counter in range(new_count):
+            settings.setValue(
+                u'%s %d' % (name, counter), QtCore.QVariant(list[counter-1]))
+        if old_count > new_count:
+            # Tidy up any old list items
+            for counter in range(new_count, old_count):
+                settings.remove(u'%s %d' % (name, counter))
+        settings.endGroup()
+
+    @staticmethod
+    def load_list(section, name):
+        """
+        Load a list from the config file.
+
+        ``section``
+            The section of the settings to load the list from.
+
+        ``name``
+            The name of the list.
+        """
+        settings = Settings()
+        settings.beginGroup(section)
+        list_count = settings.value(
+            u'%s count' % name, QtCore.QVariant(0)).toInt()[0]
+        list = []
+        if list_count:
+            for counter in range(list_count):
+                item = unicode(
+                    settings.value(u'%s %d' % (name, counter)).toString())
+                if item:
+                    list.append(item)
+        settings.endGroup()
+        return list
+
+    @staticmethod
+    def get_files(section=None, extension=None):
+        """
+        Get a list of files from the data files path.
+
+        ``section``
+            Defaults to *None*. The section of code getting the files - used
+            to load from a section's data subdirectory.
+
+        ``extension``
+            Defaults to *None*. The extension to search for.
+        """
+        path = AppLocation.get_data_path()
+        if section:
+            path = os.path.join(path, section)
+        try:
+            files = os.listdir(path)
+        except OSError:
+            return []
+        if extension:
+            return [filename for filename in files
+                if extension == os.path.splitext(filename)[1]]
+        else:
+            # no filtering required
+            return files

=== modified file 'openlp/core/lib/settingstab.py'
=== modified file 'openlp/core/lib/spelltextedit.py'
=== modified file 'openlp/core/lib/theme.py'
=== modified file 'openlp/core/lib/toolbar.py'
=== modified file 'openlp/core/lib/ui.py'
=== modified file 'openlp/core/resources.py'
=== modified file 'openlp/core/theme/__init__.py'
=== modified file 'openlp/core/theme/theme.py'
=== modified file 'openlp/core/ui/__init__.py'
=== modified file 'openlp/core/ui/aboutdialog.py'
--- openlp/core/ui/aboutdialog.py	2013-02-05 08:05:28 +0000
+++ openlp/core/ui/aboutdialog.py	2013-03-04 21:19:34 +0000
@@ -270,9 +270,15 @@
             u'\n    '.join(documentors)))
         self.aboutNotebook.setTabText(self.aboutNotebook.indexOf(self.creditsTab),
             translate('OpenLP.AboutForm', 'Credits'))
+<<<<<<< TREE
         copyright_note = translate('OpenLP.AboutForm',
             'Copyright \xa9 2004-2013 %s\n'
             'Portions copyright \xa9 2004-2013 %s') % (u'Raoul Snyman',
+=======
+        copyright = unicode(translate('OpenLP.AboutForm',
+            'Copyright \xa9 2004-2013 %s\n'
+            'Portions copyright \xa9 2004-2013 %s')) % (u'Raoul Snyman',
+>>>>>>> MERGE-SOURCE
             u'Tim Bentley, Gerald Britton, Jonathan Corwin, Samuel Findlay, '
             u'Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, '
             u'Armin K\xf6hler, Erik Lundin, Edwin Lunando, Joshua Miller, '

=== modified file 'openlp/core/ui/aboutform.py'
=== modified file 'openlp/core/ui/advancedtab.py'
=== modified file 'openlp/core/ui/exceptiondialog.py'
=== modified file 'openlp/core/ui/exceptionform.py'
=== modified file 'openlp/core/ui/filerenamedialog.py'
=== modified file 'openlp/core/ui/filerenameform.py'
=== modified file 'openlp/core/ui/firsttimeform.py'
=== modified file 'openlp/core/ui/firsttimelanguagedialog.py'
=== modified file 'openlp/core/ui/firsttimelanguageform.py'
=== modified file 'openlp/core/ui/firsttimewizard.py'
=== modified file 'openlp/core/ui/formattingtagdialog.py'
=== modified file 'openlp/core/ui/formattingtagform.py'
=== modified file 'openlp/core/ui/generaltab.py'
=== modified file 'openlp/core/ui/maindisplay.py'
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2013-03-04 18:01:57 +0000
+++ openlp/core/ui/mainwindow.py	2013-03-04 21:19:34 +0000
@@ -287,6 +287,7 @@
             icon=u':/system/system_settings.png', can_shortcuts=True, category=UiStrings().Settings)
         # Give QT Extra Hint that this is the Preferences Menu Item
         self.settingsConfigureItem.setMenuRole(QtGui.QAction.PreferencesRole)
+<<<<<<< TREE
         self.settingsImportItem = create_action(
             main_window, u'settingsImportItem', category=UiStrings().Import, can_shortcuts=True)
         self.settingsExportItem = create_action(
@@ -294,6 +295,18 @@
         action_list.add_category(UiStrings().Help, CategoryOrder.standard_menu)
         self.aboutItem = create_action(main_window, u'aboutItem', icon=u':/system/system_about.png',
             can_shortcuts=True, category=UiStrings().Help, triggers=self.onAboutItemClicked)
+=======
+        self.settingsImportItem = create_action(mainWindow,
+           u'settingsImportItem', category=UiStrings().Import)
+        self.settingsExportItem = create_action(mainWindow,
+           u'settingsExportItem', category=UiStrings().Export)
+        action_list.add_category(unicode(UiStrings().Help),
+            CategoryOrder.standardMenu)
+        self.aboutItem = create_action(mainWindow, u'aboutItem',
+            icon=u':/system/system_about.png',
+            shortcuts=[QtGui.QKeySequence(u'Ctrl+F1')],
+            category=UiStrings().Help, triggers=self.onAboutItemClicked)
+>>>>>>> MERGE-SOURCE
         # Give QT Extra Hint that this is an About Menu Item
         self.aboutItem.setMenuRole(QtGui.QAction.AboutRole)
         if os.name == u'nt':

=== modified file 'openlp/core/ui/media/__init__.py'
=== modified file 'openlp/core/ui/media/mediacontroller.py'
=== modified file 'openlp/core/ui/media/mediaplayer.py'
=== modified file 'openlp/core/ui/media/phononplayer.py'
=== modified file 'openlp/core/ui/media/vendor/vlc.py'
--- openlp/core/ui/media/vendor/vlc.py	2013-02-19 07:16:56 +0000
+++ openlp/core/ui/media/vendor/vlc.py	2013-03-04 21:19:34 +0000
@@ -2,7 +2,7 @@
 
 # Python ctypes bindings for VLC
 #
-# Copyright (C) 2009-2012 the VideoLAN team
+# Copyright (C) 2009-2013 the VideoLAN team
 # $Id: $
 #
 # Authors: Olivier Aubert <olivier.aubert at liris.cnrs.fr>

=== modified file 'openlp/core/ui/media/vlcplayer.py'
=== modified file 'openlp/core/ui/media/webkitplayer.py'
=== modified file 'openlp/core/ui/mediadockmanager.py'
=== modified file 'openlp/core/ui/plugindialog.py'
=== modified file 'openlp/core/ui/pluginform.py'
=== modified file 'openlp/core/ui/printservicedialog.py'
=== modified file 'openlp/core/ui/printserviceform.py'
=== modified file 'openlp/core/ui/serviceitemeditdialog.py'
=== modified file 'openlp/core/ui/serviceitemeditform.py'
=== modified file 'openlp/core/ui/servicemanager.py'
=== modified file 'openlp/core/ui/servicenoteform.py'
=== modified file 'openlp/core/ui/settingsdialog.py'
=== modified file 'openlp/core/ui/settingsform.py'
=== modified file 'openlp/core/ui/shortcutlistdialog.py'
=== modified file 'openlp/core/ui/shortcutlistform.py'
=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2013-03-04 18:01:57 +0000
+++ openlp/core/ui/slidecontroller.py	2013-03-04 21:19:34 +0000
@@ -274,9 +274,17 @@
             self.audioPauseItem = self.toolbar.addToolbarAction(u'audioPauseItem',
                 icon=u':/slides/media_playback_pause.png', text=translate('OpenLP.SlideController', 'Pause Audio'),
                 tooltip=translate('OpenLP.SlideController', 'Pause audio.'),
+<<<<<<< TREE
                 checked=False, visible=False, category=self.category, context=QtCore.Qt.WindowShortcut,
                 can_shortcuts=True, triggers=self.onAudioPauseClicked)
             self.audioMenu = QtGui.QMenu(translate('OpenLP.SlideController', 'Background Audio'), self.toolbar)
+=======
+                checked=False, visible=False, category=self.category,
+                context=QtCore.Qt.WindowShortcut,
+                shortcuts=[], triggers=self.onAudioPauseClicked)
+            self.audioMenu = QtGui.QMenu(
+                translate('OpenLP.SlideController', 'Background Audio'), self.toolbar)
+>>>>>>> MERGE-SOURCE
             self.audioPauseItem.setMenu(self.audioMenu)
             self.audioPauseItem.setParent(self.toolbar)
             self.toolbar.widgetForAction(self.audioPauseItem).setPopupMode(
@@ -639,6 +647,7 @@
         self.toolbar.hide()
         self.mediabar.hide()
         self.songMenu.hide()
+        self.toolbar.setWidgetVisible([u'songMenu'], False)
         self.toolbar.setWidgetVisible(self.loopList, False)
         self.toolbar.setWidgetVisible([u'songMenu'], False)
         # Reset the button
@@ -647,9 +656,18 @@
         self.playSlidesLoop.setChecked(False)
         self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
         if item.is_text():
+<<<<<<< TREE
             if Settings().value(self.main_window.songsSettingsSection + u'/display songbar') and self.slideList:
                 self.toolbar.setWidgetVisible([u'songMenu'], True)
         if item.is_capable(ItemCapabilities.CanLoop) and len(item.get_frames()) > 1:
+=======
+            if Settings().value(
+                self.parent().songsSettingsSection + u'/display songbar',
+                QtCore.QVariant(True)).toBool() and self.slideList:
+                self.toolbar.setWidgetVisible([u'songMenu'], True)
+        if item.is_capable(ItemCapabilities.CanLoop) and \
+            len(item.get_frames()) > 1:
+>>>>>>> MERGE-SOURCE
             self.toolbar.setWidgetVisible(self.loopList)
         if item.is_media():
             self.mediabar.show()

=== modified file 'openlp/core/ui/splashscreen.py'
=== modified file 'openlp/core/ui/starttimedialog.py'
=== modified file 'openlp/core/ui/starttimeform.py'
=== modified file 'openlp/core/ui/themeform.py'
=== modified file 'openlp/core/ui/themelayoutdialog.py'
=== modified file 'openlp/core/ui/themelayoutform.py'
=== modified file 'openlp/core/ui/thememanager.py'
=== modified file 'openlp/core/ui/themestab.py'
=== modified file 'openlp/core/ui/themewizard.py'
=== modified file 'openlp/core/ui/wizard.py'
=== modified file 'openlp/core/utils/__init__.py'
=== modified file 'openlp/core/utils/actions.py'
=== modified file 'openlp/core/utils/languagemanager.py'
=== modified file 'openlp/plugins/__init__.py'
=== modified file 'openlp/plugins/alerts/__init__.py'
=== modified file 'openlp/plugins/alerts/alertsplugin.py'
=== modified file 'openlp/plugins/alerts/forms/__init__.py'
=== modified file 'openlp/plugins/alerts/forms/alertdialog.py'
=== modified file 'openlp/plugins/alerts/forms/alertform.py'
=== modified file 'openlp/plugins/alerts/lib/__init__.py'
=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
=== modified file 'openlp/plugins/alerts/lib/alertstab.py'
=== modified file 'openlp/plugins/alerts/lib/db.py'
=== modified file 'openlp/plugins/bibles/__init__.py'
=== modified file 'openlp/plugins/bibles/bibleplugin.py'
=== modified file 'openlp/plugins/bibles/forms/__init__.py'
=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
=== modified file 'openlp/plugins/bibles/forms/bibleupgradeform.py'
=== modified file 'openlp/plugins/bibles/forms/booknamedialog.py'
=== modified file 'openlp/plugins/bibles/forms/booknameform.py'
=== modified file 'openlp/plugins/bibles/forms/editbibledialog.py'
=== modified file 'openlp/plugins/bibles/forms/editbibleform.py'
=== modified file 'openlp/plugins/bibles/forms/languagedialog.py'
=== modified file 'openlp/plugins/bibles/forms/languageform.py'
=== modified file 'openlp/plugins/bibles/lib/__init__.py'
=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
=== modified file 'openlp/plugins/bibles/lib/csvbible.py'
=== modified file 'openlp/plugins/bibles/lib/db.py'
=== modified file 'openlp/plugins/bibles/lib/http.py'
=== modified file 'openlp/plugins/bibles/lib/manager.py'
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
=== modified file 'openlp/plugins/bibles/lib/openlp1.py'
=== modified file 'openlp/plugins/bibles/lib/opensong.py'
=== modified file 'openlp/plugins/bibles/lib/osis.py'
=== modified file 'openlp/plugins/bibles/lib/upgrade.py'
=== modified file 'openlp/plugins/bibles/lib/versereferencelist.py'
=== modified file 'openlp/plugins/custom/__init__.py'
=== modified file 'openlp/plugins/custom/customplugin.py'
=== modified file 'openlp/plugins/custom/forms/__init__.py'
=== modified file 'openlp/plugins/custom/forms/editcustomdialog.py'
=== modified file 'openlp/plugins/custom/forms/editcustomform.py'
=== modified file 'openlp/plugins/custom/forms/editcustomslidedialog.py'
=== modified file 'openlp/plugins/custom/forms/editcustomslideform.py'
=== modified file 'openlp/plugins/custom/lib/__init__.py'
=== modified file 'openlp/plugins/custom/lib/customtab.py'
=== modified file 'openlp/plugins/custom/lib/customxmlhandler.py'
=== modified file 'openlp/plugins/custom/lib/db.py'
=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
=== modified file 'openlp/plugins/images/__init__.py'
=== modified file 'openlp/plugins/images/imageplugin.py'
=== modified file 'openlp/plugins/images/lib/__init__.py'
=== modified file 'openlp/plugins/images/lib/imagetab.py'
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
=== modified file 'openlp/plugins/media/__init__.py'
=== modified file 'openlp/plugins/media/lib/__init__.py'
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
=== modified file 'openlp/plugins/media/lib/mediatab.py'
=== modified file 'openlp/plugins/media/mediaplugin.py'
=== modified file 'openlp/plugins/presentations/__init__.py'
=== modified file 'openlp/plugins/presentations/lib/__init__.py'
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
=== modified file 'openlp/plugins/presentations/lib/pptviewlib/ppttest.py'
=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
=== modified file 'openlp/plugins/presentations/presentationplugin.py'
=== modified file 'openlp/plugins/remotes/__init__.py'
=== modified file 'openlp/plugins/remotes/html/index.html'
=== modified file 'openlp/plugins/remotes/html/stage.html'
=== modified file 'openlp/plugins/remotes/lib/__init__.py'
=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
=== modified file 'openlp/plugins/remotes/lib/remotetab.py'
=== modified file 'openlp/plugins/remotes/remoteplugin.py'
=== modified file 'openlp/plugins/songs/__init__.py'
=== modified file 'openlp/plugins/songs/forms/__init__.py'
=== modified file 'openlp/plugins/songs/forms/authorsdialog.py'
=== modified file 'openlp/plugins/songs/forms/authorsform.py'
=== modified file 'openlp/plugins/songs/forms/editsongdialog.py'
=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2013-02-24 18:13:50 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2013-03-04 21:19:34 +0000
@@ -116,6 +116,7 @@
         self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE)
         self.whitespace = re.compile(r'\W+', re.UNICODE)
 
+<<<<<<< TREE
     def keyPressEvent(self, event):
         """
         Reimplement the keyPressEvent to react on Return/Enter keys. When some combo boxes have focus we do not want
@@ -133,6 +134,28 @@
                 return
         QtGui.QDialog.keyPressEvent(self, event)
 
+=======
+    def keyPressEvent(self, event):
+        """
+        Reimplement the keyPressEvent to react on Return/Enter keys. When some
+        combo boxes have focus we do not want dialog's default action be
+        triggered but instead our own.
+
+        ``event``
+            A QtGui.QKeyEvent event.
+        """
+        if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
+            if self.authorsComboBox.hasFocus() and \
+                    self.authorsComboBox.currentText():
+                self.onAuthorAddButtonClicked()
+                return
+            if self.topicsComboBox.hasFocus() and \
+                    self.topicsComboBox.currentText():
+                self.onTopicAddButtonClicked()
+                return
+        QtGui.QDialog.keyPressEvent(self, event)
+
+>>>>>>> MERGE-SOURCE
     def initialise(self):
         """
         Set up the form for when it is displayed.
@@ -922,6 +945,7 @@
                 self.song.verse_order = re.sub(u'([' + verse.upper() + verse.lower() + u'])(\W|$)', r'\g<1>1\2',
                     self.song.verse_order)
         except:
+<<<<<<< TREE
             log.exception(u'Problem processing song Lyrics \n%s', sxml.dump_xml())
 
     def _get_plugin_manager(self):
@@ -943,4 +967,9 @@
         return self._theme_manager
 
     theme_manager = property(_get_theme_manager)
+=======
+            log.exception(u'Problem processing song Lyrics \n%s',
+                sxml.dump_xml())
+            raise
+>>>>>>> MERGE-SOURCE
 

=== modified file 'openlp/plugins/songs/forms/editversedialog.py'
=== modified file 'openlp/plugins/songs/forms/editverseform.py'
=== modified file 'openlp/plugins/songs/forms/mediafilesdialog.py'
=== modified file 'openlp/plugins/songs/forms/mediafilesform.py'
=== modified file 'openlp/plugins/songs/forms/songbookdialog.py'
=== modified file 'openlp/plugins/songs/forms/songbookform.py'
=== modified file 'openlp/plugins/songs/forms/songexportform.py'
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
=== modified file 'openlp/plugins/songs/forms/songmaintenancedialog.py'
=== modified file 'openlp/plugins/songs/forms/songmaintenanceform.py'
=== modified file 'openlp/plugins/songs/forms/topicsdialog.py'
=== modified file 'openlp/plugins/songs/forms/topicsform.py'
=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py	2013-02-27 12:41:04 +0000
+++ openlp/plugins/songs/lib/__init__.py	2013-03-04 21:19:34 +0000
@@ -561,9 +561,16 @@
                 failed = False
                 while True:
                     try:
+<<<<<<< TREE
                         encoding, default_encoding = get_encoding(font, font_table, default_encoding, failed=failed)
                         if not encoding:
                             return None
+=======
+                        encoding, default_encoding = get_encoding(font, 
+                            font_table, default_encoding, failed=failed)
+                        if not encoding:
+                            return None
+>>>>>>> MERGE-SOURCE
                         out.append(chr(charcode).decode(encoding))
                     except UnicodeDecodeError:
                         failed = True

=== modified file 'openlp/plugins/songs/lib/cclifileimport.py'
=== modified file 'openlp/plugins/songs/lib/db.py'
=== modified file 'openlp/plugins/songs/lib/dreambeamimport.py'
=== modified file 'openlp/plugins/songs/lib/easyslidesimport.py'
=== modified file 'openlp/plugins/songs/lib/ewimport.py'
--- openlp/plugins/songs/lib/ewimport.py	2013-02-24 18:13:50 +0000
+++ openlp/plugins/songs/lib/ewimport.py	2013-03-04 21:19:34 +0000
@@ -107,10 +107,6 @@
         self.encoding = retrieve_windows_encoding(self.encoding)
         if not self.encoding:
             return
-        # There does not appear to be a _reliable_ way of getting the number
-        # of songs/records, so let's use file blocks for measuring progress.
-        total_blocks = (db_size - header_size) / (block_size * 1024)
-        self.importWizard.progressBar.setMaximum(total_blocks)
         # Read the field description information
         db_file.seek(120)
         field_info = db_file.read(num_fields * 2)
@@ -134,12 +130,24 @@
         except IndexError:
             # This is the wrong table
             success = False
-        # Loop through each block of the file
+        # There does not appear to be a _reliable_ way of getting the number
+        # of songs/records, so loop through the file blocks and total the
+        # number of records. Store the information in a list so we dont have
+        # to do all this again.
         cur_block = first_block
+        total_count = 0
+        block_list = []
         while cur_block != 0 and success:
-            db_file.seek(header_size + ((cur_block - 1) * 1024 * block_size))
+            cur_block_pos = header_size + ((cur_block - 1) * 1024 * block_size)
+            db_file.seek(cur_block_pos)
             cur_block, rec_count = struct.unpack('<h2xh', db_file.read(6))
             rec_count = (rec_count + record_size) / record_size
+            block_list.append((cur_block_pos, rec_count))
+            total_count += rec_count
+        self.importWizard.progressBar.setMaximum(total_count)
+        for block in block_list:
+            cur_block_pos, rec_count = block
+            db_file.seek(cur_block_pos + 6)
             # Loop through each record within the current block
             for i in range(rec_count):
                 if self.stop_import_flag:
@@ -174,11 +182,19 @@
                         self.addAuthor(author_name.strip())
                 if words:
                     # Format the lyrics
+<<<<<<< TREE
                     result = strip_rtf(words, self.encoding)
                     if result is None:
                         return
                     words, self.encoding = result
                     verse_type = VerseType.tags[VerseType.Verse]
+=======
+                    result = strip_rtf(words, self.encoding)
+                    if result is None:
+                        return
+                    words, self.encoding = result
+                    verse_type = VerseType.Tags[VerseType.Verse]
+>>>>>>> MERGE-SOURCE
                     for verse in SLIDE_BREAK_REGEX.split(words):
                         verse = verse.strip()
                         if not verse:

=== modified file 'openlp/plugins/songs/lib/foilpresenterimport.py'
=== modified file 'openlp/plugins/songs/lib/importer.py'
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
=== modified file 'openlp/plugins/songs/lib/mediashoutimport.py'
=== modified file 'openlp/plugins/songs/lib/olp1import.py'
=== modified file 'openlp/plugins/songs/lib/olpimport.py'
=== modified file 'openlp/plugins/songs/lib/oooimport.py'
=== modified file 'openlp/plugins/songs/lib/openlyricsexport.py'
=== modified file 'openlp/plugins/songs/lib/openlyricsimport.py'
=== modified file 'openlp/plugins/songs/lib/opensongimport.py'
=== modified file 'openlp/plugins/songs/lib/powersongimport.py'
=== modified file 'openlp/plugins/songs/lib/sofimport.py'
=== modified file 'openlp/plugins/songs/lib/songbeamerimport.py'
=== modified file 'openlp/plugins/songs/lib/songimport.py'
--- openlp/plugins/songs/lib/songimport.py	2013-02-24 18:13:50 +0000
+++ openlp/plugins/songs/lib/songimport.py	2013-03-04 21:19:34 +0000
@@ -260,7 +260,8 @@
         elif int(verse_def[1:]) > self.verseCounts[verse_def[0]]:
             self.verseCounts[verse_def[0]] = int(verse_def[1:])
         self.verses.append([verse_def, verse_text.rstrip(), lang])
-        self.verseOrderListGenerated.append(verse_def)
+        if verse_def not in self.verseOrderListGenerated:
+            self.verseOrderListGenerated.append(verse_def)
 
     def repeatVerse(self):
         """

=== modified file 'openlp/plugins/songs/lib/songproimport.py'
=== modified file 'openlp/plugins/songs/lib/songshowplusimport.py'
--- openlp/plugins/songs/lib/songshowplusimport.py	2013-02-24 18:13:50 +0000
+++ openlp/plugins/songs/lib/songshowplusimport.py	2013-03-04 21:19:34 +0000
@@ -32,6 +32,7 @@
 """
 import os
 import logging
+import re
 import struct
 
 from openlp.core.ui.wizard import WizardStrings
@@ -44,13 +45,13 @@
 CCLI_NO = 5
 VERSE = 12
 CHORUS = 20
+BRIDGE = 24
 TOPIC = 29
 COMMENTS = 30
 VERSE_ORDER = 31
 SONG_BOOK = 35
 SONG_NUMBER = 36
 CUSTOM_VERSE = 37
-BRIDGE = 24
 
 log = logging.getLogger(__name__)
 
@@ -183,13 +184,19 @@
                 self.logError(file)
 
     def toOpenLPVerseTag(self, verse_name, ignore_unique=False):
-        if verse_name.find(" ") != -1:
-            verse_parts = verse_name.split(" ")
-            verse_type = verse_parts[0]
-            verse_number = verse_parts[1]
+        # have we got any digits?
+        # If so, verse number is everything from the digits
+        # to the end (openlp does not have concept of part verses, so
+        # just ignore any non integers on the end (including floats))
+        match = re.match(u'(\D*)(\d+)', verse_name)
+        if match:
+            verse_type = match.group(1).strip()
+            verse_number = match.group(2)
         else:
+            # otherwise we assume number 1 and take the whole prefix as
+            # the verse tag
             verse_type = verse_name
-            verse_number = "1"
+            verse_number = u'1'
         verse_type = verse_type.lower()
         if verse_type == "verse":
             verse_tag = VerseType.tags[VerseType.Verse]

=== modified file 'openlp/plugins/songs/lib/songstab.py'
=== modified file 'openlp/plugins/songs/lib/sundayplusimport.py'
=== modified file 'openlp/plugins/songs/lib/test/test_import_file.py'
=== modified file 'openlp/plugins/songs/lib/test/test_importing_lots.py'
=== modified file 'openlp/plugins/songs/lib/test/test_opensongimport.py'
=== modified file 'openlp/plugins/songs/lib/ui.py'
=== modified file 'openlp/plugins/songs/lib/upgrade.py'
=== modified file 'openlp/plugins/songs/lib/wowimport.py'
=== modified file 'openlp/plugins/songs/lib/xml.py'
=== modified file 'openlp/plugins/songs/lib/zionworximport.py'
=== modified file 'openlp/plugins/songs/songsplugin.py'
=== modified file 'openlp/plugins/songusage/__init__.py'
=== modified file 'openlp/plugins/songusage/forms/__init__.py'
=== modified file 'openlp/plugins/songusage/forms/songusagedeletedialog.py'
=== modified file 'openlp/plugins/songusage/forms/songusagedeleteform.py'
=== modified file 'openlp/plugins/songusage/forms/songusagedetaildialog.py'
=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
=== modified file 'openlp/plugins/songusage/lib/__init__.py'
=== modified file 'openlp/plugins/songusage/lib/db.py'
=== modified file 'openlp/plugins/songusage/lib/upgrade.py'
=== modified file 'openlp/plugins/songusage/songusageplugin.py'
=== modified file 'resources/__init__.py'
=== modified file 'resources/pyinstaller/hook-openlp.core.ui.media.py'
=== modified file 'resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py'
=== modified file 'resources/pyinstaller/hook-openlp.py'
=== modified file 'scripts/check_dependencies.py'
--- scripts/check_dependencies.py	2013-02-28 21:36:55 +0000
+++ scripts/check_dependencies.py	2013-03-04 21:19:34 +0000
@@ -38,6 +38,7 @@
 """
 import os
 import sys
+<<<<<<< TREE
 from distutils.version import LooseVersion
 
 # If we try to import uno before nose this will greate a warning. Just try to import nose first to supress the warning.
@@ -47,6 +48,11 @@
     pass
 
 IS_WIN = sys.platform.startswith('win')
+=======
+from distutils.version import LooseVersion
+
+is_win = sys.platform.startswith('win')
+>>>>>>> MERGE-SOURCE
 
 VERS = {
     'Python': '2.6',

=== modified file 'scripts/generate_resources.sh'
=== added file 'scripts/openlp-remoteclient.py.OTHER'
--- scripts/openlp-remoteclient.py.OTHER	1970-01-01 00:00:00 +0000
+++ scripts/openlp-remoteclient.py.OTHER	2013-03-04 21:19:34 +0000
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
+# Frode Woldsund, Martin Zibricky                                             #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+
+import urllib
+import sys
+from optparse import OptionParser
+
+def sendData(options):
+    addr = 'http://%s:%s/send/%s?q=%s' % (options.address, options.port,
+        options.event, options.message)
+    try:
+        urllib.urlopen(addr)
+        print u'Message sent ', addr
+    except:
+        print u'Error thrown ', sys.exc_info()[1]
+
+def main():
+    usage = "usage: %prog [-a address] [-p port] [-e event] [-m message]"
+    parser = OptionParser(usage=usage)
+    parser.add_option("-p", "--port", default=4316,
+                      help="IP Port number %default ")
+    parser.add_option("-a", "--address",
+                      help="Recipient address ",
+                      default="localhost")
+    parser.add_option("-e", "--event",
+                      help="Action to be performed",
+                      default="alerts_text")
+    parser.add_option("-m", "--message",
+                      help="Message to be passed for the action",
+                      default="")
+
+    (options, args) = parser.parse_args()
+    if args:
+        parser.print_help()
+        parser.error("incorrect number of arguments")
+    elif options.address is None:
+        parser.print_help()
+        parser.error("IP address missing")
+    else:
+        sendData(options)
+
+if __name__ == u'__main__':
+    main()

=== modified file 'scripts/resources.patch'
=== modified file 'scripts/translation_utils.py'
=== modified file 'setup.py'