diff --git a/openlp.pyw b/openlp.pyw
index 962109592..64ffb3321 100755
--- a/openlp.pyw
+++ b/openlp.pyw
@@ -25,254 +25,15 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-import os
-import sys
-import logging
+
# Import uuid now, to avoid the rare bug described in the support system:
# http://support.openlp.org/issues/102
# If https://bugs.gentoo.org/show_bug.cgi?id=317557 is fixed, the import can be
# removed.
import uuid
-from optparse import OptionParser
-from traceback import format_exception
-from PyQt4 import QtCore, QtGui
+from openlp.core import main
-from openlp.core.lib import Receiver, check_directory_exists
-from openlp.core.lib.ui import UiStrings
-from openlp.core.resources import qInitResources
-from openlp.core.ui.mainwindow import MainWindow
-from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
-from openlp.core.ui.firsttimeform import FirstTimeForm
-from openlp.core.ui.exceptionform import ExceptionForm
-from openlp.core.ui import SplashScreen, ScreenList
-from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \
- get_application_version, DelayStartThread
-
-log = logging.getLogger()
-
-application_stylesheet = u"""
-QMainWindow::separator
-{
- border: none;
-}
-
-QDockWidget::title
-{
- border: 1px solid palette(dark);
- padding-left: 5px;
- padding-top: 2px;
- margin: 1px 0;
-}
-
-QToolBar
-{
- border: none;
- margin: 0;
- padding: 0;
-}
-"""
-
-class OpenLP(QtGui.QApplication):
- """
- The core application class. This class inherits from Qt's QApplication
- class in order to provide the core of the application.
- """
-
- args = []
-
- def exec_(self):
- """
- Override exec method to allow the shared memory to be released on exit
- """
- QtGui.QApplication.exec_()
- self.sharedMemory.detach()
-
- def run(self, args):
- """
- Run the OpenLP application.
- """
- # On Windows, the args passed into the constructor are
- # ignored. Not very handy, so set the ones we want to use.
- self.args.extend(args)
- # provide a listener for widgets to reqest a screen update.
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'cursor_busy'), self.setBusyCursor)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'cursor_normal'), self.setNormalCursor)
- # Decide how many screens we have and their size
- screens = ScreenList(self.desktop())
- # First time checks in settings
- has_run_wizard = QtCore.QSettings().value(
- u'general/has run wizard', QtCore.QVariant(False)).toBool()
- if not has_run_wizard:
- if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted:
- QtCore.QSettings().setValue(u'general/has run wizard',
- QtCore.QVariant(True))
- if os.name == u'nt':
- self.setStyleSheet(application_stylesheet)
- show_splash = QtCore.QSettings().value(
- u'general/show splash', QtCore.QVariant(True)).toBool()
- if show_splash:
- self.splash = SplashScreen()
- self.splash.show()
- # make sure Qt really display the splash screen
- self.processEvents()
- # start the main app window
- self.mainWindow = MainWindow(self.clipboard(), self.args)
- self.mainWindow.show()
- if show_splash:
- # now kill the splashscreen
- self.splash.finish(self.mainWindow)
- log.debug(u'Splashscreen closed')
- # make sure Qt really display the splash screen
- self.processEvents()
- self.mainWindow.repaint()
- self.processEvents()
- if not has_run_wizard:
- self.mainWindow.firstTime()
- update_check = QtCore.QSettings().value(
- u'general/update check', QtCore.QVariant(True)).toBool()
- if update_check:
- VersionThread(self.mainWindow).start()
- Receiver.send_message(u'maindisplay_blank_check')
- self.mainWindow.appStartup()
- DelayStartThread(self.mainWindow).start()
- return self.exec_()
-
- def isAlreadyRunning(self):
- """
- Look to see if OpenLP is already running and ask if a 2nd copy
- is to be started.
- """
- self.sharedMemory = QtCore.QSharedMemory('OpenLP')
- if self.sharedMemory.attach():
- status = QtGui.QMessageBox.critical(None,
- UiStrings().Error, UiStrings().OpenLPStart,
- QtGui.QMessageBox.StandardButtons(
- QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
- if status == QtGui.QMessageBox.No:
- return True
- return False
- else:
- self.sharedMemory.create(1)
- return False
-
- def hookException(self, exctype, value, traceback):
- if not hasattr(self, u'mainWindow'):
- log.exception(''.join(format_exception(exctype, value, traceback)))
- return
- if not hasattr(self, u'exceptionForm'):
- self.exceptionForm = ExceptionForm(self.mainWindow)
- self.exceptionForm.exceptionTextEdit.setPlainText(
- ''.join(format_exception(exctype, value, traceback)))
- self.setNormalCursor()
- self.exceptionForm.exec_()
-
- def setBusyCursor(self):
- """
- Sets the Busy Cursor for the Application
- """
- self.setOverrideCursor(QtCore.Qt.BusyCursor)
- self.processEvents()
-
- def setNormalCursor(self):
- """
- Sets the Normal Cursor for the Application
- """
- self.restoreOverrideCursor()
-
- def event(self, event):
- """
- Enables direct file opening on OS X
- """
- if event.type() == QtCore.QEvent.FileOpen:
- file_name = event.file()
- log.debug(u'Got open file event for %s!', file_name)
- self.args.insert(0, unicode(file_name))
- return True
- else:
- return QtGui.QApplication.event(self, event)
-
-def main():
- """
- The main function which parses command line options and then runs
- the PyQt4 Application.
- """
- # Set up command line options.
- usage = 'Usage: %prog [options] [qt-options]'
- parser = OptionParser(usage=usage)
- parser.add_option('-e', '--no-error-form', dest='no_error_form',
- action='store_true', help='Disable the error notification form.')
- parser.add_option('-l', '--log-level', dest='loglevel',
- default='warning', metavar='LEVEL', help='Set logging to LEVEL '
- 'level. Valid values are "debug", "info", "warning".')
- parser.add_option('-p', '--portable', dest='portable',
- action='store_true', help='Specify if this should be run as a '
- 'portable app, off a USB flash drive (not implemented).')
- parser.add_option('-d', '--dev-version', dest='dev_version',
- action='store_true', help='Ignore the version file and pull the '
- 'version directly from Bazaar')
- parser.add_option('-s', '--style', dest='style',
- help='Set the Qt4 style (passed directly to Qt4).')
- # Set up logging
- log_path = AppLocation.get_directory(AppLocation.CacheDir)
- check_directory_exists(log_path)
- filename = os.path.join(log_path, u'openlp.log')
- logfile = logging.FileHandler(filename, u'w')
- logfile.setFormatter(logging.Formatter(
- u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
- log.addHandler(logfile)
- logging.addLevelName(15, u'Timer')
- # Parse command line options and deal with them.
- (options, args) = parser.parse_args()
- qt_args = []
- if options.loglevel.lower() in ['d', 'debug']:
- log.setLevel(logging.DEBUG)
- print 'Logging to:', filename
- elif options.loglevel.lower() in ['w', 'warning']:
- log.setLevel(logging.WARNING)
- else:
- log.setLevel(logging.INFO)
- if options.style:
- qt_args.extend(['-style', options.style])
- # Throw the rest of the arguments at Qt, just in case.
- qt_args.extend(args)
- # Initialise the resources
- qInitResources()
- # Now create and actually run the application.
- app = OpenLP(qt_args)
- # Instance check
- if app.isAlreadyRunning():
- sys.exit()
- app.setOrganizationName(u'OpenLP')
- app.setOrganizationDomain(u'openlp.org')
- app.setApplicationName(u'OpenLP')
- app.setApplicationVersion(get_application_version()[u'version'])
- # First time checks in settings
- if not QtCore.QSettings().value(u'general/has run wizard',
- QtCore.QVariant(False)).toBool():
- if not FirstTimeLanguageForm().exec_():
- # if cancel then stop processing
- sys.exit()
- if sys.platform == u'darwin':
- OpenLP.addLibraryPath(QtGui.QApplication.applicationDirPath()
- + "/qt4_plugins")
- # i18n Set Language
- language = LanguageManager.get_language()
- app_translator, default_translator = \
- LanguageManager.get_translator(language)
- if not app_translator.isEmpty():
- app.installTranslator(app_translator)
- if not default_translator.isEmpty():
- app.installTranslator(default_translator)
- else:
- log.debug(u'Could not find default_translator.')
- if not options.no_error_form:
- sys.excepthook = app.hookException
- sys.exit(app.run(qt_args))
if __name__ == u'__main__':
"""
diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py
index e19b9a257..896066e73 100644
--- a/openlp/core/__init__.py
+++ b/openlp/core/__init__.py
@@ -24,9 +24,265 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+
+__all__ = ('OpenLP', 'main')
+
+import os
+import sys
+import logging
+from optparse import OptionParser
+from traceback import format_exception
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import Receiver, check_directory_exists
+from openlp.core.lib.ui import UiStrings
+from openlp.core.resources import qInitResources
+from openlp.core.ui.mainwindow import MainWindow
+from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
+from openlp.core.ui.firsttimeform import FirstTimeForm
+from openlp.core.ui.exceptionform import ExceptionForm
+from openlp.core.ui import SplashScreen, ScreenList
+from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \
+ get_application_version, DelayStartThread
+
+log = logging.getLogger()
+
+
"""
The :mod:`core` module provides all core application functions
All the core functions of the OpenLP application including the GUI, settings,
logging and a plugin framework are contained within the openlp.core module.
"""
+
+application_stylesheet = u"""
+QMainWindow::separator
+{
+ border: none;
+}
+
+QDockWidget::title
+{
+ border: 1px solid palette(dark);
+ padding-left: 5px;
+ padding-top: 2px;
+ margin: 1px 0;
+}
+
+QToolBar
+{
+ border: none;
+ margin: 0;
+ padding: 0;
+}
+"""
+
+
+class OpenLP(QtGui.QApplication):
+ """
+ The core application class. This class inherits from Qt's QApplication
+ class in order to provide the core of the application.
+ """
+
+ args = []
+
+ def exec_(self):
+ """
+ Override exec method to allow the shared memory to be released on exit
+ """
+ QtGui.QApplication.exec_()
+ self.sharedMemory.detach()
+
+ def run(self, args, testing=False):
+ """
+ Run the OpenLP application.
+ """
+ # On Windows, the args passed into the constructor are
+ # ignored. Not very handy, so set the ones we want to use.
+ self.args.extend(args)
+ # provide a listener for widgets to reqest a screen update.
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'cursor_busy'), self.setBusyCursor)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'cursor_normal'), self.setNormalCursor)
+ # Decide how many screens we have and their size
+ screens = ScreenList(self.desktop())
+ # First time checks in settings
+ has_run_wizard = QtCore.QSettings().value(
+ u'general/has run wizard', QtCore.QVariant(False)).toBool()
+ if not has_run_wizard:
+ if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted:
+ QtCore.QSettings().setValue(u'general/has run wizard',
+ QtCore.QVariant(True))
+ if os.name == u'nt':
+ self.setStyleSheet(application_stylesheet)
+ show_splash = QtCore.QSettings().value(
+ u'general/show splash', QtCore.QVariant(True)).toBool()
+ if show_splash:
+ self.splash = SplashScreen()
+ self.splash.show()
+ # make sure Qt really display the splash screen
+ self.processEvents()
+ # start the main app window
+ self.mainWindow = MainWindow(self.clipboard(), self.args)
+ self.mainWindow.show()
+ if show_splash:
+ # now kill the splashscreen
+ self.splash.finish(self.mainWindow)
+ log.debug(u'Splashscreen closed')
+ # make sure Qt really display the splash screen
+ self.processEvents()
+ self.mainWindow.repaint()
+ self.processEvents()
+ if not has_run_wizard:
+ self.mainWindow.firstTime()
+ update_check = QtCore.QSettings().value(
+ u'general/update check', QtCore.QVariant(True)).toBool()
+ if update_check:
+ VersionThread(self.mainWindow).start()
+ Receiver.send_message(u'maindisplay_blank_check')
+ self.mainWindow.appStartup()
+ DelayStartThread(self.mainWindow).start()
+ # Skip exec_() for gui tests
+ if not testing:
+ return self.exec_()
+
+ def isAlreadyRunning(self):
+ """
+ Look to see if OpenLP is already running and ask if a 2nd copy
+ is to be started.
+ """
+ self.sharedMemory = QtCore.QSharedMemory('OpenLP')
+ if self.sharedMemory.attach():
+ status = QtGui.QMessageBox.critical(None,
+ UiStrings().Error, UiStrings().OpenLPStart,
+ QtGui.QMessageBox.StandardButtons(
+ QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
+ if status == QtGui.QMessageBox.No:
+ return True
+ return False
+ else:
+ self.sharedMemory.create(1)
+ return False
+
+ def hookException(self, exctype, value, traceback):
+ if not hasattr(self, u'mainWindow'):
+ log.exception(''.join(format_exception(exctype, value, traceback)))
+ return
+ if not hasattr(self, u'exceptionForm'):
+ self.exceptionForm = ExceptionForm(self.mainWindow)
+ self.exceptionForm.exceptionTextEdit.setPlainText(
+ ''.join(format_exception(exctype, value, traceback)))
+ self.setNormalCursor()
+ self.exceptionForm.exec_()
+
+ def setBusyCursor(self):
+ """
+ Sets the Busy Cursor for the Application
+ """
+ self.setOverrideCursor(QtCore.Qt.BusyCursor)
+ self.processEvents()
+
+ def setNormalCursor(self):
+ """
+ Sets the Normal Cursor for the Application
+ """
+ self.restoreOverrideCursor()
+
+ def event(self, event):
+ """
+ Enables direct file opening on OS X
+ """
+ if event.type() == QtCore.QEvent.FileOpen:
+ file_name = event.file()
+ log.debug(u'Got open file event for %s!', file_name)
+ self.args.insert(0, unicode(file_name))
+ return True
+ else:
+ return QtGui.QApplication.event(self, event)
+
+
+def main(args=None):
+ """
+ The main function which parses command line options and then runs
+ the PyQt4 Application.
+ """
+ # Set up command line options.
+ usage = 'Usage: %prog [options] [qt-options]'
+ parser = OptionParser(usage=usage)
+ parser.add_option('-e', '--no-error-form', dest='no_error_form',
+ action='store_true', help='Disable the error notification form.')
+ parser.add_option('-l', '--log-level', dest='loglevel',
+ default='warning', metavar='LEVEL', help='Set logging to LEVEL '
+ 'level. Valid values are "debug", "info", "warning".')
+ parser.add_option('-p', '--portable', dest='portable',
+ action='store_true', help='Specify if this should be run as a '
+ 'portable app, off a USB flash drive (not implemented).')
+ parser.add_option('-d', '--dev-version', dest='dev_version',
+ action='store_true', help='Ignore the version file and pull the '
+ 'version directly from Bazaar')
+ parser.add_option('-s', '--style', dest='style',
+ help='Set the Qt4 style (passed directly to Qt4).')
+ parser.add_option('--testing', dest='testing',
+ action='store_true', help='Run by testing framework')
+ # Set up logging
+ log_path = AppLocation.get_directory(AppLocation.CacheDir)
+ check_directory_exists(log_path)
+ filename = os.path.join(log_path, u'openlp.log')
+ logfile = logging.FileHandler(filename, u'w')
+ logfile.setFormatter(logging.Formatter(
+ u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
+ log.addHandler(logfile)
+ logging.addLevelName(15, u'Timer')
+ # Parse command line options and deal with them.
+ # Use args supplied programatically if possible.
+ (options, args) = parser.parse_args(args) if args else parser.parse_args()
+ qt_args = []
+ if options.loglevel.lower() in ['d', 'debug']:
+ log.setLevel(logging.DEBUG)
+ print 'Logging to:', filename
+ elif options.loglevel.lower() in ['w', 'warning']:
+ log.setLevel(logging.WARNING)
+ else:
+ log.setLevel(logging.INFO)
+ if options.style:
+ qt_args.extend(['-style', options.style])
+ # Throw the rest of the arguments at Qt, just in case.
+ qt_args.extend(args)
+ # Initialise the resources
+ qInitResources()
+ # Now create and actually run the application.
+ app = OpenLP(qt_args)
+ app.setOrganizationName(u'OpenLP')
+ app.setOrganizationDomain(u'openlp.org')
+ app.setApplicationName(u'OpenLP')
+ app.setApplicationVersion(get_application_version()[u'version'])
+ # Instance check
+ if app.isAlreadyRunning():
+ sys.exit()
+ # First time checks in settings
+ if not QtCore.QSettings().value(u'general/has run wizard',
+ QtCore.QVariant(False)).toBool():
+ if not FirstTimeLanguageForm().exec_():
+ # if cancel then stop processing
+ sys.exit()
+ # i18n Set Language
+ language = LanguageManager.get_language()
+ app_translator, default_translator = \
+ LanguageManager.get_translator(language)
+ if not app_translator.isEmpty():
+ app.installTranslator(app_translator)
+ if not default_translator.isEmpty():
+ app.installTranslator(default_translator)
+ else:
+ log.debug(u'Could not find default_translator.')
+ if not options.no_error_form:
+ sys.excepthook = app.hookException
+ # Do not run method app.exec_() when running gui tests
+ if options.testing:
+ app.run(qt_args, testing=True)
+ else:
+ sys.exit(app.run(qt_args))
diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py
index 7ad743235..2e5d011cf 100644
--- a/openlp/core/lib/db.py
+++ b/openlp/core/lib/db.py
@@ -79,8 +79,11 @@ def upgrade_db(url, upgrade):
Provides a class for the metadata table.
"""
pass
-
- tables = upgrade.upgrade_setup(metadata)
+ load_changes = True
+ try:
+ tables = upgrade.upgrade_setup(metadata)
+ except SQLAlchemyError, DBAPIError:
+ load_changes = False
metadata_table = Table(u'metadata', metadata,
Column(u'key', types.Unicode(64), primary_key=True),
Column(u'value', types.UnicodeText(), default=None)
@@ -96,16 +99,21 @@ def upgrade_db(url, upgrade):
if version > upgrade.__version__:
return version, upgrade.__version__
version += 1
- while hasattr(upgrade, u'upgrade_%d' % version):
- log.debug(u'Running upgrade_%d', version)
- try:
- getattr(upgrade, u'upgrade_%d' % version)(session, metadata, tables)
- version_meta.value = unicode(version)
- except SQLAlchemyError, DBAPIError:
- log.exception(u'Could not run database upgrade script "upgrade_%s"'\
- ', upgrade process has been halted.', version)
- break
- version += 1
+ if load_changes:
+ while hasattr(upgrade, u'upgrade_%d' % version):
+ log.debug(u'Running upgrade_%d', version)
+ try:
+ getattr(upgrade, u'upgrade_%d' % version) \
+ (session, metadata, tables)
+ version_meta.value = unicode(version)
+ except SQLAlchemyError, DBAPIError:
+ log.exception(u'Could not run database upgrade script '
+ '"upgrade_%s", upgrade process has been halted.', version)
+ break
+ version += 1
+ else:
+ version_meta = Metadata.populate(key=u'version',
+ value=int(upgrade.__version__))
session.add(version_meta)
session.commit()
return int(version_meta.value), upgrade.__version__
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index a721fabf6..f21d8df50 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -377,7 +377,7 @@ class MediaManagerItem(QtGui.QWidget):
"""
names = []
for count in range(0, self.listView.count()):
- names.append(self.listView.item(count).text())
+ names.append(unicode(self.listView.item(count).text()))
newFiles = []
duplicatesFound = False
for file in files:
@@ -396,7 +396,7 @@ class MediaManagerItem(QtGui.QWidget):
critical_error_message_box(
UiStrings().Duplicate,
unicode(translate('OpenLP.MediaManagerItem',
- 'Duplicate files found on import and ignored.')))
+ 'Duplicate files were found on import and were ignored.')))
def contextMenu(self, point):
item = self.listView.itemAt(point)
diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py
index 9ea9c8094..185d74878 100644
--- a/openlp/core/lib/renderer.py
+++ b/openlp/core/lib/renderer.py
@@ -228,15 +228,50 @@ class Renderer(object):
# Clean up line endings.
lines = self._lines_split(text)
pages = self._paginate_slide(lines, line_end)
- if len(pages) > 1:
- # Songs and Custom
- if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
- # Do not forget the line breaks!
- slides = text.split(u'[---]')
- pages = []
- for slide in slides:
- lines = slide.strip(u'\n').split(u'\n')
+ # Songs and Custom
+ if item.is_capable(ItemCapabilities.AllowsVirtualSplit) and \
+ len(pages) > 1 and u'[---]' in text:
+ pages = []
+ while True:
+ slides = text.split(u'\n[---]\n', 2)
+ # If there are (at least) two occurrences of [---] we use
+ # the first two slides (and neglect the last for now).
+ if len(slides) == 3:
+ html_text = expand_tags(u'\n'.join(slides[:2]))
+ # We check both slides to determine if the virtual break is
+ # needed (there is only one virtual break).
+ else:
+ html_text = expand_tags(u'\n'.join(slides))
+ html_text = html_text.replace(u'\n', u'
')
+ if self._text_fits_on_slide(html_text):
+ # The first two virtual slides fit (as a whole) on one
+ # slide. Replace the first occurrence of [---].
+ text = text.replace(u'\n[---]', u'', 1)
+ else:
+ # The first virtual slide fits, which means we have to
+ # render the first virtual slide.
+ text_contains_break = u'[---]' in text
+ if text_contains_break:
+ text_to_render, text = text.split(u'\n[---]\n', 1)
+ else:
+ text_to_render = text
+ text = u''
+ lines = text_to_render.strip(u'\n').split(u'\n')
+ slides = self._paginate_slide(lines, line_end)
+ if len(slides) > 1 and text:
+ # Add all slides apart from the last one the list.
+ pages.extend(slides[:-1])
+ if text_contains_break:
+ text = slides[-1] + u'\n[---]\n' + text
+ else:
+ text = slides[-1] + u'\n'+ text
+ text = text.replace(u'
', u'\n')
+ else:
+ pages.extend(slides)
+ if u'[---]' not in text:
+ lines = text.strip(u'\n').split(u'\n')
pages.extend(self._paginate_slide(lines, line_end))
+ break
new_pages = []
for page in pages:
while page.endswith(u'
'):
@@ -342,7 +377,7 @@ class Renderer(object):
separator = u'
'
html_lines = map(expand_tags, lines)
# Text too long so go to next page.
- if self._text_fits_on_slide(separator.join(html_lines)):
+ if not self._text_fits_on_slide(separator.join(html_lines)):
html_text, previous_raw = self._binary_chop(formatted,
previous_html, previous_raw, html_lines, lines, separator, u'')
else:
@@ -375,18 +410,18 @@ class Renderer(object):
line = line.strip()
html_line = expand_tags(line)
# Text too long so go to next page.
- if self._text_fits_on_slide(previous_html + html_line):
+ if not self._text_fits_on_slide(previous_html + html_line):
# Check if there was a verse before the current one and append
# it, when it fits on the page.
if previous_html:
- if not self._text_fits_on_slide(previous_html):
+ if self._text_fits_on_slide(previous_html):
formatted.append(previous_raw)
previous_html = u''
previous_raw = u''
# Now check if the current verse will fit, if it does
# not we have to start to process the verse word by
# word.
- if not self._text_fits_on_slide(html_line):
+ if self._text_fits_on_slide(html_line):
previous_html = html_line + line_end
previous_raw = line + line_end
continue
@@ -443,7 +478,7 @@ class Renderer(object):
highest_index = len(html_list) - 1
index = int(highest_index / 2)
while True:
- if self._text_fits_on_slide(
+ if not self._text_fits_on_slide(
previous_html + separator.join(html_list[:index + 1]).strip()):
# We know that it does not fit, so change/calculate the
# new index and highest_index accordingly.
@@ -466,8 +501,8 @@ class Renderer(object):
else:
continue
# Check if the remaining elements fit on the slide.
- if not self._text_fits_on_slide(
- separator.join(html_list[index + 1:]).strip()):
+ if self._text_fits_on_slide(
+ separator.join(html_list[index + 1:]).strip()):
previous_html = separator.join(
html_list[index + 1:]).strip() + line_end
previous_raw = separator.join(
@@ -489,11 +524,11 @@ class Renderer(object):
returned, otherwise ``False``.
``text``
- The text to check. It can contain HTML tags.
+ The text to check. It may contain HTML tags.
"""
self.web_frame.evaluateJavaScript(u'show_text("%s")' %
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
- return self.web_frame.contentsSize().height() > self.page_height
+ return self.web_frame.contentsSize().height() <= self.page_height
def _words_split(self, line):
"""
diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py
index 3e941c051..f4a732fb6 100644
--- a/openlp/core/ui/aboutdialog.py
+++ b/openlp/core/ui/aboutdialog.py
@@ -116,7 +116,7 @@ class Ui_AboutDialog(object):
u'Scott "sguerrieri" Guerrieri',
u'Matthias "matthub" Hub', u'Meinert "m2j" Jordan',
u'Armin "orangeshirt" K\xf6hler', u'Joshua "milleja46" Miller',
- u'Stevan "StevanP" Pettit', u'Mattias "mahfiaz" P\xf5ldaru',
+ u'Stevan "ElderP" Pettit', u'Mattias "mahfiaz" P\xf5ldaru',
u'Christian "crichter" Richter', u'Philip "Phill" Ridout',
u'Simon "samscudder" Scudder', u'Jeffrey "whydoubt" Smith',
u'Maikel Stuivenberg', u'Frode "frodus" Woldsund']
@@ -125,7 +125,7 @@ class Ui_AboutDialog(object):
packagers = ['Thomas "tabthorpe" Abthorpe (FreeBSD)',
u'Tim "TRB143" Bentley (Fedora)',
u'Matthias "matthub" Hub (Mac OS X)',
- u'Stevan "StevanP" Pettit (Windows)',
+ u'Stevan "ElderP" Pettit (Windows)',
u'Raoul "superfly" Snyman (Ubuntu)']
translators = {
u'af': [u'Johan "nuvolari" Mynhardt'],
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 4ecf792bc..e77112644 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -30,11 +30,13 @@ import os
import sys
import shutil
from tempfile import gettempdir
+from datetime import datetime
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
- PluginManager, Receiver, translate, ImageManager, PluginStatus
+ PluginManager, Receiver, translate, ImageManager, PluginStatus, \
+ SettingsManager
from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \
icon_action, shortcut_action
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
@@ -214,7 +216,7 @@ class Ui_MainWindow(object):
self.mediaManagerDock.isVisible(), UiStrings().View)
self.viewThemeManagerItem = shortcut_action(mainWindow,
u'viewThemeManagerItem', [QtGui.QKeySequence(u'F10')],
- self.toggleThemeManager, u':/system/system_thememanager.png',
+ self.toggleThemeManager, u':/system/system_thememanager.png',
self.themeManagerDock.isVisible(), UiStrings().View)
self.viewServiceManagerItem = shortcut_action(mainWindow,
u'viewServiceManagerItem', [QtGui.QKeySequence(u'F9')],
@@ -284,6 +286,10 @@ class Ui_MainWindow(object):
self.settingsConfigureItem = icon_action(mainWindow,
u'settingsConfigureItem', u':/system/system_settings.png',
category=UiStrings().Settings)
+ self.settingsImportItem = base_action(mainWindow,
+ u'settingsImportItem', category=UiStrings().Settings)
+ self.settingsExportItem = base_action(mainWindow,
+ u'settingsExportItem', category=UiStrings().Settings)
action_list.add_category(UiStrings().Help, CategoryOrder.standardMenu)
self.aboutItem = shortcut_action(mainWindow, u'aboutItem',
[QtGui.QKeySequence(u'Ctrl+F1')], self.onAboutItemClicked,
@@ -301,10 +307,10 @@ class Ui_MainWindow(object):
u':/system/system_online_help.png', category=UiStrings().Help)
self.webSiteItem = base_action(
mainWindow, u'webSiteItem', category=UiStrings().Help)
- add_actions(self.fileImportMenu,
- (self.importThemeItem, self.importLanguageItem))
- add_actions(self.fileExportMenu,
- (self.exportThemeItem, self.exportLanguageItem))
+ add_actions(self.fileImportMenu, (self.settingsImportItem, None,
+ self.importThemeItem, self.importLanguageItem))
+ add_actions(self.fileExportMenu, (self.settingsExportItem, None,
+ self.exportThemeItem, self.exportLanguageItem))
add_actions(self.fileMenu, (self.fileNewItem, self.fileOpenItem,
self.fileSaveItem, self.fileSaveAsItem,
self.recentFilesMenu.menuAction(), None,
@@ -357,6 +363,7 @@ class Ui_MainWindow(object):
self.importLanguageItem.setVisible(False)
self.exportLanguageItem.setVisible(False)
self.setLockPanel(panelLocked)
+ self.settingsImported = False
def retranslateUi(self, mainWindow):
"""
@@ -420,6 +427,15 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', 'Configure &Formatting Tags...'))
self.settingsConfigureItem.setText(
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
+ self.settingsExportItem.setStatusTip(translate('OpenLP.MainWindow',
+ 'Export OpenLP settings to a specified *.config file'))
+ self.settingsExportItem.setText(
+ translate('OpenLP.MainWindow', 'Settings'))
+ self.settingsImportItem.setStatusTip(translate('OpenLP.MainWindow',
+ 'Import OpenLP settings from a specified *.config file previously '
+ 'exported on this or another machine'))
+ self.settingsImportItem.setText(
+ translate('OpenLP.MainWindow', 'Settings'))
self.viewMediaManagerItem.setText(
translate('OpenLP.MainWindow', '&Media Manager'))
self.viewMediaManagerItem.setToolTip(
@@ -523,8 +539,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# (not for use by plugins)
self.uiSettingsSection = u'user interface'
self.generalSettingsSection = u'general'
- self.serviceSettingsSection = u'servicemanager'
+ self.advancedlSettingsSection = u'advanced'
+ self.servicemanagerSettingsSection = u'servicemanager'
self.songsSettingsSection = u'songs'
+ self.themesSettingsSection = u'themes'
+ self.displayTagsSection = u'displayTags'
+ self.headerSection = u'SettingsImport'
self.serviceNotSaved = False
self.aboutForm = AboutForm(self)
self.settingsForm = SettingsForm(self, self)
@@ -573,6 +593,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
QtCore.QObject.connect(self.settingsShortcutsItem,
QtCore.SIGNAL(u'triggered()'), self.onSettingsShortcutsItemClicked)
+ QtCore.QObject.connect(self.settingsImportItem,
+ QtCore.SIGNAL(u'triggered()'), self.onSettingsImportItemClicked)
+ QtCore.QObject.connect(self.settingsExportItem,
+ QtCore.SIGNAL(u'triggered()'), self.onSettingsExportItemClicked)
# i18n set signals for languages
self.languageGroup.triggered.connect(LanguageManager.set_language)
QtCore.QObject.connect(self.modeDefaultItem,
@@ -767,6 +791,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.themeManagerContents.loadThemes(True)
Receiver.send_message(u'theme_update_global',
self.themeManagerContents.global_theme)
+ # Check if any Bibles downloaded. If there are, they will be
+ # processed.
+ Receiver.send_message(u'bibles_load_list', True)
def blankCheck(self):
"""
@@ -868,6 +895,172 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if self.shortcutForm.exec_():
self.shortcutForm.save()
+ def onSettingsImportItemClicked(self):
+ """
+ Import settings from an export INI file
+ """
+ answer = QtGui.QMessageBox.critical(self,
+ translate('OpenLP.MainWindow', 'Import settings?'),
+ translate('OpenLP.MainWindow',
+ 'Are you sure you want to import settings?\n\n'
+ 'Importing settings will make permanent changes to your current '
+ 'OpenLP configuration.\n\n'
+ 'Importing incorrect settings may cause erratic behaviour or '
+ 'OpenLP to terminate abnormally.'),
+ QtGui.QMessageBox.StandardButtons(
+ QtGui.QMessageBox.Yes |
+ QtGui.QMessageBox.No),
+ QtGui.QMessageBox.No)
+ if answer == QtGui.QMessageBox.No:
+ return
+ importFileName = unicode(QtGui.QFileDialog.getOpenFileName(self,
+ translate('OpenLP.MainWindow', 'Open File'),
+ '',
+ translate('OpenLP.MainWindow',
+ 'OpenLP Export Settings Files (*.conf)')))
+ if not importFileName:
+ return
+ settingSections = []
+ # Add main sections.
+ settingSections.extend([self.generalSettingsSection])
+ settingSections.extend([self.advancedlSettingsSection])
+ settingSections.extend([self.uiSettingsSection])
+ settingSections.extend([self.servicemanagerSettingsSection])
+ settingSections.extend([self.themesSettingsSection])
+ settingSections.extend([self.displayTagsSection])
+ settingSections.extend([self.headerSection])
+ # Add plugin sections.
+ for plugin in self.pluginManager.plugins:
+ settingSections.extend([plugin.name])
+ settings = QtCore.QSettings()
+ importSettings = QtCore.QSettings(importFileName,
+ QtCore.QSettings.IniFormat)
+ importKeys = importSettings.allKeys()
+ for sectionKey in importKeys:
+ # We need to handle the really bad files.
+ try:
+ section, key = sectionKey.split(u'/')
+ except ValueError:
+ section = u'unknown'
+ key = u''
+ # Switch General back to lowercase.
+ if section == u'General':
+ section = u'general'
+ sectionKey = section + "/" + key
+ # Make sure it's a valid section for us.
+ if not section in settingSections:
+ QtGui.QMessageBox.critical(self,
+ translate('OpenLP.MainWindow', 'Import settings'),
+ translate('OpenLP.MainWindow',
+ 'The file you selected does appear to be a valid OpenLP '
+ 'settings file.\n\n'
+ 'Section [%s] is not valid \n\n'
+ 'Processing has terminated and no changed have been made.'
+ % section),
+ QtGui.QMessageBox.StandardButtons(
+ QtGui.QMessageBox.Ok))
+ return
+ # We have a good file, import it.
+ for sectionKey in importKeys:
+ value = importSettings.value(sectionKey)
+ settings.setValue(u'%s' % (sectionKey) ,
+ QtCore.QVariant(value))
+ now = datetime.now()
+ settings.beginGroup(self.headerSection)
+ settings.setValue( u'file_imported' , QtCore.QVariant(importFileName))
+ settings.setValue(u'file_date_imported',
+ now.strftime("%Y-%m-%d %H:%M"))
+ settings.endGroup()
+ settings.sync()
+ # We must do an immediate restart or current configuration will
+ # overwrite what was just imported when application terminates
+ # normally. We need to exit without saving configuration.
+ QtGui.QMessageBox.information(self,
+ translate('OpenLP.MainWindow', 'Import settings'),
+ translate('OpenLP.MainWindow',
+ 'OpenLP will now close. Imported settings will '
+ 'be applied the next time you start OpenLP.'),
+ QtGui.QMessageBox.StandardButtons(
+ QtGui.QMessageBox.Ok))
+ self.settingsImported = True
+ self.cleanUp()
+ QtCore.QCoreApplication.exit()
+
+ def onSettingsExportItemClicked(self, exportFileName=None):
+ """
+ Export settings to an INI file
+ """
+ if not exportFileName:
+ exportFileName = unicode(QtGui.QFileDialog.getSaveFileName(self,
+ translate('OpenLP.MainWindow', 'Export Settings File'), '',
+ translate('OpenLP.MainWindow',
+ 'OpenLP Export Settings File (*.conf)')))
+ if not exportFileName:
+ return
+ # Make sure it's an .ini file.
+ if not exportFileName.endswith(u'conf'):
+ exportFileName = exportFileName + u'.conf'
+ temp_file = os.path.join(unicode(gettempdir()),
+ u'openlp', u'exportIni.tmp')
+ self.saveSettings()
+ settingSections = []
+ # Add main sections.
+ settingSections.extend([self.generalSettingsSection])
+ settingSections.extend([self.advancedlSettingsSection])
+ settingSections.extend([self.uiSettingsSection])
+ settingSections.extend([self.servicemanagerSettingsSection])
+ settingSections.extend([self.themesSettingsSection])
+ settingSections.extend([self.displayTagsSection])
+ # Add plugin sections.
+ for plugin in self.pluginManager.plugins:
+ settingSections.extend([plugin.name])
+ # Delete old files if found.
+ if os.path.exists(temp_file):
+ os.remove(temp_file)
+ if os.path.exists(exportFileName):
+ os.remove(exportFileName)
+ settings = QtCore.QSettings()
+ settings.remove(self.headerSection)
+ # Get the settings.
+ keys = settings.allKeys()
+ exportSettings = QtCore.QSettings(temp_file,
+ QtCore.QSettings.IniFormat)
+ # Add a header section.
+ # This is to insure it's our ini file for import.
+ now = datetime.now()
+ applicationVersion = get_application_version()
+ # Write INI format using Qsettings.
+ # Write our header.
+ exportSettings.beginGroup(self.headerSection)
+ exportSettings.setValue(u'Make_Changes', u'At_Own_RISK')
+ exportSettings.setValue(u'type', u'OpenLP_settings_export')
+ exportSettings.setValue(u'file_date_created',
+ now.strftime("%Y-%m-%d %H:%M"))
+ exportSettings.setValue(u'version', applicationVersion[u'full'])
+ exportSettings.endGroup()
+ # Write all the sections and keys.
+ for sectionKey in keys:
+ section, key = sectionKey.split(u'/')
+ keyValue = settings.value(sectionKey)
+ sectionKey = section + u"/" + key
+ # Change the service section to servicemanager.
+ if section == u'service':
+ sectionKey = u'servicemanager/' + key
+ exportSettings.setValue(sectionKey, keyValue)
+ exportSettings.sync()
+ # Temp INI file has been written. Blanks in keys are now '%20'.
+ # Read the temp file and output the user's INI file with blanks to
+ # make it more readable.
+ tempIni = open(temp_file, u'r')
+ exportIni = open(exportFileName, u'w')
+ for fileRecord in tempIni:
+ fileRecord = fileRecord.replace(u'%20', u' ')
+ exportIni.write(fileRecord)
+ tempIni.close()
+ exportIni.close()
+ os.remove(temp_file)
+ return
+
def onModeDefaultItemClicked(self):
"""
Put OpenLP into "Default" view mode.
@@ -920,6 +1113,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
Hook to close the main window and display windows on exit
"""
+ # If we just did a settings import, close without saving changes.
+ if self.settingsImported:
+ event.accept()
if self.serviceManagerContents.isModified():
ret = self.serviceManagerContents.saveModifiedService()
if ret == QtGui.QMessageBox.Save:
@@ -1117,6 +1313,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
Save the main window settings.
"""
+ # Exit if we just did a settings import.
+ if self.settingsImported:
+ return
log.debug(u'Saving QSettings')
settings = QtCore.QSettings()
settings.beginGroup(self.generalSettingsSection)
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index 3ab2e9239..20edab792 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -290,7 +290,7 @@ class ServiceManager(QtGui.QWidget):
QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
# Last little bits of setting up
self.service_theme = unicode(QtCore.QSettings().value(
- self.mainwindow.serviceSettingsSection + u'/service theme',
+ self.mainwindow.servicemanagerSettingsSection + u'/service theme',
QtCore.QVariant(u'')).toString())
self.servicePath = AppLocation.get_section_data_path(u'servicemanager')
# build the drag and drop context menu
@@ -371,7 +371,7 @@ class ServiceManager(QtGui.QWidget):
self.mainwindow.setServiceModified(self.isModified(),
self.shortFileName())
QtCore.QSettings(). \
- setValue(u'service/last file',QtCore.QVariant(fileName))
+ setValue(u'servicemanager/last file',QtCore.QVariant(fileName))
def fileName(self):
"""
@@ -429,14 +429,15 @@ class ServiceManager(QtGui.QWidget):
self.mainwindow,
translate('OpenLP.ServiceManager', 'Open File'),
SettingsManager.get_last_dir(
- self.mainwindow.serviceSettingsSection),
+ self.mainwindow.servicemanagerSettingsSection),
translate('OpenLP.ServiceManager',
'OpenLP Service Files (*.osz)')))
if not fileName:
return False
else:
fileName = loadFile
- SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,
+ SettingsManager.set_last_dir(
+ self.mainwindow.servicemanagerSettingsSection,
split_filename(fileName)[0])
self.loadFile(fileName)
@@ -461,7 +462,7 @@ class ServiceManager(QtGui.QWidget):
self.setFileName(u'')
self.setModified(False)
QtCore.QSettings(). \
- setValue(u'service/last file',QtCore.QVariant(u''))
+ setValue(u'servicemanager/last file',QtCore.QVariant(u''))
def saveFile(self):
"""
@@ -474,7 +475,8 @@ class ServiceManager(QtGui.QWidget):
(basename, extension) = os.path.splitext(file_name)
service_file_name = basename + '.osd'
log.debug(u'ServiceManager.saveFile - %s' % path_file_name)
- SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection,
+ SettingsManager.set_last_dir(
+ self.mainwindow.servicemanagerSettingsSection,
path)
service = []
write_list = []
@@ -562,7 +564,7 @@ class ServiceManager(QtGui.QWidget):
fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow,
UiStrings().SaveService,
SettingsManager.get_last_dir(
- self.mainwindow.serviceSettingsSection),
+ self.mainwindow.servicemanagerSettingsSection),
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
if not fileName:
return False
@@ -584,8 +586,8 @@ class ServiceManager(QtGui.QWidget):
fileTo = None
try:
zip = zipfile.ZipFile(fileName)
- for file in zip.namelist():
- ucsfile = file_is_unicode(file)
+ for zipinfo in zip.infolist():
+ ucsfile = file_is_unicode(zipinfo.filename)
if not ucsfile:
critical_error_message_box(
message=translate('OpenLP.ServiceManager',
@@ -593,14 +595,11 @@ class ServiceManager(QtGui.QWidget):
'The content encoding is not UTF-8.'))
continue
osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile))
- filePath = os.path.join(self.servicePath,
- os.path.split(osfile)[1])
- fileTo = open(filePath, u'wb')
- fileTo.write(zip.read(file))
- fileTo.flush()
- fileTo.close()
- if filePath.endswith(u'osd'):
- p_file = filePath
+ filename_only = os.path.split(osfile)[1]
+ zipinfo.filename = filename_only
+ zip.extract(zipinfo, self.servicePath)
+ if filename_only.endswith(u'osd'):
+ p_file = os.path.join(self.servicePath, filename_only)
if 'p_file' in locals():
Receiver.send_message(u'cursor_busy')
fileTo = open(p_file, u'r')
@@ -624,7 +623,7 @@ class ServiceManager(QtGui.QWidget):
self.mainwindow.addRecentFile(fileName)
self.setModified(False)
QtCore.QSettings().setValue(
- 'service/last file', QtCore.QVariant(fileName))
+ 'servicemanager/last file', QtCore.QVariant(fileName))
else:
critical_error_message_box(
message=translate('OpenLP.ServiceManager',
@@ -666,7 +665,7 @@ class ServiceManager(QtGui.QWidget):
present.
"""
fileName = QtCore.QSettings(). \
- value(u'service/last file',QtCore.QVariant(u'')).toString()
+ value(u'servicemanager/last file',QtCore.QVariant(u'')).toString()
if fileName:
self.loadFile(fileName)
@@ -1008,7 +1007,8 @@ class ServiceManager(QtGui.QWidget):
self.service_theme = unicode(self.themeComboBox.currentText())
self.mainwindow.renderer.set_service_theme(self.service_theme)
QtCore.QSettings().setValue(
- self.mainwindow.serviceSettingsSection + u'/service theme',
+ self.mainwindow.servicemanagerSettingsSection +
+ u'/service theme',
QtCore.QVariant(self.service_theme))
self.regenerateServiceItems()
diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py
index 290da104c..2d8e16c4c 100644
--- a/openlp/plugins/bibles/lib/http.py
+++ b/openlp/plugins/bibles/lib/http.py
@@ -218,7 +218,7 @@ class BSExtract(object):
send_error_message(u'parse')
return None
content = content.find(u'div').findAll(u'div')
- verse_number = re.compile(r'v(\d{1,2})(\d{3})(\d{3}) verse')
+ verse_number = re.compile(r'v(\d{1,2})(\d{3})(\d{3}) verse.*')
verses = {}
for verse in content:
Receiver.send_message(u'openlp_process_events')
diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py
index 91009424c..9083b18a2 100644
--- a/openlp/plugins/bibles/lib/mediaitem.py
+++ b/openlp/plugins/bibles/lib/mediaitem.py
@@ -391,10 +391,13 @@ class BibleMediaItem(MediaManagerItem):
elif len(bibles):
self.initialiseAdvancedBible(bibles[0])
- def reloadBibles(self):
+ def reloadBibles(self, process=False):
log.debug(u'Reloading Bibles')
self.plugin.manager.reload_bibles()
self.loadBibles()
+ # If called from first time wizard re-run, process any new bibles.
+ if process:
+ self.plugin.appStartup()
self.updateAutoCompleter()
def initialiseAdvancedBible(self, bible):
diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py
index e2996ff8f..1b0ca316e 100644
--- a/openlp/plugins/songs/lib/__init__.py
+++ b/openlp/plugins/songs/lib/__init__.py
@@ -184,10 +184,11 @@ class VerseType(object):
verse_index = VerseType.from_translated_string(verse_name)
if verse_index is None:
verse_index = VerseType.from_string(verse_name)
- if verse_index is None:
- verse_index = VerseType.from_translated_tag(verse_name)
- if verse_index is None:
- verse_index = VerseType.from_tag(verse_name)
+ elif len(verse_name) == 1:
+ if verse_index is None:
+ verse_index = VerseType.from_translated_tag(verse_name)
+ if verse_index is None:
+ verse_index = VerseType.from_tag(verse_name)
return verse_index
def retrieve_windows_encoding(recommendation=None):
diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py
index 7fca88262..632170807 100644
--- a/openlp/plugins/songs/lib/opensongimport.py
+++ b/openlp/plugins/songs/lib/opensongimport.py
@@ -190,7 +190,10 @@ class OpenSongImport(SongImport):
# the verse tag
verse_tag = content
verse_num = u'1'
- verse_index = VerseType.from_loose_input(verse_tag)
+ if len(verse_tag) == 0:
+ verse_index = 0
+ else:
+ verse_index = VerseType.from_loose_input(verse_tag)
verse_tag = VerseType.Tags[verse_index]
inst = 1
if [verse_tag, verse_num, inst] in our_verse_order \
diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py
index c50df8752..591f71c10 100644
--- a/openlp/plugins/songs/lib/songshowplusimport.py
+++ b/openlp/plugins/songs/lib/songshowplusimport.py
@@ -103,6 +103,8 @@ class SongShowPlusImport(SongImport):
return
self.import_wizard.progressBar.setMaximum(len(self.import_source))
for file in self.import_source:
+ if self.stop_import_flag:
+ return
self.sspVerseOrderList = []
otherCount = 0
otherList = {}
diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py
index e2a5820a5..4cfb81cb1 100644
--- a/openlp/plugins/songs/lib/wowimport.py
+++ b/openlp/plugins/songs/lib/wowimport.py
@@ -105,6 +105,8 @@ class WowImport(SongImport):
if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(len(self.import_source))
for file in self.import_source:
+ if self.stop_import_flag:
+ return
file_name = os.path.split(file)[1]
# Get the song title
self.title = file_name.rpartition(u'.')[0]