diff --git a/demo_theme.xml b/demo_theme.xml deleted file mode 100644 index 118a1d7d4..000000000 --- a/demo_theme.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - openlp.org 2.0 Demo Theme - 2 - ./openlp/core/test/data_for_tests/treesbig.jpg - clBlack - - Tahoma - clWhite - 16 - -1 - $00000001 - -1 - clRed - 2 - 2 - diff --git a/documentation/api/source/plugins/songs.rst b/documentation/api/source/plugins/songs.rst index fed9907a2..1e86ce020 100644 --- a/documentation/api/source/plugins/songs.rst +++ b/documentation/api/source/plugins/songs.rst @@ -72,9 +72,6 @@ Song Importers .. automodule:: openlp.plugins.songs.lib.cclifileimport :members: -.. autoclass:: openlp.plugins.songs.lib.cclifileimport.CCLIFileImportError - :members: - .. automodule:: openlp.plugins.songs.lib.ewimport :members: diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 7ad377817..76d7c0617 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -293,6 +293,7 @@ def clean_tags(text): Remove Tags from text for display """ text = text.replace(u'
', u'\n') + text = text.replace(u' ', u' ') for tag in DisplayTags.get_html_tags(): text = text.replace(tag[u'start tag'], u'') text = text.replace(tag[u'end tag'], u'') diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index c2e1243ce..3171730ea 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -34,7 +34,7 @@ from sqlalchemy import create_engine, MetaData from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, delete_file log = logging.getLogger(__name__) @@ -75,11 +75,7 @@ def delete_database(plugin_name, db_file_name=None): else: db_file_path = os.path.join( AppLocation.get_section_data_path(plugin_name), plugin_name) - try: - os.remove(db_file_path) - return True - except OSError: - return False + return delete_file(db_file_path) class BaseModel(object): """ @@ -295,4 +291,4 @@ class Manager(object): if self.is_dirty: engine = create_engine(self.db_url) if self.db_url.startswith(u'sqlite'): - engine.execute("vacuum") \ No newline at end of file + engine.execute("vacuum") diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index 63ad5b796..6fa8e624a 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -207,14 +207,8 @@ class EventReceiver(QtCore.QObject): ``bibles_nobook`` Attempt to find book resulted in no match - ``bibles_showprogress`` - Show progress of bible verse import - - ``bibles_hideprogress`` - Hide progress of bible verse import - - ``bibles_stop_import`` - Stops the Bible Import + ``openlp_stop_wizard`` + Stops a wizard before completion ``remotes_poll_request`` Waits for openlp to do something "interesting" and sends a diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 0a26382f8..86056f4b5 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -641,4 +641,4 @@ def build_alert_css(alertTab, width): align = u'top' alert = style % (width, align, alertTab.font_face, alertTab.font_size, alertTab.font_color, alertTab.bg_color) - return alert \ No newline at end of file + return alert diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 0be1a01c8..02d7010be 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -30,7 +30,6 @@ A Thread is used to convert the image to a byte array so the user does not need to wait for the conversion to happen. """ import logging -import os import time from PyQt4 import QtCore @@ -86,8 +85,7 @@ class ImageManager(QtCore.QObject): for key in self._cache.keys(): image = self._cache[key] image.dirty = True - fullpath = os.path.join(image.path, image.name) - image.image = resize_image(fullpath, + image.image = resize_image(image.path, self.width, self.height) self._cache_dirty = True # only one thread please @@ -165,4 +163,4 @@ class ImageManager(QtCore.QObject): image = self._cache[key] if image.dirty: image.image_bytes = image_to_byte(image.image) - image.dirty = False \ No newline at end of file + image.dirty = False diff --git a/openlp/core/lib/mailto/__init__.py b/openlp/core/lib/mailto/__init__.py index f0e23f1b5..f05ebfdee 100644 --- a/openlp/core/lib/mailto/__init__.py +++ b/openlp/core/lib/mailto/__init__.py @@ -230,7 +230,7 @@ def open(filename): return _open(filename) -def _fix_addersses(**kwargs): +def _fix_addresses(**kwargs): for headername in (u'address', u'to', u'cc', u'bcc'): try: headervalue = kwargs[headername] @@ -260,7 +260,7 @@ def mailto_format(**kwargs): """ # @TODO: implement utf8 option - kwargs = _fix_addersses(**kwargs) + kwargs = _fix_addresses(**kwargs) parts = [] for headername in (u'to', u'cc', u'bcc', u'subject', u'body', u'attach'): if kwargs.has_key(headername): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 2d6bcce46..6fb834e05 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -266,7 +266,7 @@ class MediaManagerItem(QtGui.QWidget): """ Creates the main widget for listing items the media item is tracking """ - #Add the List widget + # Add the List widget self.listView = self.ListViewWithDnD_class(self) self.listView.uniformItemSizes = True self.listView.setSpacing(1) @@ -275,9 +275,9 @@ class MediaManagerItem(QtGui.QWidget): self.listView.setAlternatingRowColors(True) self.listView.setDragEnabled(True) self.listView.setObjectName(u'%sListView' % self.plugin.name) - #Add to pageLayout + # Add to pageLayout self.pageLayout.addWidget(self.listView) - #define and add the context menu + # define and add the context menu self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) name_string = self.plugin.getString(StringContent.Name) if self.hasEditIcon: @@ -314,7 +314,7 @@ class MediaManagerItem(QtGui.QWidget): context_menu_action( self.listView, u':/general/general_add.png', translate('OpenLP.MediaManagerItem', - '&Add to selected Service Item'), + '&Add to selected Service Item'), self.onAddEditClick)) QtCore.QObject.connect(self.listView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), @@ -441,7 +441,7 @@ class MediaManagerItem(QtGui.QWidget): QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'No Items Selected'), translate('OpenLP.MediaManagerItem', - 'You must select one or more items to preview.')) + 'You must select one or more items to preview.')) else: log.debug(u'%s Preview requested', self.plugin.name) serviceItem = self.buildServiceItem() diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index f18605711..ce0907fbb 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -60,6 +60,7 @@ class ItemCapabilities(object): AddIfNewItem = 9 ProvidesOwnDisplay = 10 + class ServiceItem(object): """ The service item is a base class for the plugins to use to interact with diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 5a030e841..80124c2be 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -26,6 +26,9 @@ """ The :mod:`ui` module provides the core user interface for OpenLP """ +from PyQt4 import QtGui + +from openlp.core.lib import translate, Receiver class HideMode(object): """ @@ -35,11 +38,11 @@ class HideMode(object): ``Blank`` This mode is used to hide all output, specifically by covering the display with a black screen. - + ``Theme`` This mode is used to hide all output, but covers the display with the current theme background, as opposed to black. - + ``Desktop`` This mode hides all output by minimising the display, leaving the user's desktop showing. @@ -48,6 +51,34 @@ class HideMode(object): Theme = 2 Screen = 3 + +def criticalErrorMessageBox(title=None, message=None, parent=None, + question=False): + """ + Provides a standard critical message box for errors that OpenLP displays + to users. + + ``title`` + The title for the message box. + + ``message`` + The message to display to the user. + + ``parent`` + The parent UI element to attach the dialog to. + + ``question`` + Should this message box question the user. + """ + error = translate('OpenLP.Ui', 'Error') + if question: + return QtGui.QMessageBox.critical(parent, error, message, + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) + data = {u'message': message} + data[u'title'] = title if title else error + return Receiver.send_message(u'openlp_error_message', data) + from themeform import ThemeForm from filerenameform import FileRenameForm from maindisplay import MainDisplay @@ -68,6 +99,6 @@ from mediadockmanager import MediaDockManager from servicemanager import ServiceManager from thememanager import ThemeManager -__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', - 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', - 'MediaDockManager', 'ServiceItemEditForm'] +__all__ = ['criticalErrorMessageBox', 'SplashScreen', 'AboutForm', + 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', + 'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm'] diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index 3d6cd813d..1c77084b9 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -34,6 +34,7 @@ import cPickle from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate, DisplayTags +from openlp.core.ui import criticalErrorMessageBox class DisplayTagTab(SettingsTab): ''' @@ -59,7 +60,7 @@ class DisplayTagTab(SettingsTab): # cPickle only accepts str not unicode strings user_expands_string = str(unicode(user_expands).encode(u'utf8')) if user_expands_string: - user_tags = cPickle.loads(user_expand_string) + user_tags = cPickle.loads(user_expands_string) # If we have some user ones added them as well for t in user_tags: DisplayTags.add_html_tag(t) @@ -275,12 +276,10 @@ class DisplayTagTab(SettingsTab): """ for html in DisplayTags.get_html_tags(): if self._strip(html[u'start tag']) == u'n': - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.DisplayTagTab', 'Update Error'), translate('OpenLP.DisplayTagTab', - 'Tag "n" already defined.'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), - QtGui.QMessageBox.Ok) + 'Tag "n" already defined.')) return # Add new tag to list tag = {u'desc': u'New Item', u'start tag': u'{n}', @@ -318,12 +317,10 @@ class DisplayTagTab(SettingsTab): for linenumber, html1 in enumerate(html_expands): if self._strip(html1[u'start tag']) == tag and \ linenumber != self.selected: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.DisplayTagTab', 'Update Error'), unicode(translate('OpenLP.DisplayTagTab', - 'Tag %s already defined.')) % tag, - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), - QtGui.QMessageBox.Ok) + 'Tag %s already defined.')) % tag) return html[u'desc'] = unicode(self.descriptionLineEdit.text()) html[u'start html'] = unicode(self.startTagLineEdit.text()) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 195ed6a6b..808d7a319 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -24,6 +24,8 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ +The :mod:`maindisplay` module provides the functionality to display screens +and play multimedia within OpenLP. """ import logging import os @@ -205,7 +207,7 @@ class MainDisplay(DisplayWidget): The slide text to be displayed """ log.debug(u'text to display') - # Wait for the webview to update before displayiong text. + # Wait for the webview to update before displaying text. while not self.loaded: Receiver.send_message(u'openlp_process_events') self.frame.evaluateJavaScript(u'show_text("%s")' % \ diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 70b87966c..f2545766e 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -142,7 +142,8 @@ class Ui_MainWindow(object): build_icon(u':/system/system_servicemanager.png')) self.ServiceManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ServiceManagerContents = ServiceManager(MainWindow) + self.ServiceManagerContents = ServiceManager(MainWindow, + self.ServiceManagerDock) self.ServiceManagerDock.setWidget(self.ServiceManagerContents) MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.ServiceManagerDock) @@ -152,7 +153,8 @@ class Ui_MainWindow(object): build_icon(u':/system/system_thememanager.png')) self.ThemeManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ThemeManagerContents = ThemeManager(MainWindow) + self.ThemeManagerContents = ThemeManager(MainWindow, + self.ThemeManagerDock) self.ThemeManagerContents.setObjectName(u'ThemeManagerContents') self.ThemeManagerDock.setWidget(self.ThemeManagerContents) MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 3162458bc..8e82f0003 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -61,6 +61,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): self.programaticChange = True self._clearDetails() self.programaticChange = True + pluginListWidth = 0 for plugin in self.parent.pluginManager.plugins: item = QtGui.QListWidgetItem(self.pluginListWidget) # We do this just to make 100% sure the status is an integer as @@ -83,8 +84,11 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): if plugin.icon: item.setIcon(plugin.icon) self.pluginListWidget.addItem(item) - self.pluginListWidget.setFixedWidth( - self.pluginListWidget.sizeHint().width()) + pluginListWidth = max(pluginListWidth, self.fontMetrics().width( + unicode(translate('OpenLP.PluginForm', '%s (Inactive)')) % + name_string[u'singular'])) + self.pluginListWidget.setFixedWidth(pluginListWidth + + self.pluginListWidget.iconSize().width() + 48) def _clearDetails(self): self.statusComboBox.setCurrentIndex(-1) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 7c3449615..12889a440 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -36,16 +36,18 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \ Receiver, build_icon, ItemCapabilities, SettingsManager, translate, \ ThemeLevel -from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm -from openlp.core.utils import AppLocation, split_filename, ActionList +from openlp.core.ui import criticalErrorMessageBox, ServiceNoteForm, \ + ServiceItemEditForm +from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ + split_filename, ActionList class ServiceManagerList(QtGui.QTreeWidget): """ Set up key bindings and mouse behaviour for the service list """ - def __init__(self, parent=None, name=None): + def __init__(self, mainwindow, parent=None, name=None): QtGui.QTreeWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow def mouseMoveEvent(self, event): """ @@ -70,12 +72,12 @@ class ServiceManager(QtGui.QWidget): the resources used into one OSZ file for use on any OpenLP v2 installation. Also handles the UI tasks of moving things up and down etc. """ - def __init__(self, parent): + def __init__(self, mainwindow, parent=None): """ Sets up the service manager, toolbars, list view, et al. """ QtGui.QWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow self.serviceItems = [] self.serviceName = u'' self.suffixes = [] @@ -84,8 +86,8 @@ class ServiceManager(QtGui.QWidget): # is a new service and has not been saved self._modified = False self._fileName = u'' - self.serviceNoteForm = ServiceNoteForm(self.parent) - self.serviceItemEditForm = ServiceItemEditForm(self.parent) + self.serviceNoteForm = ServiceNoteForm(self.mainwindow) + self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow) # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -221,7 +223,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.parent.serviceSettingsSection + u'/service theme', + self.mainwindow.serviceSettingsSection + u'/service theme', QtCore.QVariant(u'')).toString()) self.servicePath = AppLocation.get_section_data_path(u'servicemanager') # build the drag and drop context menu @@ -278,7 +280,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Move_down', u'Service Settings', self.onServiceDown, QtCore.Qt.Key_PageDown) - self.parent.actionList.add_action(self.serviceManagerList.move_down, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.move_down, u'Service') self.serviceManagerList.move_up = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'Move_up', parent) @@ -286,7 +288,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Move_up', u'Service Settings', self.onServiceUp, QtCore.Qt.Key_PageUp) - self.parent.actionList.add_action(self.serviceManagerList.move_up, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.move_up, u'Service') self.serviceManagerList.enter = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'Make Live', parent) @@ -294,7 +296,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Make Live', u'Service Settings', self.makeLive, QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return) - self.parent.actionList.add_action(self.serviceManagerList.enter, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.enter, u'Service') self.serviceManagerList.home = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'Home', parent) @@ -302,7 +304,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Home', u'Service Settings', self.onServiceTop, QtCore.Qt.Key_Home) - self.parent.actionList.add_action(self.serviceManagerList.home, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.home, u'Service') self.serviceManagerList.end = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'End', parent) @@ -310,7 +312,7 @@ class ServiceManager(QtGui.QWidget): widget, u'End', u'Service Settings', self.onServiceEnd, QtCore.Qt.Key_End) - self.parent.actionList.add_action(self.serviceManagerList.end, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.end, u'Service') self.serviceManagerList.up = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'Move Selection up', parent) @@ -318,7 +320,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Move Selection up', u'Service Settings', self.onMoveSelectionUp, QtCore.Qt.Key_Up) - self.parent.actionList.add_action(self.serviceManagerList.up, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.up, u'Service') self.serviceManagerList.down = \ QtGui.QAction(QtGui.QIcon(u':/services/service_up.png'), u'Move Selection down', parent) @@ -326,7 +328,7 @@ class ServiceManager(QtGui.QWidget): widget, u'Move Selection down', u'Service Settings', self.onMoveSelectionDown, QtCore.Qt.Key_Down) - self.parent.actionList.add_action(self.serviceManagerList.down, u'Service') + self.mainwindow.actionList.add_action(self.serviceManagerList.down, u'Service') def setModified(self, modified=True): """ @@ -335,7 +337,7 @@ class ServiceManager(QtGui.QWidget): """ self._modified = modified serviceFile = self.shortFileName() or u'Untitled Service' - self.parent.setServiceModified(modified, serviceFile) + self.mainwindow.setServiceModified(modified, serviceFile) def isModified(self): """ @@ -348,7 +350,8 @@ class ServiceManager(QtGui.QWidget): Setter for service file. """ self._fileName = unicode(fileName) - self.parent.setServiceModified(self.isModified(), self.shortFileName()) + self.mainwindow.setServiceModified(self.isModified(), + self.shortFileName()) QtCore.QSettings(). \ setValue(u'service/last file',QtCore.QVariant(fileName)) @@ -382,7 +385,7 @@ class ServiceManager(QtGui.QWidget): Create a new service. """ if self.isModified(): - result = QtGui.QMessageBox.question(self.parent, + result = QtGui.QMessageBox.question(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Changes'), translate('OpenLP.ServiceManager', 'The current service has ' 'been modified, would you like to save it?'), @@ -397,7 +400,7 @@ class ServiceManager(QtGui.QWidget): def onLoadServiceClicked(self): if self.isModified(): - result = QtGui.QMessageBox.question(self.parent, + result = QtGui.QMessageBox.question(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Changes'), translate('OpenLP.ServiceManager', 'The current service has ' 'been modified, would you like to save it?'), @@ -407,14 +410,14 @@ class ServiceManager(QtGui.QWidget): return False elif result == QtGui.QMessageBox.Save: self.saveFile() - fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.parent, + fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.mainwindow, translate('OpenLP.ServiceManager', 'Open File'), - SettingsManager.get_last_dir(self.parent.serviceSettingsSection), - translate('OpenLP.ServiceManager', - 'OpenLP Service Files (*.osz)'))) + SettingsManager.get_last_dir( + self.mainwindow.serviceSettingsSection), + translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) if not fileName: return False - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection, split_filename(fileName)[0]) self.loadFile(fileName) @@ -448,7 +451,7 @@ class ServiceManager(QtGui.QWidget): else: fileName = self.fileName() log.debug(u'ServiceManager.saveFile - %s' % fileName) - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection, split_filename(fileName)[0]) service = [] serviceFileName = fileName.replace(u'.osz', u'.osd') @@ -483,12 +486,8 @@ class ServiceManager(QtGui.QWidget): file.close() if zip: zip.close() - try: - os.remove(serviceFileName) - except (IOError, OSError): - # if not present do not worry - pass - self.parent.addRecentFile(fileName) + delete_file(serviceFileName) + self.mainwindow.addRecentFile(fileName) self.setModified(False) return True @@ -497,11 +496,11 @@ class ServiceManager(QtGui.QWidget): Get a file name and then call :function:`ServiceManager.saveFile` to save the file. """ - fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.parent, + fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Service'), - SettingsManager.get_last_dir(self.parent.serviceSettingsSection), - translate('OpenLP.ServiceManager', - 'OpenLP Service Files (*.osz)'))) + SettingsManager.get_last_dir( + self.mainwindow.serviceSettingsSection), + translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) if not fileName: return False if os.path.splitext(fileName)[1] == u'': @@ -520,18 +519,14 @@ class ServiceManager(QtGui.QWidget): zip = None fileTo = None try: - zip = zipfile.ZipFile(unicode(fileName)) + zip = zipfile.ZipFile(fileName) for file in zip.namelist(): - try: - ucsfile = file.decode(u'utf-8') - except UnicodeDecodeError: - QtGui.QMessageBox.critical( - self, translate('OpenLP.ServiceManager', 'Error'), - translate('OpenLP.ServiceManager', - 'File is not a valid service.\n' - 'The content encoding is not UTF-8.')) - log.exception(u'Filename "%s" is not valid UTF-8' % - file.decode(u'utf-8', u'replace')) + ucsfile = file_is_unicode(file) + if not ucsfile: + criticalErrorMessageBox( + message=translate('OpenLP.ServiceManager', + 'File is not a valid service.\n' + 'The content encoding is not UTF-8.')) continue osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) filePath = os.path.join(self.servicePath, @@ -549,24 +544,18 @@ class ServiceManager(QtGui.QWidget): self.newFile() for item in items: serviceItem = ServiceItem() - serviceItem.render_manager = self.parent.renderManager + serviceItem.render_manager = self.mainwindow.renderManager serviceItem.set_from_service(item, self.servicePath) self.validateItem(serviceItem) self.addServiceItem(serviceItem) - if serviceItem.is_capable( - ItemCapabilities.OnLoadUpdate): + if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate): Receiver.send_message(u'%s_service_load' % serviceItem.name.lower(), serviceItem) - try: - if os.path.isfile(p_file): - os.remove(p_file) - except (IOError, OSError): - log.exception(u'Failed to remove osd file') + delete_file(p_file) else: - QtGui.QMessageBox.critical( - self, translate('OpenLP.ServiceManager', 'Error'), - translate('OpenLP.ServiceManager', - 'File is not a valid service.')) + criticalErrorMessageBox( + message=translate('OpenLP.ServiceManager', + 'File is not a valid service.')) log.exception(u'File contains no service data') except (IOError, NameError): log.exception(u'Problem loading a service file') @@ -576,7 +565,7 @@ class ServiceManager(QtGui.QWidget): if zip: zip.close() self.setFileName(fileName) - self.parent.addRecentFile(fileName) + self.mainwindow.addRecentFile(fileName) self.setModified(False) QtCore.QSettings(). \ setValue(u'service/last file',QtCore.QVariant(fileName)) @@ -915,11 +904,7 @@ class ServiceManager(QtGui.QWidget): """ for file in os.listdir(self.servicePath): file_path = os.path.join(self.servicePath, file) - try: - if os.path.isfile(file_path): - os.remove(file_path) - except OSError: - log.exception(u'Failed to clean up servicePath') + delete_file(file_path) def onThemeComboBoxSelected(self, currentIndex): """ @@ -927,9 +912,9 @@ class ServiceManager(QtGui.QWidget): """ log.debug(u'onThemeComboBoxSelected') self.service_theme = unicode(self.themeComboBox.currentText()) - self.parent.renderManager.set_service_theme(self.service_theme) + self.mainwindow.renderManager.set_service_theme(self.service_theme) QtCore.QSettings().setValue( - self.parent.serviceSettingsSection + u'/service theme', + self.mainwindow.serviceSettingsSection + u'/service theme', QtCore.QVariant(self.service_theme)) self.regenerateServiceItems() @@ -939,7 +924,7 @@ class ServiceManager(QtGui.QWidget): sure the theme combo box is in the correct state. """ log.debug(u'themeChange') - if self.parent.renderManager.theme_level == ThemeLevel.Global: + if self.mainwindow.renderManager.theme_level == ThemeLevel.Global: self.toolbar.actions[u'ThemeLabel'].setVisible(False) self.toolbar.actions[u'ThemeWidget'].setVisible(False) else: @@ -954,7 +939,7 @@ class ServiceManager(QtGui.QWidget): Receiver.send_message(u'cursor_busy') log.debug(u'regenerateServiceItems') # force reset of renderer as theme data has changed - self.parent.renderManager.themedata = None + self.mainwindow.renderManager.themedata = None if self.serviceItems: tempServiceItems = self.serviceItems self.serviceManagerList.clear() @@ -989,7 +974,8 @@ class ServiceManager(QtGui.QWidget): newItem.merge(item[u'service_item']) item[u'service_item'] = newItem self.repaintServiceList(itemcount + 1, 0) - self.parent.liveController.replaceServiceManagerItem(newItem) + self.mainwindow.liveController.replaceServiceManagerItem( + newItem) self.setModified(True) def addServiceItem(self, item, rebuild=False, expand=None, replace=False): @@ -1011,7 +997,7 @@ class ServiceManager(QtGui.QWidget): item.merge(self.serviceItems[sitem][u'service_item']) self.serviceItems[sitem][u'service_item'] = item self.repaintServiceList(sitem + 1, 0) - self.parent.liveController.replaceServiceManagerItem(item) + self.mainwindow.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd if self.dropPosition == 0: @@ -1032,7 +1018,7 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(self.dropPosition, 0) # if rebuilding list make sure live is fixed. if rebuild: - self.parent.liveController.replaceServiceManagerItem(item) + self.mainwindow.liveController.replaceServiceManagerItem(item) self.dropPosition = 0 self.setModified(True) @@ -1042,10 +1028,10 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.previewController.addServiceManagerItem( + self.mainwindow.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) else: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', 'Your item cannot be ' 'displayed as there is no handler to display it')) @@ -1066,24 +1052,24 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.liveController.addServiceManagerItem( + self.mainwindow.liveController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) if QtCore.QSettings().value( - self.parent.generalSettingsSection + u'/auto preview', + self.mainwindow.generalSettingsSection + u'/auto preview', QtCore.QVariant(False)).toBool(): item += 1 if self.serviceItems and item < len(self.serviceItems) and \ self.serviceItems[item][u'service_item'].is_capable( ItemCapabilities.AllowsPreview): - self.parent.previewController.addServiceManagerItem( + self.mainwindow.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], 0) - self.parent.liveController.PreviewListWidget.setFocus() + self.mainwindow.liveController.PreviewListWidget.setFocus() else: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', 'Your item cannot be ' - 'displayed as the plugin required to display it is missing ' - 'or inactive')) + 'displayed as the plugin required to display it is missing ' + 'or inactive')) def remoteEdit(self): """ @@ -1197,7 +1183,7 @@ class ServiceManager(QtGui.QWidget): index = 0 self.service_theme = u'' self.themeComboBox.setCurrentIndex(index) - self.parent.renderManager.set_service_theme(self.service_theme) + self.mainwindow.renderManager.set_service_theme(self.service_theme) self.regenerateServiceItems() def onThemeChangeAction(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 24a1a97ec..a1036f2a5 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -457,7 +457,8 @@ class SlideController(QtGui.QWidget): def previewSizeChanged(self): """ Takes care of the SlidePreview's size. Is called when one of the the - splitters is moved or when the screen size is changed. + splitters is moved or when the screen size is changed. Note, that this + method is (also) called frequently from the mainwindow *paintEvent*. """ if self.ratio < float(self.PreviewFrame.width()) / float( self.PreviewFrame.height()): @@ -470,13 +471,19 @@ class SlideController(QtGui.QWidget): max_width = self.PreviewFrame.width() - self.grid.margin() * 2 self.SlidePreview.setFixedSize(QtCore.QSize(max_width, max_width / self.ratio)) - width = self.parent.ControlSplitter.sizes()[self.split] - self.PreviewListWidget.setColumnWidth(0, width) - # Sort out image heights (Songs, bibles excluded) - if self.serviceItem and not self.serviceItem.is_text(): - for framenumber in range(len(self.serviceItem.get_frames())): - self.PreviewListWidget.setRowHeight( - framenumber, width / self.ratio) + # Make sure that the frames have the correct size. + self.PreviewListWidget.setColumnWidth(0, + self.PreviewListWidget.viewport().size().width()) + if self.serviceItem: + # Sort out songs, bibles, etc. + if self.serviceItem.is_text(): + self.PreviewListWidget.resizeRowsToContents() + else: + # Sort out image heights. + width = self.parent.ControlSplitter.sizes()[self.split] + for framenumber in range(len(self.serviceItem.get_frames())): + self.PreviewListWidget.setRowHeight( + framenumber, width / self.ratio) def onSongBarHandler(self): request = unicode(self.sender().text()) @@ -648,7 +655,7 @@ class SlideController(QtGui.QWidget): self.parent.renderManager.height) else: image = self.parent.renderManager.image_manager. \ - get_image(frame[u'title']) + get_image(frame[u'title']) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.PreviewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent.renderManager.screen_ratio @@ -738,8 +745,17 @@ class SlideController(QtGui.QWidget): Allow the main display to blank the main display at startup time """ log.debug(u'mainDisplaySetBackground live = %s' % self.isLive) + display_type = QtCore.QSettings().value( + self.parent.generalSettingsSection + u'/screen blank', + QtCore.QVariant(u'')).toString() if not self.display.primary: - self.onBlankDisplay(True) + # Order done to handle initial conversion + if display_type == u'themed': + self.onThemeDisplay(True) + elif display_type == u'hidden': + self.onHideDisplay(True) + else: + self.onBlankDisplay(True) def onSlideBlank(self): """ @@ -763,13 +779,15 @@ class SlideController(QtGui.QWidget): self.ThemeScreen.setChecked(False) if self.screens.display_count > 1: self.DesktopScreen.setChecked(False) - QtCore.QSettings().setValue( - self.parent.generalSettingsSection + u'/screen blank', - QtCore.QVariant(checked)) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Blank) + QtCore.QSettings().setValue( + self.parent.generalSettingsSection + u'/screen blank', + QtCore.QVariant(u'blanked')) else: Receiver.send_message(u'maindisplay_show') + QtCore.QSettings().remove( + self.parent.generalSettingsSection + u'/screen blank') self.blankPlugin(checked) def onThemeDisplay(self, checked): @@ -784,8 +802,13 @@ class SlideController(QtGui.QWidget): self.DesktopScreen.setChecked(False) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Theme) + QtCore.QSettings().setValue( + self.parent.generalSettingsSection + u'/screen blank', + QtCore.QVariant(u'themed')) else: Receiver.send_message(u'maindisplay_show') + QtCore.QSettings().remove( + self.parent.generalSettingsSection + u'/screen blank') self.blankPlugin(checked) def onHideDisplay(self, checked): @@ -796,12 +819,19 @@ class SlideController(QtGui.QWidget): self.HideMenu.setDefaultAction(self.DesktopScreen) self.BlankScreen.setChecked(False) self.ThemeScreen.setChecked(False) - if self.screens.display_count > 1: - self.DesktopScreen.setChecked(checked) + # On valid if more than 1 display + if self.screens.display_count <= 1: + return + self.DesktopScreen.setChecked(checked) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Screen) + QtCore.QSettings().setValue( + self.parent.generalSettingsSection + u'/screen blank', + QtCore.QVariant(u'hidden')) else: Receiver.send_message(u'maindisplay_show') + QtCore.QSettings().remove( + self.parent.generalSettingsSection + u'/screen blank') self.hidePlugin(checked) def blankPlugin(self, blank): @@ -1091,9 +1121,8 @@ class SlideController(QtGui.QWidget): if self.BlankScreen.isChecked: self.BlankScreen.setChecked(False) self.HideMenu.setDefaultAction(self.BlankScreen) - QtCore.QSettings().setValue( - self.parent.generalSettingsSection + u'/screen blank', - QtCore.QVariant(False)) + QtCore.QSettings().remove( + self.parent.generalSettingsSection + u'/screen blank') if self.ThemeScreen.isChecked: self.ThemeScreen.setChecked(False) self.HideMenu.setDefaultAction(self.ThemeScreen) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 0155c6a4c..2db76063c 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, BackgroundType, BackgroundGradientType, \ Receiver +from openlp.core.ui import criticalErrorMessageBox from openlp.core.utils import get_images_filter from themewizard import Ui_ThemeWizard @@ -212,8 +213,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Updates the lines on a page on the wizard """ - self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', \ - '(%d lines per slide)' % int(lines)))) + self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', + '(%d lines per slide)')) % int(lines)) def resizeEvent(self, event=None): """ @@ -567,20 +568,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.theme.theme_name = \ unicode(self.field(u'name').toString()) if not self.theme.theme_name: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.ThemeForm', 'Theme Name Missing'), translate('OpenLP.ThemeForm', - 'There is no name for this theme. Please enter one.'), - (QtGui.QMessageBox.Ok), - QtGui.QMessageBox.Ok) + 'There is no name for this theme. Please enter one.')) return if self.theme.theme_name == u'-1' or self.theme.theme_name == u'None': - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.ThemeForm', 'Theme Name Invalid'), translate('OpenLP.ThemeForm', - 'Invalid theme name. Please enter one.'), - (QtGui.QMessageBox.Ok), - QtGui.QMessageBox.Ok) + 'Invalid theme name. Please enter one.')) return saveFrom = None saveTo = None @@ -592,7 +589,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): saveFrom = self.theme.background_filename if not self.edit_mode and \ not self.thememanager.checkIfThemeExists(self.theme.theme_name): - return + return self.accepted = True self.thememanager.saveTheme(self.theme, saveFrom, saveTo) return QtGui.QDialog.accept(self) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 99e5f8d5e..df1f1f775 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -32,12 +32,13 @@ import logging from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtCore, QtGui -from openlp.core.ui import FileRenameForm, ThemeForm +from openlp.core.ui import criticalErrorMessageBox, FileRenameForm, ThemeForm from openlp.core.theme import Theme from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ build_icon, Receiver, SettingsManager, translate, check_item_selected, \ BackgroundType, BackgroundGradientType, check_directory_exists -from openlp.core.utils import AppLocation, get_filesystem_encoding +from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ + get_filesystem_encoding log = logging.getLogger(__name__) @@ -45,13 +46,14 @@ class ThemeManager(QtGui.QWidget): """ Manages the orders of Theme. """ - def __init__(self, parent): + def __init__(self, mainwindow, parent=None): QtGui.QWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow self.settingsSection = u'themes' self.themeForm = ThemeForm(self) self.fileRenameForm = FileRenameForm(self) - self.serviceComboBox = self.parent.ServiceManagerContents.themeComboBox + self.serviceComboBox = \ + self.mainwindow.ServiceManagerContents.themeComboBox # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -68,7 +70,7 @@ class ThemeManager(QtGui.QWidget): u':/themes/theme_edit.png', translate('OpenLP.ThemeManager', 'Edit a theme.'), self.onEditTheme) - self.toolbar.addToolbarButton( + self.deleteToolbarAction = self.toolbar.addToolbarButton( translate('OpenLP.ThemeManager', 'Delete Theme'), u':/general/general_delete.png', translate('OpenLP.ThemeManager', 'Delete a theme.'), @@ -123,6 +125,9 @@ class ThemeManager(QtGui.QWidget): QtCore.QObject.connect(self.themeListWidget, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.changeGlobalFromScreen) + QtCore.QObject.connect(self.themeListWidget, + QtCore.SIGNAL(u'itemClicked(QListWidgetItem *)'), + self.checkListState) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.changeGlobalFromTab) QtCore.QObject.connect(Receiver.get_receiver(), @@ -146,6 +151,18 @@ class ThemeManager(QtGui.QWidget): self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) + def checkListState(self, item): + """ + If Default theme selected remove delete button. + """ + realThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) + themeName = unicode(item.text()) + # If default theme restrict actions + if realThemeName == themeName: + self.deleteToolbarAction.setVisible(True) + else: + self.deleteToolbarAction.setVisible(False) + def contextMenu(self, point): """ Build the Right Click Context menu and set state depending on @@ -252,7 +269,7 @@ class ThemeManager(QtGui.QWidget): oldThemeData = self.getThemeData(oldThemeName) self.deleteTheme(oldThemeName) self.cloneThemeData(oldThemeData, newThemeName) - for plugin in self.parent.pluginManager.plugins: + for plugin in self.mainwindow.pluginManager.plugins: if plugin.usesTheme(oldThemeName): plugin.renameTheme(oldThemeName, newThemeName) @@ -324,9 +341,9 @@ class ThemeManager(QtGui.QWidget): """ self.themelist.remove(theme) thumb = theme + u'.png' + delete_file(os.path.join(self.path, thumb)) + delete_file(os.path.join(self.thumbPath, thumb)) try: - os.remove(os.path.join(self.path, thumb)) - os.remove(os.path.join(self.thumbPath, thumb)) encoding = get_filesystem_encoding() shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) except OSError: @@ -342,9 +359,7 @@ class ThemeManager(QtGui.QWidget): """ item = self.themeListWidget.currentItem() if item is None: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', + criticalErrorMessageBox(message=translate('OpenLP.ThemeManager', 'You have not selected a theme.')) return theme = unicode(item.data(QtCore.Qt.UserRole).toString()) @@ -371,10 +386,10 @@ class ThemeManager(QtGui.QWidget): 'Your theme has been successfully exported.')) except (IOError, OSError): log.exception(u'Export Theme Failed') - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('OpenLP.ThemeManager', 'Theme Export Failed'), translate('OpenLP.ThemeManager', - 'Your theme could not be exported due to an error.')) + 'Your theme could not be exported due to an error.')) finally: if zip: zip.close() @@ -388,7 +403,8 @@ class ThemeManager(QtGui.QWidget): files = QtGui.QFileDialog.getOpenFileNames(self, translate('OpenLP.ThemeManager', 'Select Theme Import File'), SettingsManager.get_last_dir(self.settingsSection), - translate('OpenLP.ThemeManager', 'Theme (*.*)')) + translate('OpenLP.ThemeManager', 'Theme v1 (*.theme);;' + 'Theme v2 (*.otz);;All Files (*.*)')) log.info(u'New Themes %s', unicode(files)) if files: for file in files: @@ -458,7 +474,8 @@ class ThemeManager(QtGui.QWidget): unicode(themeName) + u'.xml') xml = get_text_file_string(xmlFile) if not xml: - return self._baseTheme() + log.debug("No theme data - using default theme") + return ThemeXML() else: return self._createThemeFromXml(xml, self.path) @@ -477,16 +494,12 @@ class ThemeManager(QtGui.QWidget): filexml = None themename = None for file in zip.namelist(): - try: - ucsfile = file.decode(u'utf-8') - except UnicodeDecodeError: - QtGui.QMessageBox.critical( - self, translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', - 'File is not a valid theme.\n' - 'The content encoding is not UTF-8.')) - log.exception(u'Filename "%s" is not valid UTF-8' % - file.decode(u'utf-8', u'replace')) + ucsfile = file_is_unicode(file) + if not ucsfile: + criticalErrorMessageBox( + message=translate('OpenLP.ThemeManager', + 'File is not a valid theme.\n' + 'The content encoding is not UTF-8.')) continue osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) theme_dir = None @@ -505,13 +518,10 @@ class ThemeManager(QtGui.QWidget): check_directory_exists(theme_dir) if os.path.splitext(ucsfile)[1].lower() in [u'.xml']: xml_data = zip.read(file) - try: - xml_data = xml_data.decode(u'utf-8') - except UnicodeDecodeError: - log.exception(u'Theme XML is not UTF-8 ' - u'encoded.') + xml_data = file_is_unicode(xml_data) + if not xml_data: break - filexml = self.checkVersionAndConvert(xml_data) + filexml = self._checkVersionAndConvert(xml_data) outfile = open(fullpath, u'w') outfile.write(filexml.encode(u'utf-8')) else: @@ -521,19 +531,17 @@ class ThemeManager(QtGui.QWidget): theme = self._createThemeFromXml(filexml, self.path) self.generateAndSaveImage(dir, themename, theme) else: - Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', - 'Validation Error'), - u'message':translate('OpenLP.ThemeManager', - 'File is not a valid theme.')}) + criticalErrorMessageBox( + translate('OpenLP.ThemeManager', 'Validation Error'), + translate('OpenLP.ThemeManager', + 'File is not a valid theme.')) log.exception(u'Theme file does not contain XML data %s' % filename) except (IOError, NameError): - Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', - 'Validation Error'), - u'message':translate('OpenLP.ThemeManager', - 'File is not a valid theme.')}) + criticalErrorMessageBox( + translate('OpenLP.ThemeManager', 'Validation Error'), + translate('OpenLP.ThemeManager', + 'File is not a valid theme.')) log.exception(u'Importing theme from zip failed %s' % filename) finally: if zip: @@ -541,22 +549,6 @@ class ThemeManager(QtGui.QWidget): if outfile: outfile.close() - def checkVersionAndConvert(self, xml_data): - """ - Check if a theme is from OpenLP version 1 - - ``xml_data`` - Theme XML to check the version of - """ - log.debug(u'checkVersion1 ') - theme = xml_data.encode(u'ascii', u'xmlcharrefreplace') - tree = ElementTree(element=XML(theme)).getroot() - # look for old version 1 tags - if tree.find(u'BackgroundType') is None: - return xml_data - else: - return self._migrateVersion122(xml_data) - def checkIfThemeExists(self, themeName): """ Check if theme already exists and displays error message @@ -566,11 +558,10 @@ class ThemeManager(QtGui.QWidget): """ theme_dir = os.path.join(self.path, themeName) if os.path.exists(theme_dir): - Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', - 'Validation Error'), - u'message':translate('OpenLP.ThemeManager', - 'A theme with this name already exists.')}) + criticalErrorMessageBox( + translate('OpenLP.ThemeManager', 'Validation Error'), + translate('OpenLP.ThemeManager', + 'A theme with this name already exists.')) return False return True @@ -587,10 +578,7 @@ class ThemeManager(QtGui.QWidget): theme_file = os.path.join(theme_dir, name + u'.xml') if imageTo and self.oldBackgroundImage and \ imageTo != self.oldBackgroundImage: - try: - os.remove(self.oldBackgroundImage) - except OSError: - log.exception(u'Unable to remove old theme background') + delete_file(self.oldBackgroundImage) outfile = None try: outfile = open(theme_file, u'w') @@ -637,7 +625,8 @@ class ThemeManager(QtGui.QWidget): Flag to tell message lines per page need to be generated. """ log.debug(u'generateImage \n%s ', themeData) - return self.parent.renderManager.generate_preview(themeData, forcePage) + return self.mainwindow.renderManager.generate_preview( + themeData, forcePage) def getPreviewImage(self, theme): """ @@ -650,13 +639,21 @@ class ThemeManager(QtGui.QWidget): image = os.path.join(self.path, theme + u'.png') return image - def _baseTheme(self): + def _checkVersionAndConvert(self, xml_data): """ - Provide a base theme with sensible defaults + Check if a theme is from OpenLP version 1 + + ``xml_data`` + Theme XML to check the version of """ - log.debug(u'base theme created') - newtheme = ThemeXML() - return newtheme + log.debug(u'checkVersion1 ') + theme = xml_data.encode(u'ascii', u'xmlcharrefreplace') + tree = ElementTree(element=XML(theme)).getroot() + # look for old version 1 tags + if tree.find(u'BackgroundType') is None: + return xml_data + else: + return self._migrateVersion122(xml_data) def _createThemeFromXml(self, themeXml, path): """ @@ -691,21 +688,19 @@ class ThemeManager(QtGui.QWidget): return False # should be the same unless default if theme != unicode(item.data(QtCore.Qt.UserRole).toString()): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', - 'You are unable to delete the default theme.')) + criticalErrorMessageBox( + message=translate('OpenLP.ThemeManager', + 'You are unable to delete the default theme.')) return False # check for use in the system else where. if testPlugin: - for plugin in self.parent.pluginManager.plugins: + for plugin in self.mainwindow.pluginManager.plugins: if plugin.usesTheme(theme): - Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', + criticalErrorMessageBox(translate('OpenLP.ThemeManager', 'Validation Error'), - u'message': unicode(translate('OpenLP.ThemeManager', + unicode(translate('OpenLP.ThemeManager', 'Theme %s is used in the %s plugin.')) % \ - (theme, plugin.name)}) + (theme, plugin.name)) return False return True @@ -765,4 +760,4 @@ class ThemeManager(QtGui.QWidget): vAlignCorrection = 2 newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_vertical_align = vAlignCorrection - return newtheme.extract_xml() \ No newline at end of file + return newtheme.extract_xml() diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index f61a44584..50e8109c5 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -476,8 +476,6 @@ class Ui_ThemeWizard(object): self.mainColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.mainSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.mainSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) - self.mainLineCountLabel.setText( - translate('OpenLP.ThemeWizard', '(%d lines per slide)')) self.lineSpacingLabel.setText( translate('OpenLP.ThemeWizard', 'Line Spacing:')) self.lineSpacingSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) @@ -569,17 +567,17 @@ class Ui_ThemeWizard(object): self.themeNameLabel.setText( translate('OpenLP.ThemeWizard', 'Theme name:')) # Align all QFormLayouts towards each other. - width = max(self.backgroundLabel.minimumSizeHint().width(), - self.colorLabel.minimumSizeHint().width()) - width = max(width, self.gradientStartLabel.minimumSizeHint().width()) - width = max(width, self.gradientEndLabel.minimumSizeHint().width()) - width = max(width, self.gradientTypeLabel.minimumSizeHint().width()) - width = max(width, self.imageLabel.minimumSizeHint().width()) - self.backgroundTypeSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.colorSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.gradientSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.imageSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) + labelWidth = max(self.backgroundLabel.minimumSizeHint().width(), + self.colorLabel.minimumSizeHint().width(), + self.gradientStartLabel.minimumSizeHint().width(), + self.gradientEndLabel.minimumSizeHint().width(), + self.gradientTypeLabel.minimumSizeHint().width(), + self.imageLabel.minimumSizeHint().width()) + self.backgroundTypeSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.colorSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.gradientSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.imageSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py new file mode 100644 index 000000000..3b221455b --- /dev/null +++ b/openlp/core/ui/wizard.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:``wizard`` module provides generic wizard tools for OpenLP. +""" +import logging + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import build_icon, Receiver + +log = logging.getLogger(__name__) + +class OpenLPWizard(QtGui.QWizard): + """ + Generic OpenLP wizard to provide generic functionality and a unified look + and feel. + """ + def __init__(self, parent, plugin, name, image): + QtGui.QWizard.__init__(self, parent) + self.setObjectName(name) + self.openIcon = build_icon(u':/general/general_open.png') + self.deleteIcon = build_icon(u':/general/general_delete.png') + self.finishButton = self.button(QtGui.QWizard.FinishButton) + self.cancelButton = self.button(QtGui.QWizard.CancelButton) + self.setupUi(image) + self.registerFields() + self.plugin = plugin + self.customInit() + self.customSignals() + QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), + self.onCurrentIdChanged) + + def setupUi(self, image): + """ + Set up the wizard UI + """ + self.setModal(True) + self.setWizardStyle(QtGui.QWizard.ModernStyle) + self.setOptions(QtGui.QWizard.IndependentPages | + QtGui.QWizard.NoBackButtonOnStartPage | + QtGui.QWizard.NoBackButtonOnLastPage) + self.addWelcomePage(image) + self.addCustomPages() + self.addProgressPage() + self.retranslateUi() + QtCore.QMetaObject.connectSlotsByName(self) + + def addWelcomePage(self, image): + """ + Add the opening welcome page to the wizard. + + ``image`` + A splash image for the wizard + """ + self.welcomePage = QtGui.QWizardPage() + self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, + QtGui.QPixmap(image)) + self.welcomePage.setObjectName(u'WelcomePage') + self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage) + self.welcomeLayout.setObjectName(u'WelcomeLayout') + self.titleLabel = QtGui.QLabel(self.welcomePage) + self.titleLabel.setObjectName(u'TitleLabel') + self.welcomeLayout.addWidget(self.titleLabel) + self.welcomeLayout.addSpacing(40) + self.informationLabel = QtGui.QLabel(self.welcomePage) + self.informationLabel.setWordWrap(True) + self.informationLabel.setObjectName(u'InformationLabel') + self.welcomeLayout.addWidget(self.informationLabel) + self.welcomeLayout.addStretch() + self.addPage(self.welcomePage) + + def addProgressPage(self): + """ + Add the progress page for the wizard. This page informs the user how + the wizard is progressing with its task. + """ + self.progressPage = QtGui.QWizardPage() + self.progressPage.setObjectName(u'progressPage') + self.progressLayout = QtGui.QVBoxLayout(self.progressPage) + self.progressLayout.setMargin(48) + self.progressLayout.setObjectName(u'progressLayout') + self.progressLabel = QtGui.QLabel(self.progressPage) + self.progressLabel.setObjectName(u'progressLabel') + self.progressLayout.addWidget(self.progressLabel) + self.progressBar = QtGui.QProgressBar(self.progressPage) + self.progressBar.setObjectName(u'progressBar') + self.progressLayout.addWidget(self.progressBar) + self.addPage(self.progressPage) + + def exec_(self): + """ + Run the wizard. + """ + self.setDefaults() + return QtGui.QWizard.exec_(self) + + def reject(self): + """ + Stop the wizard on cancel button, close button or ESC key. + """ + log.debug(u'Wizard cancelled by user.') + if self.currentPage() == self.progressPage: + Receiver.send_message(u'openlp_stop_wizard') + self.done(QtGui.QDialog.Rejected) + + def onCurrentIdChanged(self, pageId): + """ + Perform necessary functions depending on which wizard page is active. + """ + if self.page(pageId) == self.progressPage: + self.preWizard() + self.performWizard() + self.postWizard() + + def incrementProgressBar(self, status_text, increment=1): + """ + Update the wizard progress page. + + ``status_text`` + Current status information to display. + + ``increment`` + The value to increment the progress bar by. + """ + log.debug(u'IncrementBar %s', status_text) + self.progressLabel.setText(status_text) + if increment > 0: + self.progressBar.setValue(self.progressBar.value() + increment) + Receiver.send_message(u'openlp_process_events') + + def preWizard(self): + """ + Prepare the UI for the import. + """ + self.finishButton.setVisible(False) + self.progressBar.setMinimum(0) + self.progressBar.setMaximum(1188) + self.progressBar.setValue(0) + + def postWizard(self): + """ + Clean up the UI after the import has finished. + """ + self.progressBar.setValue(self.progressBar.maximum()) + self.finishButton.setVisible(True) + self.cancelButton.setVisible(False) + Receiver.send_message(u'openlp_process_events') diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 98b9cd0b4..b7d95a46d 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -207,7 +207,7 @@ def check_latest_version(current_version): The current version of OpenLP. """ version_string = current_version[u'full'] - #set to prod in the distribution config file. + # set to prod in the distribution config file. settings = QtCore.QSettings() settings.beginGroup(u'general') last_test = unicode(settings.value(u'last version test', @@ -282,8 +282,100 @@ def split_filename(path): else: return os.path.split(path) +def delete_file(file_path_name): + """ + Deletes a file from the system. + + ``file_path_name`` + The file, including path, to delete. + """ + if not file_path_name: + return False + try: + if os.path.exists(file_path_name): + os.remove(file_path_name) + return True + except (IOError, OSError): + log.exception("Unable to delete file %s" % file_path_name) + return False + +def get_web_page(url, header=None, update_openlp=False): + """ + Attempts to download the webpage at url and returns that page or None. + + ``url`` + The URL to be downloaded. + + ``header`` + An optional HTTP header to pass in the request to the web server. + + ``update_openlp`` + Tells OpenLP to update itself if the page is successfully downloaded. + Defaults to False. + """ + # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a + # proxy_handler, build into an opener and install the opener into urllib2. + # http://docs.python.org/library/urllib2.html + if not url: + return None + req = urllib2.Request(url) + if header: + req.add_header(header[0], header[1]) + page = None + log.debug(u'Downloading URL = %s' % url) + try: + page = urllib2.urlopen(req) + log.debug(u'Downloaded URL = %s' % page.geturl()) + except urllib2.URLError: + log.exception(u'The web page could not be downloaded') + if not page: + return None + if update_openlp: + Receiver.send_message(u'openlp_process_events') + return page + +def file_is_unicode(filename): + """ + Checks if a file is valid unicode and returns the unicode decoded file or + None. + + ``filename`` + File to check is valid unicode. + """ + if not filename: + return None + ucsfile = None + try: + ucsfile = filename.decode(u'utf-8') + except UnicodeDecodeError: + log.exception(u'Filename "%s" is not valid UTF-8' % + filename.decode(u'utf-8', u'replace')) + if not ucsfile: + return None + return ucsfile + +def string_is_unicode(test_string): + """ + Makes sure a string is unicode. + + ``test_string`` + The string to confirm is unicode. + """ + return_string = u'' + if not test_string: + return return_string + if isinstance(test_string, unicode): + return_string = test_string + if not isinstance(test_string, unicode): + try: + return_string = unicode(test_string, u'utf-8') + except UnicodeError: + log.exception("Error encoding string to unicode") + return return_string + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'check_latest_version', u'add_actions', - u'get_filesystem_encoding', u'LanguageManager'] + u'get_filesystem_encoding', u'LanguageManager', u'ActionList', + u'get_web_page', u'file_is_unicode', u'string_is_unicode'] diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 4a7e18cef..61be922d5 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -73,7 +73,7 @@ class AlertsPlugin(Plugin): self.toolsAlertItem.setStatusTip( translate('AlertsPlugin', 'Show an alert message.')) self.toolsAlertItem.setShortcut(u'F7') - self.serviceManager.parent.ToolsMenu.addAction(self.toolsAlertItem) + self.serviceManager.mainwindow.ToolsMenu.addAction(self.toolsAlertItem) QtCore.QObject.connect(self.toolsAlertItem, QtCore.SIGNAL(u'triggered()'), self.onAlertsTrigger) self.toolsAlertItem.setVisible(False) diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 4590ea739..d3f41804b 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -23,7 +23,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +The bible import functions for OpenLP +""" import csv import logging import os @@ -31,15 +33,19 @@ import os.path from PyQt4 import QtCore, QtGui -from bibleimportwizard import Ui_BibleImportWizard from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.db import delete_database -from openlp.core.utils import AppLocation +from openlp.core.ui import criticalErrorMessageBox +from openlp.core.ui.wizard import OpenLPWizard +from openlp.core.utils import AppLocation, string_is_unicode from openlp.plugins.bibles.lib.manager import BibleFormat log = logging.getLogger(__name__) class WebDownload(object): + """ + Provides an enumeration for the web bible types available to OpenLP. + """ Unknown = -1 Crosswalk = 0 BibleGateway = 1 @@ -53,10 +59,13 @@ class WebDownload(object): @classmethod def get_name(cls, name): + """ + Get the web bible type name. + """ return cls.Names[name] -class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): +class BibleImportForm(OpenLPWizard): """ This is the Bible Import Wizard, which allows easy importing of Bibles into OpenLP from other formats like OSIS, CSV and OpenSong. @@ -76,27 +85,42 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): ``bibleplugin`` The Bible plugin. """ - QtGui.QWizard.__init__(self, parent) - self.setupUi(self) - self.registerFields() + self.manager = manager + self.web_bible_list = {} + OpenLPWizard.__init__(self, parent, bibleplugin, u'bibleImportWizard', + u':/wizards/wizard_importbible.bmp') + + def setupUi(self, image): + """ + Set up the UI for the bible wizard. + """ + OpenLPWizard.setupUi(self, image) + QtCore.QObject.connect(self.formatComboBox, + QtCore.SIGNAL(u'currentIndexChanged(int)'), self.selectStack, + QtCore.SLOT(u'setCurrentIndex(int)')) + + def customInit(self): + """ + Perform any custom initialisation for bible importing. + """ if BibleFormat.get_availability(BibleFormat.OpenLP1): self.openlp1DisabledLabel.hide() else: self.openlp1FileLabel.hide() self.openlp1FileEdit.hide() self.openlp1BrowseButton.hide() - self.finishButton = self.button(QtGui.QWizard.FinishButton) - self.cancelButton = self.button(QtGui.QWizard.CancelButton) - self.manager = manager - self.bibleplugin = bibleplugin self.manager.set_process_dialog(self) - self.web_bible_list = {} self.loadWebBibles() self.restart() self.selectStack.setCurrentIndex(0) + + def customSignals(self): + """ + Set up the signals used in the bible importer. + """ QtCore.QObject.connect(self.webSourceComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), - self.onWebSourceComboBoxCurrentIndexChanged) + self.onWebSourceComboBoxIndexChanged) QtCore.QObject.connect(self.osisBrowseButton, QtCore.SIGNAL(u'clicked()'), self.onOsisBrowseButtonClicked) @@ -112,25 +136,329 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): QtCore.QObject.connect(self.openlp1BrowseButton, QtCore.SIGNAL(u'clicked()'), self.onOpenlp1BrowseButtonClicked) - QtCore.QObject.connect(self, - QtCore.SIGNAL(u'currentIdChanged(int)'), - self.onCurrentIdChanged) - def exec_(self): + def addCustomPages(self): """ - Run the wizard. + Add the bible import specific wizard pages. """ - self.setDefaults() - return QtGui.QWizard.exec_(self) + # Select Page + self.selectPage = QtGui.QWizardPage() + self.selectPage.setObjectName(u'SelectPage') + self.selectPageLayout = QtGui.QVBoxLayout(self.selectPage) + self.selectPageLayout.setObjectName(u'SelectPageLayout') + self.formatLayout = QtGui.QFormLayout() + self.formatLayout.setObjectName(u'FormatLayout') + self.formatLabel = QtGui.QLabel(self.selectPage) + self.formatLabel.setObjectName(u'FormatLabel') + self.formatComboBox = QtGui.QComboBox(self.selectPage) + self.formatComboBox.addItems([u'', u'', u'', u'', u'']) + self.formatComboBox.setObjectName(u'FormatComboBox') + self.formatLayout.addRow(self.formatLabel, self.formatComboBox) + self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, + self.formatSpacer) + self.selectPageLayout.addLayout(self.formatLayout) + self.selectStack = QtGui.QStackedLayout() + self.selectStack.setObjectName(u'SelectStack') + self.osisWidget = QtGui.QWidget(self.selectPage) + self.osisWidget.setObjectName(u'OsisWidget') + self.osisLayout = QtGui.QFormLayout(self.osisWidget) + self.osisLayout.setMargin(0) + self.osisLayout.setObjectName(u'OsisLayout') + self.osisFileLabel = QtGui.QLabel(self.osisWidget) + self.osisFileLabel.setObjectName(u'OsisFileLabel') + self.osisFileLayout = QtGui.QHBoxLayout() + self.osisFileLayout.setObjectName(u'OsisFileLayout') + self.osisFileEdit = QtGui.QLineEdit(self.osisWidget) + self.osisFileEdit.setObjectName(u'OsisFileEdit') + self.osisFileLayout.addWidget(self.osisFileEdit) + self.osisBrowseButton = QtGui.QToolButton(self.osisWidget) + self.osisBrowseButton.setIcon(self.openIcon) + self.osisBrowseButton.setObjectName(u'OsisBrowseButton') + self.osisFileLayout.addWidget(self.osisBrowseButton) + self.osisLayout.addRow(self.osisFileLabel, self.osisFileLayout) + self.osisSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.osisSpacer) + self.selectStack.addWidget(self.osisWidget) + self.csvWidget = QtGui.QWidget(self.selectPage) + self.csvWidget.setObjectName(u'CsvWidget') + self.csvLayout = QtGui.QFormLayout(self.csvWidget) + self.csvLayout.setMargin(0) + self.csvLayout.setObjectName(u'CsvLayout') + self.csvBooksLabel = QtGui.QLabel(self.csvWidget) + self.csvBooksLabel.setObjectName(u'CsvBooksLabel') + self.csvBooksLayout = QtGui.QHBoxLayout() + self.csvBooksLayout.setObjectName(u'CsvBooksLayout') + self.csvBooksEdit = QtGui.QLineEdit(self.csvWidget) + self.csvBooksEdit.setObjectName(u'CsvBooksEdit') + self.csvBooksLayout.addWidget(self.csvBooksEdit) + self.csvBooksButton = QtGui.QToolButton(self.csvWidget) + self.csvBooksButton.setIcon(self.openIcon) + self.csvBooksButton.setObjectName(u'CsvBooksButton') + self.csvBooksLayout.addWidget(self.csvBooksButton) + self.csvLayout.addRow(self.csvBooksLabel, self.csvBooksLayout) + self.csvVersesLabel = QtGui.QLabel(self.csvWidget) + self.csvVersesLabel.setObjectName(u'CsvVersesLabel') + self.csvVersesLayout = QtGui.QHBoxLayout() + self.csvVersesLayout.setObjectName(u'CsvVersesLayout') + self.csvVersesEdit = QtGui.QLineEdit(self.csvWidget) + self.csvVersesEdit.setObjectName(u'CsvVersesEdit') + self.csvVersesLayout.addWidget(self.csvVersesEdit) + self.csvVersesButton = QtGui.QToolButton(self.csvWidget) + self.csvVersesButton.setIcon(self.openIcon) + self.csvVersesButton.setObjectName(u'CsvVersesButton') + self.csvVersesLayout.addWidget(self.csvVersesButton) + self.csvLayout.addRow(self.csvVersesLabel, self.csvVersesLayout) + self.csvSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.csvLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.csvSpacer) + self.selectStack.addWidget(self.csvWidget) + self.openSongWidget = QtGui.QWidget(self.selectPage) + self.openSongWidget.setObjectName(u'OpenSongWidget') + self.openSongLayout = QtGui.QFormLayout(self.openSongWidget) + self.openSongLayout.setMargin(0) + self.openSongLayout.setObjectName(u'OpenSongLayout') + self.openSongFileLabel = QtGui.QLabel(self.openSongWidget) + self.openSongFileLabel.setObjectName(u'OpenSongFileLabel') + self.openSongFileLayout = QtGui.QHBoxLayout() + self.openSongFileLayout.setObjectName(u'OpenSongFileLayout') + self.openSongFileEdit = QtGui.QLineEdit(self.openSongWidget) + self.openSongFileEdit.setObjectName(u'OpenSongFileEdit') + self.openSongFileLayout.addWidget(self.openSongFileEdit) + self.openSongBrowseButton = QtGui.QToolButton(self.openSongWidget) + self.openSongBrowseButton.setIcon(self.openIcon) + self.openSongBrowseButton.setObjectName(u'OpenSongBrowseButton') + self.openSongFileLayout.addWidget(self.openSongBrowseButton) + self.openSongLayout.addRow(self.openSongFileLabel, + self.openSongFileLayout) + self.openSongSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole, + self.openSongSpacer) + self.selectStack.addWidget(self.openSongWidget) + self.webTabWidget = QtGui.QTabWidget(self.selectPage) + self.webTabWidget.setObjectName(u'WebTabWidget') + self.webBibleTab = QtGui.QWidget() + self.webBibleTab.setObjectName(u'WebBibleTab') + self.webBibleLayout = QtGui.QFormLayout(self.webBibleTab) + self.webBibleLayout.setObjectName(u'WebBibleLayout') + self.webSourceLabel = QtGui.QLabel(self.webBibleTab) + self.webSourceLabel.setObjectName(u'WebSourceLabel') + self.webBibleLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.webSourceLabel) + self.webSourceComboBox = QtGui.QComboBox(self.webBibleTab) + self.webSourceComboBox.setObjectName(u'WebSourceComboBox') + self.webSourceComboBox.addItems([u'', u'', u'']) + self.webBibleLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.webSourceComboBox) + self.webTranslationLabel = QtGui.QLabel(self.webBibleTab) + self.webTranslationLabel.setObjectName(u'webTranslationLabel') + self.webBibleLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.webTranslationLabel) + self.webTranslationComboBox = QtGui.QComboBox(self.webBibleTab) + self.webTranslationComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToContents) + self.webTranslationComboBox.setObjectName(u'WebTranslationComboBox') + self.webBibleLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.webTranslationComboBox) + self.webTabWidget.addTab(self.webBibleTab, u'') + self.webProxyTab = QtGui.QWidget() + self.webProxyTab.setObjectName(u'WebProxyTab') + self.webProxyLayout = QtGui.QFormLayout(self.webProxyTab) + self.webProxyLayout.setObjectName(u'WebProxyLayout') + self.webServerLabel = QtGui.QLabel(self.webProxyTab) + self.webServerLabel.setObjectName(u'WebServerLabel') + self.webProxyLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.webServerLabel) + self.webServerEdit = QtGui.QLineEdit(self.webProxyTab) + self.webServerEdit.setObjectName(u'WebServerEdit') + self.webProxyLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.webServerEdit) + self.webUserLabel = QtGui.QLabel(self.webProxyTab) + self.webUserLabel.setObjectName(u'WebUserLabel') + self.webProxyLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.webUserLabel) + self.webUserEdit = QtGui.QLineEdit(self.webProxyTab) + self.webUserEdit.setObjectName(u'WebUserEdit') + self.webProxyLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.webUserEdit) + self.webPasswordLabel = QtGui.QLabel(self.webProxyTab) + self.webPasswordLabel.setObjectName(u'WebPasswordLabel') + self.webProxyLayout.setWidget(2, QtGui.QFormLayout.LabelRole, + self.webPasswordLabel) + self.webPasswordEdit = QtGui.QLineEdit(self.webProxyTab) + self.webPasswordEdit.setObjectName(u'WebPasswordEdit') + self.webProxyLayout.setWidget(2, QtGui.QFormLayout.FieldRole, + self.webPasswordEdit) + self.webTabWidget.addTab(self.webProxyTab, u'') + self.selectStack.addWidget(self.webTabWidget) + self.openlp1Widget = QtGui.QWidget(self.selectPage) + self.openlp1Widget.setObjectName(u'Openlp1Widget') + self.openlp1Layout = QtGui.QFormLayout(self.openlp1Widget) + self.openlp1Layout.setMargin(0) + self.openlp1Layout.setObjectName(u'Openlp1Layout') + self.openlp1FileLabel = QtGui.QLabel(self.openlp1Widget) + self.openlp1FileLabel.setObjectName(u'Openlp1FileLabel') + self.openlp1FileLayout = QtGui.QHBoxLayout() + self.openlp1FileLayout.setObjectName(u'Openlp1FileLayout') + self.openlp1FileEdit = QtGui.QLineEdit(self.openlp1Widget) + self.openlp1FileEdit.setObjectName(u'Openlp1FileEdit') + self.openlp1FileLayout.addWidget(self.openlp1FileEdit) + self.openlp1BrowseButton = QtGui.QToolButton(self.openlp1Widget) + self.openlp1BrowseButton.setIcon(self.openIcon) + self.openlp1BrowseButton.setObjectName(u'Openlp1BrowseButton') + self.openlp1FileLayout.addWidget(self.openlp1BrowseButton) + self.openlp1Layout.addRow(self.openlp1FileLabel, self.openlp1FileLayout) + self.openlp1DisabledLabel = QtGui.QLabel(self.openlp1Widget) + self.openlp1DisabledLabel.setWordWrap(True) + self.openlp1DisabledLabel.setObjectName(u'Openlp1DisabledLabel') + self.openlp1Layout.addRow(self.openlp1DisabledLabel) + self.openlp1Spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole, + self.openlp1Spacer) + self.selectStack.addWidget(self.openlp1Widget) + self.selectPageLayout.addLayout(self.selectStack) + self.addPage(self.selectPage) + # License Page + self.licenseDetailsPage = QtGui.QWizardPage() + self.licenseDetailsPage.setObjectName(u'LicenseDetailsPage') + self.licenseDetailsLayout = QtGui.QFormLayout(self.licenseDetailsPage) + self.licenseDetailsLayout.setObjectName(u'LicenseDetailsLayout') + self.versionNameLabel = QtGui.QLabel(self.licenseDetailsPage) + self.versionNameLabel.setObjectName(u'VersionNameLabel') + self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.versionNameLabel) + self.versionNameEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.versionNameEdit.setObjectName(u'VersionNameEdit') + self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.versionNameEdit) + self.copyrightLabel = QtGui.QLabel(self.licenseDetailsPage) + self.copyrightLabel.setObjectName(u'CopyrightLabel') + self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.copyrightLabel) + self.copyrightEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.copyrightEdit.setObjectName(u'CopyrightEdit') + self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.copyrightEdit) + self.permissionsLabel = QtGui.QLabel(self.licenseDetailsPage) + self.permissionsLabel.setObjectName(u'PermissionsLabel') + self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, + self.permissionsLabel) + self.permissionsEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.permissionsEdit.setObjectName(u'PermissionsEdit') + self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, + self.permissionsEdit) + self.addPage(self.licenseDetailsPage) - def reject(self): + def retranslateUi(self): """ - Stop the import on cancel button, close button or ESC key. + Allow for localisation of the bible import wizard. """ - log.debug(u'Import canceled by user.') - if self.currentPage() == self.importPage: - Receiver.send_message(u'bibles_stop_import') - self.done(QtGui.QDialog.Rejected) + self.setWindowTitle( + translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard')) + self.titleLabel.setText( + u'%s' % \ + translate('BiblesPlugin.ImportWizardForm', + 'Welcome to the Bible Import Wizard')) + self.informationLabel.setText( + translate('BiblesPlugin.ImportWizardForm', + 'This wizard will help you to import Bibles from a ' + 'variety of formats. Click the next button below to start the ' + 'process by selecting a format to import from.')) + self.selectPage.setTitle(translate('BiblesPlugin.ImportWizardForm', + 'Select Import Source')) + self.selectPage.setSubTitle( + translate('BiblesPlugin.ImportWizardForm', + 'Select the import format, and where to import from.')) + self.formatLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Format:')) + self.formatComboBox.setItemText(0, + translate('BiblesPlugin.ImportWizardForm', 'OSIS')) + self.formatComboBox.setItemText(1, + translate('BiblesPlugin.ImportWizardForm', 'CSV')) + self.formatComboBox.setItemText(2, + translate('BiblesPlugin.ImportWizardForm', 'OpenSong')) + self.formatComboBox.setItemText(3, + translate('BiblesPlugin.ImportWizardForm', 'Web Download')) + self.formatComboBox.setItemText(4, + translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x')) + self.openlp1FileLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'File location:')) + self.osisFileLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'File location:')) + self.csvBooksLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Books location:')) + self.csvVersesLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Verse location:')) + self.openSongFileLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Bible filename:')) + self.webSourceLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Location:')) + self.webSourceComboBox.setItemText(0, + translate('BiblesPlugin.ImportWizardForm', 'Crosswalk')) + self.webSourceComboBox.setItemText(1, + translate('BiblesPlugin.ImportWizardForm', 'BibleGateway')) + self.webSourceComboBox.setItemText(2, + translate('BiblesPlugin.ImportWizardForm', 'Bibleserver')) + self.webTranslationLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Bible:')) + self.webTabWidget.setTabText( + self.webTabWidget.indexOf(self.webBibleTab), + translate('BiblesPlugin.ImportWizardForm', 'Download Options')) + self.webServerLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Server:')) + self.webUserLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Username:')) + self.webPasswordLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Password:')) + self.webTabWidget.setTabText( + self.webTabWidget.indexOf(self.webProxyTab), + translate('BiblesPlugin.ImportWizardForm', + 'Proxy Server (Optional)')) + self.licenseDetailsPage.setTitle( + translate('BiblesPlugin.ImportWizardForm', 'License Details')) + self.licenseDetailsPage.setSubTitle( + translate('BiblesPlugin.ImportWizardForm', + 'Set up the Bible\'s license details.')) + self.versionNameLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Version name:')) + self.copyrightLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) + self.permissionsLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Permissions:')) + self.progressPage.setTitle( + translate('BiblesPlugin.ImportWizardForm', 'Importing')) + self.progressPage.setSubTitle( + translate('BiblesPlugin.ImportWizardForm', + 'Please wait while your Bible is imported.')) + self.progressLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Ready.')) + self.progressBar.setFormat(u'%p%') + self.openlp1DisabledLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'The openlp.org 1.x ' + 'importer has been disabled due to a missing Python module. If ' + 'you want to use this importer, you will need to install the ' + '"python-sqlite" module.')) + # Align all QFormLayouts towards each other. + labelWidth = max(self.formatLabel.minimumSizeHint().width(), + self.osisFileLabel.minimumSizeHint().width(), + self.csvBooksLabel.minimumSizeHint().width(), + self.csvVersesLabel.minimumSizeHint().width(), + self.openSongFileLabel.minimumSizeHint().width(), + self.openlp1FileLabel.minimumSizeHint().width()) + self.formatSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.osisSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.csvSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.openSongSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.openlp1Spacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) def validateCurrentPage(self): """ @@ -141,7 +469,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): elif self.currentPage() == self.selectPage: if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: if not self.field(u'osis_location').toString(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid Bible Location'), translate('BiblesPlugin.ImportWizardForm', @@ -151,7 +479,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): return False elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV: if not self.field(u'csv_booksfile').toString(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid Books File'), translate('BiblesPlugin.ImportWizardForm', @@ -160,7 +488,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.csvBooksEdit.setFocus() return False elif not self.field(u'csv_versefile').toString(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid Verse File'), translate('BiblesPlugin.ImportWizardForm', @@ -171,7 +499,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): elif self.field(u'source_format').toInt()[0] == \ BibleFormat.OpenSong: if not self.field(u'opensong_file').toString(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid OpenSong Bible'), translate('BiblesPlugin.ImportWizardForm', @@ -181,7 +509,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): return False elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1: if not self.field(u'openlp1_location').toString(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid Bible Location'), translate('BiblesPlugin.ImportWizardForm', @@ -195,7 +523,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): license_copyright = \ unicode(self.field(u'license_copyright').toString()) if not license_version: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Empty Version Name'), translate('BiblesPlugin.ImportWizardForm', @@ -203,7 +531,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.versionNameEdit.setFocus() return False elif not license_copyright: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Empty Copyright'), translate('BiblesPlugin.ImportWizardForm', @@ -212,7 +540,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.copyrightEdit.setFocus() return False elif self.manager.exists(license_version): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Bible Exists'), translate('BiblesPlugin.ImportWizardForm', 'This Bible already exists. Please import ' @@ -220,10 +548,10 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.versionNameEdit.setFocus() return False return True - if self.currentPage() == self.importPage: + if self.currentPage() == self.progressPage: return True - def onWebSourceComboBoxCurrentIndexChanged(self, index): + def onWebSourceComboBoxIndexChanged(self, index): """ Setup the list of Bibles when you select a different source on the web download page. @@ -279,13 +607,10 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): u'%s (*.bible)' % translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x bible')) - def onCurrentIdChanged(self, pageId): - if self.page(pageId) == self.importPage: - self.preImport() - self.performImport() - self.postImport() - def registerFields(self): + """ + Register the bible import wizard fields. + """ self.selectPage.registerField(u'source_format', self.formatComboBox) self.selectPage.registerField(u'osis_location', self.osisFileEdit) self.selectPage.registerField(u'csv_booksfile', self.csvBooksEdit) @@ -306,8 +631,11 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): u'license_permissions', self.permissionsEdit) def setDefaults(self): + """ + Set default values for the wizard pages. + """ settings = QtCore.QSettings() - settings.beginGroup(self.bibleplugin.settingsSection) + settings.beginGroup(self.plugin.settingsSection) self.restart() self.finishButton.setVisible(False) self.cancelButton.setVisible(True) @@ -332,72 +660,50 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): QtCore.QVariant(self.copyrightEdit.text())) self.setField(u'license_permissions', QtCore.QVariant(self.permissionsEdit.text())) - self.onWebSourceComboBoxCurrentIndexChanged(WebDownload.Crosswalk) + self.onWebSourceComboBoxIndexChanged(WebDownload.Crosswalk) settings.endGroup() def loadWebBibles(self): """ - Load the list of Crosswalk and BibleGateway bibles. + Load the lists of Crosswalk, BibleGateway and Bibleserver bibles. """ + filepath = AppLocation.get_directory(AppLocation.PluginsDir) + filepath = os.path.join(filepath, u'bibles', u'resources') # Load Crosswalk Bibles. - filepath = AppLocation.get_directory(AppLocation.PluginsDir) - filepath = os.path.join(filepath, u'bibles', u'resources') - books_file = None - try: - self.web_bible_list[WebDownload.Crosswalk] = {} - books_file = open( - os.path.join(filepath, u'crosswalkbooks.csv'), 'rb') - dialect = csv.Sniffer().sniff(books_file.read(1024)) - books_file.seek(0) - books_reader = csv.reader(books_file, dialect) - for line in books_reader: - ver = unicode(line[0], u'utf-8') - name = unicode(line[1], u'utf-8') - self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip() - except IOError: - log.exception(u'Crosswalk resources missing') - finally: - if books_file: - books_file.close() + self.loadBibleResourceFile( + os.path.join(filepath, u'crosswalkbooks.csv'), + WebDownload.Crosswalk) # Load BibleGateway Bibles. - books_file = None - try: - self.web_bible_list[WebDownload.BibleGateway] = {} - books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r') - dialect = csv.Sniffer().sniff(books_file.read(1024)) - books_file.seek(0) - books_reader = csv.reader(books_file, dialect) - for line in books_reader: - ver = line[0] - name = line[1] - if not isinstance(ver, unicode): - ver = unicode(ver, u'utf8') - if not isinstance(name, unicode): - name = unicode(name, u'utf8') - self.web_bible_list[WebDownload.BibleGateway][ver] = \ - name.strip() - except IOError: - log.exception(u'Biblegateway resources missing') - finally: - if books_file: - books_file.close() + self.loadBibleResourceFile(os.path.join(filepath, u'biblegateway.csv'), + WebDownload.BibleGateway) # Load and Bibleserver Bibles. - filepath = AppLocation.get_directory(AppLocation.PluginsDir) - filepath = os.path.join(filepath, u'bibles', u'resources') + self.loadBibleResourceFile(os.path.join(filepath, u'bibleserver.csv'), + WebDownload.Bibleserver) + + def loadBibleResourceFile(self, file_path_name, download_type): + """ + Loads a web bible resource file. + + ``file_path_name`` + The file to load including the file's path. + + ``download_type`` + The WebDownload type this file is for. + """ + self.web_bible_list[download_type] = {} books_file = None try: - self.web_bible_list[WebDownload.Bibleserver] = {} - books_file = open( - os.path.join(filepath, u'bibleserver.csv'), 'rb') + books_file = open(file_path_name, 'rb') dialect = csv.Sniffer().sniff(books_file.read(1024)) books_file.seek(0) books_reader = csv.reader(books_file, dialect) for line in books_reader: - ver = unicode(line[0], u'utf-8') - name = unicode(line[1], u'utf-8') - self.web_bible_list[WebDownload.Bibleserver][ver] = name.strip() - except IOError, UnicodeError: - log.exception(u'Bibleserver resources missing') + ver = string_is_unicode(line[0]) + name = string_is_unicode(line[1]) + self.web_bible_list[download_type][ver] = name.strip() + except IOError: + log.exception(u'%s resources missing' % + WebDownload.get_name(download_type)) finally: if books_file: books_file.close() @@ -413,8 +719,8 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): A editbox (QLineEdit). ``filters`` - The file extension filters. It should contain the file description as - well as the file extension. For example:: + The file extension filters. It should contain the file description + as well as the file extension. For example:: u'openlp.org 1.x bible (*.bible)' """ @@ -424,37 +730,28 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 'All Files') filename = QtGui.QFileDialog.getOpenFileName(self, title, os.path.dirname(SettingsManager.get_last_dir( - self.bibleplugin.settingsSection, 1)), filters) + self.plugin.settingsSection, 1)), filters) if filename: editbox.setText(filename) SettingsManager.set_last_dir( - self.bibleplugin.settingsSection, filename, 1) + self.plugin.settingsSection, filename, 1) - def incrementProgressBar(self, status_text): - log.debug(u'IncrementBar %s', status_text) - self.importProgressLabel.setText(status_text) - self.importProgressBar.setValue(self.importProgressBar.value() + 1) - Receiver.send_message(u'openlp_process_events') - - def preImport(self): + def preWizard(self): """ Prepare the UI for the import. """ + OpenLPWizard.preWizard(self) bible_type = self.field(u'source_format').toInt()[0] - self.finishButton.setVisible(False) - self.importProgressBar.setMinimum(0) - self.importProgressBar.setMaximum(1188) - self.importProgressBar.setValue(0) if bible_type == BibleFormat.WebDownload: - self.importProgressLabel.setText(translate( + self.progressLabel.setText(translate( 'BiblesPlugin.ImportWizardForm', 'Starting Registering bible...')) else: - self.importProgressLabel.setText(translate( + self.progressLabel.setText(translate( 'BiblesPlugin.ImportWizardForm', 'Starting import...')) Receiver.send_message(u'openlp_process_events') - def performImport(self): + def performWizard(self): """ Perform the actual import. """ @@ -485,7 +782,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): ) elif bible_type == BibleFormat.WebDownload: # Import a bible from the web. - self.importProgressBar.setMaximum(1) + self.progressBar.setMaximum(1) download_location = self.field(u'web_location').toInt()[0] bible_version = unicode(self.webTranslationComboBox.currentText()) if download_location == WebDownload.Crosswalk: @@ -518,20 +815,14 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): license_copyright, license_permissions) self.manager.reload_bibles() if bible_type == BibleFormat.WebDownload: - self.importProgressLabel.setText( + self.progressLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Registered ' 'bible. Please note, that verses will be downloaded on\n' 'demand and thus an internet connection is required.')) else: - self.importProgressLabel.setText(translate( + self.progressLabel.setText(translate( 'BiblesPlugin.ImportWizardForm', 'Finished import.')) else: - self.importProgressLabel.setText(translate( + self.progressLabel.setText(translate( 'BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) - delete_database(self.bibleplugin.settingsSection, importer.file) - - def postImport(self): - self.importProgressBar.setValue(self.importProgressBar.maximum()) - self.finishButton.setVisible(True) - self.cancelButton.setVisible(False) - Receiver.send_message(u'openlp_process_events') + delete_database(self.plugin.settingsSection, importer.file) diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py deleted file mode 100644 index a85e430a1..000000000 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ /dev/null @@ -1,391 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2011 Raoul Snyman # -# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import build_icon, translate - -class Ui_BibleImportWizard(object): - def setupUi(self, bibleImportWizard): - bibleImportWizard.setObjectName(u'bibleImportWizard') - bibleImportWizard.setModal(True) - bibleImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle) - bibleImportWizard.setOptions( - QtGui.QWizard.IndependentPages | - QtGui.QWizard.NoBackButtonOnStartPage | - QtGui.QWizard.NoBackButtonOnLastPage) - # Welcome Page - self.welcomePage = QtGui.QWizardPage() - self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, - QtGui.QPixmap(u':/wizards/wizard_importbible.bmp')) - self.welcomePage.setObjectName(u'WelcomePage') - self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage) - self.welcomeLayout.setObjectName(u'WelcomeLayout') - self.titleLabel = QtGui.QLabel(self.welcomePage) - self.titleLabel.setObjectName(u'TitleLabel') - self.welcomeLayout.addWidget(self.titleLabel) - self.welcomeLayout.addSpacing(40) - self.informationLabel = QtGui.QLabel(self.welcomePage) - self.informationLabel.setWordWrap(True) - self.informationLabel.setObjectName(u'InformationLabel') - self.welcomeLayout.addWidget(self.informationLabel) - self.welcomeLayout.addStretch() - bibleImportWizard.addPage(self.welcomePage) - # Select Page - self.selectPage = QtGui.QWizardPage() - self.selectPage.setObjectName(u'SelectPage') - self.selectPageLayout = QtGui.QVBoxLayout(self.selectPage) - self.selectPageLayout.setObjectName(u'SelectPageLayout') - self.formatLayout = QtGui.QFormLayout() - self.formatLayout.setObjectName(u'FormatLayout') - self.formatLabel = QtGui.QLabel(self.selectPage) - self.formatLabel.setObjectName(u'FormatLabel') - self.formatComboBox = QtGui.QComboBox(self.selectPage) - self.formatComboBox.addItems([u'', u'', u'', u'', u'']) - self.formatComboBox.setObjectName(u'FormatComboBox') - self.formatLayout.addRow(self.formatLabel, self.formatComboBox) - self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, - self.formatSpacer) - self.selectPageLayout.addLayout(self.formatLayout) - self.selectStack = QtGui.QStackedLayout() - self.selectStack.setObjectName(u'SelectStack') - self.osisWidget = QtGui.QWidget(self.selectPage) - self.osisWidget.setObjectName(u'OsisWidget') - self.osisLayout = QtGui.QFormLayout(self.osisWidget) - self.osisLayout.setMargin(0) - self.osisLayout.setObjectName(u'OsisLayout') - self.osisFileLabel = QtGui.QLabel(self.osisWidget) - self.osisFileLabel.setObjectName(u'OsisFileLabel') - self.osisFileLayout = QtGui.QHBoxLayout() - self.osisFileLayout.setObjectName(u'OsisFileLayout') - self.osisFileEdit = QtGui.QLineEdit(self.osisWidget) - self.osisFileEdit.setObjectName(u'OsisFileEdit') - self.osisFileLayout.addWidget(self.osisFileEdit) - self.osisBrowseButton = QtGui.QToolButton(self.osisWidget) - self.osisBrowseButton.setIcon(build_icon(u':/general/general_open.png')) - self.osisBrowseButton.setObjectName(u'OsisBrowseButton') - self.osisFileLayout.addWidget(self.osisBrowseButton) - self.osisLayout.addRow(self.osisFileLabel, self.osisFileLayout) - self.osisSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.osisSpacer) - self.selectStack.addWidget(self.osisWidget) - self.csvWidget = QtGui.QWidget(self.selectPage) - self.csvWidget.setObjectName(u'CsvWidget') - self.csvLayout = QtGui.QFormLayout(self.csvWidget) - self.csvLayout.setMargin(0) - self.csvLayout.setObjectName(u'CsvLayout') - self.csvBooksLabel = QtGui.QLabel(self.csvWidget) - self.csvBooksLabel.setObjectName(u'CsvBooksLabel') - self.csvBooksLayout = QtGui.QHBoxLayout() - self.csvBooksLayout.setObjectName(u'CsvBooksLayout') - self.csvBooksEdit = QtGui.QLineEdit(self.csvWidget) - self.csvBooksEdit.setObjectName(u'CsvBooksEdit') - self.csvBooksLayout.addWidget(self.csvBooksEdit) - self.csvBooksButton = QtGui.QToolButton(self.csvWidget) - self.csvBooksButton.setIcon(build_icon(u':/general/general_open.png')) - self.csvBooksButton.setObjectName(u'CsvBooksButton') - self.csvBooksLayout.addWidget(self.csvBooksButton) - self.csvLayout.addRow(self.csvBooksLabel, self.csvBooksLayout) - self.csvVersesLabel = QtGui.QLabel(self.csvWidget) - self.csvVersesLabel.setObjectName(u'CsvVersesLabel') - self.csvVersesLayout = QtGui.QHBoxLayout() - self.csvVersesLayout.setObjectName(u'CsvVersesLayout') - self.csvVersesEdit = QtGui.QLineEdit(self.csvWidget) - self.csvVersesEdit.setObjectName(u'CsvVersesEdit') - self.csvVersesLayout.addWidget(self.csvVersesEdit) - self.csvVersesButton = QtGui.QToolButton(self.csvWidget) - self.csvVersesButton.setIcon(build_icon(u':/general/general_open.png')) - self.csvVersesButton.setObjectName(u'CsvVersesButton') - self.csvVersesLayout.addWidget(self.csvVersesButton) - self.csvLayout.addRow(self.csvVersesLabel, self.csvVersesLayout) - self.csvSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.csvLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.csvSpacer) - self.selectStack.addWidget(self.csvWidget) - self.openSongWidget = QtGui.QWidget(self.selectPage) - self.openSongWidget.setObjectName(u'OpenSongWidget') - self.openSongLayout = QtGui.QFormLayout(self.openSongWidget) - self.openSongLayout.setMargin(0) - self.openSongLayout.setObjectName(u'OpenSongLayout') - self.openSongFileLabel = QtGui.QLabel(self.openSongWidget) - self.openSongFileLabel.setObjectName(u'OpenSongFileLabel') - self.openSongFileLayout = QtGui.QHBoxLayout() - self.openSongFileLayout.setObjectName(u'OpenSongFileLayout') - self.openSongFileEdit = QtGui.QLineEdit(self.openSongWidget) - self.openSongFileEdit.setObjectName(u'OpenSongFileEdit') - self.openSongFileLayout.addWidget(self.openSongFileEdit) - self.openSongBrowseButton = QtGui.QToolButton(self.openSongWidget) - self.openSongBrowseButton.setIcon( - build_icon(u':/general/general_open.png')) - self.openSongBrowseButton.setObjectName(u'OpenSongBrowseButton') - self.openSongFileLayout.addWidget(self.openSongBrowseButton) - self.openSongLayout.addRow(self.openSongFileLabel, - self.openSongFileLayout) - self.openSongSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole, - self.openSongSpacer) - self.selectStack.addWidget(self.openSongWidget) - self.webTabWidget = QtGui.QTabWidget(self.selectPage) - self.webTabWidget.setObjectName(u'WebTabWidget') - self.webBibleTab = QtGui.QWidget() - self.webBibleTab.setObjectName(u'WebBibleTab') - self.webBibleLayout = QtGui.QFormLayout(self.webBibleTab) - self.webBibleLayout.setObjectName(u'WebBibleLayout') - self.webSourceLabel = QtGui.QLabel(self.webBibleTab) - self.webSourceLabel.setObjectName(u'WebSourceLabel') - self.webBibleLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.webSourceLabel) - self.webSourceComboBox = QtGui.QComboBox(self.webBibleTab) - self.webSourceComboBox.setObjectName(u'WebSourceComboBox') - self.webSourceComboBox.addItems([u'', u'', u'']) - self.webBibleLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.webSourceComboBox) - self.webTranslationLabel = QtGui.QLabel(self.webBibleTab) - self.webTranslationLabel.setObjectName(u'webTranslationLabel') - self.webBibleLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.webTranslationLabel) - self.webTranslationComboBox = QtGui.QComboBox(self.webBibleTab) - self.webTranslationComboBox.setSizeAdjustPolicy( - QtGui.QComboBox.AdjustToContents) - self.webTranslationComboBox.setObjectName(u'WebTranslationComboBox') - self.webBibleLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.webTranslationComboBox) - self.webTabWidget.addTab(self.webBibleTab, u'') - self.webProxyTab = QtGui.QWidget() - self.webProxyTab.setObjectName(u'WebProxyTab') - self.webProxyLayout = QtGui.QFormLayout(self.webProxyTab) - self.webProxyLayout.setObjectName(u'WebProxyLayout') - self.webServerLabel = QtGui.QLabel(self.webProxyTab) - self.webServerLabel.setObjectName(u'WebServerLabel') - self.webProxyLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.webServerLabel) - self.webServerEdit = QtGui.QLineEdit(self.webProxyTab) - self.webServerEdit.setObjectName(u'WebServerEdit') - self.webProxyLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.webServerEdit) - self.webUserLabel = QtGui.QLabel(self.webProxyTab) - self.webUserLabel.setObjectName(u'WebUserLabel') - self.webProxyLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.webUserLabel) - self.webUserEdit = QtGui.QLineEdit(self.webProxyTab) - self.webUserEdit.setObjectName(u'WebUserEdit') - self.webProxyLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.webUserEdit) - self.webPasswordLabel = QtGui.QLabel(self.webProxyTab) - self.webPasswordLabel.setObjectName(u'WebPasswordLabel') - self.webProxyLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.webPasswordLabel) - self.webPasswordEdit = QtGui.QLineEdit(self.webProxyTab) - self.webPasswordEdit.setObjectName(u'WebPasswordEdit') - self.webProxyLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.webPasswordEdit) - self.webTabWidget.addTab(self.webProxyTab, u'') - self.selectStack.addWidget(self.webTabWidget) - self.openlp1Widget = QtGui.QWidget(self.selectPage) - self.openlp1Widget.setObjectName(u'Openlp1Widget') - self.openlp1Layout = QtGui.QFormLayout(self.openlp1Widget) - self.openlp1Layout.setMargin(0) - self.openlp1Layout.setObjectName(u'Openlp1Layout') - self.openlp1FileLabel = QtGui.QLabel(self.openlp1Widget) - self.openlp1FileLabel.setObjectName(u'Openlp1FileLabel') - self.openlp1FileLayout = QtGui.QHBoxLayout() - self.openlp1FileLayout.setObjectName(u'Openlp1FileLayout') - self.openlp1FileEdit = QtGui.QLineEdit(self.openlp1Widget) - self.openlp1FileEdit.setObjectName(u'Openlp1FileEdit') - self.openlp1FileLayout.addWidget(self.openlp1FileEdit) - self.openlp1BrowseButton = QtGui.QToolButton(self.openlp1Widget) - self.openlp1BrowseButton.setIcon( - build_icon(u':/general/general_open.png')) - self.openlp1BrowseButton.setObjectName(u'Openlp1BrowseButton') - self.openlp1FileLayout.addWidget(self.openlp1BrowseButton) - self.openlp1Layout.addRow(self.openlp1FileLabel, self.openlp1FileLayout) - self.openlp1DisabledLabel = QtGui.QLabel(self.openlp1Widget) - self.openlp1DisabledLabel.setWordWrap(True) - self.openlp1DisabledLabel.setObjectName(u'Openlp1DisabledLabel') - self.openlp1Layout.addRow(self.openlp1DisabledLabel) - self.openlp1Spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole, - self.openlp1Spacer) - self.selectStack.addWidget(self.openlp1Widget) - self.selectPageLayout.addLayout(self.selectStack) - bibleImportWizard.addPage(self.selectPage) - # License Page - self.licenseDetailsPage = QtGui.QWizardPage() - self.licenseDetailsPage.setObjectName(u'LicenseDetailsPage') - self.licenseDetailsLayout = QtGui.QFormLayout(self.licenseDetailsPage) - self.licenseDetailsLayout.setObjectName(u'LicenseDetailsLayout') - self.versionNameLabel = QtGui.QLabel(self.licenseDetailsPage) - self.versionNameLabel.setObjectName(u'VersionNameLabel') - self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.versionNameLabel) - self.versionNameEdit = QtGui.QLineEdit(self.licenseDetailsPage) - self.versionNameEdit.setObjectName(u'VersionNameEdit') - self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.versionNameEdit) - self.copyrightLabel = QtGui.QLabel(self.licenseDetailsPage) - self.copyrightLabel.setObjectName(u'CopyrightLabel') - self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.copyrightLabel) - self.copyrightEdit = QtGui.QLineEdit(self.licenseDetailsPage) - self.copyrightEdit.setObjectName(u'CopyrightEdit') - self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.copyrightEdit) - self.permissionsLabel = QtGui.QLabel(self.licenseDetailsPage) - self.permissionsLabel.setObjectName(u'PermissionsLabel') - self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.permissionsLabel) - self.permissionsEdit = QtGui.QLineEdit(self.licenseDetailsPage) - self.permissionsEdit.setObjectName(u'PermissionsEdit') - self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.permissionsEdit) - bibleImportWizard.addPage(self.licenseDetailsPage) - # Progress Page - self.importPage = QtGui.QWizardPage() - self.importPage.setObjectName(u'ImportPage') - self.importLayout = QtGui.QVBoxLayout(self.importPage) - self.importLayout.setMargin(48) - self.importLayout.setObjectName(u'ImportLayout') - self.importProgressLabel = QtGui.QLabel(self.importPage) - self.importProgressLabel.setObjectName(u'ImportProgressLabel') - self.importLayout.addWidget(self.importProgressLabel) - self.importProgressBar = QtGui.QProgressBar(self.importPage) - self.importProgressBar.setObjectName(u'ImportProgressBar') - self.importLayout.addWidget(self.importProgressBar) - bibleImportWizard.addPage(self.importPage) - self.retranslateUi(bibleImportWizard) - QtCore.QMetaObject.connectSlotsByName(bibleImportWizard) - QtCore.QObject.connect(self.formatComboBox, - QtCore.SIGNAL(u'currentIndexChanged(int)'), self.selectStack, - QtCore.SLOT(u'setCurrentIndex(int)')) - - def retranslateUi(self, bibleImportWizard): - bibleImportWizard.setWindowTitle( - translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard')) - self.titleLabel.setText( - u'%s' % \ - translate('BiblesPlugin.ImportWizardForm', - 'Welcome to the Bible Import Wizard')) - self.informationLabel.setText( - translate('BiblesPlugin.ImportWizardForm', - 'This wizard will help you to import Bibles from a ' - 'variety of formats. Click the next button below to start the ' - 'process by selecting a format to import from.')) - self.selectPage.setTitle(translate('BiblesPlugin.ImportWizardForm', - 'Select Import Source')) - self.selectPage.setSubTitle( - translate('BiblesPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.formatLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Format:')) - self.formatComboBox.setItemText(0, - translate('BiblesPlugin.ImportWizardForm', 'OSIS')) - self.formatComboBox.setItemText(1, - translate('BiblesPlugin.ImportWizardForm', 'CSV')) - self.formatComboBox.setItemText(2, - translate('BiblesPlugin.ImportWizardForm', 'OpenSong')) - self.formatComboBox.setItemText(3, - translate('BiblesPlugin.ImportWizardForm', 'Web Download')) - self.formatComboBox.setItemText(4, - translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x')) - self.openlp1FileLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'File location:')) - self.osisFileLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'File location:')) - self.csvBooksLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Books location:')) - self.csvVersesLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Verse location:')) - self.openSongFileLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Bible filename:')) - self.webSourceLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Location:')) - self.webSourceComboBox.setItemText(0, - translate('BiblesPlugin.ImportWizardForm', 'Crosswalk')) - self.webSourceComboBox.setItemText(1, - translate('BiblesPlugin.ImportWizardForm', 'BibleGateway')) - self.webSourceComboBox.setItemText(2, - translate('BiblesPlugin.ImportWizardForm', 'Bibleserver')) - self.webTranslationLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Bible:')) - self.webTabWidget.setTabText( - self.webTabWidget.indexOf(self.webBibleTab), - translate('BiblesPlugin.ImportWizardForm', 'Download Options')) - self.webServerLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Server:')) - self.webUserLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Username:')) - self.webPasswordLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Password:')) - self.webTabWidget.setTabText( - self.webTabWidget.indexOf(self.webProxyTab), - translate('BiblesPlugin.ImportWizardForm', - 'Proxy Server (Optional)')) - self.licenseDetailsPage.setTitle( - translate('BiblesPlugin.ImportWizardForm', 'License Details')) - self.licenseDetailsPage.setSubTitle( - translate('BiblesPlugin.ImportWizardForm', - 'Set up the Bible\'s license details.')) - self.versionNameLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Version name:')) - self.copyrightLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) - self.permissionsLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Permissions:')) - self.importPage.setTitle( - translate('BiblesPlugin.ImportWizardForm', 'Importing')) - self.importPage.setSubTitle( - translate('BiblesPlugin.ImportWizardForm', - 'Please wait while your Bible is imported.')) - self.importProgressLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Ready.')) - self.importProgressBar.setFormat(u'%p%') - self.openlp1DisabledLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'The openlp.org 1.x ' - 'importer has been disabled due to a missing Python module. If ' - 'you want to use this importer, you will need to install the ' - '"python-sqlite" module.')) - # Align all QFormLayouts towards each other. - width = max(self.formatLabel.minimumSizeHint().width(), - self.osisFileLabel.minimumSizeHint().width()) - width = max(width, self.csvBooksLabel.minimumSizeHint().width()) - width = max(width, self.csvVersesLabel.minimumSizeHint().width()) - width = max(width, self.openSongFileLabel.minimumSizeHint().width()) - width = max(width, self.openlp1FileLabel.minimumSizeHint().width()) - self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.osisSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.csvSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openSongSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openlp1Spacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 8b1d70128..8959167a6 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -31,7 +31,7 @@ import csv from PyQt4 import QtCore from openlp.core.lib import Receiver, translate -from db import BibleDB +from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -51,7 +51,7 @@ class CSVBible(BibleDB): self.booksfile = kwargs[u'booksfile'] self.versesfile = kwargs[u'versefile'] QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): success = True @@ -72,7 +72,7 @@ class CSVBible(BibleDB): self.create_book(unicode(line[1], details['encoding']), line[2], int(line[0])) Receiver.send_message(u'openlp_process_events') - except IOError, IndexError: + except (IOError, IndexError): log.exception(u'Loading books from file failed') success = False finally: diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 9f4376da1..1967448cc 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -33,8 +33,9 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm.exc import UnmappedClassError -from openlp.core.lib import Receiver, translate +from openlp.core.lib import translate from openlp.core.lib.db import BaseModel, init_db, Manager +from openlp.core.ui import criticalErrorMessageBox log = logging.getLogger(__name__) @@ -354,12 +355,11 @@ class BibleDB(QtCore.QObject, Manager): verse_list.extend(verses) else: log.debug(u'OpenLP failed to find book %s', book) - Receiver.send_message(u'openlp_error_message', { - u'title': translate('BiblesPlugin', 'No Book Found'), - u'message': translate('BiblesPlugin', 'No matching book ' + criticalErrorMessageBox( + translate('BiblesPlugin', 'No Book Found'), + translate('BiblesPlugin', 'No matching book ' 'could be found in this Bible. Check that you have ' - 'spelled the name of the book correctly.') - }) + 'spelled the name of the book correctly.')) return verse_list def verse_search(self, text): diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index d9210a275..b844bbe61 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -23,20 +23,23 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +The :mod:`http` module enables OpenLP to retrieve scripture from bible +websites. +""" import logging import os import re import sqlite3 import socket import urllib -import urllib2 from HTMLParser import HTMLParseError from BeautifulSoup import BeautifulSoup, NavigableString from openlp.core.lib import Receiver, translate -from openlp.core.utils import AppLocation +from openlp.core.ui import criticalErrorMessageBox +from openlp.core.utils import AppLocation, get_web_page from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib.db import BibleDB, Book @@ -204,29 +207,12 @@ class BGExtract(object): url_params = urllib.urlencode( {u'search': u'%s %s' % (bookname, chapter), u'version': u'%s' % version}) - page = None - try: - page = urllib2.urlopen( - u'http://www.biblegateway.com/passage/?%s' % url_params) - log.debug(u'BibleGateway url = %s' % page.geturl()) - Receiver.send_message(u'openlp_process_events') - except urllib2.URLError: - log.exception(u'The web bible page could not be downloaded.') - send_error_message(u'download') - finally: - if not page: - return None cleaner = [(re.compile(' |
|\'\+\''), lambda match: '')] - soup = None - try: - soup = BeautifulSoup(page, markupMassage=cleaner) - except HTMLParseError: - log.exception(u'BeautifulSoup could not parse the bible page.') - Receiver.send_message(u'bibles_download_error') - send_error_message(u'parse') - finally: - if not soup: - return None + soup = get_soup_for_bible_ref( + u'http://www.biblegateway.com/passage/?%s' % url_params, + cleaner=cleaner) + if not soup: + return None Receiver.send_message(u'openlp_process_events') footnotes = soup.findAll(u'sup', u'footnote') if footnotes: @@ -280,36 +266,18 @@ class BSExtract(object): log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter) chapter_url = u'http://m.bibleserver.com/text/%s/%s%s' % \ (version, bookname, chapter) - - log.debug(u'URL: %s', chapter_url) - page = None - try: - page = urllib2.urlopen(chapter_url) - Receiver.send_message(u'openlp_process_events') - except urllib2.URLError: - log.exception(u'The web bible page could not be downloaded.') - send_error_message(u'download') - finally: - if not page: - return None - soup = None - try: - soup = BeautifulSoup(page) - except HTMLParseError: - log.exception(u'BeautifulSoup could not parse the bible page.') - send_error_message(u'parse') + header = (u'Accept-Language', u'en') + soup = get_soup_for_bible_ref(chapter_url, header) + if not soup: return None Receiver.send_message(u'openlp_process_events') - content = None - try: - content = soup.find(u'div', u'content').find(u'div').findAll(u'div') - except: + content = soup.find(u'div', u'content') + if not content: log.exception(u'No verses found in the Bibleserver response.') send_error_message(u'parse') - finally: - if not content: - return None - verse_number = re.compile(r'v(\d{2})(\d{3})(\d{3}) verse') + return None + content = content.find(u'div').findAll(u'div') + 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') @@ -344,21 +312,8 @@ class CWExtract(object): urlbookname = bookname.replace(u' ', u'-') chapter_url = u'http://www.biblestudytools.com/%s/%s/%s.html' % \ (version, urlbookname.lower(), chapter) - log.debug(u'URL: %s', chapter_url) - page = None - try: - page = urllib2.urlopen(chapter_url) - Receiver.send_message(u'openlp_process_events') - except urllib2.URLError: - log.exception(u'The web bible page could not be downloaded.') - send_error_message(u'download') - return None - soup = None - try: - soup = BeautifulSoup(page) - except HTMLParseError: - log.exception(u'BeautifulSoup could not parse the bible page.') - send_error_message(u'parse') + soup = get_soup_for_bible_ref(chapter_url) + if not soup: return None Receiver.send_message(u'openlp_process_events') htmlverses = soup.findAll(u'span', u'versetext') @@ -416,6 +371,8 @@ class HTTPBible(BibleDB): BibleDB.__init__(self, parent, **kwargs) self.download_source = kwargs[u'download_source'] self.download_name = kwargs[u'download_name'] + # TODO: Clean up proxy stuff. We probably want one global proxy per + # connection type (HTTP and HTTPS) at most. self.proxy_server = None self.proxy_username = None self.proxy_password = None @@ -431,7 +388,7 @@ class HTTPBible(BibleDB): Run the import. This method overrides the parent class method. Returns ``True`` on success, ``False`` on failure. """ - self.wizard.importProgressBar.setMaximum(2) + self.wizard.progressBar.setMaximum(2) self.wizard.incrementProgressBar('Registering bible...') self.create_meta(u'download source', self.download_source) self.create_meta(u'download name', self.download_name) @@ -471,21 +428,20 @@ class HTTPBible(BibleDB): book = reference[0] db_book = self.get_book(book) if not db_book: - book_details = self.lookup_book(book) + book_details = HTTPBooks.get_book(book) if not book_details: - Receiver.send_message(u'openlp_error_message', { - u'title': translate('BiblesPlugin', 'No Book Found'), - u'message': translate('BiblesPlugin', 'No matching ' + criticalErrorMessageBox( + translate('BiblesPlugin', 'No Book Found'), + translate('BiblesPlugin', 'No matching ' 'book could be found in this Bible. Check that you ' - 'have spelled the name of the book correctly.') - }) + 'have spelled the name of the book correctly.')) return [] db_book = self.create_book(book_details[u'name'], book_details[u'abbreviation'], book_details[u'testament_id']) book = db_book.name if BibleDB.get_verse_count(self, book, reference[1]) == 0: - Receiver.send_message(u'bibles_showprogress') + Receiver.send_message(u'cursor_busy') Receiver.send_message(u'openlp_process_events') search_results = self.get_chapter(book, reference[1]) if search_results and search_results.has_verselist(): @@ -500,7 +456,7 @@ class HTTPBible(BibleDB): self.create_chapter(db_book.id, search_results.chapter, search_results.verselist) Receiver.send_message(u'openlp_process_events') - Receiver.send_message(u'bibles_hideprogress') + Receiver.send_message(u'cursor_normal') Receiver.send_message(u'openlp_process_events') return BibleDB.get_verses(self, reference_list) @@ -511,12 +467,12 @@ class HTTPBible(BibleDB): log.debug(u'get_chapter %s, %s', book, chapter) log.debug(u'source = %s', self.download_source) if self.download_source.lower() == u'crosswalk': - ev = CWExtract(self.proxy_server) + handler = CWExtract(self.proxy_server) elif self.download_source.lower() == u'biblegateway': - ev = BGExtract(self.proxy_server) + handler = BGExtract(self.proxy_server) elif self.download_source.lower() == u'bibleserver': - ev = BSExtract(self.proxy_server) - return ev.get_bible_chapter(self.download_name, book, chapter) + handler = BSExtract(self.proxy_server) + return handler.get_bible_chapter(self.download_name, book, chapter) def get_books(self): """ @@ -525,12 +481,6 @@ class HTTPBible(BibleDB): return [Book.populate(name=book['name']) for book in HTTPBooks.get_books()] - def lookup_book(self, book): - """ - Look up the name of a book. - """ - return HTTPBooks.get_book(book) - def get_chapter_count(self, book): """ Return the number of chapters in a particular book. @@ -549,19 +499,56 @@ class HTTPBible(BibleDB): """ return HTTPBooks.get_verse_count(book, chapter) -def send_error_message(reason): - if reason == u'downoad': - Receiver.send_message(u'openlp_error_message', { - u'title': translate('BiblePlugin.HTTPBible', 'Download Error'), - u'message': translate('BiblePlugin.HTTPBible', 'There was a ' +def get_soup_for_bible_ref(reference_url, header=None, cleaner=None): + """ + Gets a webpage and returns a parsed and optionally cleaned soup or None. + + ``reference_url`` + The URL to obtain the soup from. + + ``header`` + An optional HTTP header to pass to the bible web server. + + ``cleaner`` + An optional regex to use during webpage parsing. + """ + if not reference_url: + return None + page = get_web_page(reference_url, header, True) + if not page: + send_error_message(u'download') + return None + soup = None + try: + if cleaner: + soup = BeautifulSoup(page, markupMassage=cleaner) + else: + soup = BeautifulSoup(page) + except HTMLParseError: + log.exception(u'BeautifulSoup could not parse the bible page.') + if not soup: + send_error_message(u'parse') + return None + Receiver.send_message(u'openlp_process_events') + return soup + +def send_error_message(error_type): + """ + Send a standard error message informing the user of an issue. + + ``error_type`` + The type of error that occured for the issue. + """ + if error_type == u'download': + criticalErrorMessageBox( + translate('BiblePlugin.HTTPBible', 'Download Error'), + translate('BiblePlugin.HTTPBible', 'There was a ' 'problem downloading your verse selection. Please check your ' 'Internet connection, and if this error continues to occur ' - 'consider reporting a bug.') - }) - elif reason == u'parse': - Receiver.send_message(u'openlp_error_message', { - u'title': translate('BiblePlugin.HTTPBible', 'Parse Error'), - u'message': translate('BiblePlugin.HTTPBible', 'There was a ' + 'please consider reporting a bug.')) + elif error_type == u'parse': + criticalErrorMessageBox( + translate('BiblePlugin.HTTPBible', 'Parse Error'), + translate('BiblePlugin.HTTPBible', 'There was a ' 'problem extracting your verse selection. If this error continues ' - 'continues to occur consider reporting a bug.') - }) + 'to occur please consider reporting a bug.')) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 066563bec..4ecd4b49e 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -25,12 +25,12 @@ ############################################################################### import logging -import time from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ ItemCapabilities, translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.lib import get_reference_match @@ -44,10 +44,6 @@ class BibleListView(BaseListWithDnD): self.PluginName = u'Bibles' BaseListWithDnD.__init__(self, parent) - def resizeEvent(self, event): - self.parent().onListViewResize(event.size().width(), - event.size().width()) - class BibleMediaItem(MediaManagerItem): """ @@ -137,9 +133,6 @@ class BibleMediaItem(MediaManagerItem): self.quickSearchButton.setObjectName(u'quickSearchButton') self.quickSearchButtonLayout.addWidget(self.quickSearchButton) self.quickLayout.addRow(self.quickSearchButtonLayout) - self.quickMessage = QtGui.QLabel(self.quickTab) - self.quickMessage.setObjectName(u'quickMessage') - self.quickLayout.addRow(self.quickMessage) self.searchTabWidget.addTab(self.quickTab, translate('BiblesPlugin.MediaItem', 'Quick')) # Add the Advanced Search tab. @@ -231,9 +224,6 @@ class BibleMediaItem(MediaManagerItem): self.advancedSearchButtonLayout.addWidget(self.advancedSearchButton) self.advancedLayout.addLayout( self.advancedSearchButtonLayout, 7, 0, 1, 3) - self.advancedMessage = QtGui.QLabel(self.advancedTab) - self.advancedMessage.setObjectName(u'advancedMessage') - self.advancedLayout.addWidget(self.advancedMessage, 8, 0, 1, 3) self.searchTabWidget.addTab(self.advancedTab, translate('BiblesPlugin.MediaItem', 'Advanced')) # Add the search tab widget to the page layout. @@ -263,22 +253,9 @@ class BibleMediaItem(MediaManagerItem): # Other stuff QtCore.QObject.connect(self.quickSearchEdit, QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_showprogress'), self.onSearchProgressShow) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_hideprogress'), self.onSearchProgressHide) def addListViewToToolBar(self): MediaManagerItem.addListViewToToolBar(self) - # Progress Bar - self.SearchProgress = QtGui.QProgressBar(self) - self.SearchProgress.setFormat('') - self.SearchProgress.setMinimum(0) - self.SearchProgress.setMaximum(0) - self.SearchProgress.setGeometry(self.listView.geometry().left(), - self.listView.geometry().top(), 81, 23) - self.SearchProgress.setVisible(False) - self.SearchProgress.setObjectName(u'SearchProgress') def configUpdated(self): log.debug(u'configUpdated') @@ -347,30 +324,11 @@ class BibleMediaItem(MediaManagerItem): self.configUpdated() log.debug(u'bible manager initialise complete') - def setQuickMessage(self, text): - self.quickMessage.setText(text) - self.advancedMessage.setText(text) - Receiver.send_message(u'openlp_process_events') - # Minor delay to get the events processed. - time.sleep(0.1) - - def onListViewResize(self, width, height): - listViewGeometry = self.listView.geometry() - self.SearchProgress.setGeometry(listViewGeometry.x(), - (listViewGeometry.y() + listViewGeometry.height()) - 23, 81, 23) - - def onSearchProgressShow(self): - self.SearchProgress.setVisible(True) - Receiver.send_message(u'openlp_process_events') - - def onSearchProgressHide(self): - self.SearchProgress.setVisible(False) - def onImportClick(self): if not hasattr(self, u'import_wizard'): self.import_wizard = BibleImportForm(self, self.parent.manager, self.parent) - # If the import was not canceled then reload. + # If the import was not cancelled then reload. if self.import_wizard.exec_(): self.reloadBibles() @@ -432,11 +390,10 @@ class BibleMediaItem(MediaManagerItem): verse_count = self.parent.manager.get_verse_count(bible, book, 1) if verse_count == 0: self.advancedSearchButton.setEnabled(False) - self.advancedMessage.setText( - translate('BiblesPlugin.MediaItem', 'Bible not fully loaded.')) + criticalErrorMessageBox(message=translate('BiblePlugin.MediaItem', + 'Bible not fully loaded')) else: self.advancedSearchButton.setEnabled(True) - self.advancedMessage.setText(u'') self.adjustComboBox(1, self.chapter_count, self.advancedFromChapter) self.adjustComboBox(1, self.chapter_count, self.advancedToChapter) self.adjustComboBox(1, verse_count, self.advancedFromVerse) @@ -575,13 +532,11 @@ class BibleMediaItem(MediaManagerItem): if item_second_bible and second_bible or not item_second_bible and \ not second_bible: self.displayResults(bible, second_bible) - elif QtGui.QMessageBox.critical(self, - translate('BiblePlugin.MediaItem', 'Error'), - translate('BiblePlugin.MediaItem', 'You cannot combine single ' - 'and second bible verses. Do you want to delete your search ' - 'results and start a new search?'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | - QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes: + elif criticalErrorMessageBox( + message=translate('BiblePlugin.MediaItem', + 'You cannot combine single and second bible verses. Do you ' + 'want to delete your search results and start a new search?'), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.listView.clear() self.displayResults(bible, second_bible) else: @@ -606,6 +561,7 @@ class BibleMediaItem(MediaManagerItem): second_bible, text) else: # We are doing a 'Text Search'. + Receiver.send_message(u'cursor_busy') bibles = self.parent.manager.get_bibles() self.search_results = self.parent.manager.verse_search(bible, second_bible, text) @@ -624,18 +580,17 @@ class BibleMediaItem(MediaManagerItem): if item_second_bible and second_bible or not item_second_bible and \ not second_bible: self.displayResults(bible, second_bible) - elif QtGui.QMessageBox.critical(self, - translate('BiblePlugin.MediaItem', 'Error'), - translate('BiblePlugin.MediaItem', 'You cannot combine single ' - 'and second bible verses. Do you want to delete your search ' - 'results and start a new search?'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | - QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes: + elif criticalErrorMessageBox( + message=translate('BiblePlugin.MediaItem', + 'You cannot combine single and second bible verses. Do you ' + 'want to delete your search results and start a new search?'), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.listView.clear() self.displayResults(bible, second_bible) elif self.search_results: self.displayResults(bible, second_bible) self.quickSearchButton.setEnabled(True) + Receiver.send_message(u'cursor_normal') def displayResults(self, bible, second_bible=u''): """ @@ -755,21 +710,21 @@ class BibleMediaItem(MediaManagerItem): second_copyright, second_permissions) if footer not in raw_footer: raw_footer.append(footer) - bible_text = u'%s\u00a0%s\n\n%s\u00a0%s' % (verse_text, text, + bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text, second_text) - raw_slides.append(bible_text) + raw_slides.append(bible_text.rstrip()) bible_text = u'' # If we are 'Verse Per Slide' then create a new slide. elif self.parent.settings_tab.layout_style == 0: - bible_text = u'%s\u00a0%s' % (verse_text, text) - raw_slides.append(bible_text) + bible_text = u'%s %s' % (verse_text, text) + raw_slides.append(bible_text.rstrip()) bible_text = u'' # If we are 'Verse Per Line' then force a new line. elif self.parent.settings_tab.layout_style == 1: - bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text) + bible_text = u'%s %s %s\n' % (bible_text, verse_text, text) # We have to be 'Continuous'. else: - bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text) + bible_text = u'%s %s %s\n' % (bible_text, verse_text, text) if not old_item: start_item = item elif self.checkTitle(item, old_item): @@ -780,7 +735,7 @@ class BibleMediaItem(MediaManagerItem): raw_title.append(self.formatTitle(start_item, item)) # If there are no more items we check whether we have to add bible_text. if bible_text: - raw_slides.append(bible_text) + raw_slides.append(bible_text.lstrip()) bible_text = u'' # Service Item: Capabilities if self.parent.settings_tab.layout_style == 2 and not second_bible: diff --git a/openlp/plugins/bibles/lib/openlp1.py b/openlp/plugins/bibles/lib/openlp1.py index 866652e5b..2df6b1677 100644 --- a/openlp/plugins/bibles/lib/openlp1.py +++ b/openlp/plugins/bibles/lib/openlp1.py @@ -30,7 +30,7 @@ import sqlite from PyQt4 import QtCore from openlp.core.lib import Receiver, translate -from db import BibleDB +from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -46,7 +46,7 @@ class OpenLP1Bible(BibleDB): BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs[u'filename'] QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ @@ -62,7 +62,7 @@ class OpenLP1Bible(BibleDB): # Create all books. cursor.execute(u'SELECT id, testament_id, name, abbreviation FROM book') books = cursor.fetchall() - self.wizard.importProgressBar.setMaximum(len(books) + 1) + self.wizard.progressBar.setMaximum(len(books) + 1) for book in books: if self.stop_import_flag: connection.close() diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index c0b60f911..2b3b6dfb7 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -30,7 +30,7 @@ from lxml import objectify from PyQt4 import QtCore from openlp.core.lib import Receiver, translate -from db import BibleDB +from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -48,7 +48,7 @@ class OpenSongBible(BibleDB): BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs['filename'] QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ @@ -89,7 +89,7 @@ class OpenSongBible(BibleDB): 'Importing ...')) % (db_book.name, int(chapter.attrib[u'n']))) self.session.commit() - except IOError, AttributeError: + except (IOError, AttributeError): log.exception(u'Loading bible from OpenSong file failed') success = False finally: diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index bf070c4bd..4a001987d 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -35,7 +35,7 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver, translate from openlp.core.utils import AppLocation -from db import BibleDB +from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -87,7 +87,7 @@ class OSISBible(BibleDB): if fbibles: fbibles.close() QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ @@ -134,9 +134,9 @@ class OSISBible(BibleDB): testament) if last_chapter == 0: if book == u'Gen': - self.wizard.importProgressBar.setMaximum(1188) + self.wizard.progressBar.setMaximum(1188) else: - self.wizard.importProgressBar.setMaximum(260) + self.wizard.progressBar.setMaximum(260) if last_chapter != chapter: if last_chapter != 0: self.session.commit() diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 2f005828a..ebc917e99 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -29,6 +29,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide from editcustomdialog import Ui_CustomEditDialog @@ -151,8 +152,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): """ valid, message = self._validate() if not valid: - QtGui.QMessageBox.critical(self, - translate('CustomPlugin.EditCustomForm', 'Error'), message) + criticalErrorMessageBox(message=message) return False sxml = CustomXMLBuilder() sxml.new_document() @@ -265,4 +265,4 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): if self.slideListView.count() == 0: return False, translate('CustomPlugin.EditCustomForm', 'You need to add at least one slide') - return True, u'' \ No newline at end of file + return True, u'' diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 063a80d02..d2652207c 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -31,8 +31,9 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ ItemCapabilities, SettingsManager, translate, check_item_selected, \ - Receiver, check_directory_exists -from openlp.core.utils import AppLocation, get_images_filter + check_directory_exists +from openlp.core.ui import criticalErrorMessageBox +from openlp.core.utils import AppLocation, delete_file, get_images_filter log = logging.getLogger(__name__) @@ -115,12 +116,8 @@ class ImageMediaItem(MediaManagerItem): for row in row_list: text = self.listView.item(row) if text: - try: - os.remove(os.path.join(self.servicePath, - unicode(text.text()))) - except OSError: - # if not present do not worry - pass + delete_file(os.path.join(self.servicePath, + unicode(text.text()))) self.listView.takeItem(row) SettingsManager.set_list(self.settingsSection, self.settingsSection, self.getFileList()) @@ -164,7 +161,7 @@ class ImageMediaItem(MediaManagerItem): items.remove(item) # We cannot continue, as all images do not exist. if not items: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('ImagePlugin.MediaItem', 'Missing Image(s)'), unicode(translate('ImagePlugin.MediaItem', 'The following image(s) no longer exist: %s')) % @@ -208,12 +205,11 @@ class ImageMediaItem(MediaManagerItem): self.parent.liveController.display.directImage(name, filename) self.resetAction.setVisible(True) else: - Receiver.send_message(u'openlp_error_message', { - u'title': translate('ImagePlugin.MediaItem', - 'Live Background Error'), - u'message': unicode(translate('ImagePlugin.MediaItem', + criticalErrorMessageBox( + translate('ImagePlugin.MediaItem', 'Live Background Error'), + unicode(translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, ' - 'the image file "%s" no longer exists.')) % filename}) + 'the image file "%s" no longer exists.')) % filename) def onPreviewClick(self): - MediaManagerItem.onPreviewClick(self) \ No newline at end of file + MediaManagerItem.onPreviewClick(self) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index cc75dfc2b..0280ba937 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -30,8 +30,8 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected, \ - Receiver + ItemCapabilities, SettingsManager, translate, check_item_selected +from openlp.core.ui import criticalErrorMessageBox log = logging.getLogger(__name__) @@ -106,12 +106,11 @@ class MediaMediaItem(MediaManagerItem): self.parent.liveController.display.video(filename, 0, True) self.resetAction.setVisible(True) else: - Receiver.send_message(u'openlp_error_message', { - u'title': translate('MediaPlugin.MediaItem', + criticalErrorMessageBox(translate('MediaPlugin.MediaItem', 'Live Background Error'), - u'message': unicode(translate('MediaPlugin.MediaItem', + unicode(translate('MediaPlugin.MediaItem', 'There was a problem replacing your background, ' - 'the media file "%s" no longer exists.')) % filename}) + 'the media file "%s" no longer exists.')) % filename) def generateSlideData(self, service_item, item=None, xmlVersion=False): if item is None: @@ -131,9 +130,8 @@ class MediaMediaItem(MediaManagerItem): return True else: # File is no longer present - QtGui.QMessageBox.critical( - self, translate('MediaPlugin.MediaItem', - 'Missing Media File'), + criticalErrorMessageBox( + translate('MediaPlugin.MediaItem', 'Missing Media File'), unicode(translate('MediaPlugin.MediaItem', 'The file %s no longer exists.')) % filename) return False diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index d7407b729..516c595c7 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -51,6 +51,7 @@ else: from PyQt4 import QtCore +from openlp.core.utils import delete_file from presentationcontroller import PresentationController, PresentationDocument log = logging.getLogger(__name__) @@ -169,7 +170,7 @@ class ImpressController(PresentationController): try: return Dispatch(u'com.sun.star.ServiceManager') except pywintypes.com_error: - log.warn(u'Failed to get COM service manager. ' + log.exception(u'Failed to get COM service manager. ' u'Impress Controller has been disabled') return None @@ -257,7 +258,6 @@ class ImpressDocument(PresentationDocument): except: log.exception(u'Failed to load presentation %s' % url) return False - self.presentation = self.document.getPresentation() self.presentation.Display = \ self.controller.plugin.renderManager.screens.current_display + 1 @@ -293,8 +293,7 @@ class ImpressDocument(PresentationDocument): try: doc.storeToURL(urlpath, props) self.convert_thumbnail(path, idx + 1) - if os.path.exists(path): - os.remove(path) + delete_file(path) except: log.exception(u'%s - Unable to store openoffice preview' % path) @@ -327,8 +326,7 @@ class ImpressDocument(PresentationDocument): self.presentation = None self.document.dispose() except: - #We tried! - pass + log.exception("Closing presentation failed") self.document = None self.controller.remove_doc(self) @@ -339,13 +337,14 @@ class ImpressDocument(PresentationDocument): log.debug(u'is loaded OpenOffice') #print "is_loaded " if self.presentation is None or self.document is None: - #print "no present or document" + log.debug("is_loaded: no presentation or document") return False try: if self.document.getPresentation() is None: - #print "no getPresentation" + log.debug("getPresentation failed to find a presentation") return False except: + log.exception("getPresentation failed to find a presentation") return False return True diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 1e65a3358..2c9381a70 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ SettingsManager, translate, check_item_selected, Receiver, ItemCapabilities +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -180,7 +181,7 @@ class PresentationMediaItem(MediaManagerItem): filename = os.path.split(unicode(file))[1] if titles.count(filename) > 0: if not initialLoad: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('PresentationPlugin.MediaItem', 'File Exists'), translate('PresentationPlugin.MediaItem', @@ -204,7 +205,7 @@ class PresentationMediaItem(MediaManagerItem): if initialLoad: icon = build_icon(u':/general/general_delete.png') else: - QtGui.QMessageBox.critical( + criticalErrorMessageBox( self, translate('PresentationPlugin.MediaItem', 'Unsupported File'), translate('PresentationPlugin.MediaItem', @@ -275,8 +276,8 @@ class PresentationMediaItem(MediaManagerItem): return True else: # File is no longer present - QtGui.QMessageBox.critical( - self, translate('PresentationPlugin.MediaItem', + criticalErrorMessageBox( + translate('PresentationPlugin.MediaItem', 'Missing Presentation'), unicode(translate('PresentationPlugin.MediaItem', 'The Presentation %s no longer exists.')) % filename) diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 28083ae05..6f1c7f2a4 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -54,7 +54,7 @@ class Ui_AuthorsDialog(object): self.displayEdit.setObjectName(u'displayEdit') self.displayLabel.setBuddy(self.displayEdit) self.authorLayout.addRow(self.displayLabel, self.displayEdit) - self.dialogLayout.addLayout(self.authorLayout) + self.dialogLayout.addLayout(self.authorLayout) self.buttonBox = QtGui.QDialogButtonBox(authorsDialog) self.buttonBox.setStandardButtons( QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel) diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index 320d3c1d3..091618bde 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -27,6 +27,7 @@ from PyQt4 import QtGui, QtCore from openlp.core.lib import translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): @@ -79,28 +80,21 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): def accept(self): if not self.firstNameEdit.text(): - QtGui.QMessageBox.critical( - self, translate('SongsPlugin.AuthorsForm', 'Error'), - translate('SongsPlugin.AuthorsForm', - 'You need to type in the first name of the author.')) + criticalErrorMessageBox(message=translate('SongsPlugin.AuthorsForm', + 'You need to type in the first name of the author.')) self.firstNameEdit.setFocus() return False elif not self.lastNameEdit.text(): - QtGui.QMessageBox.critical( - self, translate('SongsPlugin.AuthorsForm', 'Error'), - translate('SongsPlugin.AuthorsForm', - 'You need to type in the last name of the author.')) + criticalErrorMessageBox(message=translate('SongsPlugin.AuthorsForm', + 'You need to type in the last name of the author.')) self.lastNameEdit.setFocus() return False elif not self.displayEdit.text(): - if QtGui.QMessageBox.critical( - self, translate('SongsPlugin.AuthorsForm', 'Error'), - translate('SongsPlugin.AuthorsForm', - 'You have not set a display name for the ' - 'author, combine the first and last names?'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) - ) == QtGui.QMessageBox.Yes: + if criticalErrorMessageBox( + message=translate('SongsPlugin.AuthorsForm', + 'You have not set a display name for the ' + 'author, combine the first and last names?'), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.displayEdit.setText(self.firstNameEdit.text() + \ u' ' + self.lastNameEdit.text()) return QtGui.QDialog.accept(self) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 202cc43fe..a1f1e97bb 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -30,8 +30,9 @@ import re from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib import SongXMLBuilder, SongXMLParser, VerseType +from openlp.plugins.songs.lib import SongXML, VerseType from openlp.plugins.songs.lib.db import Book, Song, Author, Topic from editsongdialog import Ui_EditSongDialog @@ -263,8 +264,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if isinstance(self.song.lyrics, buffer): self.song.lyrics = unicode(self.song.lyrics) if self.song.lyrics.startswith(u'%s' % \ + translate('SongsPlugin.ImportWizardForm', + 'Welcome to the Song Import Wizard')) + self.informationLabel.setText( + translate('SongsPlugin.ImportWizardForm', + 'This wizard will help you to import songs from a variety of ' + 'formats. Click the next button below to start the process by ' + 'selecting a format to import from.')) + self.sourcePage.setTitle( + translate('SongsPlugin.ImportWizardForm', 'Select Import Source')) + self.sourcePage.setSubTitle( + translate('SongsPlugin.ImportWizardForm', + 'Select the import format, and where to import from.')) + self.formatLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Format:')) + self.formatComboBox.setItemText(0, + translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0')) + self.formatComboBox.setItemText(1, + translate('SongsPlugin.ImportWizardForm', 'openlp.org 1.x')) + self.formatComboBox.setItemText(2, + translate('SongsPlugin.ImportWizardForm', 'OpenLyrics')) + self.formatComboBox.setItemText(3, + translate('SongsPlugin.ImportWizardForm', 'OpenSong')) + self.formatComboBox.setItemText(4, + translate('SongsPlugin.ImportWizardForm', 'Words of Worship')) + self.formatComboBox.setItemText(5, + translate('SongsPlugin.ImportWizardForm', 'CCLI/SongSelect')) + self.formatComboBox.setItemText(6, + translate('SongsPlugin.ImportWizardForm', 'Songs of Fellowship')) + self.formatComboBox.setItemText(7, + translate('SongsPlugin.ImportWizardForm', + 'Generic Document/Presentation')) + self.formatComboBox.setItemText(8, + translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) + self.formatComboBox.setItemText(9, + translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) +# self.formatComboBox.setItemText(9, +# translate('SongsPlugin.ImportWizardForm', 'CSV')) + self.openLP2FilenameLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Filename:')) + self.openLP2BrowseButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.openLP1FilenameLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Filename:')) + self.openLP1BrowseButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.openLP1DisabledLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'The openlp.org 1.x ' + 'importer has been disabled due to a missing Python module. If ' + 'you want to use this importer, you will need to install the ' + '"python-sqlite" module.')) + self.openLyricsAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.openLyricsRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.openLyricsDisabledLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics ' + 'importer has not yet been developed, but as you can see, we are ' + 'still intending to do so. Hopefully it will be in the next ' + 'release.')) + self.openSongAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.openSongRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.wordsOfWorshipAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.wordsOfWorshipRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.ccliAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.ccliRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.songsOfFellowshipAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.songsOfFellowshipRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.songsOfFellowshipDisabledLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'The Songs of ' + 'Fellowship importer has been disabled because OpenLP cannot ' + 'find OpenOffice.org on your computer.')) + self.genericAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.genericRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.genericDisabledLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'The generic document/' + 'presentation importer has been disabled because OpenLP cannot ' + 'find OpenOffice.org on your computer.')) + self.ewFilenameLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Filename:')) + self.ewBrowseButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.songBeamerAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.songBeamerRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) +# self.csvFilenameLabel.setText( +# translate('SongsPlugin.ImportWizardForm', 'Filename:')) +# self.csvBrowseButton.setText( +# translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.progressPage.setTitle( + translate('SongsPlugin.ImportWizardForm', 'Importing')) + self.progressPage.setSubTitle( + translate('SongsPlugin.ImportWizardForm', + 'Please wait while your songs are imported.')) + self.progressLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Ready.')) + self.progressBar.setFormat( + translate('SongsPlugin.ImportWizardForm', '%p%')) + # Align all QFormLayouts towards each other. + width = max(self.formatLabel.minimumSizeHint().width(), + self.openLP2FilenameLabel.minimumSizeHint().width()) + self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Fixed) + self.openLP2FormLabelSpacer.changeSize(width, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.openLP1FormLabelSpacer.changeSize(width, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Fixed) +# self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, +# QtGui.QSizePolicy.Fixed) def validateCurrentPage(self): """ @@ -148,7 +326,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): source_format = self.formatComboBox.currentIndex() if source_format == SongFormat.OpenLP2: if self.openLP2FilenameEdit.text().isEmpty(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No OpenLP 2.0 Song Database Selected'), translate('SongsPlugin.ImportWizardForm', @@ -158,7 +336,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.OpenLP1: if self.openLP1FilenameEdit.text().isEmpty(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No openlp.org 1.x Song Database Selected'), translate('SongsPlugin.ImportWizardForm', @@ -167,19 +345,18 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.openLP1BrowseButton.setFocus() return False elif source_format == SongFormat.OpenLyrics: -# if self.openLyricsFileListWidget.count() == 0: -# QtGui.QMessageBox.critical(self, -# translate('SongsPlugin.ImportWizardForm', -# 'No OpenLyrics Files Selected'), -# translate('SongsPlugin.ImportWizardForm', -# 'You need to add at least one OpenLyrics ' -# 'song file to import from.')) -# self.openLyricsAddButton.setFocus() -# return False - return False + if self.openLyricsFileListWidget.count() == 0: + criticalErrorMessageBox( + translate('SongsPlugin.ImportWizardForm', + 'No OpenLyrics Files Selected'), + translate('SongsPlugin.ImportWizardForm', + 'You need to add at least one OpenLyrics ' + 'song file to import from.')) + self.openLyricsAddButton.setFocus() + return False elif source_format == SongFormat.OpenSong: if self.openSongFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No OpenSong Files Selected'), translate('SongsPlugin.ImportWizardForm', @@ -189,7 +366,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.WordsOfWorship: if self.wordsOfWorshipFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No Words of Worship Files Selected'), translate('SongsPlugin.ImportWizardForm', @@ -199,7 +376,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.CCLI: if self.ccliFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No CCLI Files Selected'), translate('SongsPlugin.ImportWizardForm', @@ -209,7 +386,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.SongsOfFellowship: if self.songsOfFellowshipFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No Songs of Fellowship File Selected'), translate('SongsPlugin.ImportWizardForm', @@ -219,7 +396,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.Generic: if self.genericFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No Document/Presentation Selected'), translate('SongsPlugin.ImportWizardForm', @@ -229,7 +406,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.EasyWorship: if self.ewFilenameEdit.text().isEmpty(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No EasyWorship Song Database Selected'), translate('SongsPlugin.ImportWizardForm', @@ -239,7 +416,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): return False elif source_format == SongFormat.SongBeamer: if self.songBeamerFileListWidget.count() == 0: - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No SongBeamer File Selected'), translate('SongsPlugin.ImportWizardForm', @@ -248,7 +425,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.songBeamerAddButton.setFocus() return False return True - elif self.currentPage() == self.importPage: + elif self.currentPage() == self.progressPage: return True def getFileName(self, title, editbox, filters=u''): @@ -309,17 +486,26 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): os.path.split(unicode(filenames[0]))[0], 1) def getListOfFiles(self, listbox): + """ + Return a list of file from the listbox + """ files = [] for row in range(0, listbox.count()): files.append(unicode(listbox.item(row).text())) return files def removeSelectedItems(self, listbox): + """ + Remove selected listbox items + """ for item in listbox.selectedItems(): item = listbox.takeItem(listbox.row(item)) del item def onOpenLP2BrowseButtonClicked(self): + """ + Get OpenLP v2 song database file + """ self.getFileName( translate('SongsPlugin.ImportWizardForm', 'Select OpenLP 2.0 Database File'), @@ -329,6 +515,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onOpenLP1BrowseButtonClicked(self): + """ + Get OpenLP v1 song database file + """ self.getFileName( translate('SongsPlugin.ImportWizardForm', 'Select openlp.org 1.x Database File'), @@ -337,27 +526,41 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): 'openlp.org v1.x Databases') ) - #def onOpenLyricsAddButtonClicked(self): - # self.getFiles( - # translate('SongsPlugin.ImportWizardForm', - # 'Select OpenLyrics Files'), - # self.openLyricsFileListWidget - # ) - - #def onOpenLyricsRemoveButtonClicked(self): - # self.removeSelectedItems(self.openLyricsFileListWidget) - - def onOpenSongAddButtonClicked(self): + def onOpenLyricsAddButtonClicked(self): + """ + Get OpenLyrics song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', - 'Select Open Song Files'), + 'Select OpenLyrics Files'), + self.openLyricsFileListWidget + ) + + def onOpenLyricsRemoveButtonClicked(self): + """ + Remove selected OpenLyrics files from the import list + """ + self.removeSelectedItems(self.openLyricsFileListWidget) + + def onOpenSongAddButtonClicked(self): + """ + Get OpenSong song database files + """ + self.getFiles( + translate('SongsPlugin.ImportWizardForm', 'Select Open Song Files'), self.openSongFileListWidget ) def onOpenSongRemoveButtonClicked(self): + """ + Remove selected OpenSong files from the import list + """ self.removeSelectedItems(self.openSongFileListWidget) def onWordsOfWorshipAddButtonClicked(self): + """ + Get Words of Worship song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', 'Select Words of Worship Files'), @@ -367,9 +570,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onWordsOfWorshipRemoveButtonClicked(self): + """ + Remove selected Words of Worship files from the import list + """ self.removeSelectedItems(self.wordsOfWorshipFileListWidget) def onCCLIAddButtonClicked(self): + """ + Get CCLI song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', 'Select CCLI Files'), @@ -377,9 +586,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onCCLIRemoveButtonClicked(self): + """ + Remove selected CCLI files from the import list + """ self.removeSelectedItems(self.ccliFileListWidget) def onSongsOfFellowshipAddButtonClicked(self): + """ + Get Songs of Fellowship song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', 'Select Songs of Fellowship Files'), @@ -389,9 +604,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onSongsOfFellowshipRemoveButtonClicked(self): + """ + Remove selected Songs of Fellowship files from the import list + """ self.removeSelectedItems(self.songsOfFellowshipFileListWidget) def onGenericAddButtonClicked(self): + """ + Get song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', 'Select Document/Presentation Files'), @@ -399,9 +620,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onGenericRemoveButtonClicked(self): + """ + Remove selected files from the import list + """ self.removeSelectedItems(self.genericFileListWidget) def onEWBrowseButtonClicked(self): + """ + Get EasyWorship song database files + """ self.getFileName( translate('SongsPlugin.ImportWizardForm', 'Select EasyWorship Database File'), @@ -409,6 +636,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onSongBeamerAddButtonClicked(self): + """ + Get SongBeamer song database files + """ self.getFiles( translate('SongsPlugin.ImportWizardForm', 'Select SongBeamer Files'), @@ -417,25 +647,28 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): ) def onSongBeamerRemoveButtonClicked(self): + """ + Remove selected SongBeamer files from the import list + """ self.removeSelectedItems(self.songBeamerFileListWidget) - def onCurrentIdChanged(self, id): - if self.page(id) == self.importPage: - self.preImport() - self.performImport() - self.postImport() - def registerFields(self): + """ + Register song import wizard fields. + """ pass def setDefaults(self): + """ + Set default form values for the song import wizard. + """ self.restart() self.finishButton.setVisible(False) self.cancelButton.setVisible(True) self.formatComboBox.setCurrentIndex(0) self.openLP2FilenameEdit.setText(u'') self.openLP1FilenameEdit.setText(u'') - #self.openLyricsFileListWidget.clear() + self.openLyricsFileListWidget.clear() self.openSongFileListWidget.clear() self.wordsOfWorshipFileListWidget.clear() self.ccliFileListWidget.clear() @@ -445,25 +678,16 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.songBeamerFileListWidget.clear() #self.csvFilenameEdit.setText(u'') - def incrementProgressBar(self, status_text, increment=1): - log.debug(u'IncrementBar %s', status_text) - if status_text: - self.importProgressLabel.setText(status_text) - if increment > 0: - self.importProgressBar.setValue(self.importProgressBar.value() + - increment) - Receiver.send_message(u'openlp_process_events') - - def preImport(self): - self.finishButton.setVisible(False) - self.importProgressBar.setMinimum(0) - self.importProgressBar.setMaximum(1188) - self.importProgressBar.setValue(0) - self.importProgressLabel.setText( + def preWizard(self): + """ + Perform pre import tasks + """ + OpenLPWizard.preWizard(self) + self.progressLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Starting import...')) Receiver.send_message(u'openlp_process_events') - def performImport(self): + def performWizard(self): """ Perform the actual import. This method pulls in the correct importer class, and then runs the ``do_import`` method of the importer to do @@ -521,20 +745,128 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): elif source_format == SongFormat.SongBeamer: # Import SongBeamer songs importer = self.plugin.importSongs(SongFormat.SongBeamer, - filenames=self.getListOfFiles( - self.songBeamerFileListWidget) + filenames=self.getListOfFiles(self.songBeamerFileListWidget) ) if importer.do_import(): # reload songs - self.importProgressLabel.setText( + self.progressLabel.setText( translate('SongsPlugin.SongImportForm', 'Finished import.')) else: - self.importProgressLabel.setText( + self.progressLabel.setText( translate('SongsPlugin.SongImportForm', 'Your song import failed.')) - def postImport(self): - self.importProgressBar.setValue(self.importProgressBar.maximum()) - self.finishButton.setVisible(True) - self.cancelButton.setVisible(False) - Receiver.send_message(u'openlp_process_events') + def addSingleFileSelectItem(self, prefix, obj_prefix=None, + can_disable=False): + if not obj_prefix: + obj_prefix = prefix + page = QtGui.QWidget() + page.setObjectName(obj_prefix + u'Page') + if can_disable: + importWidget = self.disablableWidget(page, prefix, obj_prefix) + else: + importWidget = page + importLayout = QtGui.QFormLayout(importWidget) + importLayout.setMargin(0) + if can_disable: + importLayout.setObjectName(obj_prefix + u'ImportLayout') + else: + importLayout.setObjectName(obj_prefix + u'Layout') + filenameLabel = QtGui.QLabel(importWidget) + filenameLabel.setObjectName(obj_prefix + u'FilenameLabel') + fileLayout = QtGui.QHBoxLayout() + fileLayout.setObjectName(obj_prefix + u'FileLayout') + filenameEdit = QtGui.QLineEdit(importWidget) + filenameEdit.setObjectName(obj_prefix + u'FilenameEdit') + fileLayout.addWidget(filenameEdit) + browseButton = QtGui.QToolButton(importWidget) + browseButton.setIcon(self.openIcon) + browseButton.setObjectName(obj_prefix + u'BrowseButton') + fileLayout.addWidget(browseButton) + importLayout.addRow(filenameLabel, fileLayout) + formSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + importLayout.setItem(1, QtGui.QFormLayout.LabelRole, formSpacer) + self.formatStack.addWidget(page) + setattr(self, prefix + u'Page', page) + setattr(self, prefix + u'FilenameLabel', filenameLabel) + setattr(self, prefix + u'FormLabelSpacer', formSpacer) + setattr(self, prefix + u'FileLayout', fileLayout) + setattr(self, prefix + u'FilenameEdit', filenameEdit) + setattr(self, prefix + u'BrowseButton', browseButton) + if can_disable: + setattr(self, prefix + u'ImportLayout', importLayout) + else: + setattr(self, prefix + u'Layout', importLayout) + self.formatComboBox.addItem(u'') + + def addMultiFileSelectItem(self, prefix, obj_prefix=None, + can_disable=False): + if not obj_prefix: + obj_prefix = prefix + page = QtGui.QWidget() + page.setObjectName(obj_prefix + u'Page') + if can_disable: + importWidget = self.disablableWidget(page, prefix, obj_prefix) + else: + importWidget = page + importLayout = QtGui.QVBoxLayout(importWidget) + importLayout.setMargin(0) + if can_disable: + importLayout.setObjectName(obj_prefix + u'ImportLayout') + else: + importLayout.setObjectName(obj_prefix + u'Layout') + fileListWidget = QtGui.QListWidget(importWidget) + fileListWidget.setSelectionMode( + QtGui.QAbstractItemView.ExtendedSelection) + fileListWidget.setObjectName(obj_prefix + u'FileListWidget') + importLayout.addWidget(fileListWidget) + buttonLayout = QtGui.QHBoxLayout() + buttonLayout.setObjectName(obj_prefix + u'ButtonLayout') + addButton = QtGui.QPushButton(importWidget) + addButton.setIcon(self.openIcon) + addButton.setObjectName(obj_prefix + u'AddButton') + buttonLayout.addWidget(addButton) + buttonLayout.addStretch() + removeButton = QtGui.QPushButton(importWidget) + removeButton.setIcon(self.deleteIcon) + removeButton.setObjectName(obj_prefix + u'RemoveButton') + buttonLayout.addWidget(removeButton) + importLayout.addLayout(buttonLayout) + self.formatStack.addWidget(page) + setattr(self, prefix + u'Page', page) + setattr(self, prefix + u'FileListWidget', fileListWidget) + setattr(self, prefix + u'ButtonLayout', buttonLayout) + setattr(self, prefix + u'AddButton', addButton) + setattr(self, prefix + u'RemoveButton', removeButton) + if can_disable: + setattr(self, prefix + u'ImportLayout', importLayout) + else: + setattr(self, prefix + u'Layout', importLayout) + self.formatComboBox.addItem(u'') + + def disablableWidget(self, page, prefix, obj_prefix): + layout = QtGui.QVBoxLayout(page) + layout.setMargin(0) + layout.setSpacing(0) + layout.setObjectName(obj_prefix + u'Layout') + disabledWidget = QtGui.QWidget(page) + disabledWidget.setVisible(False) + disabledWidget.setObjectName(obj_prefix + u'DisabledWidget') + disabledLayout = QtGui.QVBoxLayout(disabledWidget) + disabledLayout.setMargin(0) + disabledLayout.setObjectName(obj_prefix + u'DisabledLayout') + disabledLabel = QtGui.QLabel(disabledWidget) + disabledLabel.setWordWrap(True) + disabledLabel.setObjectName(obj_prefix + u'DisabledLabel') + disabledLayout.addWidget(disabledLabel) + layout.addWidget(disabledWidget) + importWidget = QtGui.QWidget(page) + importWidget.setObjectName(obj_prefix + u'ImportWidget') + layout.addWidget(importWidget) + setattr(self, prefix + u'Layout', layout) + setattr(self, prefix + u'DisabledWidget', disabledWidget) + setattr(self, prefix + u'DisabledLayout', disabledLayout) + setattr(self, prefix + u'DisabledLabel', disabledLabel) + setattr(self, prefix + u'ImportWidget', importWidget) + return importWidget diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py deleted file mode 100644 index 85fbb07fe..000000000 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ /dev/null @@ -1,365 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2011 Raoul Snyman # -# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import build_icon, translate - -class Ui_SongImportWizard(object): - def setupUi(self, songImportWizard): - self.openIcon = build_icon(u':/general/general_open.png') - self.deleteIcon = build_icon(u':/general/general_delete.png') - songImportWizard.setObjectName(u'songImportWizard') - songImportWizard.setModal(True) - songImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle) - songImportWizard.setOptions( - QtGui.QWizard.IndependentPages | - QtGui.QWizard.NoBackButtonOnStartPage | - QtGui.QWizard.NoBackButtonOnLastPage) - # Welcome Page - self.welcomePage = QtGui.QWizardPage() - self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, - QtGui.QPixmap(u':/wizards/wizard_importsong.bmp')) - self.welcomePage.setObjectName(u'WelcomePage') - self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage) - self.welcomeLayout.setObjectName(u'WelcomeLayout') - self.titleLabel = QtGui.QLabel(self.welcomePage) - self.titleLabel.setObjectName(u'TitleLabel') - self.welcomeLayout.addWidget(self.titleLabel) - self.welcomeLayout.addSpacing(40) - self.informationLabel = QtGui.QLabel(self.welcomePage) - self.informationLabel.setWordWrap(True) - self.informationLabel.setObjectName(u'InformationLabel') - self.welcomeLayout.addWidget(self.informationLabel) - self.welcomeLayout.addStretch() - songImportWizard.addPage(self.welcomePage) - # Source Page - self.sourcePage = QtGui.QWizardPage() - self.sourcePage.setObjectName(u'SourcePage') - self.sourceLayout = QtGui.QVBoxLayout(self.sourcePage) - self.sourceLayout.setObjectName(u'SourceLayout') - self.formatLayout = QtGui.QFormLayout() - self.formatLayout.setObjectName(u'FormatLayout') - self.formatLabel = QtGui.QLabel(self.sourcePage) - self.formatLabel.setObjectName(u'FormatLabel') - self.formatComboBox = QtGui.QComboBox(self.sourcePage) - self.formatComboBox.setObjectName(u'FormatComboBox') - self.formatLayout.addRow(self.formatLabel, self.formatComboBox) - self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, - self.formatSpacer) - self.sourceLayout.addLayout(self.formatLayout) - self.formatStack = QtGui.QStackedLayout() - self.formatStack.setObjectName(u'FormatStack') - # OpenLP 2.0 - self.addSingleFileSelectItem(u'openLP2') - # openlp.org 1.x - self.addSingleFileSelectItem(u'openLP1', None, True) - # OpenLyrics - self.addMultiFileSelectItem(u'openLyrics', u'OpenLyrics', True) - # set OpenLyrics to disabled by default - self.openLyricsDisabledWidget.setVisible(True) - self.openLyricsImportWidget.setVisible(False) - # Open Song - self.addMultiFileSelectItem(u'openSong', u'OpenSong') - # Words of Worship - self.addMultiFileSelectItem(u'wordsOfWorship') - # CCLI File import - self.addMultiFileSelectItem(u'ccli') - # Songs of Fellowship - self.addMultiFileSelectItem(u'songsOfFellowship', None, True) - # Generic Document/Presentation import - self.addMultiFileSelectItem(u'generic', None, True) - # EasyWorship - self.addSingleFileSelectItem(u'ew') - # Words of Worship - self.addMultiFileSelectItem(u'songBeamer') -# Commented out for future use. -# self.addSingleFileSelectItem(u'csv', u'CSV') - self.sourceLayout.addLayout(self.formatStack) - songImportWizard.addPage(self.sourcePage) - # Import Page - self.importPage = QtGui.QWizardPage() - self.importPage.setObjectName(u'ImportPage') - self.importLayout = QtGui.QVBoxLayout(self.importPage) - self.importLayout.setMargin(48) - self.importLayout.setObjectName(u'ImportLayout') - self.importProgressLabel = QtGui.QLabel(self.importPage) - self.importProgressLabel.setObjectName(u'ImportProgressLabel') - self.importLayout.addWidget(self.importProgressLabel) - self.importProgressBar = QtGui.QProgressBar(self.importPage) - self.importProgressBar.setObjectName(u'ImportProgressBar') - self.importLayout.addWidget(self.importProgressBar) - songImportWizard.addPage(self.importPage) - self.retranslateUi(songImportWizard) - self.formatStack.setCurrentIndex(0) - QtCore.QObject.connect(self.formatComboBox, - QtCore.SIGNAL(u'currentIndexChanged(int)'), - self.formatStack.setCurrentIndex) - QtCore.QMetaObject.connectSlotsByName(songImportWizard) - - def retranslateUi(self, songImportWizard): - songImportWizard.setWindowTitle( - translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard')) - self.titleLabel.setText( - u'%s' % \ - translate('SongsPlugin.ImportWizardForm', - 'Welcome to the Song Import Wizard')) - self.informationLabel.setText( - translate('SongsPlugin.ImportWizardForm', - 'This wizard will help you to import songs from a variety of ' - 'formats. Click the next button below to start the process by ' - 'selecting a format to import from.')) - self.sourcePage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Select Import Source')) - self.sourcePage.setSubTitle( - translate('SongsPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.formatLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Format:')) - self.formatComboBox.setItemText(0, - translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0')) - self.formatComboBox.setItemText(1, - translate('SongsPlugin.ImportWizardForm', 'openlp.org 1.x')) - self.formatComboBox.setItemText(2, - translate('SongsPlugin.ImportWizardForm', 'OpenLyrics')) - self.formatComboBox.setItemText(3, - translate('SongsPlugin.ImportWizardForm', 'OpenSong')) - self.formatComboBox.setItemText(4, - translate('SongsPlugin.ImportWizardForm', 'Words of Worship')) - self.formatComboBox.setItemText(5, - translate('SongsPlugin.ImportWizardForm', 'CCLI/SongSelect')) - self.formatComboBox.setItemText(6, - translate('SongsPlugin.ImportWizardForm', 'Songs of Fellowship')) - self.formatComboBox.setItemText(7, - translate('SongsPlugin.ImportWizardForm', - 'Generic Document/Presentation')) - self.formatComboBox.setItemText(8, - translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) - self.formatComboBox.setItemText(9, - translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) -# self.formatComboBox.setItemText(9, -# translate('SongsPlugin.ImportWizardForm', 'CSV')) - self.openLP2FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP2BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.openLP1FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP1BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.openLP1DisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The openlp.org 1.x ' - 'importer has been disabled due to a missing Python module. If ' - 'you want to use this importer, you will need to install the ' - '"python-sqlite" module.')) - #self.openLyricsAddButton.setText( - # translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - #self.openLyricsRemoveButton.setText( - # translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.openLyricsDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics ' - 'importer has not yet been developed, but as you can see, we are ' - 'still intending to do so. Hopefully it will be in the next ' - 'release.')) - self.openSongAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.openSongRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.wordsOfWorshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.wordsOfWorshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.ccliAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.ccliRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songsOfFellowshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The Songs of ' - 'Fellowship importer has been disabled because OpenLP cannot ' - 'find OpenOffice.org on your computer.')) - self.genericAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.genericRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.genericDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The generic document/' - 'presentation importer has been disabled because OpenLP cannot ' - 'find OpenOffice.org on your computer.')) - self.ewFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.ewBrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.songBeamerAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songBeamerRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) -# self.csvFilenameLabel.setText( -# translate('SongsPlugin.ImportWizardForm', 'Filename:')) -# self.csvBrowseButton.setText( -# translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.importPage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Importing')) - self.importPage.setSubTitle( - translate('SongsPlugin.ImportWizardForm', - 'Please wait while your songs are imported.')) - self.importProgressLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Ready.')) - self.importProgressBar.setFormat( - translate('SongsPlugin.ImportWizardForm', '%p%')) - # Align all QFormLayouts towards each other. - width = max(self.formatLabel.minimumSizeHint().width(), - self.openLP2FilenameLabel.minimumSizeHint().width()) - self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openLP2FormLabelSpacer.changeSize(width, 0, - QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - self.openLP1FormLabelSpacer.changeSize(width, 0, - QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) -# self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, -# QtGui.QSizePolicy.Fixed) - - def addSingleFileSelectItem(self, prefix, obj_prefix=None, - can_disable=False): - if not obj_prefix: - obj_prefix = prefix - page = QtGui.QWidget() - page.setObjectName(obj_prefix + u'Page') - if can_disable: - importWidget = self.disablableWidget(page, prefix, obj_prefix) - else: - importWidget = page - importLayout = QtGui.QFormLayout(importWidget) - importLayout.setMargin(0) - if can_disable: - importLayout.setObjectName(obj_prefix + u'ImportLayout') - else: - importLayout.setObjectName(obj_prefix + u'Layout') - filenameLabel = QtGui.QLabel(importWidget) - filenameLabel.setObjectName(obj_prefix + u'FilenameLabel') - fileLayout = QtGui.QHBoxLayout() - fileLayout.setObjectName(obj_prefix + u'FileLayout') - filenameEdit = QtGui.QLineEdit(importWidget) - filenameEdit.setObjectName(obj_prefix + u'FilenameEdit') - fileLayout.addWidget(filenameEdit) - browseButton = QtGui.QToolButton(importWidget) - browseButton.setIcon(self.openIcon) - browseButton.setObjectName(obj_prefix + u'BrowseButton') - fileLayout.addWidget(browseButton) - importLayout.addRow(filenameLabel, fileLayout) - formSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - importLayout.setItem(1, QtGui.QFormLayout.LabelRole, formSpacer) - self.formatStack.addWidget(page) - setattr(self, prefix + u'Page', page) - setattr(self, prefix + u'FilenameLabel', filenameLabel) - setattr(self, prefix + u'FormLabelSpacer', formSpacer) - setattr(self, prefix + u'FileLayout', fileLayout) - setattr(self, prefix + u'FilenameEdit', filenameEdit) - setattr(self, prefix + u'BrowseButton', browseButton) - if can_disable: - setattr(self, prefix + u'ImportLayout', importLayout) - else: - setattr(self, prefix + u'Layout', importLayout) - self.formatComboBox.addItem(u'') - - def addMultiFileSelectItem(self, prefix, obj_prefix=None, - can_disable=False): - if not obj_prefix: - obj_prefix = prefix - page = QtGui.QWidget() - page.setObjectName(obj_prefix + u'Page') - if can_disable: - importWidget = self.disablableWidget(page, prefix, obj_prefix) - else: - importWidget = page - importLayout = QtGui.QVBoxLayout(importWidget) - importLayout.setMargin(0) - if can_disable: - importLayout.setObjectName(obj_prefix + u'ImportLayout') - else: - importLayout.setObjectName(obj_prefix + u'Layout') - fileListWidget = QtGui.QListWidget(importWidget) - fileListWidget.setSelectionMode( - QtGui.QAbstractItemView.ExtendedSelection) - fileListWidget.setObjectName(obj_prefix + u'FileListWidget') - importLayout.addWidget(fileListWidget) - buttonLayout = QtGui.QHBoxLayout() - buttonLayout.setObjectName(obj_prefix + u'ButtonLayout') - addButton = QtGui.QPushButton(importWidget) - addButton.setIcon(self.openIcon) - addButton.setObjectName(obj_prefix + u'AddButton') - buttonLayout.addWidget(addButton) - buttonLayout.addStretch() - removeButton = QtGui.QPushButton(importWidget) - removeButton.setIcon(self.deleteIcon) - removeButton.setObjectName(obj_prefix + u'RemoveButton') - buttonLayout.addWidget(removeButton) - importLayout.addLayout(buttonLayout) - self.formatStack.addWidget(page) - setattr(self, prefix + u'Page', page) - setattr(self, prefix + u'FileListWidget', fileListWidget) - setattr(self, prefix + u'ButtonLayout', buttonLayout) - setattr(self, prefix + u'AddButton', addButton) - setattr(self, prefix + u'RemoveButton', removeButton) - if can_disable: - setattr(self, prefix + u'ImportLayout', importLayout) - else: - setattr(self, prefix + u'Layout', importLayout) - self.formatComboBox.addItem(u'') - - def disablableWidget(self, page, prefix, obj_prefix): - layout = QtGui.QVBoxLayout(page) - layout.setMargin(0) - layout.setSpacing(0) - layout.setObjectName(obj_prefix + u'Layout') - disabledWidget = QtGui.QWidget(page) - disabledWidget.setVisible(False) - disabledWidget.setObjectName(obj_prefix + u'DisabledWidget') - disabledLayout = QtGui.QVBoxLayout(disabledWidget) - disabledLayout.setMargin(0) - disabledLayout.setObjectName(obj_prefix + u'DisabledLayout') - disabledLabel = QtGui.QLabel(disabledWidget) - disabledLabel.setWordWrap(True) - disabledLabel.setObjectName(obj_prefix + u'DisabledLabel') - disabledLayout.addWidget(disabledLabel) - layout.addWidget(disabledWidget) - importWidget = QtGui.QWidget(page) - importWidget.setObjectName(obj_prefix + u'ImportWidget') - layout.addWidget(importWidget) - setattr(self, prefix + u'Layout', layout) - setattr(self, prefix + u'DisabledWidget', disabledWidget) - setattr(self, prefix + u'DisabledLayout', disabledLayout) - setattr(self, prefix + u'DisabledLabel', disabledLabel) - setattr(self, prefix + u'ImportWidget', importWidget) - return importWidget diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 582b6ebe5..51fafcc7a 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -36,8 +36,6 @@ class Ui_SongMaintenanceDialog(object): self.dialogLayout = QtGui.QGridLayout(songMaintenanceDialog) self.dialogLayout.setObjectName(u'dialogLayout') self.typeListWidget = QtGui.QListWidget(songMaintenanceDialog) - # Caution: fixed widget width - self.typeListWidget.setFixedWidth(172) self.typeListWidget.setIconSize(QtCore.QSize(32, 32)) self.typeListWidget.setUniformItemSizes(True) self.typeListWidget.setObjectName(u'typeListWidget') @@ -147,12 +145,12 @@ class Ui_SongMaintenanceDialog(object): def retranslateUi(self, songMaintenanceDialog): songMaintenanceDialog.setWindowTitle( translate('SongsPlugin.SongMaintenanceForm', 'Song Maintenance')) - self.listItemAuthors.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Authors')) - self.listItemTopics.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Topics')) - self.listItemBooks.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Song Books')) + authorsString = translate('SongsPlugin.SongMaintenanceForm', 'Authors') + topicsString = translate('SongsPlugin.SongMaintenanceForm', 'Topics') + booksString = translate('SongsPlugin.SongMaintenanceForm', 'Song Books') + self.listItemAuthors.setText(authorsString) + self.listItemTopics.setText(topicsString) + self.listItemBooks.setText(booksString) self.authorsAddButton.setText( translate('SongsPlugin.SongMaintenanceForm', '&Add')) self.authorsEditButton.setText( @@ -171,3 +169,8 @@ class Ui_SongMaintenanceDialog(object): translate('SongsPlugin.SongMaintenanceForm', '&Edit')) self.booksDeleteButton.setText( translate('SongsPlugin.SongMaintenanceForm', '&Delete')) + typeListWidth = max(self.fontMetrics().width(authorsString), + self.fontMetrics().width(topicsString), + self.fontMetrics().width(booksString)) + self.typeListWidget.setFixedWidth(typeListWidth + + self.typeListWidget.iconSize().width() + 32) diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index c964c5192..cd10dca9b 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -23,15 +23,19 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +import logging from PyQt4 import QtGui, QtCore from sqlalchemy.sql import and_ from openlp.core.lib import Receiver, translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm from openlp.plugins.songs.lib.db import Author, Book, Topic, Song from songmaintenancedialog import Ui_SongMaintenanceDialog +log = logging.getLogger(__name__) + class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Class documentation goes here. @@ -87,15 +91,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if item_id != -1: item = self.manager.get_object(item_class, item_id) if item and len(item.songs) == 0: - if QtGui.QMessageBox.warning(self, dlg_title, del_text, - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | - QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes: + if criticalErrorMessageBox(title=dlg_title, message=del_text, + parent=self, question=True) == QtGui.QMessageBox.Yes: self.manager.delete_object(item_class, item.id) reset_func() else: - QtGui.QMessageBox.critical(self, dlg_title, err_text) + criticalErrorMessageBox(dlg_title, err_text) else: - QtGui.QMessageBox.critical(self, dlg_title, sel_text) + criticalErrorMessageBox(dlg_title, sel_text) def resetAuthors(self): """ @@ -229,14 +232,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.manager.save_object(author): self.resetAuthors() else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your author.')) else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'This author already exists.')) def onTopicAddButtonClick(self): @@ -246,14 +247,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.manager.save_object(topic): self.resetTopics() else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your topic.')) else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'This topic already exists.')) def onBookAddButtonClick(self): @@ -264,14 +263,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.manager.save_object(book): self.resetBooks() else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your book.')) else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'This book already exists.')) def onAuthorEditButtonClick(self): @@ -298,20 +295,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): self.resetAuthors() Receiver.send_message(u'songs_load_list') else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', - 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.')) - elif QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - unicode(translate('SongsPlugin.SongMaintenanceForm', - 'The author %s already exists. Would you like to make songs' - ' with author %s use the existing author %s?')) % - (author.display_name, temp_display_name, - author.display_name), QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == \ - QtGui.QMessageBox.Yes: + elif criticalErrorMessageBox(message=unicode(translate( + 'SongsPlugin.SongMaintenanceForm', 'The author %s already ' + 'exists. Would you like to make songs with author %s use ' + 'the existing author %s?')) % (author.display_name, + temp_display_name, author.display_name), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.mergeAuthors(author) self.resetAuthors() Receiver.send_message(u'songs_load_list') @@ -321,9 +313,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author.first_name = temp_first_name author.last_name = temp_last_name author.display_name = temp_display_name - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your modified author, because the ' 'author already exists.')) @@ -340,27 +331,22 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.manager.save_object(topic): self.resetTopics() else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', - 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.')) - elif QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - unicode(translate('SongsPlugin.SongMaintenanceForm', + elif criticalErrorMessageBox( + message=unicode(translate('SongsPlugin.SongMaintenanceForm', 'The topic %s already exists. Would you like to make songs ' 'with topic %s use the existing topic %s?')) % (topic.name, - temp_name, topic.name), QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == \ - QtGui.QMessageBox.Yes: + temp_name, topic.name), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.mergeTopics(topic) self.resetTopics() else: # We restore the topics's old name. topic.name = temp_name - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your modified topic, because it ' 'already exists.')) @@ -383,19 +369,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.manager.save_object(book): self.resetBooks() else: - QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', - 'Error'), - translate('SongsPlugin.SongMaintenanceForm', + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.')) - elif QtGui.QMessageBox.critical(self, - translate('SongsPlugin.SongMaintenanceForm', 'Error'), - unicode(translate('SongsPlugin.SongMaintenanceForm', + elif criticalErrorMessageBox( + message=unicode(translate('SongsPlugin.SongMaintenanceForm', 'The book %s already exists. Would you like to make songs ' 'with book %s use the existing book %s?')) % (book.name, - temp_name, book.name), QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == \ - QtGui.QMessageBox.Yes: + temp_name, book.name), + parent=self, question=True) == QtGui.QMessageBox.Yes: self.mergeBooks(book) self.resetBooks() else: diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index 1ff827423..4ab2b63fa 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -27,6 +27,7 @@ from PyQt4 import QtGui from openlp.core.lib import translate +from openlp.core.ui import criticalErrorMessageBox from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): @@ -48,10 +49,8 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): def accept(self): if not self.nameEdit.text(): - QtGui.QMessageBox.critical( - self, translate('SongsPlugin.TopicsForm', 'Error'), - translate('SongsPlugin.TopicsForm', - 'You need to type in a topic name.')) + criticalErrorMessageBox(message=translate('SongsPlugin.TopicsForm', + 'You need to type in a topic name.')) self.nameEdit.setFocus() return False else: diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 0ef2200ea..462dac89a 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -175,6 +175,6 @@ def retrieve_windows_encoding(recommendation=None): return None return filter(lambda item: item[1] == choice[0], encodings)[0][0] -from xml import LyricsXML, SongXMLBuilder, SongXMLParser, OpenLyricsParser +from xml import OpenLyrics, SongXML from songstab import SongsTab from mediaitem import SongMediaItem diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 1b8531755..441391d02 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -34,9 +34,6 @@ from songimport import SongImport log = logging.getLogger(__name__) -class CCLIFileImportError(Exception): - pass - class CCLIFileImport(SongImport): """ The :class:`CCLIFileImport` class provides OpenLP with the ability to @@ -67,7 +64,7 @@ class CCLIFileImport(SongImport): """ log.debug(u'Starting CCLI File Import') song_total = len(self.filenames) - self.import_wizard.importProgressBar.setMaximum(song_total) + self.import_wizard.progressBar.setMaximum(song_total) song_count = 1 for filename in self.filenames: self.import_wizard.incrementProgressBar(unicode(translate( @@ -152,7 +149,6 @@ class CCLIFileImport(SongImport): """ log.debug(u'USR file text: %s', textList) - lyrics = [] self.set_defaults() for line in textList: if line.startswith(u'Title='): diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index fc3aa06d1..faa0a88da 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -72,7 +72,7 @@ def init_schema(url): ``url`` The database to setup """ - session, metadata = init_db(url) + session, metadata = init_db(url, False) # Definition of the "authors" table authors_table = Table(u'authors', metadata, @@ -181,4 +181,4 @@ def init_schema(url): mapper(Topic, topics_table) metadata.create_all(checkfirst=True) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index d74cd284f..312e3b759 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -186,7 +186,7 @@ class EasyWorshipSongImport(SongImport): # 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.import_wizard.importProgressBar.setMaximum(total_blocks) + self.import_wizard.progressBar.setMaximum(total_blocks) # Read the field description information db_file.seek(120) field_info = db_file.read(num_fields * 2) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index b82e14c12..128d80138 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -26,6 +26,7 @@ from opensongimport import OpenSongImport from olpimport import OpenLPSongImport +from openlyricsimport import OpenLyricsImport from wowimport import WowImport from cclifileimport import CCLIFileImport from ewimport import EasyWorshipSongImport @@ -77,8 +78,10 @@ class SongFormat(object): """ if format == SongFormat.OpenLP2: return OpenLPSongImport - if format == SongFormat.OpenLP1: + elif format == SongFormat.OpenLP1: return OpenLP1SongImport + elif format == SongFormat.OpenLyrics: + return OpenLyricsImport elif format == SongFormat.OpenSong: return OpenSongImport elif format == SongFormat.SongsOfFellowship: @@ -93,7 +96,6 @@ class SongFormat(object): return EasyWorshipSongImport elif format == SongFormat.SongBeamer: return SongBeamerImport -# else: return None @staticmethod diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 050d88d63..93e40f58a 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -35,7 +35,7 @@ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \ ItemCapabilities, translate, check_item_selected from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm -from openlp.plugins.songs.lib import SongXMLParser, OpenLyricsParser +from openlp.plugins.songs.lib import OpenLyrics, SongXML from openlp.plugins.songs.lib.db import Author, Song from openlp.core.lib.searchedit import SearchEdit @@ -58,7 +58,7 @@ class SongMediaItem(MediaManagerItem): self.ListViewWithDnD_class = SongListView MediaManagerItem.__init__(self, parent, self, icon) self.edit_song_form = EditSongForm(self, self.parent.manager) - self.openLyrics = OpenLyricsParser(self.parent.manager) + self.openLyrics = OpenLyrics(self.parent.manager) self.singleServiceItem = False self.song_maintenance_form = SongMaintenanceForm( self.parent.manager, self) @@ -322,15 +322,14 @@ class SongMediaItem(MediaManagerItem): translate('SongsPlugin.MediaItem', 'You must select an item to delete.')): items = self.listView.selectedIndexes() - ans = QtGui.QMessageBox.question(self, + if QtGui.QMessageBox.question(self, translate('SongsPlugin.MediaItem', 'Delete Song(s)?'), translate('SongsPlugin.MediaItem', 'Are you sure you want to delete the %n selected song(s)?', '', QtCore.QCoreApplication.CodecForTr, len(items)), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok| - QtGui.QMessageBox.Cancel), - QtGui.QMessageBox.Ok) - if ans == QtGui.QMessageBox.Cancel: + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok | + QtGui.QMessageBox.Cancel), + QtGui.QMessageBox.Ok) == QtGui.QMessageBox.Cancel: return for item in items: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] @@ -362,8 +361,7 @@ class SongMediaItem(MediaManagerItem): service_item.theme = song.theme_name service_item.edit_id = item_id if song.lyrics.startswith(u' - + + + +The XML of `OpenLyrics `_ songs is of the format:: + + + + + Amazing Grace + + + + + + Amazing grace how sweet the sound + + + + """ import logging import re from lxml import etree, objectify + +from openlp.core.lib import translate from openlp.plugins.songs.lib import VerseType -from openlp.plugins.songs.lib.db import Author, Song +from openlp.plugins.songs.lib.db import Author, Book, Song, Topic log = logging.getLogger(__name__) -class SongXMLBuilder(object): +class SongXML(object): """ - This class builds the XML used to describe songs. + This class builds and parses the XML used to describe songs. """ - log.info(u'SongXMLBuilder Loaded') + log.info(u'SongXML Loaded') - def __init__(self, song_language=None): + def __init__(self): """ - Set up the song builder. - - ``song_language`` - The language used in this song + Set up the default variables. """ - lang = u'en' - if song_language: - lang = song_language self.song_xml = objectify.fromstring(u'') - self.lyrics = etree.SubElement(self.song_xml, u'lyrics', language=lang) + self.lyrics = etree.SubElement(self.song_xml, u'lyrics') def add_verse_to_lyrics(self, type, number, content): """ - Add a verse to the ```` tag. + Add a verse to the ** tag. ``type`` - A string denoting the type of verse. Possible values are "Chorus", - "Verse", "Bridge", and "Custom". + A string denoting the type of verse. Possible values are "V", + "C", "B", "P", "I", "E" and "O". ``number`` An integer denoting the number of the item, for example: verse 1. @@ -80,18 +98,11 @@ class SongXMLBuilder(object): ``content`` The actual text of the verse to be stored. """ - verse = etree.Element(u'verse', type = unicode(type), - label = unicode(number)) + verse = etree.Element(u'verse', type=unicode(type), + label=unicode(number)) verse.text = etree.CDATA(content) self.lyrics.append(verse) - def dump_xml(self): - """ - Debugging aid to dump XML so that we can see what we have. - """ - return etree.tostring(self.song_xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=True) - def extract_xml(self): """ Extract our newly created XML song. @@ -99,16 +110,10 @@ class SongXMLBuilder(object): return etree.tostring(self.song_xml, encoding=u'UTF-8', xml_declaration=True) - -class SongXMLParser(object): - """ - A class to read in and parse a song's XML. - """ - log.info(u'SongXMLParser Loaded') - - def __init__(self, xml): + def get_verses(self, xml): """ - Set up our song XML parser. + Iterates through the verses in the XML and returns a list of verses + and their attributes. ``xml`` The XML of the song to be parsed. @@ -120,12 +125,6 @@ class SongXMLParser(object): self.song_xml = objectify.fromstring(xml) except etree.XMLSyntaxError: log.exception(u'Invalid xml %s', xml) - - def get_verses(self): - """ - Iterates through the verses in the XML and returns a list of verses - and their attributes. - """ xml_iter = self.song_xml.getiterator() verse_list = [] for element in xml_iter: @@ -142,137 +141,110 @@ class SongXMLParser(object): return etree.dump(self.song_xml) -class LyricsXML(object): +class OpenLyrics(object): """ - This class represents the XML in the ``lyrics`` field of a song. - """ - def __init__(self, song=None): - if song: - if song.lyrics.startswith(u'* + OpenLP does not support the attribute *type* and *lang*. - def extract(self, text): - """ - If the ``lyrics`` field in the database is not XML, this method is - called and used to construct the verse structure similar to the output - of the ``parse`` function. + ** + This property is not supported. - ``text`` - The text to pull verses out of. - """ - text = text.replace('\r\n', '\n') - verses = text.split('\n\n') - self.languages = [{u'language': u'en', u'verses': []}] - counter = 0 - for verse in verses: - counter = counter + 1 - self.languages[0][u'verses'].append({ - u'type': u'verse', - u'label': unicode(counter), - u'text': verse - }) - return True + ** + The ** property is fully supported. But comments in lyrics + are not supported. - def add_verse(self, type, label, text): - """ - Add a verse to the list of verses. + ** + This property is fully supported. - ``type`` - The type of list, one of "verse", "chorus", "bridge", "pre-chorus", - "intro", "outtro". + ** + This property is not supported. - ``label`` - The number associated with this verse, like 1 or 2. + ** + This property is not supported. - ``text`` - The text of the verse. - """ - self.verses.append({ - u'type': type, - u'label': label, - u'text': text - }) + ** + This property is not supported. - def export(self): - """ - Build up the XML for the verse structure. - """ - lyrics_output = u'' - for language in self.languages: - verse_output = u'' - for verse in language[u'verses']: - verse_output = verse_output + \ - u'' % \ - (verse[u'type'], verse[u'label'], verse[u'text']) - lyrics_output = lyrics_output + \ - u'%s' % \ - (language[u'language'], verse_output) - song_output = u'' + \ - u'%s' % lyrics_output - return song_output + ** + The attribute *part* is not supported. + ** + This property is not supported. -class OpenLyricsParser(object): - """ - This class represents the converter for Song to/from OpenLyrics XML. + ** + As OpenLP does only support one songbook, we cannot consider more than + one songbook. + + ** + This property is not supported. + + ** + Topics, as they are called in OpenLP, are fully supported, whereby only + the topic text (e. g. Grace) is considered, but neither the *id* nor + *lang*. + + ** + This property is not supported. + + ** + This property is not supported. + + ** + The attribute *translit* and *lang* are not supported. + + ** + OpenLP supports this property. """ def __init__(self, manager): self.manager = manager def song_to_xml(self, song): """ - Convert the song to OpenLyrics Format + Convert the song to OpenLyrics Format. """ - song_xml_parser = SongXMLParser(song.lyrics) - verse_list = song_xml_parser.get_verses() + sxml = SongXML() + verse_list = sxml.get_verses(song.lyrics) song_xml = objectify.fromstring( u'') properties = etree.SubElement(song_xml, u'properties') titles = etree.SubElement(properties, u'titles') - self._add_text_to_element(u'title', titles, song.title) + self._add_text_to_element(u'title', titles, song.title.strip()) if song.alternate_title: - self._add_text_to_element(u'title', titles, song.alternate_title) - if song.theme_name: - themes = etree.SubElement(properties, u'themes') - self._add_text_to_element(u'theme', themes, song.theme_name) - self._add_text_to_element(u'copyright', properties, song.copyright) - self._add_text_to_element(u'verseOrder', properties, song.verse_order) + self._add_text_to_element( + u'title', titles, song.alternate_title.strip()) + if song.comments: + comments = etree.SubElement(properties, u'comments') + self._add_text_to_element(u'comment', comments, song.comments) + if song.copyright: + self._add_text_to_element(u'copyright', properties, song.copyright) + if song.verse_order: + self._add_text_to_element( + u'verseOrder', properties, song.verse_order) if song.ccli_number: self._add_text_to_element(u'ccliNo', properties, song.ccli_number) - authors = etree.SubElement(properties, u'authors') - for author in song.authors: - self._add_text_to_element(u'author', authors, author.display_name) + if song.authors: + authors = etree.SubElement(properties, u'authors') + for author in song.authors: + self._add_text_to_element( + u'author', authors, author.display_name) + book = self.manager.get_object_filtered( + Book, Book.id == song.song_book_id) + if book is not None: + book = book.name + songbooks = etree.SubElement(properties, u'songbooks') + element = self._add_text_to_element( + u'songbook', songbooks, None, book) + element.set(u'entry', song.song_number) + if song.topics: + themes = etree.SubElement(properties, u'themes') + for topic in song.topics: + self._add_text_to_element(u'theme', themes, topic.name) lyrics = etree.SubElement(song_xml, u'lyrics') for verse in verse_list: verse_tag = u'%s%s' % ( @@ -286,74 +258,32 @@ class OpenLyricsParser(object): def xml_to_song(self, xml): """ - Create a Song from OpenLyrics format xml + Create and save a song from OpenLyrics format xml to the database. Since + we also export XML from external sources (e. g. OpenLyrics import), we + cannot ensure, that it completely conforms to the OpenLyrics standard. + + ``xml`` + The XML to parse (unicode). """ - # No xml get out of here + # No xml get out of here. if not xml: - return 0 + return None song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) properties = song_xml.properties - song.copyright = unicode(properties.copyright.text) - if song.copyright == u'None': - song.copyright = u'' - song.verse_order = unicode(properties.verseOrder.text) - if song.verse_order == u'None': - song.verse_order = u'' - song.topics = [] - song.book = None - theme_name = None - try: - song.ccli_number = unicode(properties.ccliNo.text) - except: - song.ccli_number = u'' - try: - theme_name = unicode(properties.themes.theme) - except: - pass - if theme_name: - song.theme_name = theme_name - else: - song.theme_name = u'' - # Process Titles - for title in properties.titles.title: - if not song.title: - song.title = unicode(title.text) - song.search_title = unicode(song.title) - song.alternate_title = u'' - else: - song.alternate_title = unicode(title.text) - song.search_title += u'@' + song.alternate_title - song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', - unicode(song.search_title)).lower() - # Process Lyrics - sxml = SongXMLBuilder() - search_text = u'' - for lyrics in song_xml.lyrics: - for verse in song_xml.lyrics.verse: - text = u'' - for line in verse.lines.line: - line = unicode(line) - if not text: - text = line - else: - text += u'\n' + line - type = VerseType.expand_string(verse.attrib[u'name'][0]) - sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) - search_text = search_text + text - song.search_lyrics = search_text.lower() - song.lyrics = unicode(sxml.extract_xml(), u'utf-8') - song.comments = u'' - song.song_number = u'' - # Process Authors - try: - for author in properties.authors.author: - self._process_author(author.text, song) - except: - # No Author in XML so ignore - pass + self._process_copyright(properties, song) + self._process_cclinumber(properties, song) + self._process_titles(properties, song) + # The verse order is processed with the lyrics! + self._process_lyrics(properties, song_xml.lyrics, song) + self._process_comments(properties, song) + self._process_authors(properties, song) + self._process_songbooks(properties, song) + self._process_topics(properties, song) self.manager.save_object(song) return song.id @@ -367,13 +297,6 @@ class OpenLyricsParser(object): parent.append(element) return element - def _dump_xml(self, xml): - """ - Debugging aid to dump XML so that we can see what we have. - """ - return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=True) - def _extract_xml(self, xml): """ Extract our newly created XML song. @@ -381,19 +304,251 @@ class OpenLyricsParser(object): return etree.tostring(xml, encoding=u'UTF-8', xml_declaration=True) - def _process_author(self, name, song): + def _get(self, element, attribute): """ - Find or create an Author from display_name. + This returns the element's attribute as unicode string. + + ``element`` + The element. + + ``attribute`` + The element's attribute (unicode). """ - name = unicode(name) - author = self.manager.get_object_filtered(Author, - Author.display_name == name) - if author: - # should only be one! so take the first + if element.get(attribute) is not None: + return unicode(element.get(attribute)) + return u'' + + def _text(self, element): + """ + This returns the text of an element as unicode string. + + ``element`` + The element. + """ + if element.text is not None: + return unicode(element.text) + return u'' + + def _process_authors(self, properties, song): + """ + Adds the authors specified in the XML to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + authors = [] + try: + for author in properties.authors.author: + display_name = self._text(author) + if display_name: + authors.append(display_name) + except AttributeError: + pass + if not authors: + # Add "Author unknown" (can be translated). + authors.append((unicode(translate('SongsPlugin.XML', + 'Author unknown')))) + for display_name in authors: + author = self.manager.get_object_filtered(Author, + Author.display_name == display_name) + if author is None: + # We need to create a new author, as the author does not exist. + author = Author.populate(display_name=display_name, + last_name=display_name.split(u' ')[-1], + first_name=u' '.join(display_name.split(u' ')[:-1])) + self.manager.save_object(author) song.authors.append(author) - else: - # Need a new author - new_author = Author.populate(first_name=name.rsplit(u' ', 1)[0], - last_name=name.rsplit(u' ', 1)[1], display_name=name) - self.manager.save_object(new_author) - song.authors.append(new_author) \ No newline at end of file + + def _process_cclinumber(self, properties, song): + """ + Adds the CCLI number to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + song.ccli_number = self._text(properties.ccliNo) + except AttributeError: + song.ccli_number = u'' + + def _process_comments(self, properties, song): + """ + Joins the comments specified in the XML and add it to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + comments_list = [] + for comment in properties.comments.comment: + commenttext = self._text(comment) + if commenttext: + comments_list.append(commenttext) + song.comments = u'\n'.join(comments_list) + except AttributeError: + song.comments = u'' + + def _process_copyright(self, properties, song): + """ + Adds the copyright to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + song.copyright = self._text(properties.copyright) + except AttributeError: + song.copyright = u'' + + def _process_lyrics(self, properties, lyrics, song): + """ + Processes the verses and search_lyrics for the song. + + ``properties`` + The properties object (lxml.objectify.ObjectifiedElement). + + ``lyrics`` + The lyrics object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + sxml = SongXML() + search_text = u'' + temp_verse_order = [] + for verse in lyrics.verse: + text = u'' + for lines in verse.lines: + if text: + text += u'\n' + text += u'\n'.join([unicode(line) for line in lines.line]) + verse_name = self._get(verse, u'name') + verse_type = unicode(VerseType.expand_string(verse_name[0]))[0] + verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name) + verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:]) + # OpenLyrics allows e. g. "c", but we need "c1". + if not verse_number: + verse_number = u'1' + temp_verse_order.append((verse_type, verse_number, verse_part)) + sxml.add_verse_to_lyrics(verse_type, verse_number, text) + search_text = search_text + text + song.search_lyrics = search_text.lower() + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + # Process verse order + try: + song.verse_order = self._text(properties.verseOrder) + except AttributeError: + # We have to process the temp_verse_order, as the verseOrder + # property is not present. + previous_type = u'' + previous_number = u'' + previous_part = u'' + verse_order = [] + # Currently we do not support different "parts"! + for name in temp_verse_order: + if name[0] == previous_type: + if name[1] != previous_number: + verse_order.append(u''.join((name[0], name[1]))) + else: + verse_order.append(u''.join((name[0], name[1]))) + previous_type = name[0] + previous_number = name[1] + previous_part = name[2] + song.verse_order = u' '.join(verse_order) + + def _process_songbooks(self, properties, song): + """ + Adds the song book and song number specified in the XML to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + song.song_book_id = 0 + song.song_number = u'' + try: + for songbook in properties.songbooks.songbook: + bookname = self._get(songbook, u'name') + if bookname: + book = self.manager.get_object_filtered(Book, + Book.name == bookname) + if book is None: + # We need to create a book, because it does not exist. + book = Book.populate(name=bookname, publisher=u'') + self.manager.save_object(book) + song.song_book_id = book.id + try: + if self._get(songbook, u'entry'): + song.song_number = self._get(songbook, u'entry') + except AttributeError: + pass + # We only support one song book, so take the first one. + break + except AttributeError: + pass + + def _process_titles(self, properties, song): + """ + Processes the titles specified in the song's XML. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + for title in properties.titles.title: + if not song.title: + song.title = self._text(title) + song.search_title = unicode(song.title) + song.alternate_title = u'' + else: + song.alternate_title = self._text(title) + song.search_title += u'@' + song.alternate_title + song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', + unicode(song.search_title)).lower() + + def _process_topics(self, properties, song): + """ + Adds the topics to the song. + + ``properties`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + for topictext in properties.themes.theme: + topictext = self._text(topictext) + if topictext: + topic = self.manager.get_object_filtered(Topic, + Topic.name == topictext) + if topic is None: + # We need to create a topic, because it does not exist. + topic = Topic.populate(name=topictext) + self.manager.save_object(topic) + song.topics.append(topic) + except AttributeError: + pass + + def _dump_xml(self, xml): + """ + Debugging aid to dump XML so that we can see what we have. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True, pretty_print=True) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 545497acb..17e609fd4 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager -from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXMLParser +from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.importer import SongFormat @@ -153,7 +153,7 @@ class SongsPlugin(Plugin): song.search_title = self.whitespace.sub(u' ', song.title.lower() + \ u' ' + song.alternate_title.lower()) lyrics = u'' - verses = SongXMLParser(song.lyrics).get_verses() + verses = SongXML().get_verses(song.lyrics) for verse in verses: lyrics = lyrics + self.whitespace.sub(u' ', verse[1]) + u' ' song.search_lyrics = lyrics.lower()