From 599ee1f7fa75feef878e4507445f91ade4df14d0 Mon Sep 17 00:00:00 2001 From: M2j Date: Fri, 31 Dec 2010 03:17:41 +0100 Subject: [PATCH 1/6] Lots of i18n fixes and some others. In detail: translate() expanded for numbered strings MediaManager context menus are using the plugins strings instead of own string manipulations Removed string manipulations from ThemeManager and fixed the delete validation Added disambiguation for some plugin strings to distinguish between name plural and container title Added or repaired translate() calls at several positions. --- openlp/core/lib/__init__.py | 7 +-- openlp/core/lib/mediamanageritem.py | 16 +++---- openlp/core/ui/exceptionform.py | 6 ++- openlp/core/ui/generaltab.py | 10 ++--- openlp/core/ui/themeform.py | 8 ++-- openlp/core/ui/thememanager.py | 36 ++++++++------- openlp/plugins/alerts/alertsplugin.py | 8 ++-- openlp/plugins/bibles/bibleplugin.py | 45 +++++++++---------- openlp/plugins/bibles/lib/csvbible.py | 9 ++-- openlp/plugins/bibles/lib/mediaitem.py | 4 +- openlp/plugins/bibles/lib/openlp1.py | 6 +-- openlp/plugins/bibles/lib/opensong.py | 9 ++-- openlp/plugins/bibles/lib/osis.py | 9 ++-- openlp/plugins/custom/customplugin.py | 24 +++++----- openlp/plugins/images/imageplugin.py | 8 ++-- openlp/plugins/images/lib/mediaitem.py | 4 +- openlp/plugins/media/lib/mediaitem.py | 9 ++-- openlp/plugins/media/mediaplugin.py | 22 ++++----- openlp/plugins/presentations/lib/mediaitem.py | 6 +-- .../presentations/presentationplugin.py | 21 +++++---- openlp/plugins/remotes/remoteplugin.py | 8 ++-- .../songs/forms/songmaintenanceform.py | 41 ++++++++--------- openlp/plugins/songs/lib/cclifileimport.py | 8 ++-- openlp/plugins/songs/lib/mediaitem.py | 15 +++---- openlp/plugins/songs/lib/olpimport.py | 8 ++-- openlp/plugins/songs/lib/songbeamerimport.py | 14 +++--- openlp/plugins/songs/songsplugin.py | 20 ++++----- .../songusage/forms/songusagedetailform.py | 5 ++- openlp/plugins/songusage/songusageplugin.py | 11 +++-- 29 files changed, 201 insertions(+), 196 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 99255c6ee..ebbe31597 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -84,7 +84,8 @@ html_expands.append({u'desc': u'Underline', u'start tag': u'{u}', u'start html': u'', u'end tag': u'{/u}', u'end html': u'', u'protected': True}) -def translate(context, text, comment=None): +def translate(context, text, comment=None, + encoding=QtCore.QCoreApplication.CodecForTr, n=-1): """ A special shortcut method to wrap around the Qt4 translation functions. This abstracts the translation procedure so that we can change it if at a @@ -101,7 +102,7 @@ def translate(context, text, comment=None): An identifying string for when the same text is used in different roles within the same context. """ - return QtCore.QCoreApplication.translate(context, text, comment) + return QtCore.QCoreApplication.translate(context, text, comment, encoding, n) def get_text_file_string(text_file): """ @@ -325,4 +326,4 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from baselistwithdnd import BaseListWithDnD \ No newline at end of file +from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 50e43afd0..7991135f7 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -284,34 +284,30 @@ class MediaManagerItem(QtGui.QWidget): self.listView.addAction( context_menu_action( self.listView, u':/general/general_edit.png', - unicode(translate('OpenLP.MediaManagerItem', '&Edit %s')) % - name_string[u'singular'], + self.plugin.getString(StringContent.Edit)[u'title'], self.onEditClick)) self.listView.addAction(context_menu_separator(self.listView)) if self.hasDeleteIcon: self.listView.addAction( context_menu_action( self.listView, u':/general/general_delete.png', - unicode(translate('OpenLP.MediaManagerItem', - '&Delete %s')) % - name_string[u'singular'], + self.plugin.getString(StringContent.Delete)[u'title'], self.onDeleteClick)) self.listView.addAction(context_menu_separator(self.listView)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_preview.png', - unicode(translate('OpenLP.MediaManagerItem', '&Preview %s')) % - name_string[u'singular'], + self.plugin.getString(StringContent.Preview)[u'title'], self.onPreviewClick)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_live.png', - translate('OpenLP.MediaManagerItem', '&Show Live'), + self.plugin.getString(StringContent.Live)[u'title'], self.onLiveClick)) self.listView.addAction( context_menu_action( self.listView, u':/general/general_add.png', - translate('OpenLP.MediaManagerItem', '&Add to Service'), + self.plugin.getString(StringContent.Service)[u'title'], self.onAddClick)) if self.addToServiceItem: self.listView.addAction( @@ -544,4 +540,4 @@ class MediaManagerItem(QtGui.QWidget): Method to add processing when a service has been loaded and individual service items need to be processed by the plugins """ - pass \ No newline at end of file + pass diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index 90a54e12e..3272c7af9 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -135,7 +135,9 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): '--- Please enter the report below this line. ---\n\n\n' '--- Exception Traceback ---\n%s\n' '--- System information ---\n%s\n' - '--- Library Versions ---\n%s\n')) + '--- Library Versions ---\n%s\n', + 'Please add the information that bug reports are favoured written ' + 'in English.')) content = self._createReport() for line in content[1].split(u'\n'): if re.search(r'[/\\]openlp[/\\]', line): @@ -144,4 +146,4 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): exception = line.split(u'\n')[-1].split(u':')[0] subject = u'Bug report: %s in %s' % (exception, source) mailto(address=u'bugs@openlp.org', subject=subject, - body=body % content) \ No newline at end of file + body=body % content) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 8c56648c8..6d98d0858 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -389,11 +389,11 @@ class GeneralTab(SettingsTab): settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) for screen in self.screens.screen_list: - screen_name = u'%s %d' % (translate('OpenLP.GeneralTab', 'Screen'), - screen[u'number'] + 1) + screen_name = unicode(translate('OpenLP.GeneralTab', 'Screen %d')) \ + % (screen[u'number'] + 1) if screen[u'primary']: - screen_name = u'%s (%s)' % (screen_name, - translate('OpenLP.GeneralTab', 'primary')) + screen_name = unicode(translate('OpenLP.GeneralTab', + '%s (primary)')) % screen_name self.monitorComboBox.addItem(screen_name) self.numberEdit.setText(unicode(settings.value( u'ccli number', QtCore.QVariant(u'')).toString())) @@ -530,4 +530,4 @@ class GeneralTab(SettingsTab): """ Called when the width, height, x position or y position has changed. """ - self.overrideChanged = True \ No newline at end of file + self.overrideChanged = True diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index c7854e187..44720cbcc 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -586,8 +586,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeForm', 'Theme Name Missing'), translate('OpenLP.ThemeForm', - 'There is no name for this theme. ' - 'Please enter one.'), + 'There is no name for this theme. Please enter one.'), (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) return @@ -595,8 +594,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeForm', 'Theme Name Invalid'), translate('OpenLP.ThemeForm', - 'Invalid theme name. ' - 'Please enter one.'), + 'Invalid theme name. Please enter one.'), (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) return @@ -620,4 +618,4 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtGui.QColor(field), self) if new_color.isValid(): field = new_color.name() - return field \ No newline at end of file + return field diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 82d7c4b0e..584edf909 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -223,8 +223,11 @@ class ThemeManager(QtGui.QWidget): """ Renames an existing theme to a new name """ - action = unicode(translate('OpenLP.ThemeManager', 'Rename')) - if self._validate_theme_action(action, False): + if self._validate_theme_action(unicode(translate('OpenLP.ThemeManager', + 'You must select a theme to rename.')), + unicode(translate('OpenLP.ThemeManager', 'Rename Confirmation')), + unicode(translate('OpenLP.ThemeManager', 'Rename %s theme?')), + False): item = self.themeListWidget.currentItem() oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) self.fileRenameForm.fileNameEdit.setText(oldThemeName) @@ -288,8 +291,10 @@ class ThemeManager(QtGui.QWidget): """ Delete a theme """ - action = unicode(translate('OpenLP.ThemeManager', 'Delete')) - if self._validate_theme_action(action): + if self._validate_theme_action(unicode(translate('OpenLP.ThemeManager', + 'You must select a theme to delete.')), + unicode(translate('OpenLP.ThemeManager', 'Delete Confirmation')), + unicode(translate('OpenLP.ThemeManager', 'Delete %s theme?'))): item = self.themeListWidget.currentItem() theme = unicode(item.text()) row = self.themeListWidget.row(item) @@ -750,7 +755,8 @@ class ThemeManager(QtGui.QWidget): theme.extend_image_filename(path) return theme - def _validate_theme_action(self, action, testPlugin=True): + def _validate_theme_action(self, select_text, confirm_title, confirm_text, + testPlugin=True): """ Check to see if theme has been selected and the destructive action is allowed. @@ -758,19 +764,14 @@ class ThemeManager(QtGui.QWidget): self.global_theme = unicode(QtCore.QSettings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) - if check_item_selected(self.themeListWidget, - unicode(translate('OpenLP.ThemeManager', - 'You must select a theme to %s.')) % action): + if check_item_selected(self.themeListWidget, select_text): item = self.themeListWidget.currentItem() theme = unicode(item.text()) # confirm deletion - answer = QtGui.QMessageBox.question(self, - unicode(translate('OpenLP.ThemeManager', '%s Confirmation')) - % action, - unicode(translate('OpenLP.ThemeManager', '%s %s theme?')) - % (action, theme), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), QtGui.QMessageBox.No) + answer = QtGui.QMessageBox.question(self, confirm_title, + confirm_text % theme, QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), + QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: return False # should be the same unless default @@ -779,6 +780,7 @@ class ThemeManager(QtGui.QWidget): translate('OpenLP.ThemeManager', 'Error'), translate('OpenLP.ThemeManager', 'You are unable to delete the default theme.')) + return False else: if testPlugin: for plugin in self.parent.pluginManager.plugins: @@ -795,4 +797,6 @@ class ThemeManager(QtGui.QWidget): unicode(translate('OpenLP.ThemeManager', 'Theme %s is used by the service manager.')) % theme) return False - return True \ No newline at end of file + else: + return False + return True diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 277a3903a..4a7e18cef 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -114,10 +114,10 @@ class AlertsPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('AlertsPlugin', 'Alert'), - u'plural': translate('AlertsPlugin', 'Alerts') + u'singular': translate('AlertsPlugin', 'Alert', 'name singular'), + u'plural': translate('AlertsPlugin', 'Alerts', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('AlertsPlugin', 'Alerts') - } \ No newline at end of file + u'title': translate('AlertsPlugin', 'Alerts', 'container title') + } diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 3e8dc82ee..15181e871 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -126,53 +126,48 @@ class BiblePlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('BiblesPlugin', 'Bible'), - u'plural': translate('BiblesPlugin', 'Bibles') + u'singular': translate('BiblesPlugin', 'Bible', 'name singular'), + u'plural': translate('BiblesPlugin', 'Bibles', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('BiblesPlugin', 'Bibles') + u'title': translate('BiblesPlugin', 'Bibles', 'container title') } # Middle Header Bar - ## Import Button ## + ## Import Action ## self.textStrings[StringContent.Import] = { - u'title': translate('BiblesPlugin', 'Import'), - u'tooltip': translate('BiblesPlugin', - 'Import a Bible') + u'title': translate('BiblesPlugin', '&Import'), + u'tooltip': translate('BiblesPlugin', 'Import a Bible') } - ## New Button ## + ## New Action ## self.textStrings[StringContent.New] = { - u'title': translate('BiblesPlugin', 'Add'), - u'tooltip': translate('BiblesPlugin', - 'Add a new Bible') + u'title': translate('BiblesPlugin', '&Add'), + u'tooltip': translate('BiblesPlugin', 'Add a new Bible') } - ## Edit Button ## + ## Edit Action ## self.textStrings[StringContent.Edit] = { - u'title': translate('BiblesPlugin', 'Edit'), - u'tooltip': translate('BiblesPlugin', - 'Edit the selected Bible') + u'title': translate('BiblesPlugin', '&Edit'), + u'tooltip': translate('BiblesPlugin', 'Edit the selected Bible') } - ## Delete Button ## + ## Delete Action ## self.textStrings[StringContent.Delete] = { - u'title': translate('BiblesPlugin', 'Delete'), - u'tooltip': translate('BiblesPlugin', - 'Delete the selected Bible') + u'title': translate('BiblesPlugin', '&Delete'), + u'tooltip': translate('BiblesPlugin', 'Delete the selected Bible') } - ## Preview ## + ## Preview Action ## self.textStrings[StringContent.Preview] = { u'title': translate('BiblesPlugin', 'Preview'), - u'tooltip': translate('BiblesPlugin', - 'Preview the selected Bible') + u'tooltip': translate('BiblesPlugin', 'Preview the selected Bible') } - ## Live Button ## + ## Send Live Action ## self.textStrings[StringContent.Live] = { u'title': translate('BiblesPlugin', 'Live'), u'tooltip': translate('BiblesPlugin', 'Send the selected Bible live') } - ## Add to service Button ## + ## Add to Service Action ## self.textStrings[StringContent.Service] = { u'title': translate('BiblesPlugin', 'Service'), u'tooltip': translate('BiblesPlugin', 'Add the selected Bible to the service') - } \ No newline at end of file + } diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index b6cd81bf5..143b427fb 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -92,9 +92,10 @@ class CSVBible(BibleDB): if book_ptr != line[0]: book = self.get_book(line[0]) book_ptr = book.name - self.wizard.incrementProgressBar(u'%s %s %s...' % ( - translate('BiblesPlugin.CSVImport', 'Importing'), - book.name, line[1])) + self.wizard.incrementProgressBar(unicode(translate( + 'BiblesPlugin.CSVImport', 'Importing %s %s...', + 'Importing ...')) % + (book.name, int(line[1]))) self.session.commit() self.create_verse(book.id, line[1], line[2], unicode(line[3], details['encoding'])) @@ -109,4 +110,4 @@ class CSVBible(BibleDB): if self.stop_import_flag: return False else: - return success \ No newline at end of file + return success diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 20fa9e1f6..3f5ed41e4 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -912,7 +912,7 @@ class BibleMediaItem(MediaManagerItem): old_chapter != chapter: verse_text = unicode(chapter) + verse_separator + unicode(verse) else: - verse_text = u'%s' % verse + verse_text = unicode(verse) if self.parent.settings_tab.display_style == 1: verse_text = u'{su}(' + verse_text + u'){/su}' elif self.parent.settings_tab.display_style == 2: @@ -921,4 +921,4 @@ class BibleMediaItem(MediaManagerItem): verse_text = u'{su}[' + verse_text + u']{/su}' else: verse_text = u'{su}' + verse_text + u'{/su}' - return verse_text \ No newline at end of file + return verse_text diff --git a/openlp/plugins/bibles/lib/openlp1.py b/openlp/plugins/bibles/lib/openlp1.py index 41f4a2836..866652e5b 100644 --- a/openlp/plugins/bibles/lib/openlp1.py +++ b/openlp/plugins/bibles/lib/openlp1.py @@ -73,8 +73,8 @@ class OpenLP1Bible(BibleDB): abbreviation = unicode(book[3], u'cp1252') self.create_book(name, abbreviation, testament_id) # Update the progess bar. - self.wizard.incrementProgressBar(u'%s %s...' % (translate( - 'BiblesPlugin.OpenLP1Import', 'Importing'), name)) + self.wizard.incrementProgressBar(unicode(translate( + 'BiblesPlugin.OpenLP1Import', 'Importing %s...')) % name) # Import the verses for this book. cursor.execute(u'SELECT chapter, verse, text || \'\' AS text FROM ' 'verse WHERE book_id=%s' % book_id) @@ -90,4 +90,4 @@ class OpenLP1Bible(BibleDB): Receiver.send_message(u'openlp_process_events') self.session.commit() connection.close() - return True \ No newline at end of file + return True diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 241efbc0e..0d02cf11f 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -84,9 +84,10 @@ class OpenSongBible(BibleDB): unicode(verse.text) ) Receiver.send_message(u'openlp_process_events') - self.wizard.incrementProgressBar(u'%s %s %s...' % ( - translate('BiblesPlugin.Opensong', 'Importing'), - db_book.name, chapter.attrib[u'n'])) + self.wizard.incrementProgressBar(unicode(translate( + 'BiblesPlugin.Opensong', 'Importing %s %s...', + 'Importing ...')) % + (db_book.name, int(chapter.attrib[u'n']))) self.session.commit() except IOError: log.exception(u'Loading bible from OpenSong file failed') @@ -97,4 +98,4 @@ class OpenSongBible(BibleDB): if self.stop_import_flag: return False else: - return success \ No newline at end of file + return success diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 5b359240f..8bf2462ac 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -140,9 +140,10 @@ class OSISBible(BibleDB): if last_chapter != chapter: if last_chapter != 0: self.session.commit() - self.wizard.incrementProgressBar(u'%s %s %s...' % ( - translate('BiblesPlugin.OsisImport', 'Importing'), - self.books[match.group(1)][0], chapter)) + self.wizard.incrementProgressBar(unicode(translate( + 'BiblesPlugin.OsisImport', 'Importing %s %s...', + 'Importing ...')) % + (self.books[match.group(1)][0], chapter)) last_chapter = chapter # All of this rigmarol below is because the mod2osis # tool from the Sword library embeds XML in the OSIS @@ -180,4 +181,4 @@ class OSISBible(BibleDB): if self.stop_import_flag: return False else: - return success \ No newline at end of file + return success diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 9580077a8..54cb38501 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -104,57 +104,57 @@ class CustomPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('CustomsPlugin', 'Custom'), - u'plural': translate('CustomsPlugin', 'Customs') + u'singular': translate('CustomsPlugin', 'Custom', 'name singular'), + u'plural': translate('CustomsPlugin', 'Customs', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('CustomsPlugin', 'Custom') + u'title': translate('CustomsPlugin', 'Custom', 'container title') } # Middle Header Bar - ## Import Button ## + ## Import Action ## self.textStrings[StringContent.Import] = { u'title': translate('CustomsPlugin', 'Import'), u'tooltip': translate('CustomsPlugin', 'Import a Custom') } - ## Load Button ## + ## Load Action ## self.textStrings[StringContent.Load] = { u'title': translate('CustomsPlugin', 'Load'), u'tooltip': translate('CustomsPlugin', 'Load a new Custom') } - ## New Button ## + ## New Action ## self.textStrings[StringContent.New] = { u'title': translate('CustomsPlugin', 'Add'), u'tooltip': translate('CustomsPlugin', 'Add a new Custom') } - ## Edit Button ## + ## Edit Action ## self.textStrings[StringContent.Edit] = { u'title': translate('CustomsPlugin', 'Edit'), u'tooltip': translate('CustomsPlugin', 'Edit the selected Custom') } - ## Delete Button ## + ## Delete Action ## self.textStrings[StringContent.Delete] = { u'title': translate('CustomsPlugin', 'Delete'), u'tooltip': translate('CustomsPlugin', 'Delete the selected Custom') } - ## Preview ## + ## Preview Action ## self.textStrings[StringContent.Preview] = { u'title': translate('CustomsPlugin', 'Preview'), u'tooltip': translate('CustomsPlugin', 'Preview the selected Custom') } - ## Live Button ## + ## Send Live Action ## self.textStrings[StringContent.Live] = { u'title': translate('CustomsPlugin', 'Live'), u'tooltip': translate('CustomsPlugin', 'Send the selected Custom live') } - ## Add to service Button ## + ## Add to Service Action ## self.textStrings[StringContent.Service] = { u'title': translate('CustomsPlugin', 'Service'), u'tooltip': translate('CustomsPlugin', @@ -167,4 +167,4 @@ class CustomPlugin(Plugin): """ log.info(u'Custom Finalising') self.manager.finalise() - Plugin.finalise(self) \ No newline at end of file + Plugin.finalise(self) diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 4bd7783ee..79b08eb8c 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -64,12 +64,12 @@ class ImagePlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('ImagePlugin', 'Image'), - u'plural': translate('ImagePlugin', 'Images') + u'singular': translate('ImagePlugin', 'Image', 'name singular'), + u'plural': translate('ImagePlugin', 'Images', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('ImagePlugin', 'Images') + u'title': translate('ImagePlugin', 'Images', 'container title') } # Middle Header Bar ## Load Button ## @@ -113,4 +113,4 @@ class ImagePlugin(Plugin): u'title': translate('ImagePlugin', 'Service'), u'tooltip': translate('ImagePlugin', 'Add the selected Image to the service') - } \ No newline at end of file + } diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index fabad8e8c..9be08df4b 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -109,7 +109,7 @@ class ImageMediaItem(MediaManagerItem): translate('ImagePlugin.MediaItem', 'Replace Live Background'), self.onReplaceClick, False) self.resetButton = self.toolbar.addToolbarButton( - translate('ImagePlugin.MediaItem', u'Reset Background'), + translate('ImagePlugin.MediaItem', 'Reset Background'), u':/system/system_close.png', translate('ImagePlugin.MediaItem', 'Reset Live Background'), self.onResetClick, False) @@ -195,4 +195,4 @@ class ImageMediaItem(MediaManagerItem): self.resetButton.setVisible(True) 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 e2309ea76..bf4aac918 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -60,10 +60,9 @@ class MediaMediaItem(MediaManagerItem): def retranslateUi(self): self.OnNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media') - self.OnNewFileMasks = translate('MediaPlugin.MediaItem', - u'Videos (%s);;' - u'Audio (%s);;' - u'All files (*)' % (self.parent.video_list, self.parent.audio_list)) + self.OnNewFileMasks = unicode(translate('MediaPlugin.MediaItem', + 'Videos (%s);;Audio (%s);;All files (*)')) % \ + (self.parent.video_list, self.parent.audio_list) def requiredIcons(self): MediaManagerItem.requiredIcons(self) @@ -159,4 +158,4 @@ class MediaMediaItem(MediaManagerItem): img = QtGui.QPixmap(u':/media/media_video.png').toImage() item_name.setIcon(build_icon(img)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) - self.listView.addItem(item_name) \ No newline at end of file + self.listView.addItem(item_name) diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 2f5b78b8e..920f703f2 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -93,53 +93,53 @@ class MediaPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('MediaPlugin', 'Media'), - u'plural': translate('MediaPlugin', 'Media') + u'singular': translate('MediaPlugin', 'Media', 'name singular'), + u'plural': translate('MediaPlugin', 'Media', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('MediaPlugin', 'Media') + u'title': translate('MediaPlugin', 'Media', 'container title') } # Middle Header Bar - ## Load Button ## + ## Load Action ## self.textStrings[StringContent.Load] = { u'title': translate('MediaPlugin', 'Load'), u'tooltip': translate('MediaPlugin', 'Load a new Media') } - ## New Button ## + ## New Action ## self.textStrings[StringContent.New] = { u'title': translate('MediaPlugin', 'Add'), u'tooltip': translate('MediaPlugin', 'Add a new Media') } - ## Edit Button ## + ## Edit Action ## self.textStrings[StringContent.Edit] = { u'title': translate('MediaPlugin', 'Edit'), u'tooltip': translate('MediaPlugin', 'Edit the selected Media') } - ## Delete Button ## + ## Delete Action ## self.textStrings[StringContent.Delete] = { u'title': translate('MediaPlugin', 'Delete'), u'tooltip': translate('MediaPlugin', 'Delete the selected Media') } - ## Preview ## + ## Preview Action ## self.textStrings[StringContent.Preview] = { u'title': translate('MediaPlugin', 'Preview'), u'tooltip': translate('MediaPlugin', 'Preview the selected Media') } - ## Live Button ## + ## Send Live Action ## self.textStrings[StringContent.Live] = { u'title': translate('MediaPlugin', 'Live'), u'tooltip': translate('MediaPlugin', 'Send the selected Media live') } - ## Add to service Button ## + ## Add to Service Action ## self.textStrings[StringContent.Service] = { u'title': translate('MediaPlugin', 'Service'), u'tooltip': translate('MediaPlugin', 'Add the selected Media to the service') - } \ No newline at end of file + } diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 4b1067e8e..a7739fa55 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -90,8 +90,8 @@ class PresentationMediaItem(MediaManagerItem): if fileType.find(type) == -1: fileType += u'*.%s ' % type self.parent.serviceManager.supportedSuffixes(type) - self.OnNewFileMasks = translate('PresentationPlugin.MediaItem', - 'Presentations (%s)' % fileType) + self.OnNewFileMasks = unicode(translate('PresentationPlugin.MediaItem', + 'Presentations (%s)')) % fileType def requiredIcons(self): """ @@ -293,4 +293,4 @@ class PresentationMediaItem(MediaManagerItem): if self.controllers[controller].enabled(): if filetype in self.controllers[controller].alsosupports: return controller - return None \ No newline at end of file + return None diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 9c4a64866..8afed6022 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -152,41 +152,44 @@ class PresentationPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('PresentationPlugin', 'Presentation'), - u'plural': translate('PresentationPlugin', 'Presentations') + u'singular': translate('PresentationPlugin', 'Presentation', + 'name singular'), + u'plural': translate('PresentationPlugin', 'Presentations', + 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('PresentationPlugin', 'Presentations') + u'title': translate('PresentationPlugin', 'Presentations', + 'container title') } # Middle Header Bar - ## Load Button ## + ## Load Action ## self.textStrings[StringContent.Load] = { u'title': translate('PresentationPlugin', 'Load'), u'tooltip': translate('PresentationPlugin', 'Load a new Presentation') } - ## Delete Button ## + ## Delete Action ## self.textStrings[StringContent.Delete] = { u'title': translate('PresentationPlugin', 'Delete'), u'tooltip': translate('PresentationPlugin', 'Delete the selected Presentation') } - ## Preview ## + ## Preview Action ## self.textStrings[StringContent.Preview] = { u'title': translate('PresentationPlugin', 'Preview'), u'tooltip': translate('PresentationPlugin', 'Preview the selected Presentation') } - ## Live Button ## + ## Send Live Action ## self.textStrings[StringContent.Live] = { u'title': translate('PresentationPlugin', 'Live'), u'tooltip': translate('PresentationPlugin', 'Send the selected Presentation live') } - ## Add to service Button ## + ## Add to Service Action ## self.textStrings[StringContent.Service] = { u'title': translate('PresentationPlugin', 'Service'), u'tooltip': translate('PresentationPlugin', 'Add the selected Presentation to the service') - } \ No newline at end of file + } diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 419a51a72..dbc56a61c 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -84,10 +84,10 @@ class RemotesPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('RemotePlugin', 'Remote'), - u'plural': translate('RemotePlugin', 'Remotes') + u'singular': translate('RemotePlugin', 'Remote', 'name singular'), + u'plural': translate('RemotePlugin', 'Remotes', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('RemotePlugin', 'Remote') - } \ No newline at end of file + u'title': translate('RemotePlugin', 'Remote', 'container title') + } diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 0fcdc6ab1..0364a4df4 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -109,7 +109,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author_name = QtGui.QListWidgetItem(author.display_name) else: author_name = QtGui.QListWidgetItem( - u'%s %s' % (author.first_name, author.last_name)) + u' '.join(author.first_name, author.last_name)) author_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id)) self.AuthorsListWidget.addItem(author_name) if self.AuthorsListWidget.count() == 0: @@ -305,12 +305,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): 'Could not save your changes.')) elif QtGui.QMessageBox.critical(self, translate('SongsPlugin.SongMaintenanceForm', 'Error'), - 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: + 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: self.mergeAuthors(author) self.resetAuthors() Receiver.send_message(u'songs_load_list') @@ -346,12 +347,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): 'Could not save your changes.')) elif QtGui.QMessageBox.critical(self, translate('SongsPlugin.SongMaintenanceForm', 'Error'), - 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: + 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: self.mergeTopics(topic) self.resetTopics() else: @@ -389,12 +390,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): 'Could not save your changes.')) elif QtGui.QMessageBox.critical(self, translate('SongsPlugin.SongMaintenanceForm', 'Error'), - 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: + 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: self.mergeBooks(book) self.resetBooks() else: @@ -498,4 +499,4 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): translate('SongsPlugin.SongMaintenanceForm', 'This book cannot be deleted, it is currently ' 'assigned to at least one song.'), - translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) \ No newline at end of file + translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 79a7260bb..98e4be51e 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -29,6 +29,7 @@ import os import chardet import codecs +from openlp.core.lib import translate from songimport import SongImport log = logging.getLogger(__name__) @@ -69,8 +70,9 @@ class CCLIFileImport(SongImport): self.import_wizard.importProgressBar.setMaximum(song_total) song_count = 1 for filename in self.filenames: - self.import_wizard.incrementProgressBar( - u'Importing song %s of %s' % (song_count, song_total)) + self.import_wizard.incrementProgressBar(unicode(translate( + 'SongsPlugin.CCLIFileImport', 'Importing song %d of %d')) % + (song_count, song_total)) filename = unicode(filename) log.debug(u'Importing CCLI File: %s', filename) lines = [] @@ -337,4 +339,4 @@ class CCLIFileImport(SongImport): self.copyright = song_copyright self.ccli_number = song_ccli self.comments = song_comments - self.finish() \ No newline at end of file + self.finish() diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 3be60dec4..6521aa5cd 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -235,7 +235,7 @@ class SongMediaItem(MediaManagerItem): self.listView.clear() for author in searchresults: for song in author.songs: - song_detail = '%s (%s)' % (author.display_name, song.title) + song_detail = u'%s (%s)' % (author.display_name, song.title) song_name = QtGui.QListWidgetItem(song_detail) song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id)) self.listView.addItem(song_name) @@ -315,16 +315,11 @@ class SongMediaItem(MediaManagerItem): translate('SongsPlugin.MediaItem', 'You must select an item to delete.')): items = self.listView.selectedIndexes() - if len(items) == 1: - del_message = translate('SongsPlugin.MediaItem', - 'Are you sure you want to delete the selected song?') - else: - del_message = unicode(translate('SongsPlugin.MediaItem', - 'Are you sure you want to delete the %d selected ' - 'songs?')) % len(items) ans = QtGui.QMessageBox.question(self, translate('SongsPlugin.MediaItem', 'Delete Song(s)?'), - del_message, + 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) @@ -457,4 +452,4 @@ class SongMediaItem(MediaManagerItem): """ Locale aware collation of song titles """ - return locale.strcoll(unicode(song_1.title), unicode(song_2.title)) \ No newline at end of file + return locale.strcoll(unicode(song_1.title), unicode(song_2.title)) diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index b0175d45f..e366ddf4b 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -34,6 +34,7 @@ from sqlalchemy.orm import class_mapper, mapper, relation, scoped_session, \ sessionmaker from sqlalchemy.orm.exc import UnmappedClassError +from openlp.core.lib import translate from openlp.core.lib.db import BaseModel from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile from songimport import SongImport @@ -148,8 +149,9 @@ class OpenLPSongImport(SongImport): self.import_wizard.importProgressBar.setMaximum(song_total) song_count = 1 for song in source_songs: - self.import_wizard.incrementProgressBar( - u'Importing song %s of %s' % (song_count, song_total)) + self.import_wizard.incrementProgressBar(unicode(translate( + 'SongsPlugin.OpenLPSongImport', 'Importing song %d of %d.')) % + (song_count, song_total)) new_song = Song() new_song.title = song.title if has_media_files and hasattr(song, 'alternate_title'): @@ -220,4 +222,4 @@ class OpenLPSongImport(SongImport): if self.stop_import_flag: return False engine.dispose() - return True \ No newline at end of file + return True diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 29884b80c..a69aa0bc1 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -126,17 +126,17 @@ class SongBeamerImport(SongImport): if verse_start: verse_start = False if not self.check_verse_marks(line): - self.current_verse = u'%s\n' % line + self.current_verse = line + u'\n' else: - self.current_verse += u'%s\n' % line + self.current_verse += line + u'\n' if self.current_verse: self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) if self.check_complete(): self.finish() - self.import_wizard.incrementProgressBar(u'%s %s...' % - (translate('SongsPlugin.SongBeamerImport', 'Importing'), - self.file_name)) + self.import_wizard.incrementProgressBar(unicode(translate( + 'SongsPlugin.SongBeamerImport', 'Importing %s...')) % + self.file_name) return True def replace_html_tags(self): @@ -252,7 +252,7 @@ class SongBeamerImport(SongImport): elif tag_val[0] == u'#TextAlign': pass elif tag_val[0] == u'#Title': - self.title = u'%s' % tag_val[1] + self.title = unicode(tag_val[1]) elif tag_val[0] == u'#TitleAlign': pass elif tag_val[0] == u'#TitleFontSize': @@ -292,4 +292,4 @@ class SongBeamerImport(SongImport): self.current_verse_type += marks[1] return True else: - return False \ No newline at end of file + return False diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index a44188c87..545497acb 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -213,45 +213,45 @@ class SongsPlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('SongsPlugin', 'Song'), - u'plural': translate('SongsPlugin', 'Songs') + u'singular': translate('SongsPlugin', 'Song', 'name singular'), + u'plural': translate('SongsPlugin', 'Songs', 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('SongsPlugin', 'Songs') + u'title': translate('SongsPlugin', 'Songs', 'container title') } # Middle Header Bar - ## New Button ## + ## New Action ## self.textStrings[StringContent.New] = { u'title': translate('SongsPlugin', 'Add'), u'tooltip': translate('SongsPlugin', 'Add a new Song') } - ## Edit Button ## + ## Edit Action ## self.textStrings[StringContent.Edit] = { u'title': translate('SongsPlugin', 'Edit'), u'tooltip': translate('SongsPlugin', 'Edit the selected Song') } - ## Delete Button ## + ## Delete Action ## self.textStrings[StringContent.Delete] = { u'title': translate('SongsPlugin', 'Delete'), u'tooltip': translate('SongsPlugin', 'Delete the selected Song') } - ## Preview ## + ## Preview Action ## self.textStrings[StringContent.Preview] = { u'title': translate('SongsPlugin', 'Preview'), u'tooltip': translate('SongsPlugin', 'Preview the selected Song') } - ## Live Button ## + ## Send Live Action ## self.textStrings[StringContent.Live] = { u'title': translate('SongsPlugin', 'Live'), u'tooltip': translate('SongsPlugin', 'Send the selected Song live') } - ## Add to service Button ## + ## Add to Service Action ## self.textStrings[StringContent.Service] = { u'title': translate('SongsPlugin', 'Service'), u'tooltip': translate('SongsPlugin', @@ -265,4 +265,4 @@ class SongsPlugin(Plugin): log.info(u'Songs Finalising') self.manager.finalise() self.toolsReindexItem.setVisible(False) - Plugin.finalise(self) \ No newline at end of file + Plugin.finalise(self) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index c9c357a84..8588ddcff 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -73,7 +73,8 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): def accept(self): log.debug(u'Detailed report generated') - filename = u'usage_detail_%s_%s.txt' % ( + filename = unicode(translate('SongUsagePlugin.SongUsageDetailForm', + 'usage_detail_%s_%s.txt')) % ( self.fromDate.selectedDate().toString(u'ddMMyyyy'), self.toDate.selectedDate().toString(u'ddMMyyyy')) usage = self.plugin.manager.get_all_objects( @@ -95,4 +96,4 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): finally: if file: file.close() - self.close() \ No newline at end of file + self.close() diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 4a95b00f7..ec37dc65e 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -175,10 +175,13 @@ class SongUsagePlugin(Plugin): """ ## Name PluginList ## self.textStrings[StringContent.Name] = { - u'singular': translate('SongUsagePlugin', 'SongUsage'), - u'plural': translate('SongUsagePlugin', 'SongUsage') + u'singular': translate('SongUsagePlugin', 'SongUsage', + 'name singular'), + u'plural': translate('SongUsagePlugin', 'SongUsage', + 'name plural') } ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { - u'title': translate('SongUsagePlugin', 'SongUsage') - } \ No newline at end of file + u'title': translate('SongUsagePlugin', 'SongUsage', + 'container title') + } From a83df7ce045a90365c21a005ea54c50fc82c0142 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Fri, 31 Dec 2010 17:13:23 +0000 Subject: [PATCH 2/6] Fix https://bugs.launchpad.net/openlp/+bug/672164/comments/9 --- openlp/core/ui/slidecontroller.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index dd7853216..6a5e313f0 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1042,7 +1042,8 @@ class SlideController(QtGui.QWidget): if self.ThemeScreen.isChecked: self.ThemeScreen.setChecked(False) self.HideMenu.setDefaultAction(self.ThemeScreen) - if self.DesktopScreen.isChecked: - self.DesktopScreen.setChecked(False) - self.HideMenu.setDefaultAction(self.DesktopScreen) + if self.screens.display_count > 1: + if self.DesktopScreen.isChecked: + self.DesktopScreen.setChecked(False) + self.HideMenu.setDefaultAction(self.DesktopScreen) From 3198de5c555e28c59073cc71b1d1d6a7e7f6a176 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 31 Dec 2010 23:43:02 +0200 Subject: [PATCH 3/6] For once and for all, change the save/save as/load/etc of services. --- openlp/core/ui/mainwindow.py | 39 ++- openlp/core/ui/servicemanager.py | 495 +++++++++++++++++-------------- openlp/core/utils/__init__.py | 9 +- 3 files changed, 305 insertions(+), 238 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index b88f69910..7beae55fa 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -582,16 +582,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.QObject.connect(self.SettingsShortcutsItem, QtCore.SIGNAL(u'triggered()'), self.onSettingsShortcutsItemClicked) QtCore.QObject.connect(self.FileNewItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onNewService) + self.ServiceManagerContents.onNewServiceClicked) QtCore.QObject.connect(self.FileOpenItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onLoadService) + self.ServiceManagerContents.onLoadServiceClicked) QtCore.QObject.connect(self.FileSaveItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onQuickSaveService) + self.ServiceManagerContents.onSaveServiceClicked) QtCore.QObject.connect(self.FileSaveAsItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onSaveService) + self.ServiceManagerContents.onSaveServiceAsClicked) # i18n set signals for languages QtCore.QObject.connect(self.AutoLanguageItem, QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage) @@ -691,7 +691,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if QtCore.QSettings().value( self.generalSettingsSection + u'/auto open', QtCore.QVariant(False)).toBool(): - self.ServiceManagerContents.onLoadService(True) + #self.ServiceManagerContents.onLoadService(True) + self.ServiceManagerContents.loadLastFile() view_mode = QtCore.QSettings().value(u'%s/view mode' % \ self.generalSettingsSection, u'default') if view_mode == u'default': @@ -805,7 +806,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ Hook to close the main window and display windows on exit """ - if self.serviceNotSaved: + if self.ServiceManagerContents.isModified(): ret = QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'Save Changes to Service?'), translate('OpenLP.MainWindow', 'Your service has changed. ' @@ -816,9 +817,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtGui.QMessageBox.Save), QtGui.QMessageBox.Save) if ret == QtGui.QMessageBox.Save: - self.ServiceManagerContents.onSaveService(True) - self.cleanUp() - event.accept() + #self.ServiceManagerContents.onSaveService(True) + if self.ServiceManagerContents.saveFile(): + self.cleanUp() + event.accept() + else: + event.ignore() elif ret == QtGui.QMessageBox.Discard: self.cleanUp() event.accept() @@ -878,6 +882,23 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): title = u'%s - %s*' % (self.mainTitle, service_name) self.setWindowTitle(title) + def setServiceModified(self, modified, fileName): + """ + This method is called from the ServiceManager to set the title of the + main window. + + ``modified`` + Whether or not this service has been modified. + + ``fileName`` + The file name of the service file. + """ + if modified: + title = u'%s - %s*' % (self.mainTitle, fileName) + else: + title = u'%s - %s' % (self.mainTitle, fileName) + self.setWindowTitle(title) + def showStatusMessage(self, message): self.StatusBar.showMessage(message) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e2c1a765b..18dba7058 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -37,7 +37,7 @@ 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 +from openlp.core.utils import AppLocation, split_filename class ServiceManagerList(QtGui.QTreeWidget): """ @@ -90,6 +90,7 @@ class ServiceManagerList(QtGui.QTreeWidget): mimeData.setText(u'ServiceManager') drag.start(QtCore.Qt.CopyAction) + class ServiceManager(QtGui.QWidget): """ Manages the services. This involves taking text strings from plugins and @@ -101,15 +102,16 @@ class ServiceManager(QtGui.QWidget): """ Sets up the service manager, toolbars, list view, et al. """ - QtGui.QWidget.__init__(self) + QtGui.QWidget.__init__(self, parent) self.parent = parent self.serviceItems = [] self.serviceName = u'' self.suffixes = [] - self.droppos = 0 + self.dropPosition = 0 self.expandTabs = False #is a new service and has not been saved - self.isNew = True + self._modified = False + self._fileName = u'' self.serviceNoteForm = ServiceNoteForm(self.parent) self.serviceItemEditForm = ServiceItemEditForm(self.parent) #start with the layout @@ -123,17 +125,17 @@ class ServiceManager(QtGui.QWidget): translate('OpenLP.ServiceManager', 'New Service'), u':/general/general_new.png', translate('OpenLP.ServiceManager', 'Create a new service'), - self.onNewService) + self.onNewServiceClicked) self.toolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Open Service'), u':/general/general_open.png', translate('OpenLP.ServiceManager', 'Load an existing service'), - self.onLoadService) + self.onLoadServiceClicked) self.toolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Save Service'), u':/general/general_save.png', translate('OpenLP.ServiceManager', 'Save this service'), - self.onQuickSaveService) + self.onSaveServiceClicked) self.toolbar.addSeparator() self.themeLabel = QtGui.QLabel(translate('OpenLP.ServiceManager', 'Theme:'), self) @@ -282,6 +284,40 @@ class ServiceManager(QtGui.QWidget): self.menu.addMenu(self.themeMenu) self.configUpdated(True) + def setModified(self, modified=True): + """ + Setter for property "modified". Sets whether or not the current service + has been modified. + """ + self._modified = modified + serviceFile = self.shortFileName() or u'Untitled Service' + self.parent.setServiceModified(modified, serviceFile) + + def isModified(self): + """ + Getter for boolean property "modified". + """ + return self._modified + + def setFileName(self, fileName): + """ + Setter for service file. + """ + self._fileName = unicode(fileName) + self.parent.setServiceModified(self.isModified, self.shortFileName()) + + def fileName(self): + """ + Return the current file name including path. + """ + return self._fileName + + def shortFileName(self): + """ + Return the current file name, excluding the path. + """ + return split_filename(self._fileName)[1] + def configUpdated(self, firstTime=False): """ Triggered when Config dialog is updated. @@ -295,6 +331,201 @@ class ServiceManager(QtGui.QWidget): def supportedSuffixes(self, suffix): self.suffixes.append(suffix) + def onNewServiceClicked(self): + """ + Create a new service. + """ + if self.isModified(): + result = QtGui.QMessageBox.question(self.parent, + translate('OpenLP.ServiceManager', 'Save Changes'), + translate('OpenLP.ServiceManager', 'The current service has ' + 'been modified, would you like to save it?'), + QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | + QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) + if result == QtGui.QMessageBox.Cancel: + return False + elif result == QtGui.QMessageBox.Save: + if not self.saveFile(): + return False + self.serviceManagerList.clear() + self.serviceItems = [] + self.setFileName(u'') + self.setModified(False) + + def onLoadServiceClicked(self): + if self.isModified(): + result = QtGui.QMessageBox.question(self.parent, + translate('OpenLP.ServiceManager', 'Save Changes'), + translate('OpenLP.ServiceManager', 'The current service has ' + 'been modified, would you like to save it?'), + QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | + QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) + if result == QtGui.QMessageBox.Cancel: + return False + elif result == QtGui.QMessageBox.Save: + self.saveFile() + fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.parent, + translate('OpenLP.ServiceManager', 'Open File'), + SettingsManager.get_last_dir(self.parent.serviceSettingsSection), + translate('OpenLP.ServiceManager', + 'OpenLP Service Files (*.osz) (*.osz)'))) + if not fileName: + return False + SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + split_filename(fileName)[0]) + self.loadFile(fileName) + + def onSaveServiceClicked(self): + self.saveFile() + + def onSaveServiceAsClicked(self): + self.saveFileAs() + + def saveFile(self): + """ + Save the current Service file. + """ + if not self.fileName(): + return self.saveFileAs() + else: + fileName = self.fileName() + log.debug(u'ServiceManager.saveFile - %s' % fileName) + SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + split_filename(fileName)[0]) + service = [] + serviceFileName = fileName.replace(u'.osz', u'.osd') + zip = None + file = None + try: + write_list = [] + zip = zipfile.ZipFile(unicode(fileName), 'w') + for item in self.serviceItems: + service.append({u'serviceitem': \ + item[u'service_item'].get_service_repr()}) + if item[u'service_item'].uses_file(): + for frame in item[u'service_item'].get_frames(): + if item[u'service_item'].is_image(): + path_from = frame[u'path'] + else: + path_from = unicode(os.path.join( + frame[u'path'], + frame[u'title'])) + # On write a file once + if not path_from in write_list: + write_list.append(path_from) + zip.write(path_from.encode(u'utf-8')) + file = open(serviceFileName, u'wb') + cPickle.dump(service, file) + file.close() + zip.write(serviceFileName.encode(u'utf-8')) + except IOError: + log.exception(u'Failed to save service to disk') + finally: + if file: + file.close() + if zip: + zip.close() + try: + os.remove(serviceFileName) + except (IOError, OSError): + # if not present do not worry + pass + self.parent.addRecentFile(fileName) + self.setModified(False) + return True + + def saveFileAs(self): + """ + Get a file name and then call :function:`ServiceManager.saveFile` to + save the file. + """ + fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.parent, + translate('OpenLP.ServiceManager', 'Save Service'), + SettingsManager.get_last_dir(self.parent.serviceSettingsSection), + translate('OpenLP.ServiceManager', + 'OpenLP Service Files (*.osz) (*.osz)'))) + if not fileName: + return False + if os.path.splitext(fileName)[1] == u'': + fileName += u'.osz' + else: + ext = os.path.splitext(fileName)[1] + fileName.replace(ext, u'.osz') + self.setFileName(fileName) + return self.saveFile() + + def loadFile(self, fileName): + if not fileName: + return False + zip = None + fileTo = None + try: + zip = zipfile.ZipFile(unicode(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')) + continue + osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) + filePath = os.path.join(self.servicePath, + split_filename(osfile)[1]) + fileTo = open(filePath, u'wb') + fileTo.write(zip.read(file)) + fileTo.flush() + fileTo.close() + if file_path.endswith(u'osd'): + p_file = file_path + if 'p_file' in locals(): + fileTo = open(p_file, u'r') + items = cPickle.load(fileTo) + fileTo.close() + self.onNewService() + for item in items: + serviceItem = ServiceItem() + serviceItem.render_manager = self.parent.renderManager + serviceItem.set_from_service(item, self.servicePath) + self.validateItem(serviceItem) + self.addServiceItem(serviceItem) + 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') + else: + QtGui.QMessageBox.critical( + self, translate('OpenLP.ServiceManager', 'Error'), + 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') + finally: + if fileTo: + fileTo.close() + if zip: + zip.close() + self.setFileName(fileName) + self.parent.addRecentFile(fileName) + self.setModified(False) + # Refresh Plugin lists + Receiver.send_message(u'plugin_list_refresh') + + def loadLastFile(self): + if not self.parent.recentFiles: + return + self.loadFile(self.parent.recentFiles[0]) + def contextMenu(self, point): item = self.serviceManagerList.itemAt(point) if item is None: @@ -427,6 +658,7 @@ class ServiceManager(QtGui.QWidget): # Top Item was selected so set the last one if setLastItem: lastItem.setSelected(True) + self.isModified = True def onMoveSelectionDown(self): """ @@ -449,6 +681,7 @@ class ServiceManager(QtGui.QWidget): serviceIterator += 1 if setSelected: firstItem.setSelected(True) + self.isModified = True def onCollapseAll(self): """ @@ -492,7 +725,7 @@ class ServiceManager(QtGui.QWidget): self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(0, temp) self.repaintServiceList(0, count) - self.parent.serviceChanged(False, self.serviceName) + self.isModified = True def onServiceUp(self): """ @@ -505,7 +738,7 @@ class ServiceManager(QtGui.QWidget): self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(item - 1, temp) self.repaintServiceList(item - 1, count) - self.parent.serviceChanged(False, self.serviceName) + self.setModified(True) def onServiceDown(self): """ @@ -518,7 +751,7 @@ class ServiceManager(QtGui.QWidget): self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(item + 1, temp) self.repaintServiceList(item + 1, count) - self.parent.serviceChanged(False, self.serviceName) + self.setModified(True) def onServiceEnd(self): """ @@ -530,30 +763,7 @@ class ServiceManager(QtGui.QWidget): self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(len(self.serviceItems), temp) self.repaintServiceList(len(self.serviceItems) - 1, count) - self.parent.serviceChanged(False, self.serviceName) - - def onNewService(self): - """ - Clear the list to create a new service - """ - if self.parent.serviceNotSaved and QtCore.QSettings().value( - self.parent.generalSettingsSection + u'/save prompt', - QtCore.QVariant(False)).toBool(): - ret = QtGui.QMessageBox.question(self, - translate('OpenLP.ServiceManager', 'Save Changes to Service?'), - translate('OpenLP.ServiceManager', - 'Your service is unsaved, do you want to save ' - 'those changes before creating a new one?'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Save), - QtGui.QMessageBox.Save) - if ret == QtGui.QMessageBox.Save: - self.onSaveService() - self.serviceManagerList.clear() - self.serviceItems = [] - self.serviceName = u'' - self.isNew = True - self.parent.serviceChanged(True, self.serviceName) + self.setModified(True) def onDeleteFromService(self): """ @@ -563,13 +773,19 @@ class ServiceManager(QtGui.QWidget): if item is not -1: self.serviceItems.remove(self.serviceItems[item]) self.repaintServiceList(0, 0) - self.parent.serviceChanged(False, self.serviceName) + self.setModified(True) def repaintServiceList(self, serviceItem, serviceItemCount): """ - Clear the existing service list and prepaint all the items - Used when moving items as the move takes place in supporting array, - and when regenerating all the items due to theme changes + Clear the existing service list and prepaint all the items. This is + used when moving items as the move takes place in a supporting list, + and when regenerating all the items due to theme changes. + + ``serviceItem`` + The item which changed. + + ``serviceItemCount`` + The number of items in the service. """ # Correct order of items in array count = 1 @@ -615,183 +831,6 @@ class ServiceManager(QtGui.QWidget): item[u'expanded'] = temp treewidgetitem.setExpanded(item[u'expanded']) - def onSaveService(self, quick=False): - """ - Save the current service in a zip (OSZ) file - This file contains - * An osd which is a pickle of the service items - * All image, presentation and video files needed to run the service. - """ - log.debug(u'onSaveService %s' % quick) - if not quick or self.isNew: - filename = QtGui.QFileDialog.getSaveFileName(self, - translate('OpenLP.ServiceManager', 'Save Service'), - SettingsManager.get_last_dir(self.parent.serviceSettingsSection), - translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')) - else: - filename = os.path.join(SettingsManager.get_last_dir( - self.parent.serviceSettingsSection), self.serviceName) - if filename: - filename = QtCore.QDir.toNativeSeparators(filename) - splittedFile = filename.split(u'.') - if splittedFile[-1] != u'osz': - filename = filename + u'.osz' - filename = unicode(filename) - self.isNew = False - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, - os.path.split(filename)[0]) - service = [] - servicefile = filename + u'.osd' - zip = None - file = None - try: - write_list = [] - zip = zipfile.ZipFile(unicode(filename), 'w') - for item in self.serviceItems: - service.append({u'serviceitem':item[u'service_item'] - .get_service_repr()}) - if item[u'service_item'].uses_file(): - for frame in item[u'service_item'].get_frames(): - if item[u'service_item'].is_image(): - path_from = frame[u'path'] - else: - path_from = unicode(os.path.join( - frame[u'path'], - frame[u'title'])) - # On write a file once - if not path_from in write_list: - write_list.append(path_from) - zip.write(path_from.encode(u'utf-8')) - file = open(servicefile, u'wb') - cPickle.dump(service, file) - file.close() - zip.write(servicefile.encode(u'utf-8')) - except IOError: - log.exception(u'Failed to save service to disk') - finally: - if file: - file.close() - if zip: - zip.close() - try: - os.remove(servicefile) - except (IOError, OSError): - pass #if not present do not worry - name = filename.split(os.path.sep) - self.serviceName = name[-1] - self.parent.addRecentFile(filename) - self.parent.serviceChanged(True, self.serviceName) - - def onQuickSaveService(self): - self.onSaveService(True) - - def onLoadService(self, lastService=False): - if lastService: - if not self.parent.recentFiles: - return - filename = self.parent.recentFiles[0] - else: - filename = QtGui.QFileDialog.getOpenFileName( - self, translate('OpenLP.ServiceManager', 'Open Service'), - SettingsManager.get_last_dir( - self.parent.serviceSettingsSection), u'Services (*.osz)') - filename = QtCore.QDir.toNativeSeparators(filename) - self.loadService(filename) - - def loadService(self, filename=None): - """ - Load an existing service from disk and rebuild the serviceitems. All - files retrieved from the zip file are placed in a temporary directory - and will only be used for this service. - """ - if self.parent.serviceNotSaved: - ret = QtGui.QMessageBox.question(self, - translate('OpenLP.ServiceManager', 'Save Changes to Service?'), - translate('OpenLP.ServiceManager', - 'Your current service is unsaved, do you want to ' - 'save the changes before opening a new one?'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Discard | QtGui.QMessageBox.Save), - QtGui.QMessageBox.Save) - if ret == QtGui.QMessageBox.Save: - self.onSaveService() - if filename is None: - action = self.sender() - if isinstance(action, QtGui.QAction): - filename = action.data().toString() - else: - return - filename = unicode(filename) - name = filename.split(os.path.sep) - if filename: - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, - os.path.split(filename)[0]) - zip = None - file_to = None - try: - zip = zipfile.ZipFile(unicode(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')) - continue - osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) - names = osfile.split(os.path.sep) - file_path = os.path.join(self.servicePath, - names[len(names) - 1]) - file_to = open(file_path, u'wb') - file_to.write(zip.read(file)) - file_to.flush() - file_to.close() - if file_path.endswith(u'osd'): - p_file = file_path - if 'p_file' in locals(): - file_to = open(p_file, u'r') - items = cPickle.load(file_to) - file_to.close() - self.onNewService() - for item in items: - serviceitem = ServiceItem() - serviceitem.render_manager = self.parent.renderManager - serviceitem.set_from_service(item, self.servicePath) - self.validateItem(serviceitem) - self.addServiceItem(serviceitem) - 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') - else: - QtGui.QMessageBox.critical( - self, translate('OpenLP.ServiceManager', 'Error'), - 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') - finally: - if file_to: - file_to.close() - if zip: - zip.close() - self.isNew = False - self.serviceName = name[len(name) - 1] - self.parent.addRecentFile(filename) - self.parent.serviceChanged(True, self.serviceName) - # Refresh Plugin lists - Receiver.send_message(u'plugin_list_refresh') - def validateItem(self, serviceItem): """ Validates the service item and if the suffix matches an accepted @@ -857,7 +896,7 @@ class ServiceManager(QtGui.QWidget): item[u'service_item'], False, expand=item[u'expanded']) # Set to False as items may have changed rendering # does not impact the saved song so True may also be valid - self.parent.serviceChanged(False, self.serviceName) + self.setModified(True) def serviceItemUpdate(self, message): """ @@ -881,7 +920,7 @@ class ServiceManager(QtGui.QWidget): item[u'service_item'] = newItem self.repaintServiceList(itemcount + 1, 0) self.parent.liveController.replaceServiceManagerItem(newItem) - self.parent.serviceChanged(False, self.serviceName) + self.setModified(True) def addServiceItem(self, item, rebuild=False, expand=None, replace=False): """ @@ -905,7 +944,7 @@ class ServiceManager(QtGui.QWidget): self.parent.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd - if self.droppos == 0: + if self.dropPosition == 0: if isinstance(item, list): for inditem in item: self.serviceItems.append({u'service_item': inditem, @@ -917,15 +956,15 @@ class ServiceManager(QtGui.QWidget): u'expanded':expand}) self.repaintServiceList(len(self.serviceItems) + 1, 0) else: - self.serviceItems.insert(self.droppos, {u'service_item': item, - u'order': self.droppos, + self.serviceItems.insert(self.dropPosition, {u'service_item': item, + u'order': self.dropPosition, u'expanded':expand}) - self.repaintServiceList(self.droppos, 0) + self.repaintServiceList(self.dropPosition, 0) # if rebuilding list make sure live is fixed. if rebuild: self.parent.liveController.replaceServiceManagerItem(item) - self.droppos = 0 - self.parent.serviceChanged(False, self.serviceName) + self.dropPosition = 0 + self.setModified(True) def makePreview(self): """ @@ -1045,7 +1084,7 @@ class ServiceManager(QtGui.QWidget): # we are not over anything so drop replace = False if item is None: - self.droppos = len(self.serviceItems) + self.dropPosition = len(self.serviceItems) else: # we are over somthing so lets investigate pos = self._getParentItemData(item) - 1 @@ -1056,14 +1095,14 @@ class ServiceManager(QtGui.QWidget): action = self.dndMenu.exec_(QtGui.QCursor.pos()) # New action required if action == self.newAction: - self.droppos = self._getParentItemData(item) + self.dropPosition = self._getParentItemData(item) # Append to existing action if action == self.addToAction: - self.droppos = self._getParentItemData(item) + self.dropPosition = self._getParentItemData(item) item.setSelected(True) replace = True else: - self.droppos = self._getParentItemData(item) + self.dropPosition = self._getParentItemData(item) Receiver.send_message(u'%s_add_service_item' % plugin, replace) def updateThemeList(self, theme_list): @@ -1119,4 +1158,4 @@ class ServiceManager(QtGui.QWidget): data_item[u'notes'] = unicode(service_item.notes) data_item[u'selected'] = (item == curitem) data.append(data_item) - Receiver.send_message(u'servicemanager_list_response', data) \ No newline at end of file + Receiver.send_message(u'servicemanager_list_response', data) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index ff354b1c6..54bd78ccc 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -275,8 +275,15 @@ def get_images_filter(): visible_formats, actual_formats) return images_filter +def split_filename(path): + path = os.path.abspath(path) + if not os.path.isfile(path): + return path, u'' + else: + return os.path.split(path) + 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'ActionList'] \ No newline at end of file + u'get_filesystem_encoding', u'LanguageManager', u'ActionList'] From f7943d5746574a32e249c44e6ff354e70c031de1 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 1 Jan 2011 01:06:35 +0200 Subject: [PATCH 4/6] Add in an error message if there is a problem with the user's downloaded Bibles. --- openlp/plugins/bibles/lib/http.py | 19 +++++++++++++++++-- openlp/plugins/bibles/lib/mediaitem.py | 11 +++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index e0aeafa48..219c845fb 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -28,6 +28,7 @@ import logging import os import re import sqlite3 +import socket import urllib import urllib2 from HTMLParser import HTMLParseError @@ -184,6 +185,7 @@ class BGExtract(object): def __init__(self, proxyurl=None): log.debug(u'init %s', proxyurl) self.proxyurl = proxyurl + socket.setdefaulttimeout(30) def get_bible_chapter(self, version, bookname, chapter): """ @@ -210,6 +212,7 @@ class BGExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') + Receiver.send_message(u'bibles_download_error') finally: if not page: return None @@ -219,6 +222,7 @@ class BGExtract(object): soup = BeautifulSoup(page, markupMassage=cleaner) except HTMLParseError: log.exception(u'BeautifulSoup could not parse the bible page.') + Receiver.send_message(u'bibles_download_error') finally: if not soup: return None @@ -247,6 +251,7 @@ class BSExtract(object): def __init__(self, proxyurl=None): log.debug(u'init %s', proxyurl) self.proxyurl = proxyurl + socket.setdefaulttimeout(30) def get_bible_chapter(self, version, bookname, chapter): """ @@ -264,7 +269,7 @@ 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: @@ -272,6 +277,7 @@ class BSExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') + Receiver.send_message(u'bibles_download_error') finally: if not page: return None @@ -280,6 +286,7 @@ class BSExtract(object): soup = BeautifulSoup(page) except HTMLParseError: log.exception(u'BeautifulSoup could not parse the bible page.') + Receiver.send_message(u'bibles_download_error') finally: if not soup: return None @@ -308,6 +315,7 @@ class CWExtract(object): def __init__(self, proxyurl=None): log.debug(u'init %s', proxyurl) self.proxyurl = proxyurl + socket.setdefaulttimeout(30) def get_bible_chapter(self, version, bookname, chapter): """ @@ -333,6 +341,7 @@ class CWExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') + Receiver.send_message(u'bibles_download_error') finally: if not page: return None @@ -341,6 +350,7 @@ class CWExtract(object): soup = BeautifulSoup(page) except HTMLParseError: log.exception(u'BeautifulSoup could not parse the bible page.') + Receiver.send_message(u'bibles_download_error') finally: if not soup: return None @@ -491,7 +501,12 @@ class HTTPBible(BibleDB): ev = 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) + try: + return ev.get_bible_chapter(self.download_name, book, chapter) + except: + log.exception(u'Error occurred while downloading verses') + Receiver.send_message(u'bibles_download_error') + return None def get_books(self): """ diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 3f5ed41e4..39225acf1 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -261,6 +261,8 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'bibles_hideprogress'), self.onSearchProgressHide) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_nobook'), self.onNoBookFound) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'bibles_download_error'), self.onDownloadError) def addListViewToToolBar(self): MediaManagerItem.addListViewToToolBar(self) @@ -367,6 +369,15 @@ class BibleMediaItem(MediaManagerItem): 'No matching book could be found in this Bible.')) self.AdvancedSearchButton.setEnabled(True) + def onDownloadError(self): + QtGui.QMessageBox.critical(self, + translate('BiblesPlugin.MediaItem', 'Download Error'), + translate('BiblesPlugin.MediaItem', + 'There was a problem downloading your verse selection. Please ' + 'check your Internet connection, and if this error continues to ' + 'occur please consider reporting a bug.')) + self.AdvancedSearchButton.setEnabled(True) + def onImportClick(self): if not hasattr(self, u'import_wizard'): self.import_wizard = BibleImportForm(self, self.parent.manager, From 4bb59bff6734339064c83a721e54c2a221bb54f2 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 1 Jan 2011 12:33:14 +0200 Subject: [PATCH 5/6] Fix bug #641661 --- openlp/core/lib/eventreceiver.py | 2 +- openlp/core/ui/mainwindow.py | 19 +++++++- openlp/plugins/bibles/lib/db.py | 14 +++--- openlp/plugins/bibles/lib/http.py | 66 +++++++++++++++++--------- openlp/plugins/bibles/lib/mediaitem.py | 20 -------- 5 files changed, 70 insertions(+), 51 deletions(-) diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index 4f69c519f..b39173849 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -278,4 +278,4 @@ class Receiver(object): """ Get the global ``eventreceiver`` instance. """ - return Receiver.eventreceiver \ No newline at end of file + return Receiver.eventreceiver diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index a378dd633..ee15b31b1 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -612,6 +612,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'maindisplay_status_text'), self.showStatusMessage) + # Simple message boxes + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlp_error_message'), self.onErrorMessage) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlp_warning_message'), self.onWarningMessage) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlp_information_message'), + self.onInformationMessage) # warning cyclic dependency # RenderManager needs to call ThemeManager and # ThemeManager needs to call RenderManager @@ -720,6 +728,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): translate('OpenLP.MainWindow', 'The Main Display has been blanked out')) + def onErrorMessage(self, data): + QtGui.QMessageBox.critical(self, data[u'title'], data[u'message']) + + def onWarningMessage(self, data): + QtGui.QMessageBox.warning(self, data[u'title'], data[u'message']) + + def onInformationMessage(self, data): + QtGui.QMessageBox.information(self, data[u'title'], data[u'message']) + def onHelpWebSiteClicked(self): """ Load the OpenLP website @@ -834,7 +851,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): else: ret = QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'Close OpenLP'), - translate('OpenLP.MainWindow', 'Are you sure you want to Exit?'), + translate('OpenLP.MainWindow', 'Are you sure you want to close OpenLP?'), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 5f37f3c73..62068437a 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -33,7 +33,7 @@ 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 translate +from openlp.core.lib import Receiver, translate from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) @@ -354,12 +354,12 @@ class BibleDB(QtCore.QObject, Manager): verse_list.extend(verses) else: log.debug(u'OpenLP failed to find book %s', book) - QtGui.QMessageBox.information(self.bible_plugin.mediaItem, - translate('BiblesPlugin.BibleDB', 'Book not found'), - translate('BiblesPlugin.BibleDB', 'The book you requested ' - 'could not be found in this Bible. Please check your ' - 'spelling and that this is a complete Bible not just ' - 'one testament.')) + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblesPlugin', 'No Book Found'), + u'message': translate('BiblesPlugin', 'No matching book ' + 'could be found in this Bible. Check that you have ' + '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 219c845fb..a4f93f929 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -35,7 +35,7 @@ from HTMLParser import HTMLParseError from BeautifulSoup import BeautifulSoup, NavigableString -from openlp.core.lib import Receiver +from openlp.core.lib import Receiver, translate from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib.db import BibleDB, Book @@ -212,7 +212,13 @@ class BGExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') - Receiver.send_message(u'bibles_download_error') + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblePlugin.HTTPBible', 'Download Error'), + u'message': 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.') + }) finally: if not page: return None @@ -277,7 +283,13 @@ class BSExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') - Receiver.send_message(u'bibles_download_error') + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblePlugin.HTTPBible', 'Download Error'), + u'message': 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.') + }) finally: if not page: return None @@ -286,10 +298,13 @@ class BSExtract(object): soup = BeautifulSoup(page) except HTMLParseError: log.exception(u'BeautifulSoup could not parse the bible page.') - Receiver.send_message(u'bibles_download_error') - finally: - if not soup: - return None + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblePlugin.HTTPBible', 'Parse Error'), + u'message': translate('BiblePlugin.HTTPBible', 'There was a ' + 'problem extracting your verse selection. If this error ' + 'continues to occur consider reporting a bug.') + }) + return None Receiver.send_message(u'openlp_process_events') content = None try: @@ -341,19 +356,26 @@ class CWExtract(object): Receiver.send_message(u'openlp_process_events') except urllib2.URLError: log.exception(u'The web bible page could not be downloaded.') - Receiver.send_message(u'bibles_download_error') - finally: - if not page: - return None + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblePlugin.HTTPBible', 'Download Error'), + u'message': 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.') + }) + return None soup = None try: soup = BeautifulSoup(page) except HTMLParseError: log.exception(u'BeautifulSoup could not parse the bible page.') - Receiver.send_message(u'bibles_download_error') - finally: - if not soup: - return None + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblePlugin.HTTPBible', 'Parse Error'), + u'message': translate('BiblePlugin.HTTPBible', 'There was a ' + 'problem extracting your verse selection. If this error ' + 'continues to occur consider reporting a bug.') + }) + return None Receiver.send_message(u'openlp_process_events') htmlverses = soup.findAll(u'span', u'versetext') verses = {} @@ -463,7 +485,12 @@ class HTTPBible(BibleDB): if not db_book: book_details = self.lookup_book(book) if not book_details: - Receiver.send_message(u'bibles_nobook') + Receiver.send_message(u'openlp_error_message', { + u'title': translate('BiblesPlugin', 'No Book Found'), + u'message': translate('BiblesPlugin', 'No matching ' + 'book could be found in this Bible. Check that you' + 'have spelled the name of the book correctly.') + }) return [] db_book = self.create_book(book_details[u'name'], book_details[u'abbreviation'], @@ -501,12 +528,7 @@ class HTTPBible(BibleDB): ev = BGExtract(self.proxy_server) elif self.download_source.lower() == u'bibleserver': ev = BSExtract(self.proxy_server) - try: - return ev.get_bible_chapter(self.download_name, book, chapter) - except: - log.exception(u'Error occurred while downloading verses') - Receiver.send_message(u'bibles_download_error') - return None + return ev.get_bible_chapter(self.download_name, book, chapter) def get_books(self): """ diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 39225acf1..d557897ed 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -259,10 +259,6 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'bibles_showprogress'), self.onSearchProgressShow) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_hideprogress'), self.onSearchProgressHide) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_nobook'), self.onNoBookFound) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'bibles_download_error'), self.onDownloadError) def addListViewToToolBar(self): MediaManagerItem.addListViewToToolBar(self) @@ -362,22 +358,6 @@ class BibleMediaItem(MediaManagerItem): def onSearchProgressHide(self): self.SearchProgress.setVisible(False) - def onNoBookFound(self): - QtGui.QMessageBox.critical(self, - translate('BiblesPlugin.MediaItem', 'No Book Found'), - translate('BiblesPlugin.MediaItem', - 'No matching book could be found in this Bible.')) - self.AdvancedSearchButton.setEnabled(True) - - def onDownloadError(self): - QtGui.QMessageBox.critical(self, - translate('BiblesPlugin.MediaItem', 'Download Error'), - translate('BiblesPlugin.MediaItem', - 'There was a problem downloading your verse selection. Please ' - 'check your Internet connection, and if this error continues to ' - 'occur please consider reporting a bug.')) - self.AdvancedSearchButton.setEnabled(True) - def onImportClick(self): if not hasattr(self, u'import_wizard'): self.import_wizard = BibleImportForm(self, self.parent.manager, From 8cd04bc0173b88bbab7c616a9246c21dac2b68dd Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 1 Jan 2011 14:25:12 +0200 Subject: [PATCH 6/6] Fixed a few stray bugs to do with services. --- openlp/core/ui/mainwindow.py | 5 +++-- openlp/core/ui/servicemanager.py | 28 ++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 260384a5f..a442f983d 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1007,11 +1007,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if recentFilesToDisplay: self.FileMenu.addSeparator() for fileId, filename in enumerate(recentFilesToDisplay): - action = QtGui.QAction(u'&%d %s' % (fileId +1, + log.debug('Recent file name: %s', filename) + action = QtGui.QAction(u'&%d %s' % (fileId + 1, QtCore.QFileInfo(filename).fileName()), self) action.setData(QtCore.QVariant(filename)) self.connect(action, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.loadService) + self.ServiceManagerContents.onRecentServiceClicked) self.FileMenu.addAction(action) self.FileMenu.addSeparator() self.FileMenu.addAction(self.FileMenuActions[-1]) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 18dba7058..9d7bada14 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -347,10 +347,7 @@ class ServiceManager(QtGui.QWidget): elif result == QtGui.QMessageBox.Save: if not self.saveFile(): return False - self.serviceManagerList.clear() - self.serviceItems = [] - self.setFileName(u'') - self.setModified(False) + self.newFile() def onLoadServiceClicked(self): if self.isModified(): @@ -381,6 +378,19 @@ class ServiceManager(QtGui.QWidget): def onSaveServiceAsClicked(self): self.saveFileAs() + def onRecentServiceClicked(self): + sender = self.sender() + self.loadFile(sender.data().toString()) + + def newFile(self): + """ + Create a blank new service file. + """ + self.serviceManagerList.clear() + self.serviceItems = [] + self.setFileName(u'') + self.setModified(False) + def saveFile(self): """ Save the current Service file. @@ -457,6 +467,8 @@ class ServiceManager(QtGui.QWidget): def loadFile(self, fileName): if not fileName: return False + else: + fileName = unicode(fileName) zip = None fileTo = None try: @@ -475,18 +487,18 @@ class ServiceManager(QtGui.QWidget): continue osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) filePath = os.path.join(self.servicePath, - split_filename(osfile)[1]) + os.path.split(osfile)[1]) fileTo = open(filePath, u'wb') fileTo.write(zip.read(file)) fileTo.flush() fileTo.close() - if file_path.endswith(u'osd'): - p_file = file_path + if filePath.endswith(u'osd'): + p_file = filePath if 'p_file' in locals(): fileTo = open(p_file, u'r') items = cPickle.load(fileTo) fileTo.close() - self.onNewService() + self.newFile() for item in items: serviceItem = ServiceItem() serviceItem.render_manager = self.parent.renderManager