diff --git a/documentation/manual.txt b/documentation/manual.txt new file mode 100644 index 000000000..55a3f7d98 --- /dev/null +++ b/documentation/manual.txt @@ -0,0 +1,7 @@ +OpenLP Manual +============= + +If you're reading this file, you're probably looking for the OpenLP manual. The +manual is hosted online at http://manual.openlp.org/. If you want to help with +the manual, contact the OpenLP team via IRC in the #openlp.org channel on the +Freenode network. diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index e51271624..3b7f633d9 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -32,7 +32,7 @@ import os from PyQt4 import QtCore from sqlalchemy import create_engine, MetaData -from sqlalchemy.exceptions import InvalidRequestError +from sqlalchemy.exc import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.pool import NullPool diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 61cc6af73..6a5a753f3 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -179,7 +179,7 @@ class Ui_MainWindow(object): u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')], self.serviceManagerContents.printServiceOrder, category=UiStrings().File) - self.fileExitItem = shortcut_action(mainWindow, u'FileExitItem', + self.fileExitItem = shortcut_action(mainWindow, u'fileExitItem', [QtGui.QKeySequence(u'Alt+F4')], mainWindow.close, u':/system/system_exit.png', category=UiStrings().File) action_list.add_category(UiStrings().Import, CategoryOrder.standardMenu) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 08e1c0366..97ee61114 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -66,7 +66,7 @@ class SlideController(QtGui.QWidget): float(self.screens.current[u'size'].height()) self.image_manager = self.parent.image_manager self.loopList = [ - u'Start Loop', + u'Play Slides Menu', u'Loop Separator', u'Image SpinBox' ] @@ -153,6 +153,7 @@ class SlideController(QtGui.QWidget): context=QtCore.Qt.WidgetWithChildrenShortcut) self.toolbar.addToolbarSeparator(u'Close Separator') if self.isLive: + # Hide Menu self.hideMenu = QtGui.QToolButton(self.toolbar) self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide')) self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) @@ -180,27 +181,34 @@ class SlideController(QtGui.QWidget): self.hideMenu.menu().addAction(self.themeScreen) self.hideMenu.menu().addAction(self.desktopScreen) self.toolbar.addToolbarSeparator(u'Loop Separator') - startLoop = self.toolbar.addToolbarButton( - # Does not need translating - control string. - u'Start Loop', u':/media/media_time.png', - translate('OpenLP.SlideController', 'Enable timed slides.'), - self.onStartLoop) - startLoop.setObjectName(u'startLoop') - action_list = ActionList.get_instance() - action_list.add_action(startLoop, UiStrings().LiveToolbar) - stopLoop = self.toolbar.addToolbarButton( - # Does not need translating - control string. - u'Stop Loop', u':/media/media_stop.png', - translate('OpenLP.SlideController', 'Stop timed slides.'), - self.onStopLoop) - stopLoop.setObjectName(u'stopLoop') - action_list.add_action(stopLoop, UiStrings().LiveToolbar) - self.toogleLoop = shortcut_action(self, u'toogleLoop', - [QtGui.QKeySequence(u'L')], self.onToggleLoop, - category=UiStrings().LiveToolbar) - self.toogleLoop.setText(translate('OpenLP.SlideController', - 'Start/Stop continuous loop')) - self.addAction(self.toogleLoop) + # Play Slides Menu + self.playSlidesMenu = QtGui.QToolButton(self.toolbar) + self.playSlidesMenu.setText(translate('OpenLP.SlideController', + 'Play Slides')) + self.playSlidesMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) + self.toolbar.addToolbarWidget(u'Play Slides Menu', + self.playSlidesMenu) + self.playSlidesMenu.setMenu(QtGui.QMenu( + translate('OpenLP.SlideController', 'Play Slides'), + self.toolbar)) + self.playSlidesLoop = shortcut_action(self.playSlidesMenu, + u'playSlidesLoop', [], self.onPlaySlidesLoop, + u':/media/media_time.png', False, UiStrings().LiveToolbar) + self.playSlidesLoop.setText( + translate('OpenLP.SlideController', 'Play Slides in Loop')) + self.playSlidesOnce = shortcut_action(self.playSlidesMenu, + u'playSlidesOnce', [], self.onPlaySlidesOnce, + u':/media/media_time.png', False, UiStrings().LiveToolbar) + self.playSlidesOnce.setText( + translate('OpenLP.SlideController', 'Play Slides to End')) + if QtCore.QSettings().value(self.parent.generalSettingsSection + + u'/enable slide loop', QtCore.QVariant(True)).toBool(): + self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) + else: + self.playSlidesMenu.setDefaultAction(self.playSlidesOnce) + self.playSlidesMenu.menu().addAction(self.playSlidesLoop) + self.playSlidesMenu.menu().addAction(self.playSlidesOnce) + # Loop Delay Spinbox self.delaySpinBox = QtGui.QSpinBox() self.delaySpinBox.setRange(1, 180) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) @@ -321,7 +329,6 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), self.receiveSpinDelay) self.toolbar.makeWidgetsInvisible(self.loopList) - self.toolbar.actions[u'Stop Loop'].setVisible(False) else: QtCore.QObject.connect(self.previewListWidget, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), @@ -496,10 +503,6 @@ class SlideController(QtGui.QWidget): self.mediabar.setVisible(False) self.toolbar.makeWidgetsInvisible([u'Song Menu']) self.toolbar.makeWidgetsInvisible(self.loopList) - self.toogleLoop.setEnabled(False) - self.toolbar.actions[u'Start Loop'].setEnabled(False) - self.toolbar.actions[u'Stop Loop'].setEnabled(False) - self.toolbar.actions[u'Stop Loop'].setVisible(False) if item.is_text(): if QtCore.QSettings().value( self.parent.songsSettingsSection + u'/display songbar', @@ -508,9 +511,6 @@ class SlideController(QtGui.QWidget): if item.is_capable(ItemCapabilities.AllowsLoop) and \ len(item.get_frames()) > 1: self.toolbar.makeWidgetsVisible(self.loopList) - self.toogleLoop.setEnabled(True) - self.toolbar.actions[u'Start Loop'].setEnabled(True) - self.toolbar.actions[u'Stop Loop'].setEnabled(True) if item.is_media(): self.toolbar.setVisible(False) self.mediabar.setVisible(True) @@ -841,6 +841,11 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive]) + else: + if hide_mode: + Receiver.send_message(u'maindisplay_hide', hide_mode) + else: + Receiver.send_message(u'maindisplay_show') def hidePlugin(self, hide): """ @@ -859,6 +864,11 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive]) + else: + if hide: + Receiver.send_message(u'maindisplay_hide', HideMode.Screen) + else: + Receiver.send_message(u'maindisplay_show') def onSlideSelected(self, start=False): """ @@ -933,7 +943,7 @@ class SlideController(QtGui.QWidget): rect.y(), rect.width(), rect.height()) self.slidePreview.setPixmap(winimg) - def onSlideSelectedNext(self): + def onSlideSelectedNext(self, wrap=None): """ Go to the next slide. """ @@ -946,8 +956,11 @@ class SlideController(QtGui.QWidget): else: row = self.previewListWidget.currentRow() + 1 if row == self.previewListWidget.rowCount(): - if QtCore.QSettings().value(self.parent.generalSettingsSection + - u'/enable slide loop', QtCore.QVariant(True)).toBool(): + if wrap is None: + wrap = QtCore.QSettings().value( + self.parent.generalSettingsSection + + u'/enable slide loop', QtCore.QVariant(True)).toBool() + if wrap: row = 0 else: row = self.previewListWidget.rowCount() - 1 @@ -996,11 +1009,11 @@ class SlideController(QtGui.QWidget): self.previewListWidget.rowCount() - 1) self.slideSelected() - def onToggleLoop(self, toggled): + def onToggleLoop(self): """ Toggles the loop state. """ - if self.toolbar.actions[u'Start Loop'].isVisible(): + if self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked(): self.onStartLoop() else: self.onStopLoop() @@ -1012,8 +1025,6 @@ class SlideController(QtGui.QWidget): if self.previewListWidget.rowCount() > 1: self.timer_id = self.startTimer( int(self.delaySpinBox.value()) * 1000) - self.toolbar.actions[u'Stop Loop'].setVisible(True) - self.toolbar.actions[u'Start Loop'].setVisible(False) def onStopLoop(self): """ @@ -1022,15 +1033,39 @@ class SlideController(QtGui.QWidget): if self.timer_id != 0: self.killTimer(self.timer_id) self.timer_id = 0 - self.toolbar.actions[u'Start Loop'].setVisible(True) - self.toolbar.actions[u'Stop Loop'].setVisible(False) + + def onPlaySlidesLoop(self, checked=None): + """ + Start or stop 'Play Slides in Loop' + """ + if checked is None: + checked = self.playSlidesLoop.isChecked() + else: + self.playSlidesLoop.setChecked(checked) + log.debug(u'onPlaySlidesLoop %s' % checked) + self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) + self.playSlidesOnce.setChecked(False) + self.onToggleLoop() + + def onPlaySlidesOnce(self, checked=None): + """ + Start or stop 'Play Slides to End' + """ + if checked is None: + checked = self.playSlidesOnce.isChecked() + else: + self.playSlidesOnce.setChecked(checked) + log.debug(u'onPlaySlidesOnce %s' % checked) + self.playSlidesMenu.setDefaultAction(self.playSlidesOnce) + self.playSlidesLoop.setChecked(False) + self.onToggleLoop() def timerEvent(self, event): """ If the timer event is for this window select next slide """ if event.timerId() == self.timer_id: - self.onSlideSelectedNext() + self.onSlideSelectedNext(self.playSlidesLoop.isChecked()) def onEditSong(self): """ diff --git a/openlp/plugins/bibles/forms/bibleupgradeform.py b/openlp/plugins/bibles/forms/bibleupgradeform.py index bd9a3172d..0fdcdfd11 100644 --- a/openlp/plugins/bibles/forms/bibleupgradeform.py +++ b/openlp/plugins/bibles/forms/bibleupgradeform.py @@ -29,6 +29,7 @@ The bible import functions for OpenLP import logging import os.path import re +import shutil from PyQt4 import QtCore, QtGui @@ -133,6 +134,38 @@ class BibleUpgradeForm(OpenLPWizard): if number in self.success and self.success[number] == True: delete_file(os.path.join(self.path, filename[0])) + def onBackupBrowseButtonClicked(self): + """ + Show the file open dialog for the OSIS file. + """ + filename = QtGui.QFileDialog.getExistingDirectory(self, translate( + 'BiblesPlugin.UpgradeWizardForm', 'Select a Backup Directory'), + os.path.dirname(SettingsManager.get_last_dir( + self.plugin.settingsSection, 1))) + if filename: + self.backupDirectoryEdit.setText(filename) + SettingsManager.set_last_dir(self.plugin.settingsSection, + filename, 1) + + def onNoBackupCheckBoxToggled(self, checked): + """ + Enable or disable the backup directory widgets. + """ + self.backupDirectoryEdit.setEnabled(not checked) + self.backupBrowseButton.setEnabled(not checked) + + def backupOldBibles(self, backupdirectory): + """ + Backup old bible databases in a given folder. + """ + for filename in self.files: + try: + shutil.copy(os.path.join(self.path, filename[0]), + backupdirectory) + except: + return False + return True + def customInit(self): """ Perform any custom initialisation for bible upgrading. @@ -146,11 +179,54 @@ class BibleUpgradeForm(OpenLPWizard): """ QtCore.QObject.connect(self.finishButton, QtCore.SIGNAL(u'clicked()'), self.onFinishButton) + QtCore.QObject.connect(self.backupBrowseButton, + QtCore.SIGNAL(u'clicked()'), self.onBackupBrowseButtonClicked) + QtCore.QObject.connect(self.noBackupCheckBox, + QtCore.SIGNAL(u'toggled(bool)'), self.onNoBackupCheckBoxToggled) def addCustomPages(self): """ Add the bible import specific wizard pages. """ + # Backup Page + self.backupPage = QtGui.QWizardPage() + self.backupPage.setObjectName(u'BackupPage') + self.backupLayout = QtGui.QVBoxLayout(self.backupPage) + self.backupLayout.setObjectName(u'BackupLayout') + self.backupInfoLabel = QtGui.QLabel(self.backupPage) + self.backupInfoLabel.setOpenExternalLinks(True) + self.backupInfoLabel.setTextFormat(QtCore.Qt.RichText) + self.backupInfoLabel.setWordWrap(True) + self.backupInfoLabel.setObjectName(u'backupInfoLabel') + self.backupLayout.addWidget(self.backupInfoLabel) + self.selectLabel = QtGui.QLabel(self.backupPage) + self.selectLabel.setObjectName(u'selectLabel') + self.backupLayout.addWidget(self.selectLabel) + self.formLayout = QtGui.QFormLayout() + self.formLayout.setMargin(0) + self.formLayout.setObjectName(u'FormLayout') + self.backupDirectoryLabel = QtGui.QLabel(self.backupPage) + self.backupDirectoryLabel.setObjectName(u'backupDirectoryLabel') + self.backupDirectoryLayout = QtGui.QHBoxLayout() + self.backupDirectoryLayout.setObjectName(u'BackupDirectoryLayout') + self.backupDirectoryEdit = QtGui.QLineEdit(self.backupPage) + self.backupDirectoryEdit.setObjectName(u'BackupFolderEdit') + self.backupDirectoryLayout.addWidget(self.backupDirectoryEdit) + self.backupBrowseButton = QtGui.QToolButton(self.backupPage) + self.backupBrowseButton.setIcon(self.openIcon) + self.backupBrowseButton.setObjectName(u'BackupBrowseButton') + self.backupDirectoryLayout.addWidget(self.backupBrowseButton) + self.formLayout.addRow(self.backupDirectoryLabel, + self.backupDirectoryLayout) + self.backupLayout.addLayout(self.formLayout) + self.noBackupCheckBox = QtGui.QCheckBox(self.backupPage) + self.noBackupCheckBox.setObjectName('NoBackupCheckBox') + self.backupLayout.addWidget(self.noBackupCheckBox) + self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Minimum) + self.backupLayout.addItem(self.spacer) + self.addPage(self.backupPage) + # Select Page self.selectPage = QtGui.QWizardPage() self.selectPage.setObjectName(u'SelectPage') self.pageLayout = QtGui.QVBoxLayout(self.selectPage) @@ -289,7 +365,27 @@ class BibleUpgradeForm(OpenLPWizard): translate('BiblesPlugin.UpgradeWizardForm', 'This wizard will help you to upgrade your existing Bibles from a ' 'prior version of OpenLP 2. Click the next button below to start ' - 'the process by selecting the Bibles to upgrade.')) + 'the upgrade process.')) + self.backupPage.setTitle( + translate('BiblesPlugin.UpgradeWizardForm', + 'Select Backup Directory')) + self.backupPage.setSubTitle( + translate('BiblesPlugin.UpgradeWizardForm', + 'Please select a backup directory for your Bibles')) + self.backupInfoLabel.setText(translate('BiblesPlugin.UpgradeWizardForm', + 'Previous releases of OpenLP 2.0 are unable to use upgraded Bibles.' + ' This will create a backup of your current Bibles so that you can ' + 'simply copy the files back to your OpenLP data directory if you ' + 'need to revert to a previous release of OpenLP. Instructions on ' + 'how to restore the files can be found in our Frequently Asked Questions.')) + self.selectLabel.setText(translate('BiblesPlugin.UpgradeWizardForm', + 'Please select a backup location for your Bibles.')) + self.backupDirectoryLabel.setText( + translate('BiblesPlugin.UpgradeWizardForm', 'Backup Directory:')) + self.noBackupCheckBox.setText( + translate('BiblesPlugin.UpgradeWizardForm', + 'There is no need to backup my Bibles')) self.selectPage.setTitle( translate('BiblesPlugin.UpgradeWizardForm', 'Select Bibles')) @@ -316,6 +412,33 @@ class BibleUpgradeForm(OpenLPWizard): """ if self.currentPage() == self.welcomePage: return True + elif self.currentPage() == self.backupPage: + if not self.noBackupCheckBox.checkState() == QtCore.Qt.Checked: + if not unicode(self.backupDirectoryEdit.text()): + critical_error_message_box(UiStrings().EmptyField, + translate('BiblesPlugin.UpgradeWizardForm', + 'You need to specify a Backup Directory for your ' + 'Bibles.')) + self.backupDirectoryEdit.setFocus() + return False + elif not os.path.exists(unicode( + self.backupDirectoryEdit.text())): + critical_error_message_box(UiStrings().Error, + translate('BiblesPlugin.UpgradeWizardForm', + 'The given path is not an existing directory.')) + self.backupDirectoryEdit.setFocus() + return False + else: + if not self.backupOldBibles(unicode( + self.backupDirectoryEdit.text())): + critical_error_message_box(UiStrings().Error, + translate('BiblesPlugin.UpgradeWizardForm', + 'The backup was not successfull.\nTo backup your ' + 'Bibles you need the permission to write in the given ' + 'directory. If you have a permissions to write and ' + 'this error still occurs, please report a bug.')) + return False + return True elif self.currentPage() == self.selectPage: for number, filename in enumerate(self.files): if not self.checkBox[number].checkState() == QtCore.Qt.Checked: @@ -627,7 +750,6 @@ class BibleUpgradeForm(OpenLPWizard): successful_import = 0 failed_import = 0 for number, filename in enumerate(self.files): - #for number, success in self.success.iteritems(): if number in self.success and self.success[number] == True: successful_import += 1 elif self.checkBox[number].checkState() == QtCore.Qt.Checked: @@ -635,21 +757,21 @@ class BibleUpgradeForm(OpenLPWizard): if failed_import > 0: failed_import_text = unicode(translate( 'BiblesPlugin.UpgradeWizardForm', - ' - %s upgrade fail')) % failed_import + ', %s failed')) % failed_import else: failed_import_text = u'' if successful_import > 0: if include_webbible: self.progressLabel.setText(unicode( - translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade %s ' - 'Bible(s) successful%s.\nPlease note, that verses from ' + translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading ' + 'Bible(s): %s successful%s\nPlease note, that verses from ' 'Web Bibles will be downloaded\non demand and so an ' 'Internet connection is required.')) % (successful_import, failed_import_text)) else: self.progressLabel.setText(unicode( - translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade %s ' - 'Bible(s) successful.%s')) % (successful_import, + translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading ' + 'Bible(s): %s successful%s')) % (successful_import, failed_import_text)) else: self.progressLabel.setText( diff --git a/openlp/plugins/bibles/forms/booknameform.py b/openlp/plugins/bibles/forms/booknameform.py index 8ad3ad977..28e4c9df1 100644 --- a/openlp/plugins/bibles/forms/booknameform.py +++ b/openlp/plugins/bibles/forms/booknameform.py @@ -80,7 +80,6 @@ class BookNameForm(QDialog, Ui_BookNameDialog): Reload the Combobox items ''' self.correspondingComboBox.clear() - self.correspondingComboBox.addItem(u'') items = BiblesResourcesDB.get_books() for item in items: addBook = True diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 9e068e7f1..53b3d7cb1 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -265,52 +265,57 @@ def clean_song(manager, song): whitespace = re.compile(r'\W+', re.UNICODE) song.search_title = (whitespace.sub(u' ', song.title).strip() + u'@' + whitespace.sub(u' ', song.alternate_title).strip()).strip().lower() - # Remove the old "language" attribute from lyrics tag (prior to 1.9.5). This - # is not very important, but this keeps the database clean. This can be - # removed when everybody has cleaned his songs. - song.lyrics = song.lyrics.replace(u'', u'') - verses = SongXML().get_verses(song.lyrics) - lyrics = u' '.join([whitespace.sub(u' ', verse[1]) for verse in verses]) - song.search_lyrics = lyrics.lower() - # We need a new and clean SongXML instance. - sxml = SongXML() - # Rebuild the song's verses, to remove any wrong verse names (for example - # translated ones), which might have been added prior to 1.9.5. - # List for later comparison. - compare_order = [] - for verse in verses: - verse_type = VerseType.Tags[VerseType.from_loose_input( - verse[0][u'type'])] - sxml.add_verse_to_lyrics( - verse_type, - verse[0][u'label'], - verse[1], - verse[0][u'lang'] if verse[0].has_key(u'lang') else None - ) - compare_order.append((u'%s%s' % (verse_type, verse[0][u'label']) - ).upper()) - if verse[0][u'label'] == u'1': - compare_order.append(verse_type.upper()) - song.lyrics = unicode(sxml.extract_xml(), u'utf-8') - # Rebuild the verse order, to convert translated verse tags, which might - # have been added prior to 1.9.5. - if song.verse_order: - order = song.verse_order.strip().split() - else: - order = [] - new_order = [] - for verse_def in order: - verse_type = VerseType.Tags[VerseType.from_loose_input(verse_def[0])] - if len(verse_def) > 1: - new_order.append((u'%s%s' % (verse_type, verse_def[1:])).upper()) + # Only do this, if we the song is a 1.9.4 song (or older). + if song.lyrics.find(u'') != -1: + # Remove the old "language" attribute from lyrics tag (prior to 1.9.5). + # This is not very important, but this keeps the database clean. This + # can be removed when everybody has cleaned his songs. + song.lyrics = song.lyrics.replace( + u'', u'') + verses = SongXML().get_verses(song.lyrics) + lyrics = u' '.join([whitespace.sub(u' ', verse[1]) for verse in verses]) + song.search_lyrics = lyrics.lower() + # We need a new and clean SongXML instance. + sxml = SongXML() + # Rebuild the song's verses, to remove any wrong verse names (for + # example translated ones), which might have been added prior to 1.9.5. + # List for later comparison. + compare_order = [] + for verse in verses: + verse_type = VerseType.Tags[VerseType.from_loose_input( + verse[0][u'type'])] + sxml.add_verse_to_lyrics( + verse_type, + verse[0][u'label'], + verse[1], + verse[0][u'lang'] if verse[0].has_key(u'lang') else None + ) + compare_order.append((u'%s%s' % (verse_type, verse[0][u'label']) + ).upper()) + if verse[0][u'label'] == u'1': + compare_order.append(verse_type.upper()) + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + # Rebuild the verse order, to convert translated verse tags, which might + # have been added prior to 1.9.5. + if song.verse_order: + order = song.verse_order.strip().split() else: - new_order.append(verse_type.upper()) - song.verse_order = u' '.join(new_order) - # Check if the verse order contains tags for verses which do not exist. - for order in new_order: - if order not in compare_order: - song.verse_order = u'' - break + order = [] + new_order = [] + for verse_def in order: + verse_type = VerseType.Tags[ + VerseType.from_loose_input(verse_def[0])] + if len(verse_def) > 1: + new_order.append( + (u'%s%s' % (verse_type, verse_def[1:])).upper()) + else: + new_order.append(verse_type.upper()) + song.verse_order = u' '.join(new_order) + # Check if the verse order contains tags for verses which do not exist. + for order in new_order: + if order not in compare_order: + song.verse_order = u'' + break # The song does not have any author, add one. if not song.authors: name = SongStrings.AuthorUnknown diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 7d05e0add..9a4f6910f 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -62,44 +62,44 @@ class SongUsagePlugin(Plugin): """ log.info(u'add tools menu') self.toolsMenu = tools_menu - self.SongUsageMenu = QtGui.QMenu(tools_menu) - self.SongUsageMenu.setObjectName(u'SongUsageMenu') - self.SongUsageMenu.setTitle(translate( + self.songUsageMenu = QtGui.QMenu(tools_menu) + self.songUsageMenu.setObjectName(u'songUsageMenu') + self.songUsageMenu.setTitle(translate( 'SongUsagePlugin', '&Song Usage Tracking')) # SongUsage Delete - self.SongUsageDelete = base_action(tools_menu, u'SongUsageDelete') - self.SongUsageDelete.setText(translate('SongUsagePlugin', + self.songUsageDelete = base_action(tools_menu, u'songUsageDelete') + self.songUsageDelete.setText(translate('SongUsagePlugin', '&Delete Tracking Data')) - self.SongUsageDelete.setStatusTip(translate('SongUsagePlugin', + self.songUsageDelete.setStatusTip(translate('SongUsagePlugin', 'Delete song usage data up to a specified date.')) # SongUsage Report - self.SongUsageReport = base_action(tools_menu, u'SongUsageReport') - self.SongUsageReport.setText( + self.songUsageReport = base_action(tools_menu, u'songUsageReport') + self.songUsageReport.setText( translate('SongUsagePlugin', '&Extract Tracking Data')) - self.SongUsageReport.setStatusTip( + self.songUsageReport.setStatusTip( translate('SongUsagePlugin', 'Generate a report on song usage.')) # SongUsage activation - self.SongUsageStatus = shortcut_action(tools_menu, u'SongUsageStatus', + self.songUsageStatus = shortcut_action(tools_menu, u'songUsageStatus', [QtCore.Qt.Key_F4], self.toggleSongUsageState, checked=False) - self.SongUsageStatus.setText(translate( + self.songUsageStatus.setText(translate( 'SongUsagePlugin', 'Toggle Tracking')) - self.SongUsageStatus.setStatusTip(translate('SongUsagePlugin', + self.songUsageStatus.setStatusTip(translate('SongUsagePlugin', 'Toggle the tracking of song usage.')) #Add Menus together - self.toolsMenu.addAction(self.SongUsageMenu.menuAction()) - self.SongUsageMenu.addAction(self.SongUsageStatus) - self.SongUsageMenu.addSeparator() - self.SongUsageMenu.addAction(self.SongUsageDelete) - self.SongUsageMenu.addAction(self.SongUsageReport) + self.toolsMenu.addAction(self.songUsageMenu.menuAction()) + self.songUsageMenu.addAction(self.songUsageStatus) + self.songUsageMenu.addSeparator() + self.songUsageMenu.addAction(self.songUsageDelete) + self.songUsageMenu.addAction(self.songUsageReport) # Signals and slots - QtCore.QObject.connect(self.SongUsageStatus, + QtCore.QObject.connect(self.songUsageStatus, QtCore.SIGNAL(u'visibilityChanged(bool)'), - self.SongUsageStatus.setChecked) - QtCore.QObject.connect(self.SongUsageDelete, + self.songUsageStatus.setChecked) + QtCore.QObject.connect(self.songUsageDelete, QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete) - QtCore.QObject.connect(self.SongUsageReport, + QtCore.QObject.connect(self.songUsageReport, QtCore.SIGNAL(u'triggered()'), self.onSongUsageReport) - self.SongUsageMenu.menuAction().setVisible(False) + self.songUsageMenu.menuAction().setVisible(False) def initialise(self): log.info(u'SongUsage Initialising') @@ -110,20 +110,20 @@ class SongUsagePlugin(Plugin): self.SongUsageActive = QtCore.QSettings().value( self.settingsSection + u'/active', QtCore.QVariant(False)).toBool() - self.SongUsageStatus.setChecked(self.SongUsageActive) + self.songUsageStatus.setChecked(self.SongUsageActive) action_list = ActionList.get_instance() - action_list.add_action(self.SongUsageDelete, + action_list.add_action(self.songUsageDelete, translate('SongUsagePlugin', 'Song Usage')) - action_list.add_action(self.SongUsageReport, + action_list.add_action(self.songUsageReport, translate('SongUsagePlugin', 'Song Usage')) - action_list.add_action(self.SongUsageStatus, + action_list.add_action(self.songUsageStatus, translate('SongUsagePlugin', 'Song Usage')) if self.manager is None: self.manager = Manager(u'songusage', init_schema) - self.SongUsagedeleteform = SongUsageDeleteForm(self.manager, + self.songUsageDeleteForm = SongUsageDeleteForm(self.manager, self.formparent) - self.SongUsagedetailform = SongUsageDetailForm(self, self.formparent) - self.SongUsageMenu.menuAction().setVisible(True) + self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent) + self.songUsageMenu.menuAction().setVisible(True) def finalise(self): """ @@ -132,13 +132,13 @@ class SongUsagePlugin(Plugin): log.info(u'Plugin Finalise') self.manager.finalise() Plugin.finalise(self) - self.SongUsageMenu.menuAction().setVisible(False) + self.songUsageMenu.menuAction().setVisible(False) action_list = ActionList.get_instance() - action_list.remove_action(self.SongUsageDelete, + action_list.remove_action(self.songUsageDelete, translate('SongUsagePlugin', 'Song Usage')) - action_list.remove_action(self.SongUsageReport, + action_list.remove_action(self.songUsageReport, translate('SongUsagePlugin', 'Song Usage')) - action_list.remove_action(self.SongUsageStatus, + action_list.remove_action(self.songUsageStatus, translate('SongUsagePlugin', 'Song Usage')) #stop any events being processed self.SongUsageActive = False @@ -160,17 +160,15 @@ class SongUsagePlugin(Plugin): song_usage_item.title = audit[0] song_usage_item.copyright = audit[2] song_usage_item.ccl_number = audit[3] - song_usage_item.authors = u'' - for author in audit[1]: - song_usage_item.authors += author + u' ' + song_usage_item.authors = u' '.join(audit[1]) self.manager.save_object(song_usage_item) def onSongUsageDelete(self): - self.SongUsagedeleteform.exec_() + self.songUsageDeleteForm.exec_() def onSongUsageReport(self): - self.SongUsagedetailform.initialise() - self.SongUsagedetailform.exec_() + self.songUsageDetailForm.initialise() + self.songUsageDetailForm.exec_() def about(self): about_text = translate('SongUsagePlugin', 'SongUsage Plugin'