From 7ab1538460ee5762d00a0f5330a78edfcaaefdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 15 Aug 2011 12:54:07 +0300 Subject: [PATCH 01/17] Supposed to fix #819271, crash when downloading some chapters. --- openlp/plugins/bibles/lib/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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') From aca0a86915e050546f30a5d64d0c7127216da933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 01:42:48 +0300 Subject: [PATCH 02/17] Fix comparison of always unequal unicode and non-unicode string on drag-and-drop. --- openlp/core/lib/mediamanageritem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index a721fabf6..4bf3732e6 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: From bdde2a4fb4e8e6c885e14eb028d550d0ee5ff1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 01:44:02 +0300 Subject: [PATCH 03/17] String fix. --- openlp/core/lib/mediamanageritem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 4bf3732e6..f21d8df50 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -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) From a3ddb50479ef90b615a6d1996cb64e5a07eb46b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 01:46:31 +0300 Subject: [PATCH 04/17] Now we do not read several GB video files entirely into memory when opening service, this also fixes #257 in tracker. --- openlp/core/ui/servicemanager.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 3ab2e9239..5bb396bf1 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -584,8 +584,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 +593,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') From bbba7203e324a4da82c749c41ac38c36c7234670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 03:08:16 +0300 Subject: [PATCH 05/17] Fix #249 on tracker, exception on opensong files with verse name containing only number [1] --- openlp/plugins/songs/lib/__init__.py | 9 +++++---- openlp/plugins/songs/lib/opensongimport.py | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) 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..afdf3fe63 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -191,6 +191,8 @@ class OpenSongImport(SongImport): verse_tag = content verse_num = u'1' verse_index = VerseType.from_loose_input(verse_tag) + if not verse_index: + verse_index = 0 # Verse verse_tag = VerseType.Tags[verse_index] inst = 1 if [verse_tag, verse_num, inst] in our_verse_order \ From 509bc9e7044a8fdd2814521a7b8c1519c799d57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 03:59:45 +0300 Subject: [PATCH 06/17] Two last importers, which did not stop on cancel. --- openlp/plugins/songs/lib/songshowplusimport.py | 2 ++ openlp/plugins/songs/lib/wowimport.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index 7f7527c6d..9a21d33b9 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -104,6 +104,8 @@ class SongShowPlusImport(SongImport): 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] From da758fbb897a1c6a1028b6edda7d5d3d952c25c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 16 Aug 2011 11:46:55 +0300 Subject: [PATCH 07/17] Removed wrong comment --- openlp/plugins/songs/lib/opensongimport.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index afdf3fe63..632170807 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -190,9 +190,10 @@ class OpenSongImport(SongImport): # the verse tag verse_tag = content verse_num = u'1' - verse_index = VerseType.from_loose_input(verse_tag) - if not verse_index: - verse_index = 0 # Verse + 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 \ From 68facbf2b50fabe2283b7981cf54e06b92707424 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Thu, 25 Aug 2011 11:04:41 +0200 Subject: [PATCH 08/17] Move class OpenLP from openlp.pyw to openlp.core.__init__ --- openlp.pyw | 146 +-------------------------------- openlp/core/__init__.py | 177 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 145 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 962109592..378b78c37 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -38,6 +38,7 @@ from traceback import format_exception from PyQt4 import QtCore, QtGui +from openlp.core import OpenLP from openlp.core.lib import Receiver, check_directory_exists from openlp.core.lib.ui import UiStrings from openlp.core.resources import qInitResources @@ -51,151 +52,6 @@ from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \ 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 diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index e19b9a257..b06fffe79 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -24,9 +24,186 @@ # 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 +# 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.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): + """ + 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) + + From 7fae06483a615da3c314e72d84b393ade1e3f011 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Thu, 25 Aug 2011 12:04:17 +0200 Subject: [PATCH 09/17] Move main() from openlp.pyw to openlp.core.__init__ --- openlp.pyw | 99 +---------------------------------------- openlp/core/__init__.py | 83 +++++++++++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 102 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 378b78c37..64ffb3321 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -25,110 +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 import OpenLP -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() - -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 b06fffe79..d9a671f65 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -30,11 +30,6 @@ __all__ = ('OpenLP', 'main') 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 @@ -83,6 +78,7 @@ QToolBar } """ + class OpenLP(QtGui.QApplication): """ The core application class. This class inherits from Qt's QApplication @@ -102,6 +98,10 @@ class OpenLP(QtGui.QApplication): """ Run the OpenLP application. """ + self.setOrganizationName(u'OpenLP') + self.setOrganizationDomain(u'openlp.org') + self.setApplicationName(u'OpenLP') + self.setApplicationVersion(get_application_version()[u'version']) # 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) @@ -207,3 +207,76 @@ class OpenLP(QtGui.QApplication): 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() + # 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)) From 1dc05c0f662032b8324bac430efd4c8ae8df68e2 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Thu, 25 Aug 2011 13:16:04 +0200 Subject: [PATCH 10/17] Add ability to run openlp without app.exec_() method (needed to run gui tests) --- openlp/core/__init__.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index d9a671f65..8493b7b65 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -94,7 +94,7 @@ class OpenLP(QtGui.QApplication): QtGui.QApplication.exec_() self.sharedMemory.detach() - def run(self, args): + def run(self, args, testing=False): """ Run the OpenLP application. """ @@ -150,7 +150,9 @@ class OpenLP(QtGui.QApplication): Receiver.send_message(u'maindisplay_blank_check') self.mainWindow.appStartup() DelayStartThread(self.mainWindow).start() - return self.exec_() + # Skip exec_() for gui tests + if not testing: + return self.exec_() def isAlreadyRunning(self): """ @@ -207,7 +209,7 @@ class OpenLP(QtGui.QApplication): return QtGui.QApplication.event(self, event) -def main(): +def main(args=None): """ The main function which parses command line options and then runs the PyQt4 Application. @@ -228,6 +230,8 @@ def main(): '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) @@ -238,7 +242,9 @@ def main(): log.addHandler(logfile) logging.addLevelName(15, u'Timer') # Parse command line options and deal with them. - (options, args) = parser.parse_args() + if not args: + args = sys.argv # Use args not supplied programatically + (options, args) = parser.parse_args(args) qt_args = [] if options.loglevel.lower() in ['d', 'debug']: log.setLevel(logging.DEBUG) @@ -279,4 +285,8 @@ def main(): log.debug(u'Could not find default_translator.') if not options.no_error_form: sys.excepthook = app.hookException - sys.exit(app.run(qt_args)) + # 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)) From 20c431a6e503b891e4bf81962c59611c63c48b76 Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Thu, 25 Aug 2011 17:33:21 +0200 Subject: [PATCH 11/17] - Remove darwin specific dead code - Move app.setOrganization and app.setApplication to orgininal place --- openlp/core/__init__.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 8493b7b65..e1d85fd8f 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -98,10 +98,6 @@ class OpenLP(QtGui.QApplication): """ Run the OpenLP application. """ - self.setOrganizationName(u'OpenLP') - self.setOrganizationDomain(u'openlp.org') - self.setApplicationName(u'OpenLP') - self.setApplicationVersion(get_application_version()[u'version']) # 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) @@ -261,6 +257,10 @@ def main(args=None): 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() @@ -270,9 +270,6 @@ def main(args=None): 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 = \ From eef0af11ac0ab4d59cf2729e1b056bca33e1772a Mon Sep 17 00:00:00 2001 From: Martin Zibricky Date: Fri, 26 Aug 2011 13:04:56 +0200 Subject: [PATCH 12/17] Fix error msg with corrupted file --- openlp/core/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index e1d85fd8f..896066e73 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -238,9 +238,8 @@ def main(args=None): log.addHandler(logfile) logging.addLevelName(15, u'Timer') # Parse command line options and deal with them. - if not args: - args = sys.argv # Use args not supplied programatically - (options, args) = parser.parse_args(args) + # 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) From ccd0a46e2b337c51adcf63ae187b39ade2b86129 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 29 Aug 2011 22:56:07 +0200 Subject: [PATCH 13/17] do not expand the tags --- openlp/core/lib/renderer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 8c63facb8..e0a07a556 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -259,8 +259,7 @@ class Renderer(object): else: html_text = text text = u'' - lines = expand_tags(html_text) - lines = lines.strip(u'\n').split(u'\n') + lines = html_text.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 @@ -274,8 +273,7 @@ class Renderer(object): else: pages.extend(slides) if u'[---]' not in text: - lines = expand_tags(text) - lines = lines.strip(u'\n').split(u'\n') + lines = text.strip(u'\n').split(u'\n') pages.extend(self._paginate_slide(lines, line_end)) break new_pages = [] From 6c7527349d4fe5a3b3e388a2325a7074b3bde37f Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 29 Aug 2011 22:58:32 +0200 Subject: [PATCH 14/17] do not use the same name twice --- openlp/core/lib/renderer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index e0a07a556..3fff5cbe0 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -255,11 +255,11 @@ class Renderer(object): # we have to render the first virtual slide. text_contains_break = u'[---]' in text if text_contains_break: - html_text, text = text.split(u'\n[---]\n', 1) + text_to_render, text = text.split(u'\n[---]\n', 1) else: - html_text = text + text_to_render = text text = u'' - lines = html_text.strip(u'\n').split(u'\n') + 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 From 88704fbc68d302b276813f89370e3e88a5316223 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 30 Aug 2011 15:35:06 +0200 Subject: [PATCH 15/17] fix soft break --- openlp/core/lib/renderer.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 3fff5cbe0..f9166e7d2 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -235,27 +235,36 @@ class Renderer(object): while True: # Check if the first two potential virtual slides will fit # (as a whole) on one slide. - html_text = expand_tags( - u'\n'.join(text.split(u'\n[---]\n', 2)[:-1])) + slides = text.split(u'\n[---]\n', 2) + # If there are (at least) two occurrences of [---] we use + # the 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. + 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 occurrences of [---]. - text = text.replace(u'\n[---]', u'', 2) + text = text.replace(u'\n[---]', u'', 1) else: # The first two virtual slides did not fit as a whole. - # Check if the first virtual slide will fit. + # Check if the second part fits. html_text = expand_tags(text.split(u'\n[---]\n', 1)[1]) html_text = html_text.replace(u'\n', u'
') - if self._text_fits_on_slide(html_text): + if not self._text_fits_on_slide(html_text): # The first virtual slide fits, so remove it. text = text.replace(u'\n[---]', u'', 1) else: - # The first virtual slide does not fit, which means + # 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) + text_to_render, text = text.split( + u'\n[---]\n', 1) else: text_to_render = text text = u'' From 25ce484fb1ce7b57a84a117a267698c7aaaef776 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 30 Aug 2011 17:12:16 +0200 Subject: [PATCH 16/17] hopefully fixed it now completely --- openlp/core/lib/renderer.py | 55 ++++++++++++++----------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index f9166e7d2..6ae0fa426 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -233,54 +233,41 @@ class Renderer(object): len(pages) > 1 and u'[---]' in text: pages = [] while True: - # Check if the first two potential virtual slides will fit - # (as a whole) on one slide. slides = text.split(u'\n[---]\n', 2) # If there are (at least) two occurrences of [---] we use - # the use the first two slides (and neglect the last for - # now). + # 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. + # 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 occurrences of [---]. + # slide. Replace the first occurrence of [---]. text = text.replace(u'\n[---]', u'', 1) else: - # The first two virtual slides did not fit as a whole. - # Check if the second part fits. - html_text = expand_tags(text.split(u'\n[---]\n', 1)[1]) - html_text = html_text.replace(u'\n', u'
') - if not self._text_fits_on_slide(html_text): - # The first virtual slide fits, so remove it. - text = text.replace(u'\n[---]', u'', 1) + # The first virtual slide fits, which means + # we have to render the first virtual slide. + if u'[---]' in text: + text_to_render, text = text.split(u'\n[---]\n', 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) + 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_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) + 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)) From 71bdaf0708c45f984952f8628444a5f5e896e010 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 30 Aug 2011 17:15:39 +0200 Subject: [PATCH 17/17] comments --- openlp/core/lib/renderer.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 6ae0fa426..185d74878 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -248,9 +248,10 @@ class Renderer(object): # 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. - if u'[---]' in text: + # 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 @@ -258,8 +259,7 @@ class Renderer(object): 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. + # 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