From ce230df91d889faae6ca1f0300f1fb458eb8c1c6 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 19 Jan 2012 15:25:53 -0500 Subject: [PATCH 01/46] Added code to allow user to change the location of the OpenLP data directory --- openlp/core/ui/advancedtab.py | 240 ++++++++++++++++++++++++++++++++- openlp/core/ui/mainwindow.py | 56 +++++++- openlp/core/ui/settingsform.py | 4 +- openlp/core/utils/__init__.py | 24 +++- 4 files changed, 318 insertions(+), 6 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 045d38a7e..9dd8dbf70 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -29,9 +29,11 @@ The :mod:`advancedtab` provides an advanced settings facility. """ from PyQt4 import QtCore, QtGui +import os +import sys from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib.ui import UiStrings -from openlp.core.utils import get_images_filter +from openlp.core.utils import get_images_filter, AppLocation class AdvancedTab(SettingsTab): """ @@ -84,6 +86,53 @@ class AdvancedTab(SettingsTab): u'enableAutoCloseCheckBox') self.uiLayout.addRow(self.enableAutoCloseCheckBox) self.leftLayout.addWidget(self.uiGroupBox) + self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn) + self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox') + self.dataDirectoryLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel') + self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox) + self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit') + self.newDataDirectoryEdit.setReadOnly(True) + self.newDataDirectoryHasFilesLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.newDataDirectoryHasFilesLabel.setObjectName( + u'newDataDirectoryHasFilesLabel') + self.newDataDirectoryHasFilesLabel.setWordWrap(True) + self.dataDirectoryBrowseButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryBrowseButton.setObjectName( + u'dataDirectoryBrowseButton') + self.dataDirectoryBrowseButton.setIcon( + build_icon(u':/general/general_open.png')) + self.dataDirectoryDefaultButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryDefaultButton.setObjectName( + u'dataDirectoryBrowseButton') + self.dataDirectoryDefaultButton.setIcon( + build_icon(u':/general/general_revert.png')) + self.dataDirectoryCancelButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryCancelButton.setObjectName( + u'dataDirectoryCancelButton') + self.dataDirectoryCancelButton.setIcon( + build_icon(u':/general/general_revert.png')) + self.dataDirectoryCopyCheckBox = QtGui.QCheckBox( + self.dataDirectoryGroupBox) + self.dataDirectoryCopyCheckBox.setObjectName( + u'dataDirectoryCopyCheckBox') + self.dataDirectoryCopyCheckBox.hide() + self.newDataDirectoryHasFilesLabel.hide() + self.dataDirectoryDefaultButton.hide() + self.dataDirectoryCancelButton.hide() + self.dataDirectoryLayout =QtGui.QFormLayout(self.dataDirectoryGroupBox) + self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout') + self.dataDirectoryLayout.addWidget(self.dataDirectoryLabel) + self.dataDirectoryLayout.addWidget(self.dataDirectoryBrowseButton) + self.dataDirectoryLayout.addWidget(self.newDataDirectoryEdit) + self.dataDirectoryLayout.addWidget(self.dataDirectoryCopyCheckBox) + self.dataDirectoryLayout.addWidget(self.newDataDirectoryHasFilesLabel) + self.dataDirectoryLayout.addWidget(self.dataDirectoryDefaultButton) + self.dataDirectoryLayout.addWidget(self.dataDirectoryCancelButton) + self.leftLayout.addWidget(self.dataDirectoryGroupBox) self.leftLayout.addStretch() self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox') @@ -141,6 +190,15 @@ class AdvancedTab(SettingsTab): QtCore.SIGNAL(u'pressed()'), self.onDefaultRevertButtonPressed) QtCore.QObject.connect(self.x11BypassCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled) + QtCore.QObject.connect(self.dataDirectoryBrowseButton, + QtCore.SIGNAL(u'pressed()'), + self.onDataDirectoryBrowseButtonPressed) + QtCore.QObject.connect(self.dataDirectoryDefaultButton, + QtCore.SIGNAL(u'pressed()'), + self.onDataDirectoryDefaultButtonPressed) + QtCore.QObject.connect(self.dataDirectoryCancelButton, + QtCore.SIGNAL(u'pressed()'), + self.onDataDirectoryCancelButtonPressed) def retranslateUi(self): """ @@ -149,6 +207,8 @@ class AdvancedTab(SettingsTab): self.tabTitleVisible = UiStrings().Advanced self.uiGroupBox.setTitle( translate('OpenLP.AdvancedTab', 'UI Settings')) + self.dataDirectoryGroupBox.setTitle( + translate('OpenLP.AdvancedTab', 'Data Location')) self.recentLabel.setText( translate('OpenLP.AdvancedTab', 'Number of recent files to display:')) @@ -178,6 +238,33 @@ class AdvancedTab(SettingsTab): 'Browse for an image file to display.')) self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', 'Revert to the default OpenLP logo.')) + self.dataDirectoryBrowseButton.setText(translate('OpenLP.AdvancedTab', + 'Select new location.')) + self.dataDirectoryBrowseButton.setToolTip( + translate('OpenLP.AdvancedTab', + 'Browse for new data file location.')) + self.dataDirectoryDefaultButton.setText( + translate('OpenLP.AdvancedTab', + 'Set to default location.')) + self.dataDirectoryDefaultButton.setToolTip( + translate('OpenLP.AdvancedTab', + 'Set the data location to the default.')) + self.dataDirectoryCancelButton.setText( + translate('OpenLP.AdvancedTab', + 'Cancel data directory change')) + self.dataDirectoryCancelButton.setToolTip( + translate('OpenLP.AdvancedTab', + 'Cancel OpenLP data directory location change.')) + self.dataDirectoryCopyCheckBox.setText( + translate('OpenLP.AdvancedTab', + 'Copy data to new location.')) + self.dataDirectoryCopyCheckBox.setToolTip( + translate('OpenLP.AdvancedTab', + 'Copy the OpenLP data files to the new location.')) + self.newDataDirectoryHasFilesLabel.setText( + translate('OpenLP.AdvancedTab', + 'Warning - New data directory location contains OpenLP ' + 'data files. These files WILL be replaced during a copy.')) self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11')) self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab', @@ -221,6 +308,35 @@ class AdvancedTab(SettingsTab): QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ .toString()) settings.endGroup() + # Since data location can be changed, make sure the path is present. + data_path = AppLocation.get_data_path() + if not os.path.exists(data_path): + answer = QtGui.QMessageBox.critical(self, + translate('OpenLP.AdvancedTab', + 'Data directory error - Reset to default?'), + translate('OpenLP.AdvancedTab', + 'OpenLP data directory was not found \n\n %s \n\n' + 'This data directory was previously changed from the OpenLP ' + 'default location. If the new location was on removable ' + 'media, that media needs to be made available.\n\n' + 'Click "No" to stop loading OpenLP. allowing you to fix ' + 'the the problem.\n\n' + 'Click "Yes" to reset the data directory location to the ' + 'default' % data_path), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), + QtGui.QMessageBox.No) + if answer == QtGui.QMessageBox.No: + Receiver.send_message(u'cleanup') + sys.exit() + data_path = AppLocation.set_default_data_path() + print AppLocation.IsDefaultDataPath + if AppLocation.IsDefaultDataPath: + self.dataDirectoryDefaultButton.hide() + else: + self.dataDirectoryDefaultButton.show() + self.dataDirectoryLabel.setText(data_path) self.defaultColorButton.setStyleSheet( u'background-color: %s' % self.default_color) @@ -248,6 +364,10 @@ class AdvancedTab(SettingsTab): QtCore.QVariant(self.x11BypassCheckBox.isChecked())) settings.setValue(u'default color', self.default_color) settings.setValue(u'default image', self.defaultFileEdit.text()) + if not AppLocation.IsDefaultDataPath: + settings.setValue(u'data path', self.dataDirectoryLabel.text()) + settings.setValue(u'copy data', + QtCore.QVariant(self.dataDirectoryCopyCheckBox.isChecked())) settings.endGroup() if self.display_changed: Receiver.send_message(u'config_screen_changed') @@ -271,6 +391,124 @@ class AdvancedTab(SettingsTab): self.defaultFileEdit.setText(filename) self.defaultFileEdit.setFocus() + def onDataDirectoryBrowseButtonPressed(self): + """ + Browse for a new data directory location. + """ + old_data_path = str(self.dataDirectoryLabel.text()) + old_root_path = os.path.abspath(os.path.join( + old_data_path, u'..', u'..')) + # Get the new directory location. + new_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, + translate('OpenLP.AdvancedTab', + 'Select Data Folder Root Directory'), old_root_path, + options=QtGui.QFileDialog.ShowDirsOnly)) + # Set the new data path + settings = QtCore.QSettings() + new_data_path = os.path.join(new_path, 'OpenLP', 'Data') + if new_path: + if old_data_path.lower() == new_data_path.lower(): + self.onDataDirectoryCancelButtonPressed() + return + else: + return + # Make sure they want to change the data. + answer = QtGui.QMessageBox.question(self, + translate('OpenLP.AdvancedTab', 'Change data directory?'), + translate('OpenLP.AdvancedTab', + 'Are you sure you want to change the location of the OpenLP data\n' + 'directory to:\n\n %s \n\n' + 'This is the root folder for the data. The data will be stored ' + 'in:\n\n %s \n\n ' + 'The data directory will be changed when OpenLP is closed.' + % (new_path, new_data_path)), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), + QtGui.QMessageBox.No) + if answer != QtGui.QMessageBox.Yes: + return + # Check if data already exists here + self.checkDataOverwrite(new_data_path) + # Save the new location. + settings.setValue(u'%s/new data path' % self.settingsSection, + new_data_path) + self.newDataDirectoryEdit.setText(new_data_path) + self.dataDirectoryCancelButton.show() + + def onDataDirectoryDefaultButtonPressed(self): + """ + Re-set the data directory location to the 'default' location. + """ + # Make sure they want to change the data location back to the default. + answer = QtGui.QMessageBox.question(self, + translate('OpenLP.AdvancedTab', 'Reset data directory to default?'), + translate('OpenLP.AdvancedTab', + 'Are you sure you want to change the location of the OpenLP data\n' + 'directory to the default locatiom? \n\n' + 'This location will be used after OpenLP is closed.'), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), + QtGui.QMessageBox.No) + if answer != QtGui.QMessageBox.Yes: + return + old_data_path = str(self.dataDirectoryLabel.text()) + new_data_path = AppLocation.get_directory(AppLocation.DataDir) + if old_data_path.lower() == new_data_path.lower(): + self.onDataDirectoryCancelButtonPressed() + return + self.checkDataOverwrite(new_data_path) + # Save the new location. + settings = QtCore.QSettings() + settings.setValue(u'%s/new data path' % self.settingsSection, + new_data_path) + self.newDataDirectoryEdit.setText(new_data_path) + self.dataDirectoryCancelButton.show() + + def checkDataOverwrite(self, data_path ): + test_path = os.path.join(data_path, u'songs') + self.dataDirectoryCopyCheckBox.show() + if os.path.exists(test_path): + # Check is they want to replace existing data + answer = QtGui.QMessageBox.warning(self, + translate('OpenLP.AdvancedTab', 'Replace existing data?'), + translate('OpenLP.AdvancedTab', + 'WARNING \n\n' + 'The location you have selected \n\n %s \n\n' + 'appears to contain OpenLP data files. Do you wish to replace ' + 'these files with the current data files?' % data_path), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), + QtGui.QMessageBox.No) + if answer == QtGui.QMessageBox.Yes: + self.dataDirectoryCopyCheckBox.setChecked(True) + else: + self.dataDirectoryCopyCheckBox.setChecked(False) + self.newDataDirectoryHasFilesLabel.show() + else: + self.dataDirectoryCopyCheckBox.setChecked(True) + self.newDataDirectoryHasFilesLabel.hide() + + def onDataDirectoryCancelButtonPressed(self): + """ + Cancel the data directory location change + """ + self.newDataDirectoryEdit.setText(u'') + self.dataDirectoryCopyCheckBox.setChecked(False) + settings = QtCore.QSettings() + settings.remove(u'%s/new data path' % self.settingsSection) + settings.remove(u'%s/copy data' % self.settingsSection) + self.dataDirectoryCopyCheckBox.hide() + self.dataDirectoryCancelButton.hide() + self.newDataDirectoryHasFilesLabel.hide() + print AppLocation.IsDefaultDataPath + if AppLocation.IsDefaultDataPath: + self.dataDirectoryDefaultButton.hide() + else: + self.dataDirectoryDefaultButton.show() + def onDefaultRevertButtonPressed(self): self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png') self.defaultFileEdit.setFocus() diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 3490dfada..f5d493ff4 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -29,13 +29,16 @@ import logging import os import sys import shutil +from distutils import dir_util +from distutils.errors import DistutilsFileError from tempfile import gettempdir from datetime import datetime from PyQt4 import QtCore, QtGui from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ - PluginManager, Receiver, translate, ImageManager, PluginStatus + PluginManager, Receiver, translate, ImageManager, PluginStatus, \ + SettingsManager from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ icon_action, shortcut_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ @@ -629,6 +632,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'cleanup'), self.cleanUp) # Media Manager QtCore.QObject.connect(self.mediaToolBox, QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged) @@ -1181,6 +1186,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.pluginManager.finalise_plugins() # Save settings self.saveSettings() + # Check if we need to change the data directory + if QtCore.QSettings().value(u'advanced/new data path', + QtCore.QVariant(u'none')).toString() != u'none': + self.changeDataDirectory() # Close down the display self.liveController.display.close() @@ -1445,3 +1454,48 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.timer_id = 0 self.loadProgressBar.hide() Receiver.send_message(u'openlp_process_events') + + def changeDataDirectory(self): + old_data_path = str(AppLocation.get_data_path()) + settings = QtCore.QSettings() + new_data_path = str(settings.value(u'advanced/new data path', + QtCore.QVariant(u'none')).toString()) + settings.remove(u'advanced/new data path') + # Copy OpenLP data to new location if requested. + if settings.value(u'advanced/copy data', + QtCore.QVariant(u'none')).toBool(): + try: + Receiver.send_message(u'openlp_process_events') + QtGui.QMessageBox.information(self, + translate('OpenLP.MainWindow', 'Copy Data Directory'), + translate('OpenLP.MainWindow', + 'OpenLP will now copy your data files from \n\n %s \n\n' + 'to \n\n %s' % (old_data_path, new_data_path)), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Ok)) + Receiver.send_message(u'cursor_busy') + dir_util.copy_tree(old_data_path, new_data_path) + except (IOError, os.error, DistutilsFileError), why: + Receiver.send_message(u'cursor_normal') + QtGui.QMessageBox.critical(self, + translate('OpenLP.MainWindow', 'New data directory error'), + translate('OpenLP.MainWindow', + 'OpenLP Data directory copy failed \n\n %s' % str(why)), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Ok)) + return False + settings.remove(u'advanced/copy data') + Receiver.send_message(u'cursor_normal') + # Change the location of data directory in config file. + settings.setValue(u'advanced/data path', new_data_path) + QtGui.QMessageBox.information(self, + translate('OpenLP.MainWindow', 'New data directory'), + translate('OpenLP.MainWindow', + 'OpenLP Data directory successfully changed to:\n\n %s \n\n' + 'The new data directory location will be used ' + 'the next time you start OpenLP.' % new_data_path), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Ok)) + # Check if the new data path is our default. + if new_data_path == AppLocation.get_directory(AppLocation.DataDir): + settings.remove(u'advanced/data path') diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 0aa5d44d0..abafe2af7 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings """ import logging -from PyQt4 import QtGui +from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, build_icon, PluginStatus from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab @@ -102,6 +102,8 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Process the form saving the settings """ + # Dialog was cancelled, remove any pending data move + QtCore.QSettings().remove(u'advanced/new data path') for tabIndex in range(0, self.stackedLayout.count()): self.stackedLayout.widget(tabIndex).cancel() return QtGui.QDialog.reject(self) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 9fa5bcd77..00e763751 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -126,7 +126,8 @@ class AppLocation(object): VersionDir = 5 CacheDir = 6 LanguageDir = 7 - + IsDefaultDataPath = True + # Base path where data/config/cache dir is located BaseDir = None @@ -165,10 +166,27 @@ class AppLocation(object): """ Return the path OpenLP stores all its data under. """ - path = AppLocation.get_directory(AppLocation.DataDir) - check_directory_exists(path) + # Check if we have a different data location. + path = unicode(QtCore.QSettings().value( + u'advanced/data path', QtCore.QVariant(u'none')).toString()) + if path == u'none': + AppLocation.IsDefaultDataPath = True + path = AppLocation.get_directory(AppLocation.DataDir) + check_directory_exists(path) + else: + AppLocation.IsDefaultDataPath = False return path + @staticmethod + def set_default_data_path(): + """ + Reset to default and return the path OpenLP stores all its data under. + """ + # Remove override location. + QtCore.QSettings().remove(u'advanced/data path') + data_path = AppLocation.get_data_path() + return data_path + @staticmethod def get_section_data_path(section): """ From e86272f4d501a44762a94b0159b16a242fb5d9f2 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 3 May 2012 14:30:30 -0400 Subject: [PATCH 02/46] Fixed dialogues. Made changes to GUI. --- openlp/core/ui/advancedtab.py | 311 ++++++++++++++++++--------------- openlp/core/ui/mainwindow.py | 67 +++---- openlp/core/ui/settingsform.py | 4 +- openlp/core/utils/__init__.py | 21 +-- 4 files changed, 207 insertions(+), 196 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index d04da8b61..1af8d1268 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -31,12 +31,15 @@ from datetime import datetime, timedelta from PyQt4 import QtCore, QtGui +import logging import os import sys from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib.ui import UiStrings -from openlp.core.lib import SlideLimits from openlp.core.utils import get_images_filter, AppLocation +from openlp.core.lib import SlideLimits + +log = logging.getLogger(__name__) class AdvancedTab(SettingsTab): """ @@ -61,6 +64,7 @@ class AdvancedTab(SettingsTab): '#strftime-strptime-behavior for more information.')) self.defaultImage = u':/graphics/openlp-splash-screen.png' self.defaultColor = u'#ffffff' + self.dataExists = False self.iconPath = u':/system/system_settings.png' advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') SettingsTab.__init__(self, parent, u'Advanced', advanced_translated) @@ -100,53 +104,6 @@ class AdvancedTab(SettingsTab): u'enableAutoCloseCheckBox') self.uiLayout.addRow(self.enableAutoCloseCheckBox) self.leftLayout.addWidget(self.uiGroupBox) - self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn) - self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox') - self.dataDirectoryLabel= QtGui.QLabel(self.dataDirectoryGroupBox) - self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel') - self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox) - self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit') - self.newDataDirectoryEdit.setReadOnly(True) - self.newDataDirectoryHasFilesLabel= QtGui.QLabel(self.dataDirectoryGroupBox) - self.newDataDirectoryHasFilesLabel.setObjectName( - u'newDataDirectoryHasFilesLabel') - self.newDataDirectoryHasFilesLabel.setWordWrap(True) - self.dataDirectoryBrowseButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryBrowseButton.setObjectName( - u'dataDirectoryBrowseButton') - self.dataDirectoryBrowseButton.setIcon( - build_icon(u':/general/general_open.png')) - self.dataDirectoryDefaultButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryDefaultButton.setObjectName( - u'dataDirectoryBrowseButton') - self.dataDirectoryDefaultButton.setIcon( - build_icon(u':/general/general_revert.png')) - self.dataDirectoryCancelButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryCancelButton.setObjectName( - u'dataDirectoryCancelButton') - self.dataDirectoryCancelButton.setIcon( - build_icon(u':/general/general_revert.png')) - self.dataDirectoryCopyCheckBox = QtGui.QCheckBox( - self.dataDirectoryGroupBox) - self.dataDirectoryCopyCheckBox.setObjectName( - u'dataDirectoryCopyCheckBox') - self.dataDirectoryCopyCheckBox.hide() - self.newDataDirectoryHasFilesLabel.hide() - self.dataDirectoryDefaultButton.hide() - self.dataDirectoryCancelButton.hide() - self.dataDirectoryLayout =QtGui.QFormLayout(self.dataDirectoryGroupBox) - self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout') - self.dataDirectoryLayout.addWidget(self.dataDirectoryLabel) - self.dataDirectoryLayout.addWidget(self.dataDirectoryBrowseButton) - self.dataDirectoryLayout.addWidget(self.newDataDirectoryEdit) - self.dataDirectoryLayout.addWidget(self.dataDirectoryCopyCheckBox) - self.dataDirectoryLayout.addWidget(self.newDataDirectoryHasFilesLabel) - self.dataDirectoryLayout.addWidget(self.dataDirectoryDefaultButton) - self.dataDirectoryLayout.addWidget(self.dataDirectoryCancelButton) - self.leftLayout.addWidget(self.dataDirectoryGroupBox) # Default service name self.serviceNameGroupBox = QtGui.QGroupBox(self.leftColumn) self.serviceNameGroupBox.setObjectName(u'serviceNameGroupBox') @@ -200,6 +157,70 @@ class AdvancedTab(SettingsTab): self.serviceNameLayout.addRow(self.serviceNameExampleLabel, self.serviceNameExample) self.leftLayout.addWidget(self.serviceNameGroupBox) + # Data Directory + self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn) + self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox') + self.dataDirectoryLayout =QtGui.QFormLayout(self.dataDirectoryGroupBox) + self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout') + self.dataDirectoryCurrentLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryCurrentLabel.setObjectName( + u'dataDirectoryCurrentLabel') + self.dataDirectoryLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel') + self.dataDirectoryNewLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryNewLabel.setObjectName(u'dataDirectoryCurrentLabel') + self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox) + self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit') + self.newDataDirectoryEdit.setReadOnly(True) + self.newDataDirectoryHasFilesLabel = QtGui.QLabel( + self.dataDirectoryGroupBox) + self.newDataDirectoryHasFilesLabel.setObjectName( + u'newDataDirectoryHasFilesLabel') + self.newDataDirectoryHasFilesLabel.setWordWrap(True) + self.newDataDirectoryLabelHBox = QtGui.QHBoxLayout() + self.newDataDirectoryLabelHBox.setObjectName( + u'newDataDirectoryLabelHBox') + self.dataDirectoryBrowseButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryBrowseButton.setObjectName( + u'dataDirectoryBrowseButton') + self.dataDirectoryBrowseButton.setIcon( + build_icon(u':/general/general_open.png')) + self.dataDirectoryDefaultButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryDefaultButton.setObjectName( + u'dataDirectoryDefaultButton') + self.dataDirectoryDefaultButton.setIcon( + build_icon(u':/general/general_revert.png')) + self.dataDirectoryCancelButton = QtGui.QPushButton( + self.dataDirectoryGroupBox) + self.dataDirectoryCancelButton.setObjectName( + u'dataDirectoryCancelButton') + self.dataDirectoryCancelButton.setIcon( + build_icon(u':/general/general_delete.png')) + self.newDataDirectoryLabelHBox.addWidget(self.newDataDirectoryEdit) + self.newDataDirectoryLabelHBox.addWidget( + self.dataDirectoryBrowseButton) + self.newDataDirectoryLabelHBox.addWidget( + self.dataDirectoryDefaultButton) + self.dataDirectoryCopyCheckHBox = QtGui.QHBoxLayout() + self.dataDirectoryCopyCheckHBox.setObjectName( + u'dataDirectoryCopyCheckHBox') + self.dataDirectoryCopyCheckBox = QtGui.QCheckBox( + self.dataDirectoryGroupBox) + self.dataDirectoryCopyCheckBox.setObjectName( + u'dataDirectoryCopyCheckBox') + self.dataDirectoryCopyCheckHBox.addWidget( + self.dataDirectoryCopyCheckBox) + self.dataDirectoryCopyCheckHBox.addWidget( + self.dataDirectoryCancelButton) + self.dataDirectoryLayout.addRow(self.dataDirectoryCurrentLabel, + self.dataDirectoryLabel) + self.dataDirectoryLayout.addRow(self.dataDirectoryNewLabel, + self.newDataDirectoryLabelHBox) + self.dataDirectoryLayout.addRow(self.dataDirectoryCopyCheckHBox) + self.dataDirectoryLayout.addRow(self.newDataDirectoryHasFilesLabel) + self.leftLayout.addWidget(self.dataDirectoryGroupBox) self.leftLayout.addStretch() # Default Image self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) @@ -268,7 +289,6 @@ class AdvancedTab(SettingsTab): self.x11Layout.addWidget(self.x11BypassCheckBox) self.rightLayout.addWidget(self.x11GroupBox) self.rightLayout.addStretch() - self.shouldUpdateServiceNameExample = False QtCore.QObject.connect(self.serviceNameCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled) @@ -292,21 +312,24 @@ class AdvancedTab(SettingsTab): QtCore.SIGNAL(u'clicked()'), self.onDefaultRevertButtonClicked) QtCore.QObject.connect(self.x11BypassCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled) + QtCore.QObject.connect(self.dataDirectoryBrowseButton, + QtCore.SIGNAL(u'clicked()'), + self.onDataDirectoryBrowseButtonClicked) + QtCore.QObject.connect(self.dataDirectoryDefaultButton, + QtCore.SIGNAL(u'clicked()'), + self.onDataDirectoryDefaultButtonClicked) + QtCore.QObject.connect(self.dataDirectoryCancelButton, + QtCore.SIGNAL(u'clicked()'), + self.onDataDirectoryCancelButtonClicked) + QtCore.QObject.connect(self.dataDirectoryCopyCheckBox, + QtCore.SIGNAL(u'toggled(bool)'), + self.onDataDirectoryCopyCheckBoxToggled) QtCore.QObject.connect(self.endSlideRadioButton, QtCore.SIGNAL(u'clicked()'), self.onEndSlideButtonClicked) QtCore.QObject.connect(self.wrapSlideRadioButton, QtCore.SIGNAL(u'clicked()'), self.onWrapSlideButtonClicked) QtCore.QObject.connect(self.nextItemRadioButton, QtCore.SIGNAL(u'clicked()'), self.onnextItemButtonClicked) - QtCore.QObject.connect(self.dataDirectoryBrowseButton, - QtCore.SIGNAL(u'pressed()'), - self.onDataDirectoryBrowseButtonPressed) - QtCore.QObject.connect(self.dataDirectoryDefaultButton, - QtCore.SIGNAL(u'pressed()'), - self.onDataDirectoryDefaultButtonPressed) - QtCore.QObject.connect(self.dataDirectoryCancelButton, - QtCore.SIGNAL(u'pressed()'), - self.onDataDirectoryCancelButtonPressed) def retranslateUi(self): """ @@ -380,20 +403,19 @@ class AdvancedTab(SettingsTab): 'Browse for an image file to display.')) self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', 'Revert to the default OpenLP logo.')) - self.dataDirectoryBrowseButton.setText(translate('OpenLP.AdvancedTab', - 'Select new location.')) + self.dataDirectoryCurrentLabel.setText(translate('OpenLP.AdvancedTab', + 'Current:')) + self.dataDirectoryNewLabel.setText(translate('OpenLP.AdvancedTab', + 'New:')) self.dataDirectoryBrowseButton.setToolTip( translate('OpenLP.AdvancedTab', 'Browse for new data file location.')) - self.dataDirectoryDefaultButton.setText( - translate('OpenLP.AdvancedTab', - 'Set to default location.')) self.dataDirectoryDefaultButton.setToolTip( translate('OpenLP.AdvancedTab', 'Set the data location to the default.')) self.dataDirectoryCancelButton.setText( translate('OpenLP.AdvancedTab', - 'Cancel data directory change')) + 'Cancel Location Change')) self.dataDirectoryCancelButton.setToolTip( translate('OpenLP.AdvancedTab', 'Cancel OpenLP data directory location change.')) @@ -405,8 +427,8 @@ class AdvancedTab(SettingsTab): 'Copy the OpenLP data files to the new location.')) self.newDataDirectoryHasFilesLabel.setText( translate('OpenLP.AdvancedTab', - 'Warning - New data directory location contains OpenLP ' - 'data files. These files WILL be replaced during a copy.')) + 'WARNING: New data directory location contains' + 'OpenLP data files. These files WILL be replaced during a copy.')) self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11')) self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab', @@ -484,12 +506,16 @@ class AdvancedTab(SettingsTab): else: self.nextItemRadioButton.setChecked(True) settings.endGroup() + self.dataDirectoryCopyCheckBox.hide() + self.newDataDirectoryHasFilesLabel.hide() + self.dataDirectoryCancelButton.hide() # Since data location can be changed, make sure the path is present. - data_path = AppLocation.get_data_path() - if not os.path.exists(data_path): + self.currentDataPath = AppLocation.get_data_path() + if not os.path.exists(self.currentDataPath): + log.exception(u'Data path not found %s' % self.currentDataPath) answer = QtGui.QMessageBox.critical(self, translate('OpenLP.AdvancedTab', - 'Data directory error - Reset to default?'), + 'Data Directory Error'), translate('OpenLP.AdvancedTab', 'OpenLP data directory was not found \n\n %s \n\n' 'This data directory was previously changed from the OpenLP ' @@ -497,22 +523,23 @@ class AdvancedTab(SettingsTab): 'media, that media needs to be made available.\n\n' 'Click "No" to stop loading OpenLP. allowing you to fix ' 'the the problem.\n\n' - 'Click "Yes" to reset the data directory location to the ' - 'default' % data_path), + 'Click "Yes" to reset the data directory to the default ' + 'location.' % self.currentDataPath), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: + log.exception(u'User requested termination') Receiver.send_message(u'cleanup') sys.exit() - data_path = AppLocation.set_default_data_path() - print AppLocation.IsDefaultDataPath - if AppLocation.IsDefaultDataPath: - self.dataDirectoryDefaultButton.hide() - else: - self.dataDirectoryDefaultButton.show() - self.dataDirectoryLabel.setText(data_path) + # Set data location to default. + settings.remove(u'advanced/data path') + self.currentDataPath = AppLocation.get_data_path() + log.exception(u'User requested data path set to default %s' + % self.currentDataPath) + self.dataDirectoryLabel.setText(os.path.abspath( + os.path.join(self.currentDataPath, u'..'))) self.defaultColorButton.setStyleSheet( u'background-color: %s' % self.defaultColor) @@ -556,10 +583,6 @@ class AdvancedTab(SettingsTab): settings.setValue(u'default color', self.defaultColor) settings.setValue(u'default image', self.defaultFileEdit.text()) settings.setValue(u'slide limits', QtCore.QVariant(self.slide_limits)) - if not AppLocation.IsDefaultDataPath: - settings.setValue(u'data path', self.dataDirectoryLabel.text()) - settings.setValue(u'copy data', - QtCore.QVariant(self.dataDirectoryCopyCheckBox.isChecked())) settings.endGroup() if self.displayChanged: Receiver.send_message(u'config_screen_changed') @@ -627,123 +650,123 @@ class AdvancedTab(SettingsTab): self.defaultFileEdit.setText(filename) self.defaultFileEdit.setFocus() - def onDataDirectoryBrowseButtonPressed(self): + def onDataDirectoryBrowseButtonClicked(self): """ Browse for a new data directory location. """ - old_data_path = str(self.dataDirectoryLabel.text()) - old_root_path = os.path.abspath(os.path.join( - old_data_path, u'..', u'..')) + old_root_path = unicode(str(self.dataDirectoryLabel.text())) # Get the new directory location. new_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, translate('OpenLP.AdvancedTab', - 'Select Data Folder Root Directory'), old_root_path, + 'Select Data Directory Location'), old_root_path, options=QtGui.QFileDialog.ShowDirsOnly)) - # Set the new data path - settings = QtCore.QSettings() - new_data_path = os.path.join(new_path, 'OpenLP', 'Data') + # Set the new data path. + new_data_path = os.path.join(new_path, 'openlp_data') if new_path: - if old_data_path.lower() == new_data_path.lower(): - self.onDataDirectoryCancelButtonPressed() + if self.currentDataPath.lower() == new_data_path.lower(): + self.onDataDirectoryCancelButtonClicked() return else: return # Make sure they want to change the data. answer = QtGui.QMessageBox.question(self, - translate('OpenLP.AdvancedTab', 'Change data directory?'), + translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'), translate('OpenLP.AdvancedTab', - 'Are you sure you want to change the location of the OpenLP data\n' - 'directory to:\n\n %s \n\n' - 'This is the root folder for the data. The data will be stored ' - 'in:\n\n %s \n\n ' - 'The data directory will be changed when OpenLP is closed.' - % (new_path, new_data_path)), + 'Are you sure you want to change the location of the OpenLP ' + 'data directory to:\n\n %s \n\n' + 'The data directory will be changed when OpenLP is closed.' + % new_path), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer != QtGui.QMessageBox.Yes: return - # Check if data already exists here + # Check if data already exists here. self.checkDataOverwrite(new_data_path) # Save the new location. - settings.setValue(u'%s/new data path' % self.settingsSection, - new_data_path) - self.newDataDirectoryEdit.setText(new_data_path) + Receiver.send_message(u'set_new_data_path', new_data_path) + self.newDataDirectoryEdit.setText(new_path) self.dataDirectoryCancelButton.show() - def onDataDirectoryDefaultButtonPressed(self): + def onDataDirectoryDefaultButtonClicked(self): """ Re-set the data directory location to the 'default' location. """ - # Make sure they want to change the data location back to the default. - answer = QtGui.QMessageBox.question(self, - translate('OpenLP.AdvancedTab', 'Reset data directory to default?'), - translate('OpenLP.AdvancedTab', - 'Are you sure you want to change the location of the OpenLP data\n' - 'directory to the default locatiom? \n\n' - 'This location will be used after OpenLP is closed.'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if answer != QtGui.QMessageBox.Yes: - return - old_data_path = str(self.dataDirectoryLabel.text()) new_data_path = AppLocation.get_directory(AppLocation.DataDir) - if old_data_path.lower() == new_data_path.lower(): - self.onDataDirectoryCancelButtonPressed() - return - self.checkDataOverwrite(new_data_path) - # Save the new location. - settings = QtCore.QSettings() - settings.setValue(u'%s/new data path' % self.settingsSection, - new_data_path) - self.newDataDirectoryEdit.setText(new_data_path) - self.dataDirectoryCancelButton.show() + if self.currentDataPath.lower() != new_data_path.lower(): + # Make sure they want to change the data location back to the default. + answer = QtGui.QMessageBox.question(self, + translate('OpenLP.AdvancedTab', 'Reset Data Directory'), + translate('OpenLP.AdvancedTab', + 'Are you sure you want to change the location of the OpenLP ' + 'data directory to the default location? \n\n' + 'This location will be used after OpenLP is closed.'), + QtGui.QMessageBox.StandardButtons( + QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), + QtGui.QMessageBox.No) + if answer != QtGui.QMessageBox.Yes: + return + self.checkDataOverwrite(new_data_path) + # Save the new location. + Receiver.send_message(u'set_new_data_path', new_data_path) + self.newDataDirectoryEdit.setText(os.path.abspath( + os.path.join(new_data_path, u'..'))) + self.dataDirectoryCancelButton.show() + else: + # We cancel the change in case user changed their mind. + self.onDataDirectoryCancelButtonClicked() + + def onDataDirectoryCopyCheckBoxToggled(self): + Receiver.send_message(u'set_copy_data', + self.dataDirectoryCopyCheckBox.isChecked()) + if self.dataExists: + if self.dataDirectoryCopyCheckBox.isChecked(): + self.newDataDirectoryHasFilesLabel.show() + else: + self.newDataDirectoryHasFilesLabel.hide() def checkDataOverwrite(self, data_path ): test_path = os.path.join(data_path, u'songs') self.dataDirectoryCopyCheckBox.show() if os.path.exists(test_path): - # Check is they want to replace existing data + self.dataExists = True + # Check is they want to replace existing data. answer = QtGui.QMessageBox.warning(self, - translate('OpenLP.AdvancedTab', 'Replace existing data?'), + translate('OpenLP.AdvancedTab', 'Overwrite Existing Data'), translate('OpenLP.AdvancedTab', - 'WARNING \n\n' + 'WARNING: \n\n' 'The location you have selected \n\n %s \n\n' 'appears to contain OpenLP data files. Do you wish to replace ' - 'these files with the current data files?' % data_path), + 'these files with the current data files?' + % os.path.abspath(os.path.join(data_path, u'..'))), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.Yes: self.dataDirectoryCopyCheckBox.setChecked(True) + self.newDataDirectoryHasFilesLabel.show() else: self.dataDirectoryCopyCheckBox.setChecked(False) - self.newDataDirectoryHasFilesLabel.show() + self.newDataDirectoryHasFilesLabel.hide() else: + self.dataExists = False self.dataDirectoryCopyCheckBox.setChecked(True) self.newDataDirectoryHasFilesLabel.hide() - - def onDataDirectoryCancelButtonPressed(self): + + def onDataDirectoryCancelButtonClicked(self): """ Cancel the data directory location change """ - self.newDataDirectoryEdit.setText(u'') + self.newDataDirectoryEdit.clear() self.dataDirectoryCopyCheckBox.setChecked(False) - settings = QtCore.QSettings() - settings.remove(u'%s/new data path' % self.settingsSection) - settings.remove(u'%s/copy data' % self.settingsSection) + Receiver.send_message(u'set_new_data_path', u'') + Receiver.send_message(u'set_copy_data', False) self.dataDirectoryCopyCheckBox.hide() self.dataDirectoryCancelButton.hide() self.newDataDirectoryHasFilesLabel.hide() - print AppLocation.IsDefaultDataPath - if AppLocation.IsDefaultDataPath: - self.dataDirectoryDefaultButton.hide() - else: - self.dataDirectoryDefaultButton.show() def onDefaultRevertButtonClicked(self): self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png') diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index af95d5782..0ee6c2606 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -37,8 +37,7 @@ from datetime import datetime from PyQt4 import QtCore, QtGui from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ - PluginManager, Receiver, translate, ImageManager, PluginStatus, \ - SettingsManager + PluginManager, Receiver, translate, ImageManager, PluginStatus from openlp.core.lib.ui import UiStrings, create_action from openlp.core.lib import SlideLimits from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ @@ -583,6 +582,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Once settings are loaded update the menu with the recent files. self.updateRecentFilesMenu() self.pluginForm = PluginForm(self) + self.newDataPath = u'' + self.copyData = False # Set up signals and slots QtCore.QObject.connect(self.importThemeItem, QtCore.SIGNAL(u'triggered()'), @@ -649,6 +650,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_information_message'), self.onInformationMessage) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'set_new_data_path'), self.setNewDataPath) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'set_copy_data'), self.setCopyData) # warning cyclic dependency # renderer needs to call ThemeManager and # ThemeManager needs to call Renderer @@ -1189,8 +1194,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Save settings self.saveSettings() # Check if we need to change the data directory - if QtCore.QSettings().value(u'advanced/new data path', - QtCore.QVariant(u'none')).toString() != u'none': + if self.newDataPath: self.changeDataDirectory() # Close down the display self.liveController.display.close() @@ -1467,47 +1471,44 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.loadProgressBar.hide() Receiver.send_message(u'openlp_process_events') + def setNewDataPath(self, new_data_path): + self.newDataPath = new_data_path + + def setCopyData(self, copy_data): + self.copyData = copy_data + def changeDataDirectory(self): - old_data_path = str(AppLocation.get_data_path()) - settings = QtCore.QSettings() - new_data_path = str(settings.value(u'advanced/new data path', - QtCore.QVariant(u'none')).toString()) - settings.remove(u'advanced/new data path') + log.info(u'Changing data path to %s' % self.newDataPath ) + old_data_path = unicode(str(AppLocation.get_data_path())) # Copy OpenLP data to new location if requested. - if settings.value(u'advanced/copy data', - QtCore.QVariant(u'none')).toBool(): + if self.copyData: + log.info(u'Copying data to new path') try: Receiver.send_message(u'openlp_process_events') - QtGui.QMessageBox.information(self, - translate('OpenLP.MainWindow', 'Copy Data Directory'), - translate('OpenLP.MainWindow', - 'OpenLP will now copy your data files from \n\n %s \n\n' - 'to \n\n %s' % (old_data_path, new_data_path)), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Ok)) Receiver.send_message(u'cursor_busy') - dir_util.copy_tree(old_data_path, new_data_path) + self.showStatusMessage( + translate('OpenLP.MainWindow', + 'Copying OpenLP data to new data directory location - %s ' + '- Please wait for copy to finish' + % os.path.abspath(os.path.join(self.newDataPath, u'..')))) + dir_util.copy_tree(old_data_path, self.newDataPath) + log.info(u'Copy sucessful') except (IOError, os.error, DistutilsFileError), why: Receiver.send_message(u'cursor_normal') + log.exception(u'Data copy failed %s' % unicode(str(why))) QtGui.QMessageBox.critical(self, - translate('OpenLP.MainWindow', 'New data directory error'), + translate('OpenLP.MainWindow', 'New Data Directory Error'), translate('OpenLP.MainWindow', - 'OpenLP Data directory copy failed \n\n %s' % str(why)), + 'OpenLP Data directory copy failed \n\n %s' + % unicode(str(why))), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Ok)) return False - settings.remove(u'advanced/copy data') - Receiver.send_message(u'cursor_normal') + else: + log.info(u'No data copy requested') # Change the location of data directory in config file. - settings.setValue(u'advanced/data path', new_data_path) - QtGui.QMessageBox.information(self, - translate('OpenLP.MainWindow', 'New data directory'), - translate('OpenLP.MainWindow', - 'OpenLP Data directory successfully changed to:\n\n %s \n\n' - 'The new data directory location will be used ' - 'the next time you start OpenLP.' % new_data_path), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Ok)) + settings = QtCore.QSettings() + settings.setValue(u'advanced/data path', self.newDataPath) # Check if the new data path is our default. - if new_data_path == AppLocation.get_directory(AppLocation.DataDir): + if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir): settings.remove(u'advanced/data path') diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 0b1d3e894..9c3dcac03 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -102,8 +102,8 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Process the form saving the settings """ - # Dialog was cancelled, remove any pending data move - QtCore.QSettings().remove(u'advanced/new data path') + # Dialogue was cancelled, remove any pending data path change. + self.advancedTab.onDataDirectoryCancelButtonClicked(); for tabIndex in range(0, self.stackedLayout.count()): self.stackedLayout.widget(tabIndex).cancel() return QtGui.QDialog.reject(self) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index cd97b2a2a..d07727b2d 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -128,7 +128,6 @@ class AppLocation(object): VersionDir = 5 CacheDir = 6 LanguageDir = 7 - IsDefaultDataPath = True # Base path where data/config/cache dir is located BaseDir = None @@ -169,26 +168,14 @@ class AppLocation(object): Return the path OpenLP stores all its data under. """ # Check if we have a different data location. - path = unicode(QtCore.QSettings().value( - u'advanced/data path', QtCore.QVariant(u'none')).toString()) - if path == u'none': - AppLocation.IsDefaultDataPath = True + if QtCore.QSettings().contains("advanced/data path"): + path = unicode(QtCore.QSettings().value( + u'advanced/data path', QtCore.QVariant(u'')).toString()) + else: path = AppLocation.get_directory(AppLocation.DataDir) check_directory_exists(path) - else: - AppLocation.IsDefaultDataPath = False return path - @staticmethod - def set_default_data_path(): - """ - Reset to default and return the path OpenLP stores all its data under. - """ - # Remove override location. - QtCore.QSettings().remove(u'advanced/data path') - data_path = AppLocation.get_data_path() - return data_path - @staticmethod def get_section_data_path(section): """ From cf0e8c184e72c6e4ee610bd466a2d1b3381830b5 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 10 May 2012 19:23:45 -0400 Subject: [PATCH 03/46] Fixed code per comments. Fixed misc syntax errors. --- openlp/core/ui/advancedtab.py | 26 +++++++++++++------------- openlp/core/ui/mainwindow.py | 8 ++++---- openlp/core/utils/__init__.py | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 1af8d1268..a623c6a40 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -160,14 +160,14 @@ class AdvancedTab(SettingsTab): # Data Directory self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn) self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox') - self.dataDirectoryLayout =QtGui.QFormLayout(self.dataDirectoryGroupBox) + self.dataDirectoryLayout = QtGui.QFormLayout(self.dataDirectoryGroupBox) self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout') - self.dataDirectoryCurrentLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryCurrentLabel = QtGui.QLabel(self.dataDirectoryGroupBox) self.dataDirectoryCurrentLabel.setObjectName( u'dataDirectoryCurrentLabel') - self.dataDirectoryLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryLabel = QtGui.QLabel(self.dataDirectoryGroupBox) self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel') - self.dataDirectoryNewLabel= QtGui.QLabel(self.dataDirectoryGroupBox) + self.dataDirectoryNewLabel = QtGui.QLabel(self.dataDirectoryGroupBox) self.dataDirectoryNewLabel.setObjectName(u'dataDirectoryCurrentLabel') self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox) self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit') @@ -512,12 +512,12 @@ class AdvancedTab(SettingsTab): # Since data location can be changed, make sure the path is present. self.currentDataPath = AppLocation.get_data_path() if not os.path.exists(self.currentDataPath): - log.exception(u'Data path not found %s' % self.currentDataPath) + log.error(u'Data path not found %s' % self.currentDataPath) answer = QtGui.QMessageBox.critical(self, translate('OpenLP.AdvancedTab', 'Data Directory Error'), translate('OpenLP.AdvancedTab', - 'OpenLP data directory was not found \n\n %s \n\n' + 'OpenLP data directory was not found\n\n%s\n\n' 'This data directory was previously changed from the OpenLP ' 'default location. If the new location was on removable ' 'media, that media needs to be made available.\n\n' @@ -530,13 +530,13 @@ class AdvancedTab(SettingsTab): QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: - log.exception(u'User requested termination') + log.info(u'User requested termination') Receiver.send_message(u'cleanup') sys.exit() # Set data location to default. settings.remove(u'advanced/data path') self.currentDataPath = AppLocation.get_data_path() - log.exception(u'User requested data path set to default %s' + log.warning(u'User requested data path set to default %s' % self.currentDataPath) self.dataDirectoryLabel.setText(os.path.abspath( os.path.join(self.currentDataPath, u'..'))) @@ -654,12 +654,12 @@ class AdvancedTab(SettingsTab): """ Browse for a new data directory location. """ - old_root_path = unicode(str(self.dataDirectoryLabel.text())) + old_root_path = unicode(self.dataDirectoryLabel.text()) # Get the new directory location. new_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, translate('OpenLP.AdvancedTab', 'Select Data Directory Location'), old_root_path, - options=QtGui.QFileDialog.ShowDirsOnly)) + options = QtGui.QFileDialog.ShowDirsOnly)) # Set the new data path. new_data_path = os.path.join(new_path, 'openlp_data') if new_path: @@ -673,7 +673,7 @@ class AdvancedTab(SettingsTab): translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'), translate('OpenLP.AdvancedTab', 'Are you sure you want to change the location of the OpenLP ' - 'data directory to:\n\n %s \n\n' + 'data directory to:\n\n%s\n\n' 'The data directory will be changed when OpenLP is closed.' % new_path), QtGui.QMessageBox.StandardButtons( @@ -700,7 +700,7 @@ class AdvancedTab(SettingsTab): translate('OpenLP.AdvancedTab', 'Reset Data Directory'), translate('OpenLP.AdvancedTab', 'Are you sure you want to change the location of the OpenLP ' - 'data directory to the default location? \n\n' + 'data directory to the default location?\n\n' 'This location will be used after OpenLP is closed.'), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | @@ -737,7 +737,7 @@ class AdvancedTab(SettingsTab): translate('OpenLP.AdvancedTab', 'Overwrite Existing Data'), translate('OpenLP.AdvancedTab', 'WARNING: \n\n' - 'The location you have selected \n\n %s \n\n' + 'The location you have selected \n\n%s\n\n' 'appears to contain OpenLP data files. Do you wish to replace ' 'these files with the current data files?' % os.path.abspath(os.path.join(data_path, u'..'))), diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 68078d305..fdcacd3d8 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1479,7 +1479,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def changeDataDirectory(self): log.info(u'Changing data path to %s' % self.newDataPath ) - old_data_path = unicode(str(AppLocation.get_data_path())) + old_data_path = unicode(AppLocation.get_data_path()) # Copy OpenLP data to new location if requested. if self.copyData: log.info(u'Copying data to new path') @@ -1495,12 +1495,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): log.info(u'Copy sucessful') except (IOError, os.error, DistutilsFileError), why: Receiver.send_message(u'cursor_normal') - log.exception(u'Data copy failed %s' % unicode(str(why))) + log.exception(u'Data copy failed %s' % unicode(why)) QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'), translate('OpenLP.MainWindow', - 'OpenLP Data directory copy failed \n\n %s' - % unicode(str(why))), + 'OpenLP Data directory copy failed\n\n%s' + % unicode(why)), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Ok)) return False diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 9e8efa153..fd54aa338 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -128,9 +128,9 @@ class AppLocation(object): Return the path OpenLP stores all its data under. """ # Check if we have a different data location. - if QtCore.QSettings().contains("advanced/data path"): + if QtCore.QSettings().contains(u'advanced/data path'): path = unicode(QtCore.QSettings().value( - u'advanced/data path', QtCore.QVariant(u'')).toString()) + u'advanced/data path').toString()) else: path = AppLocation.get_directory(AppLocation.DataDir) check_directory_exists(path) From f1586052a622a01ede9a9b91851cb2e24cf42a69 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Fri, 11 May 2012 08:22:34 -0400 Subject: [PATCH 04/46] Added code to allow OpenLP to run portable --- openlp/core/__init__.py | 34 +++++-- openlp/core/lib/db.py | 3 +- openlp/core/lib/formattingtags.py | 5 +- openlp/core/lib/mediamanageritem.py | 5 +- openlp/core/lib/plugin.py | 5 +- openlp/core/lib/settings.py | 67 ++++++++++++++ openlp/core/lib/settingsmanager.py | 9 +- openlp/core/ui/advancedtab.py | 7 +- openlp/core/ui/firsttimeform.py | 13 +-- openlp/core/ui/generaltab.py | 5 +- openlp/core/ui/maindisplay.py | 17 ++-- openlp/core/ui/mainwindow.py | 89 ++++++++++--------- openlp/core/ui/media/__init__.py | 10 ++- openlp/core/ui/media/mediacontroller.py | 3 +- openlp/core/ui/media/vlcplayer.py | 3 +- openlp/core/ui/printserviceform.py | 7 +- openlp/core/ui/screen.py | 3 +- openlp/core/ui/servicemanager.py | 27 +++--- openlp/core/ui/shortcutlistform.py | 3 +- openlp/core/ui/slidecontroller.py | 27 +++--- openlp/core/ui/thememanager.py | 9 +- openlp/core/ui/themestab.py | 7 +- openlp/core/utils/__init__.py | 8 +- openlp/core/utils/actions.py | 4 +- openlp/core/utils/languagemanager.py | 5 +- openlp/plugins/alerts/alertsplugin.py | 3 +- openlp/plugins/alerts/lib/alertstab.py | 5 +- openlp/plugins/bibles/bibleplugin.py | 3 +- .../plugins/bibles/forms/bibleimportform.py | 3 +- .../plugins/bibles/forms/bibleupgradeform.py | 3 +- openlp/plugins/bibles/lib/__init__.py | 3 +- openlp/plugins/bibles/lib/biblestab.py | 5 +- openlp/plugins/bibles/lib/manager.py | 7 +- openlp/plugins/bibles/lib/mediaitem.py | 19 ++-- openlp/plugins/custom/lib/customtab.py | 5 +- openlp/plugins/custom/lib/mediaitem.py | 7 +- openlp/plugins/images/imageplugin.py | 3 +- openlp/plugins/images/lib/imagetab.py | 5 +- openlp/plugins/images/lib/mediaitem.py | 5 +- openlp/plugins/media/lib/mediatab.py | 7 +- openlp/plugins/media/mediaplugin.py | 3 +- openlp/plugins/presentations/lib/mediaitem.py | 3 +- .../lib/presentationcontroller.py | 3 +- .../presentations/lib/presentationtab.py | 13 +-- openlp/plugins/remotes/lib/httpserver.py | 7 +- openlp/plugins/remotes/lib/remotetab.py | 17 ++-- openlp/plugins/songs/forms/songimportform.py | 5 +- openlp/plugins/songs/lib/mediaitem.py | 15 ++-- openlp/plugins/songs/lib/songstab.py | 5 +- .../songusage/forms/songusagedetailform.py | 9 +- openlp/plugins/songusage/songusageplugin.py | 5 +- 51 files changed, 344 insertions(+), 199 deletions(-) create mode 100644 openlp/core/lib/settings.py diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 71c27a1d0..e3dc92af7 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -41,6 +41,7 @@ from traceback import format_exception from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, check_directory_exists +from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings from openlp.core.resources import qInitResources from openlp.core.ui.mainwindow import MainWindow @@ -48,7 +49,7 @@ from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui import SplashScreen, ScreenList -from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \ +from openlp.core.utils import AppLocation, LanguageManager, VersionThread,\ get_application_version @@ -111,15 +112,15 @@ class OpenLP(QtGui.QApplication): # Decide how many screens we have and their size screens = ScreenList(self.desktop()) # First time checks in settings - has_run_wizard = QtCore.QSettings().value( + has_run_wizard = Settings().value( u'general/has run wizard', QtCore.QVariant(False)).toBool() if not has_run_wizard: if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted: - QtCore.QSettings().setValue(u'general/has run wizard', + Settings().setValue(u'general/has run wizard', QtCore.QVariant(True)) if os.name == u'nt': self.setStyleSheet(application_stylesheet) - show_splash = QtCore.QSettings().value( + show_splash = Settings().value( u'general/show splash', QtCore.QVariant(True)).toBool() if show_splash: self.splash = SplashScreen() @@ -139,7 +140,7 @@ class OpenLP(QtGui.QApplication): self.processEvents() if not has_run_wizard: self.mainWindow.firstTime() - update_check = QtCore.QSettings().value( + update_check = Settings().value( u'general/update check', QtCore.QVariant(True)).toBool() if update_check: VersionThread(self.mainWindow).start() @@ -256,7 +257,26 @@ def main(args=None): app = OpenLP(qt_args) app.setOrganizationName(u'OpenLP') app.setOrganizationDomain(u'openlp.org') - app.setApplicationName(u'OpenLP') + if options.portable: + log.info(u'Running portable') + app.setApplicationName(u'OpenLPPortable') + QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) + # Get location OpenLPPortable.ini + app_path = AppLocation.get_directory(AppLocation.AppDir) + portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', + u'Data', u'Settings', u'OpenLPPortable.ini')) + # Make this our settings file + log.info(u'INI file: %s' % portable_settings_file) + Settings.setFilename(portable_settings_file) + portable_settings = Settings() + # Set our data path + data_path = os.path.abspath(os.path.join(app_path, u'..', u'Data',)) + log.info(u'Data path: %s' % data_path) + # Point to our data path + portable_settings.setValue(u'advanced/data path',data_path) + portable_settings.sync() + else: + app.setApplicationName(u'OpenLP') app.setApplicationVersion(get_application_version()[u'version']) # Instance check if not options.testing: @@ -264,7 +284,7 @@ def main(args=None): if app.isAlreadyRunning(): sys.exit() # First time checks in settings - if not QtCore.QSettings().value(u'general/has run wizard', + if not Settings().value(u'general/has run wizard', QtCore.QVariant(False)).toBool(): if not FirstTimeLanguageForm().exec_(): # if cancel then stop processing diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index e097983eb..d7687c56f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -41,6 +41,7 @@ from sqlalchemy.pool import NullPool from openlp.core.lib import translate from openlp.core.lib.ui import critical_error_message_box from openlp.core.utils import AppLocation, delete_file +from openlp.core.lib.settings import Settings log = logging.getLogger(__name__) @@ -179,7 +180,7 @@ class Manager(object): The file name to use for this database. Defaults to None resulting in the plugin_name being used. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(plugin_name) self.db_url = u'' self.is_dirty = False diff --git a/openlp/core/lib/formattingtags.py b/openlp/core/lib/formattingtags.py index bec2db63a..9c45e40e2 100644 --- a/openlp/core/lib/formattingtags.py +++ b/openlp/core/lib/formattingtags.py @@ -32,6 +32,7 @@ import cPickle from PyQt4 import QtCore from openlp.core.lib import translate +from openlp.core.lib.settings import Settings class FormattingTags(object): @@ -160,7 +161,7 @@ class FormattingTags(object): if isinstance(tag[element], unicode): tag[element] = tag[element].encode('utf8') # Formatting Tags were also known as display tags. - QtCore.QSettings().setValue(u'displayTags/html_tags', + Settings().setValue(u'displayTags/html_tags', QtCore.QVariant(cPickle.dumps(tags) if tags else u'')) @staticmethod @@ -173,7 +174,7 @@ class FormattingTags(object): # Initial Load of the Tags FormattingTags.reset_html_tags() # Formatting Tags were also known as display tags. - user_expands = QtCore.QSettings().value(u'displayTags/html_tags', + user_expands = Settings().value(u'displayTags/html_tags', QtCore.QVariant(u'')).toString() # cPickle only accepts str not unicode strings user_expands_string = str(user_expands) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 9bd6fc2a7..703b6e9e5 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -38,6 +38,7 @@ from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \ from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import UiStrings, create_widget_action, \ critical_error_message_box +from openlp.core.lib.settings import Settings log = logging.getLogger(__name__) @@ -462,7 +463,7 @@ class MediaManagerItem(QtGui.QWidget): """ Allows the list click action to be determined dynamically """ - if QtCore.QSettings().value(u'advanced/double click live', + if Settings().value(u'advanced/double click live', QtCore.QVariant(False)).toBool(): self.onLiveClick() else: @@ -472,7 +473,7 @@ class MediaManagerItem(QtGui.QWidget): """ Allows the change of current item in the list to be actioned """ - if QtCore.QSettings().value(u'advanced/single click preview', + if Settings().value(u'advanced/single click preview', QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \ and self.listView.selectedIndexes() \ and self.autoSelectId == -1: diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index a27e496cf..7a34626ad 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -32,6 +32,7 @@ import logging from PyQt4 import QtCore from openlp.core.lib import Receiver +from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings from openlp.core.utils import get_application_version @@ -190,7 +191,7 @@ class Plugin(QtCore.QObject): """ Sets the status of the plugin """ - self.status = QtCore.QSettings().value( + self.status = Settings().value( self.settingsSection + u'/status', QtCore.QVariant(PluginStatus.Inactive)).toInt()[0] @@ -199,7 +200,7 @@ class Plugin(QtCore.QObject): Changes the status of the plugin and remembers it """ self.status = new_status - QtCore.QSettings().setValue( + Settings().setValue( self.settingsSection + u'/status', QtCore.QVariant(self.status)) if new_status == PluginStatus.Active: self.initialise() diff --git a/openlp/core/lib/settings.py b/openlp/core/lib/settings.py new file mode 100644 index 000000000..cf98896a9 --- /dev/null +++ b/openlp/core/lib/settings.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2012 Raoul Snyman # +# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # +# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # +# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:``settings`` module provides a thin wrapper for QSettings, which OpenLP +uses to manage settings persistence. +""" + +import logging + +from PyQt4 import QtCore + +log = logging.getLogger() + +class Settings(QtCore.QSettings): + """ + Class to wrap QSettings. + + * Exposes all the methods of QSettings. + * Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to + ``IniFormat``, and the path to the Ini file is set using ``setFilename``, + then the Settings constructor will create a Settings object for accessing + settings stored in that Ini file. + """ + + FilePath = u'' + + @staticmethod + def setFilename(filepath): + """ + Sets the complete path to an Ini file to be used by Settings objects. + + Does not affect existing Settings objects. + """ + Settings.FilePath = filepath + log.info(u'Set Settings file: %s' % filepath) + + def __init__(self, *args): + if Settings.FilePath and (Settings.defaultFormat() == + Settings.IniFormat): + QtCore.QSettings.__init__(self, Settings.FilePath, + Settings.IniFormat) + else: + QtCore.QSettings.__init__(self, *args) diff --git a/openlp/core/lib/settingsmanager.py b/openlp/core/lib/settingsmanager.py index 0fc4cac96..245b98ef8 100644 --- a/openlp/core/lib/settingsmanager.py +++ b/openlp/core/lib/settingsmanager.py @@ -34,6 +34,7 @@ import os from PyQt4 import QtCore +from openlp.core.lib.settings import Settings from openlp.core.utils import AppLocation class SettingsManager(object): @@ -58,7 +59,7 @@ class SettingsManager(object): name = u'last directory %d' % num else: name = u'last directory' - last_dir = unicode(QtCore.QSettings().value( + last_dir = unicode(Settings().value( section + u'/' + name, QtCore.QVariant(u'')).toString()) return last_dir @@ -81,7 +82,7 @@ class SettingsManager(object): name = u'last directory %d' % num else: name = u'last directory' - QtCore.QSettings().setValue( + Settings().setValue( section + u'/' + name, QtCore.QVariant(directory)) @staticmethod @@ -98,7 +99,7 @@ class SettingsManager(object): ``list`` The list of values to save. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(section) old_count = settings.value( u'%s count' % name, QtCore.QVariant(0)).toInt()[0] @@ -124,7 +125,7 @@ class SettingsManager(object): ``name`` The name of the list. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(section) list_count = settings.value( u'%s count' % name, QtCore.QVariant(0)).toInt()[0] diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index a623c6a40..21cb42a7e 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -36,6 +36,7 @@ import os import sys from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib.ui import UiStrings +from openlp.core.lib.settings import Settings from openlp.core.utils import get_images_filter, AppLocation from openlp.core.lib import SlideLimits @@ -449,12 +450,12 @@ class AdvancedTab(SettingsTab): """ Load settings from disk. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) # The max recent files value does not have an interface and so never # gets actually stored in the settings therefore the default value of # 20 will always be used. - self.recentSpinBox.setMaximum(QtCore.QSettings().value( + self.recentSpinBox.setMaximum(Settings().value( u'max recent files', QtCore.QVariant(20)).toInt()[0]) self.recentSpinBox.setValue(settings.value(u'recent file count', QtCore.QVariant(4)).toInt()[0]) @@ -547,7 +548,7 @@ class AdvancedTab(SettingsTab): """ Save settings to disk. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'default service enabled', self.serviceNameCheckBox.isChecked()) diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 5926733a8..9d00b6577 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -39,6 +39,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \ check_directory_exists +from openlp.core.lib.settings import Settings from openlp.core.utils import get_web_page, AppLocation from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage @@ -113,7 +114,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): check_directory_exists(os.path.join(gettempdir(), u'openlp')) self.noInternetFinishButton.setVisible(False) # Check if this is a re-run of the wizard. - self.hasRunWizard = QtCore.QSettings().value( + self.hasRunWizard = Settings().value( u'general/has run wizard', QtCore.QVariant(False)).toBool() # Sort out internet access for downloads if self.webAccess: @@ -206,7 +207,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): index = self.themeComboBox.findText(theme) if index == -1: self.themeComboBox.addItem(theme) - default_theme = unicode(QtCore.QSettings().value( + default_theme = unicode(Settings().value( u'themes/global theme', QtCore.QVariant(u'')).toString()) # Pre-select the current default theme. @@ -257,7 +258,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): self._performWizard() Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'cursor_normal') - QtCore.QSettings().setValue(u'general/has run wizard', + Settings().setValue(u'general/has run wizard', QtCore.QVariant(True)) self.close() @@ -456,16 +457,16 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): os.path.join(themes_destination, theme)) # Set Default Display if self.displayComboBox.currentIndex() != -1: - QtCore.QSettings().setValue(u'General/monitor', + Settings().setValue(u'General/monitor', QtCore.QVariant(self.displayComboBox.currentIndex())) self.screens.set_current_display( self.displayComboBox.currentIndex()) # Set Global Theme if self.themeComboBox.currentIndex() != -1: - QtCore.QSettings().setValue(u'themes/global theme', + Settings().setValue(u'themes/global theme', QtCore.QVariant(self.themeComboBox.currentText())) def _setPluginStatus(self, field, tag): status = PluginStatus.Active if field.checkState() \ == QtCore.Qt.Checked else PluginStatus.Inactive - QtCore.QSettings().setValue(tag, QtCore.QVariant(status)) + Settings().setValue(tag, QtCore.QVariant(status)) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index baf28f40f..84aa76b7c 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib.ui import UiStrings +from openlp.core.lib.settings import Settings from openlp.core.ui import ScreenList log = logging.getLogger(__name__) @@ -265,7 +266,7 @@ class GeneralTab(SettingsTab): """ Load the settings to populate the form """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.monitorComboBox.clear() self.monitorComboBox.addItems(self.screens.get_screen_list()) @@ -327,7 +328,7 @@ class GeneralTab(SettingsTab): """ Save the settings from the form """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'monitor', QtCore.QVariant(self.monitorComboBox.currentIndex())) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 15fb9eefe..4325b842d 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -38,6 +38,7 @@ from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ translate, PluginManager, expand_tags from openlp.core.lib.theme import BackgroundType +from openlp.core.lib.settings import Settings from openlp.core.ui import HideMode, ScreenList, AlertLocation @@ -134,7 +135,7 @@ class MainDisplay(Display): self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \ QtCore.Qt.WindowStaysOnTopHint - if QtCore.QSettings().value(u'advanced/x11 bypass wm', + if Settings().value(u'advanced/x11 bypass wm', QtCore.QVariant(True)).toBool(): windowFlags |= QtCore.Qt.X11BypassWindowManagerHint # FIXME: QtCore.Qt.SplashScreen is workaround to make display screen @@ -195,11 +196,11 @@ class MainDisplay(Display): Display.setup(self) if self.isLive: # Build the initial frame. - image_file = QtCore.QSettings().value(u'advanced/default image', + image_file = Settings().value(u'advanced/default image', QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ .toString() background_color = QtGui.QColor() - background_color.setNamedColor(QtCore.QSettings().value( + background_color.setNamedColor(Settings().value( u'advanced/default color', QtCore.QVariant(u'#ffffff')).toString()) if not background_color.isValid(): @@ -352,7 +353,7 @@ class MainDisplay(Display): # Single screen active if self.screens.display_count == 1: # Only make visible if setting enabled. - if QtCore.QSettings().value(u'general/display on monitor', + if Settings().value(u'general/display on monitor', QtCore.QVariant(True)).toBool(): self.setVisible(True) else: @@ -401,7 +402,7 @@ class MainDisplay(Display): self.footer(serviceItem.foot_text) # if was hidden keep it hidden if self.hideMode and self.isLive and not serviceItem.is_media(): - if QtCore.QSettings().value(u'general/auto unblank', + if Settings().value(u'general/auto unblank', QtCore.QVariant(False)).toBool(): Receiver.send_message(u'slidecontroller_live_unblank') else: @@ -425,7 +426,7 @@ class MainDisplay(Display): log.debug(u'hideDisplay mode = %d', mode) if self.screens.display_count == 1: # Only make visible if setting enabled. - if not QtCore.QSettings().value(u'general/display on monitor', + if not Settings().value(u'general/display on monitor', QtCore.QVariant(True)).toBool(): return if mode == HideMode.Screen: @@ -450,7 +451,7 @@ class MainDisplay(Display): log.debug(u'showDisplay') if self.screens.display_count == 1: # Only make visible if setting enabled. - if not QtCore.QSettings().value(u'general/display on monitor', + if not Settings().value(u'general/display on monitor', QtCore.QVariant(True)).toBool(): return self.frame.evaluateJavaScript('show_blank("show");') @@ -465,7 +466,7 @@ class MainDisplay(Display): """ Hide mouse cursor when moved over display. """ - if QtCore.QSettings().value(u'advanced/hide mouse', + if Settings().value(u'advanced/hide mouse', QtCore.QVariant(False)).toBool(): self.setCursor(QtCore.Qt.BlankCursor) self.frame.evaluateJavaScript('document.body.style.cursor = "none"') diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index fdcacd3d8..d38bf9569 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -39,6 +39,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ PluginManager, Receiver, translate, ImageManager, PluginStatus from openlp.core.lib.ui import UiStrings, create_action +from openlp.core.lib.settings import Settings from openlp.core.lib import SlideLimits from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \ @@ -101,12 +102,12 @@ class Ui_MainWindow(object): # Create slide controllers self.previewController = SlideController(self) self.liveController = SlideController(self, True) - previewVisible = QtCore.QSettings().value( + previewVisible = Settings().value( u'user interface/preview panel', QtCore.QVariant(True)).toBool() self.previewController.panel.setVisible(previewVisible) - liveVisible = QtCore.QSettings().value(u'user interface/live panel', + liveVisible = Settings().value(u'user interface/live panel', QtCore.QVariant(True)).toBool() - panelLocked = QtCore.QSettings().value(u'user interface/lock panel', + panelLocked = Settings().value(u'user interface/lock panel', QtCore.QVariant(False)).toBool() self.liveController.panel.setVisible(liveVisible) # Create menu @@ -694,9 +695,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.previewController.screenSizeChanged() self.liveController.screenSizeChanged() log.info(u'Load data from Settings') - if QtCore.QSettings().value(u'advanced/save current plugin', + if Settings().value(u'advanced/save current plugin', QtCore.QVariant(False)).toBool(): - savedPlugin = QtCore.QSettings().value( + savedPlugin = Settings().value( u'advanced/current media plugin', QtCore.QVariant()).toInt()[0] if savedPlugin != -1: self.mediaToolBox.setCurrentIndex(savedPlugin) @@ -748,11 +749,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if not isinstance(filename, unicode): filename = unicode(filename, sys.getfilesystemencoding()) self.serviceManagerContents.loadFile(filename) - elif QtCore.QSettings().value( + elif Settings().value( self.generalSettingsSection + u'/auto open', QtCore.QVariant(False)).toBool(): self.serviceManagerContents.loadLastFile() - view_mode = QtCore.QSettings().value(u'%s/view mode' % \ + view_mode = Settings().value(u'%s/view mode' % \ self.generalSettingsSection, u'default').toString() if view_mode == u'default': self.modeDefaultItem.setChecked(True) @@ -830,7 +831,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ Check and display message if screen blank on setup. """ - settings = QtCore.QSettings() + settings = Settings() self.liveController.mainDisplaySetBackground() if settings.value(u'%s/screen blank' % self.generalSettingsSection, QtCore.QVariant(False)).toBool(): @@ -964,9 +965,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Add plugin sections. for plugin in self.pluginManager.plugins: setting_sections.extend([plugin.name]) - settings = QtCore.QSettings() - import_settings = QtCore.QSettings(import_file_name, - QtCore.QSettings.IniFormat) + settings = Settings() + import_settings = Settings(import_file_name, + Settings.IniFormat) import_keys = import_settings.allKeys() for section_key in import_keys: # We need to handle the really bad files. @@ -1018,19 +1019,24 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.cleanUp() QtCore.QCoreApplication.exit() - def onSettingsExportItemClicked(self): + def onSettingsExportItemClicked(self, export_file = None): """ - Export settings to a .conf file in INI format + Export settings to a .conf file in INI format. If no filename is, + get one from the user. A filename is passed from self.cleanup if + OpenLP is running as a portable app. """ - export_file_name = unicode(QtGui.QFileDialog.getSaveFileName(self, - translate('OpenLP.MainWindow', 'Export Settings File'), '', - translate('OpenLP.MainWindow', - 'OpenLP Export Settings File (*.conf)'))) - if not export_file_name: - return - # Make sure it's a .conf file. - if not export_file_name.endswith(u'conf'): - export_file_name = export_file_name + u'.conf' + if not export_file: + export_file_name = unicode(QtGui.QFileDialog.getSaveFileName(self, + translate('OpenLP.MainWindow', 'Export Settings File'), '', + translate('OpenLP.MainWindow', + 'OpenLP Export Settings File (*.conf)'))) + if not export_file_name: + return + # Make sure it's a .conf file. + if not export_file_name.endswith(u'conf'): + export_file_name = export_file_name + u'.conf' + else: + export_file_name = unicode(export_file) temp_file = os.path.join(unicode(gettempdir()), u'openlp', u'exportConf.tmp') self.saveSettings() @@ -1051,12 +1057,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): os.remove(temp_file) if os.path.exists(export_file_name): os.remove(export_file_name) - settings = QtCore.QSettings() + settings = Settings() settings.remove(self.headerSection) # Get the settings. keys = settings.allKeys() export_settings = QtCore.QSettings(temp_file, - QtCore.QSettings.IniFormat) + Settings.IniFormat) # Add a header section. # This is to insure it's our conf file for import. now = datetime.now() @@ -1114,7 +1120,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): Set OpenLP to a different view mode. """ if mode: - settings = QtCore.QSettings() + settings = Settings() settings.setValue(u'%s/view mode' % self.generalSettingsSection, mode) self.mediaManagerDock.setVisible(media) @@ -1159,7 +1165,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): else: event.ignore() else: - if QtCore.QSettings().value(u'advanced/enable exit confirmation', + if Settings().value(u'advanced/enable exit confirmation', QtCore.QVariant(True)).toBool(): ret = QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'Close OpenLP'), @@ -1184,9 +1190,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ # Clean temporary files used by services self.serviceManagerContents.cleanUp() - if QtCore.QSettings().value(u'advanced/save current plugin', + settings = Settings() + if Settings().value(u'advanced/save current plugin', QtCore.QVariant(False)).toBool(): - QtCore.QSettings().setValue(u'advanced/current media plugin', + Settings().setValue(u'advanced/current media plugin', QtCore.QVariant(self.mediaToolBox.currentIndex())) # Call the cleanup method to shutdown plugins. log.info(u'cleanup plugins') @@ -1267,7 +1274,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): False - Hidden """ self.previewController.panel.setVisible(visible) - QtCore.QSettings().setValue(u'user interface/preview panel', + Settings().setValue(u'user interface/preview panel', QtCore.QVariant(visible)) self.viewPreviewPanel.setChecked(visible) @@ -1299,7 +1306,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.viewThemeManagerItem.setEnabled(True) self.viewPreviewPanel.setEnabled(True) self.viewLivePanel.setEnabled(True) - QtCore.QSettings().setValue(u'user interface/lock panel', + Settings().setValue(u'user interface/lock panel', QtCore.QVariant(lock)) def setLivePanelVisibility(self, visible): @@ -1313,7 +1320,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): False - Hidden """ self.liveController.panel.setVisible(visible) - QtCore.QSettings().setValue(u'user interface/live panel', + Settings().setValue(u'user interface/live panel', QtCore.QVariant(visible)) self.viewLivePanel.setChecked(visible) @@ -1323,19 +1330,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ log.debug(u'Loading QSettings') # Migrate Wrap Settings to Slide Limits Settings - if QtCore.QSettings().contains(self.generalSettingsSection + + if Settings().contains(self.generalSettingsSection + u'/enable slide loop'): - if QtCore.QSettings().value(self.generalSettingsSection + + if Settings().value(self.generalSettingsSection + u'/enable slide loop', QtCore.QVariant(True)).toBool(): - QtCore.QSettings().setValue(self.advancedSettingsSection + + Settings().setValue(self.advancedSettingsSection + u'/slide limits', QtCore.QVariant(SlideLimits.Wrap)) else: - QtCore.QSettings().setValue(self.advancedSettingsSection + + Settings().setValue(self.advancedSettingsSection + u'/slide limits', QtCore.QVariant(SlideLimits.End)) - QtCore.QSettings().remove(self.generalSettingsSection + + Settings().remove(self.generalSettingsSection + u'/enable slide loop') Receiver.send_message(u'slidecontroller_update_slide_limits') - settings = QtCore.QSettings() + settings = Settings() # Remove obsolete entries. settings.remove(u'custom slide') settings.remove(u'service') @@ -1364,7 +1371,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if self.settingsImported: return log.debug(u'Saving QSettings') - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.generalSettingsSection) recentFiles = QtCore.QVariant(self.recentFiles) \ if self.recentFiles else QtCore.QVariant() @@ -1390,7 +1397,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): Updates the recent file menu with the latest list of service files accessed. """ - recentFileCount = QtCore.QSettings().value( + recentFileCount = Settings().value( u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0] existingRecentFiles = [recentFile for recentFile in self.recentFiles if os.path.isfile(unicode(recentFile))] @@ -1423,7 +1430,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # The maxRecentFiles value does not have an interface and so never gets # actually stored in the settings therefore the default value of 20 will # always be used. - maxRecentFiles = QtCore.QSettings().value(u'advanced/max recent files', + maxRecentFiles = Settings().value(u'advanced/max recent files', QtCore.QVariant(20)).toInt()[0] if filename: # Add some cleanup to reduce duplication in the recent file list @@ -1507,7 +1514,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): else: log.info(u'No data copy requested') # Change the location of data directory in config file. - settings = QtCore.QSettings() + settings = Settings() settings.setValue(u'advanced/data path', self.newDataPath) # Check if the new data path is our default. if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir): diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py index 5c4428a61..10583ffe0 100644 --- a/openlp/core/ui/media/__init__.py +++ b/openlp/core/ui/media/__init__.py @@ -26,6 +26,8 @@ ############################################################################### import logging +from openlp.core.lib.settings import Settings + from PyQt4 import QtCore log = logging.getLogger(__name__) @@ -78,11 +80,11 @@ def get_media_players(): Here an special media player is chosen for all media actions. """ log.debug(u'get_media_players') - players = unicode(QtCore.QSettings().value(u'media/players').toString()) + players = unicode(Settings().value(u'media/players').toString()) if not players: players = u'webkit' reg_ex = QtCore.QRegExp(".*\[(.*)\].*") - if QtCore.QSettings().value(u'media/override player', + if Settings().value(u'media/override player', QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == QtCore.Qt.Checked: if reg_ex.exactMatch(players): overridden_player = u'%s' % reg_ex.cap(1) @@ -107,10 +109,10 @@ def set_media_players(players_list, overridden_player=u'auto'): """ log.debug(u'set_media_players') players = u','.join(players_list) - if QtCore.QSettings().value(u'media/override player', + if Settings().value(u'media/override player', QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == \ QtCore.Qt.Checked and overridden_player != u'auto': players = players.replace(overridden_player, u'[%s]' % overridden_player) - QtCore.QSettings().setValue(u'media/players', QtCore.QVariant(players)) + Settings().setValue(u'media/players', QtCore.QVariant(players)) from mediacontroller import MediaController diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index b7356fcf5..324721568 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -30,6 +30,7 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, Receiver, translate +from openlp.core.lib.settings import Settings from openlp.core.lib.mediaplayer import MediaPlayer from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \ @@ -333,7 +334,7 @@ class MediaController(object): "setBackBoard", null, null, null,"visible");') # now start playing if controller.isLive and \ - (QtCore.QSettings().value(u'general/auto unblank', + (Settings().value(u'general/auto unblank', QtCore.QVariant(False)).toBool() or \ controller.media_info.is_background == True) or \ controller.isLive == False: diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 6d26f3b34..3879adb29 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -34,6 +34,7 @@ import sys from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver +from openlp.core.lib.settings import Settings from openlp.core.lib.mediaplayer import MediaPlayer from openlp.core.ui.media import MediaState @@ -114,7 +115,7 @@ class VlcPlayer(MediaPlayer): command_line_options = u'--no-video-title-show' if not display.hasAudio: command_line_options += u' --no-audio --no-video-title-show' - if QtCore.QSettings().value(u'advanced/hide mouse', + if Settings().value(u'advanced/hide mouse', QtCore.QVariant(False)).toBool() and \ display.controller.isLive: command_line_options += u' --mouse-hide-timeout=0' diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index 943f8daff..65ee03b0a 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -33,6 +33,7 @@ from lxml import html from openlp.core.lib import translate, get_text_file_string, Receiver from openlp.core.lib.ui import UiStrings +from openlp.core.lib.settings import Settings from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize from openlp.core.utils import AppLocation @@ -120,7 +121,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): self.zoom = 0 self.setupUi(self) # Load the settings for the dialog. - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'advanced') self.slideTextCheckBox.setChecked(settings.value( u'print slide text', QtCore.QVariant(False)).toBool()) @@ -318,7 +319,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): elif display == ZoomSize.TwentyFive: self.previewWidget.fitToWidth() self.previewWidget.zoomIn(0.25) - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'advanced') settings.setValue(u'display size', QtCore.QVariant(display)) settings.endGroup() @@ -389,7 +390,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): Save the settings and close the dialog. """ # Save the settings for this dialog. - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'advanced') settings.setValue(u'print slide text', QtCore.QVariant(self.slideTextCheckBox.isChecked())) diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py index 21fbd6144..acb6cf856 100644 --- a/openlp/core/ui/screen.py +++ b/openlp/core/ui/screen.py @@ -34,6 +34,7 @@ import copy from PyQt4 import QtCore from openlp.core.lib import Receiver, translate +from openlp.core.lib.settings import Settings log = logging.getLogger(__name__) @@ -241,7 +242,7 @@ class ScreenList(object): """ Loads the screen size and the monitor number from the settings. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'general') self.set_current_display(settings.value(u'monitor', QtCore.QVariant(self.display_count - 1)).toInt()[0]) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index c9dfeae50..9c6c119fa 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -40,6 +40,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \ ItemCapabilities, SettingsManager, translate, str_to_bool from openlp.core.lib.theme import ThemeLevel +from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_widget_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm @@ -271,7 +272,7 @@ class ServiceManager(QtGui.QWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate) # Last little bits of setting up - self.service_theme = unicode(QtCore.QSettings().value( + self.service_theme = unicode(Settings().value( self.mainwindow.serviceManagerSettingsSection + u'/service theme', QtCore.QVariant(u'')).toString()) self.servicePath = AppLocation.get_section_data_path(u'servicemanager') @@ -352,7 +353,7 @@ class ServiceManager(QtGui.QWidget): self._fileName = unicode(fileName) self.mainwindow.setServiceModified(self.isModified(), self.shortFileName()) - QtCore.QSettings(). \ + Settings(). \ setValue(u'servicemanager/last file',QtCore.QVariant(fileName)) def fileName(self): @@ -371,7 +372,7 @@ class ServiceManager(QtGui.QWidget): """ Triggered when Config dialog is updated. """ - self.expandTabs = QtCore.QSettings().value( + self.expandTabs = Settings().value( u'advanced/expand service item', QtCore.QVariant(u'False')).toBool() @@ -444,7 +445,7 @@ class ServiceManager(QtGui.QWidget): self.setFileName(u'') self.serviceId += 1 self.setModified(False) - QtCore.QSettings(). \ + Settings(). \ setValue(u'servicemanager/last file',QtCore.QVariant(u'')) Receiver.send_message(u'servicemanager_new_service') @@ -593,17 +594,17 @@ class ServiceManager(QtGui.QWidget): Get a file name and then call :func:`ServiceManager.saveFile` to save the file. """ - default_service_enabled = QtCore.QSettings().value( + default_service_enabled = Settings().value( u'advanced/default service enabled', QtCore.QVariant(True)).toBool() if default_service_enabled: - service_day = QtCore.QSettings().value( + service_day = Settings().value( u'advanced/default service day', 7).toInt()[0] if service_day == 7: time = datetime.now() else: - service_hour = QtCore.QSettings().value( + service_hour = Settings().value( u'advanced/default service hour', 11).toInt()[0] - service_minute = QtCore.QSettings().value( + service_minute = Settings().value( u'advanced/default service minute', 0).toInt()[0] now = datetime.now() day_delta = service_day - now.weekday() @@ -611,7 +612,7 @@ class ServiceManager(QtGui.QWidget): day_delta += 7 time = now + timedelta(days=day_delta) time = time.replace(hour=service_hour, minute=service_minute) - default_pattern = unicode(QtCore.QSettings().value( + default_pattern = unicode(Settings().value( u'advanced/default service name', translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M', 'This may not contain any of the following characters: ' @@ -692,7 +693,7 @@ class ServiceManager(QtGui.QWidget): self.setFileName(fileName) self.mainwindow.addRecentFile(fileName) self.setModified(False) - QtCore.QSettings().setValue( + Settings().setValue( 'servicemanager/last file', QtCore.QVariant(fileName)) else: critical_error_message_box( @@ -734,7 +735,7 @@ class ServiceManager(QtGui.QWidget): service was last closed. Can be blank if there was no service present. """ - fileName = QtCore.QSettings(). \ + fileName = Settings(). \ value(u'servicemanager/last file',QtCore.QVariant(u'')).toString() if fileName: self.loadFile(fileName) @@ -1106,7 +1107,7 @@ class ServiceManager(QtGui.QWidget): log.debug(u'onThemeComboBoxSelected') self.service_theme = unicode(self.themeComboBox.currentText()) self.mainwindow.renderer.set_service_theme(self.service_theme) - QtCore.QSettings().setValue( + Settings().setValue( self.mainwindow.serviceManagerSettingsSection + u'/service theme', QtCore.QVariant(self.service_theme)) @@ -1287,7 +1288,7 @@ class ServiceManager(QtGui.QWidget): if self.serviceItems[item][u'service_item'].is_valid: self.mainwindow.liveController.addServiceManagerItem( self.serviceItems[item][u'service_item'], child) - if QtCore.QSettings().value( + if Settings().value( self.mainwindow.generalSettingsSection + u'/auto preview', QtCore.QVariant(False)).toBool(): item += 1 diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py index 457525dc0..fb0e8585c 100644 --- a/openlp/core/ui/shortcutlistform.py +++ b/openlp/core/ui/shortcutlistform.py @@ -31,6 +31,7 @@ import re from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver +from openlp.core.lib.settings import Settings from openlp.core.utils import translate from openlp.core.utils.actions import ActionList from shortcutlistdialog import Ui_ShortcutListDialog @@ -337,7 +338,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog): Save the shortcuts. **Note**, that we do not have to load the shortcuts, as they are loaded in :class:`~openlp.core.utils.ActionList`. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'shortcuts') for category in self.action_list.categories: # Check if the category is for internal use only. diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 1dc005aa6..1e44386c9 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \ translate, build_icon, build_html, PluginManager, ServiceItem from openlp.core.lib.ui import UiStrings, create_action +from openlp.core.lib.settings import Settings from openlp.core.lib import SlideLimits, ServiceItemAction from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList from openlp.core.utils.actions import ActionList, CategoryOrder @@ -236,7 +237,7 @@ class SlideController(Controller): text=UiStrings().PlaySlidesToEnd, icon=u':/media/media_time.png', checked=False, shortcuts=[], category=self.category, triggers=self.onPlaySlidesOnce) - if QtCore.QSettings().value(self.parent().generalSettingsSection + + if Settings().value(self.parent().generalSettingsSection + u'/enable slide loop', QtCore.QVariant(True)).toBool(): self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) else: @@ -662,7 +663,7 @@ class SlideController(Controller): """ Updates the Slide Limits variable from the settings. """ - self.slide_limits = QtCore.QSettings().value( + self.slide_limits = Settings().value( self.parent().advancedSettingsSection + u'/slide limits', QtCore.QVariant(SlideLimits.End)).toInt()[0] @@ -692,7 +693,7 @@ class SlideController(Controller): self.playSlidesLoop.setChecked(False) self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png')) if item.is_text(): - if QtCore.QSettings().value( + if Settings().value( self.parent().songsSettingsSection + u'/display songbar', QtCore.QVariant(True)).toBool() and self.slideList: self.songMenu.show() @@ -813,11 +814,11 @@ class SlideController(Controller): QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), self.onTrackTriggered) - self.display.audioPlayer.repeat = QtCore.QSettings().value( + self.display.audioPlayer.repeat = Settings().value( self.parent().generalSettingsSection + \ u'/audio repeat list', QtCore.QVariant(False)).toBool() - if QtCore.QSettings().value( + if Settings().value( self.parent().generalSettingsSection + \ u'/audio start paused', QtCore.QVariant(True)).toBool(): @@ -930,7 +931,7 @@ class SlideController(Controller): Allow the main display to blank the main display at startup time """ log.debug(u'mainDisplaySetBackground live = %s' % self.isLive) - display_type = QtCore.QSettings().value( + display_type = Settings().value( self.parent().generalSettingsSection + u'/screen blank', QtCore.QVariant(u'')).toString() if self.screens.which_screen(self.window()) != \ @@ -971,11 +972,11 @@ class SlideController(Controller): self.themeScreen.setChecked(False) self.desktopScreen.setChecked(False) if checked: - QtCore.QSettings().setValue( + Settings().setValue( self.parent().generalSettingsSection + u'/screen blank', QtCore.QVariant(u'blanked')) else: - QtCore.QSettings().remove( + Settings().remove( self.parent().generalSettingsSection + u'/screen blank') self.blankPlugin() self.updatePreview() @@ -992,11 +993,11 @@ class SlideController(Controller): self.themeScreen.setChecked(checked) self.desktopScreen.setChecked(False) if checked: - QtCore.QSettings().setValue( + Settings().setValue( self.parent().generalSettingsSection + u'/screen blank', QtCore.QVariant(u'themed')) else: - QtCore.QSettings().remove( + Settings().remove( self.parent().generalSettingsSection + u'/screen blank') self.blankPlugin() self.updatePreview() @@ -1013,11 +1014,11 @@ class SlideController(Controller): self.themeScreen.setChecked(False) self.desktopScreen.setChecked(checked) if checked: - QtCore.QSettings().setValue( + Settings().setValue( self.parent().generalSettingsSection + u'/screen blank', QtCore.QVariant(u'hidden')) else: - QtCore.QSettings().remove( + Settings().remove( self.parent().generalSettingsSection + u'/screen blank') self.hidePlugin(checked) self.updatePreview() @@ -1311,7 +1312,7 @@ class SlideController(Controller): """ triggered by clicking the Preview slide items """ - if QtCore.QSettings().value(u'advanced/double click live', + if Settings().value(u'advanced/double click live', QtCore.QVariant(False)).toBool(): # Live and Preview have issues if we have video or presentations # playing in both at the same time. diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 665c435b9..733599672 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -40,6 +40,7 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \ check_directory_exists, create_thumb, validate_thumb from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ BackgroundGradientType +from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_widget_action from openlp.core.theme import Theme @@ -164,7 +165,7 @@ class ThemeManager(QtGui.QWidget): """ Triggered when Config dialog is updated. """ - self.global_theme = unicode(QtCore.QSettings().value( + self.global_theme = unicode(Settings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) @@ -244,7 +245,7 @@ class ThemeManager(QtGui.QWidget): name = unicode(translate('OpenLP.ThemeManager', '%s (default)')) % self.global_theme self.themeListWidget.item(count).setText(name) - QtCore.QSettings().setValue( + Settings().setValue( self.settingsSection + u'/global theme', QtCore.QVariant(self.global_theme)) Receiver.send_message(u'theme_update_global', @@ -448,7 +449,7 @@ class ThemeManager(QtGui.QWidget): theme = ThemeXML() theme.theme_name = UiStrings().Default self._writeTheme(theme, None, None) - QtCore.QSettings().setValue( + Settings().setValue( self.settingsSection + u'/global theme', QtCore.QVariant(theme.theme_name)) self.configUpdated() @@ -767,7 +768,7 @@ class ThemeManager(QtGui.QWidget): Check to see if theme has been selected and the destructive action is allowed. """ - self.global_theme = unicode(QtCore.QSettings().value( + self.global_theme = unicode(Settings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) if check_item_selected(self.themeListWidget, select_text): diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index f763a9e74..8d5c5fb47 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box +from openlp.core.lib.settings import Settings class ThemesTab(SettingsTab): """ @@ -132,7 +133,7 @@ class ThemesTab(SettingsTab): 'any themes associated with either the service or the songs.')) def load(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.theme_level = settings.value( u'theme level', ThemeLevel.Song).toInt()[0] @@ -146,7 +147,7 @@ class ThemesTab(SettingsTab): self.SongLevelRadioButton.setChecked(True) def save(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'theme level', QtCore.QVariant(self.theme_level)) settings.setValue(u'global theme', QtCore.QVariant(self.global_theme)) @@ -183,7 +184,7 @@ class ThemesTab(SettingsTab): [u'Bible Theme', u'Song Theme'] """ # Reload as may have been triggered by the ThemeManager. - self.global_theme = unicode(QtCore.QSettings().value( + self.global_theme = unicode(Settings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) self.DefaultComboBox.clear() diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index fd54aa338..b9ee6785e 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -37,6 +37,8 @@ import sys import time import urllib2 +from openlp.core.lib.settings import Settings + from PyQt4 import QtGui, QtCore if sys.platform != u'win32' and sys.platform != u'darwin': @@ -128,8 +130,8 @@ class AppLocation(object): Return the path OpenLP stores all its data under. """ # Check if we have a different data location. - if QtCore.QSettings().contains(u'advanced/data path'): - path = unicode(QtCore.QSettings().value( + if Settings().contains(u'advanced/data path'): + path = unicode(Settings().value( u'advanced/data path').toString()) else: path = AppLocation.get_directory(AppLocation.DataDir) @@ -286,7 +288,7 @@ def check_latest_version(current_version): """ version_string = current_version[u'full'] # set to prod in the distribution config file. - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'general') last_test = unicode(settings.value(u'last version test', QtCore.QVariant(datetime.now().date())).toString()) diff --git a/openlp/core/utils/actions.py b/openlp/core/utils/actions.py index 271a7c884..087da222c 100644 --- a/openlp/core/utils/actions.py +++ b/openlp/core/utils/actions.py @@ -30,6 +30,8 @@ by the shortcuts system. """ from PyQt4 import QtCore, QtGui +from openlp.core.lib.settings import Settings + class ActionCategory(object): """ The :class:`~openlp.core.utils.ActionCategory` class encapsulates a @@ -226,7 +228,7 @@ class ActionList(object): else: self.categories[category].actions.add(action, weight) # Load the shortcut from the config. - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'shortcuts') shortcuts = settings.value(action.objectName(), QtCore.QVariant(action.shortcuts())).toStringList() diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/utils/languagemanager.py index 929105ad2..24899fd41 100644 --- a/openlp/core/utils/languagemanager.py +++ b/openlp/core/utils/languagemanager.py @@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.utils import AppLocation from openlp.core.lib import translate +from openlp.core.lib.settings import Settings log = logging.getLogger(__name__) @@ -101,7 +102,7 @@ class LanguageManager(object): """ Retrieve a saved language to use from settings """ - settings = QtCore.QSettings() + settings = Settings() language = unicode(settings.value( u'general/language', QtCore.QVariant(u'[en]')).toString()) log.info(u'Language file: \'%s\' Loaded from conf file' % language) @@ -133,7 +134,7 @@ class LanguageManager(object): language = unicode(qm_list[action_name]) if LanguageManager.auto_language: language = u'[%s]' % language - QtCore.QSettings().setValue( + Settings().setValue( u'general/language', QtCore.QVariant(language)) log.info(u'Language file: \'%s\' written to conf file' % language) if message: diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index ebaabb214..1a7fe565a 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager from openlp.core.lib.ui import create_action, UiStrings +from openlp.core.lib.settings import Settings from openlp.core.lib.theme import VerticalType from openlp.core.utils.actions import ActionList from openlp.plugins.alerts.lib import AlertsManager, AlertsTab @@ -160,7 +161,7 @@ class AlertsPlugin(Plugin): def toggleAlertsState(self): self.alertsActive = not self.alertsActive - QtCore.QSettings().setValue(self.settingsSection + u'/active', + Settings().setValue(self.settingsSection + u'/active', QtCore.QVariant(self.alertsActive)) def onAlertsTrigger(self): diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 22346b0aa..6a323eb2a 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.ui import AlertLocation from openlp.core.lib.ui import UiStrings, create_valign_selection_widgets +from openlp.core.lib.settings import Settings class AlertsTab(SettingsTab): """ @@ -152,7 +153,7 @@ class AlertsTab(SettingsTab): self.updateDisplay() def load(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.timeout = settings.value(u'timeout', QtCore.QVariant(5)).toInt()[0] self.font_color = unicode(settings.value( @@ -180,7 +181,7 @@ class AlertsTab(SettingsTab): self.changed = False def save(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) # Check value has changed as no event handles this field if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \ diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 0dddab214..e1209514c 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.ui import create_action, UiStrings +from openlp.core.lib.settings import Settings from openlp.core.utils.actions import ActionList from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem from openlp.plugins.bibles.forms import BibleUpgradeForm @@ -91,7 +92,7 @@ class BiblePlugin(Plugin): QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == QtGui.QMessageBox.Yes: self.onToolsUpgradeItemTriggered() - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) if settings.contains(u'bookname language'): settings.setValue(u'book name language', settings.value( diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index cc50fdf9b..92911c22a 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate from openlp.core.lib.db import delete_database from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.lib.settings import Settings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.manager import BibleFormat @@ -590,7 +591,7 @@ class BibleImportForm(OpenLPWizard): """ Set default values for the wizard pages. """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.plugin.settingsSection) self.restart() self.finishButton.setVisible(False) diff --git a/openlp/plugins/bibles/forms/bibleupgradeform.py b/openlp/plugins/bibles/forms/bibleupgradeform.py index 88bbd8c63..4013284e4 100644 --- a/openlp/plugins/bibles/forms/bibleupgradeform.py +++ b/openlp/plugins/bibles/forms/bibleupgradeform.py @@ -36,6 +36,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate, \ check_directory_exists from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.lib.settings import Settings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.utils import AppLocation, delete_file from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, \ @@ -341,7 +342,7 @@ class BibleUpgradeForm(OpenLPWizard): Set default values for the wizard pages. """ log.debug(u'BibleUpgrade setDefaults') - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.plugin.settingsSection) self.stop_import_flag = False self.success.clear() diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index 6cd8b8d8e..9d4d62bf8 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -34,6 +34,7 @@ import re from PyQt4 import QtCore from openlp.core.lib import translate +from openlp.core.lib.settings import Settings from openlp.plugins.bibles.lib.db import BiblesResourcesDB log = logging.getLogger(__name__) @@ -185,7 +186,7 @@ def update_reference_separators(): ':|v|V|verse|verses;;-|to;;,|and;;end', 'Double-semicolon delimited separators for parsing references. ' 'Consult the developers for further information.')).split(u';;') - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(u'bibles') custom_separators = [ unicode(settings.value(u'verse separator').toString()), diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index c352a5faf..0b4de68d9 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -31,6 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsTab, translate from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box +from openlp.core.lib.settings import Settings from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ update_reference_separators, get_reference_separator, LanguageSelection @@ -414,7 +415,7 @@ class BiblesTab(SettingsTab): self.getGreyTextPalette(True)) def load(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.show_new_chapters = settings.value( u'display new chapter', QtCore.QVariant(False)).toBool() @@ -488,7 +489,7 @@ class BiblesTab(SettingsTab): settings.endGroup() def save(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'display new chapter', QtCore.QVariant(self.show_new_chapters)) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 9a82cc388..e046ae362 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.utils import AppLocation, delete_file +from openlp.core.lib.settings import Settings from openlp.plugins.bibles.lib import parse_reference, \ get_reference_separator, LanguageSelection from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta @@ -126,7 +127,7 @@ class BibleManager(object): self.db_cache = None self.path = AppLocation.get_section_data_path(self.settingsSection) self.proxy_name = unicode( - QtCore.QSettings().value(self.settingsSection + u'/proxy name', + Settings().value(self.settingsSection + u'/proxy name', QtCore.QVariant(u'')).toString()) self.suffix = u'.sqlite' self.import_wizard = None @@ -334,7 +335,7 @@ class BibleManager(object): if language_selection: language_selection = int(language_selection.value) if language_selection is None or language_selection == -1: - language_selection = QtCore.QSettings().value( + language_selection = Settings().value( self.settingsSection + u'/bookname language', QtCore.QVariant(0)).toInt()[0] reflist = parse_reference(versetext, self.db_cache[bible], @@ -381,7 +382,7 @@ class BibleManager(object): if language_selection and language_selection.value != u'None': return int(language_selection.value) if language_selection is None or language_selection.value == u'None': - return QtCore.QSettings().value( + return Settings().value( self.settingsSection + u'/bookname language', QtCore.QVariant(0)).toInt()[0] diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 3c723d760..9607785fd 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -33,6 +33,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ translate, create_separated_list from openlp.core.lib.searchedit import SearchEdit +from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \ create_horizontal_adjusting_combo_box, critical_error_message_box, \ find_and_set_in_combo_box, build_icon @@ -294,7 +295,7 @@ class BibleMediaItem(MediaManagerItem): def configUpdated(self): log.debug(u'configUpdated') - if QtCore.QSettings().value(self.settingsSection + u'/second bibles', + if Settings().value(self.settingsSection + u'/second bibles', QtCore.QVariant(True)).toBool(): self.advancedSecondLabel.setVisible(True) self.advancedSecondComboBox.setVisible(True) @@ -362,7 +363,7 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'Text Search'), translate('BiblesPlugin.MediaItem', 'Search Text...')) ]) - self.quickSearchEdit.setCurrentSearchType(QtCore.QSettings().value( + self.quickSearchEdit.setCurrentSearchType(Settings().value( u'%s/last search type' % self.settingsSection, QtCore.QVariant(BibleSearch.Reference)).toInt()[0]) self.configUpdated() @@ -386,7 +387,7 @@ class BibleMediaItem(MediaManagerItem): self.advancedVersionComboBox.addItems(bibles) self.advancedSecondComboBox.addItems(bibles) # set the default value - bible = QtCore.QSettings().value( + bible = Settings().value( self.settingsSection + u'/advanced bible', QtCore.QVariant(u'')).toString() if bible in bibles: @@ -394,7 +395,7 @@ class BibleMediaItem(MediaManagerItem): self.initialiseAdvancedBible(unicode(bible)) elif bibles: self.initialiseAdvancedBible(bibles[0]) - bible = QtCore.QSettings().value( + bible = Settings().value( self.settingsSection + u'/quick bible', QtCore.QVariant( self.quickVersionComboBox.currentText())).toString() find_and_set_in_combo_box(self.quickVersionComboBox, bible) @@ -497,11 +498,11 @@ class BibleMediaItem(MediaManagerItem): """ log.debug(u'updateAutoCompleter') # Save the current search type to the configuration. - QtCore.QSettings().setValue(u'%s/last search type' % + Settings().setValue(u'%s/last search type' % self.settingsSection, QtCore.QVariant(self.quickSearchEdit.currentSearchType())) # Save the current bible to the configuration. - QtCore.QSettings().setValue(self.settingsSection + u'/quick bible', + Settings().setValue(self.settingsSection + u'/quick bible', QtCore.QVariant(self.quickVersionComboBox.currentText())) books = [] # We have to do a 'Reference Search'. @@ -596,7 +597,7 @@ class BibleMediaItem(MediaManagerItem): self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style) self.settings.layoutStyleComboBox.setCurrentIndex( self.settings.layout_style) - QtCore.QSettings().setValue( + Settings().setValue( self.settingsSection + u'/verse layout style', QtCore.QVariant(self.settings.layout_style)) @@ -605,12 +606,12 @@ class BibleMediaItem(MediaManagerItem): self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style) self.settings.layoutStyleComboBox.setCurrentIndex( self.settings.layout_style) - QtCore.QSettings().setValue( + Settings().setValue( self.settingsSection + u'/verse layout style', QtCore.QVariant(self.settings.layout_style)) def onAdvancedVersionComboBox(self): - QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible', + Settings().setValue(self.settingsSection + u'/advanced bible', QtCore.QVariant(self.advancedVersionComboBox.currentText())) self.initialiseAdvancedBible( unicode(self.advancedVersionComboBox.currentText()), diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py index 0466cf696..bd6b854e4 100644 --- a/openlp/plugins/custom/lib/customtab.py +++ b/openlp/plugins/custom/lib/customtab.py @@ -28,6 +28,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate +from openlp.core.lib.settings import Settings class CustomTab(SettingsTab): """ @@ -66,11 +67,11 @@ class CustomTab(SettingsTab): self.displayFooter = True def load(self): - self.displayFooter = QtCore.QSettings().value( + self.displayFooter = Settings().value( self.settingsSection + u'/display footer', QtCore.QVariant(True)).toBool() self.displayFooterCheckBox.setChecked(self.displayFooter) def save(self): - QtCore.QSettings().setValue(self.settingsSection + u'/display footer', + Settings().setValue(self.settingsSection + u'/display footer', QtCore.QVariant(self.displayFooter)) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index af2f261ca..7b7284b55 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -34,6 +34,7 @@ from sqlalchemy.sql import or_, func from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings +from openlp.core.lib.settings import Settings from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -99,7 +100,7 @@ class CustomMediaItem(MediaManagerItem): ]) self.loadList(self.manager.get_all_objects( CustomSlide, order_by_ref=CustomSlide.title)) - self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( + self.searchTextEdit.setCurrentSearchType(Settings().value( u'%s/last search type' % self.settingsSection, QtCore.QVariant(CustomSearch.Titles)).toInt()[0]) @@ -218,7 +219,7 @@ class CustomMediaItem(MediaManagerItem): service_item.title = title for slide in raw_slides: service_item.add_from_text(slide[:30], slide) - if QtCore.QSettings().value(self.settingsSection + u'/display footer', + if Settings().value(self.settingsSection + u'/display footer', QtCore.QVariant(True)).toBool() or credit: raw_footer.append(title + u' ' + credit) else: @@ -228,7 +229,7 @@ class CustomMediaItem(MediaManagerItem): def onSearchTextButtonClicked(self): # Save the current search type to the configuration. - QtCore.QSettings().setValue(u'%s/last search type' % + Settings().setValue(u'%s/last search type' % self.settingsSection, QtCore.QVariant(self.searchTextEdit.currentSearchType())) # Reload the list considering the new search type. diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 53f825916..832fb9097 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -31,6 +31,7 @@ import logging from openlp.core.lib import Plugin, StringContent, build_icon, translate, \ Receiver +from openlp.core.lib.settings import Settings from openlp.plugins.images.lib import ImageMediaItem, ImageTab log = logging.getLogger(__name__) @@ -94,6 +95,6 @@ class ImagePlugin(Plugin): image manager to require updates. Actual update is triggered by the last part of saving the config. """ - background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + background = QtGui.QColor(Settings().value(self.settingsSection + u'/background color', QtCore.QVariant(u'#000000'))) self.liveController.imageManager.update_images(u'image', background) diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index a8188ace6..d80240005 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -28,6 +28,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate, Receiver +from openlp.core.lib.settings import Settings class ImageTab(SettingsTab): """ @@ -82,7 +83,7 @@ class ImageTab(SettingsTab): u'background-color: %s' % self.bg_color) def load(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.bg_color = unicode(settings.value( u'background color', QtCore.QVariant(u'#000000')).toString()) @@ -92,7 +93,7 @@ class ImageTab(SettingsTab): u'background-color: %s' % self.bg_color) def save(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'background color', QtCore.QVariant(self.bg_color)) settings.endGroup() diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index ffa67b95e..7e66ad9c0 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -35,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \ SettingsManager, translate, check_item_selected, check_directory_exists, \ Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.lib.settings import Settings from openlp.core.utils import AppLocation, delete_file, get_images_filter log = logging.getLogger(__name__) @@ -151,7 +152,7 @@ class ImageMediaItem(MediaManagerItem): def generateSlideData(self, service_item, item=None, xmlVersion=False, remote=False): - background = QtGui.QColor(QtCore.QSettings().value(self.settingsSection + background = QtGui.QColor(Settings().value(self.settingsSection + u'/background color', QtCore.QVariant(u'#000000'))) if item: items = [item] @@ -220,7 +221,7 @@ class ImageMediaItem(MediaManagerItem): if check_item_selected(self.listView, translate('ImagePlugin.MediaItem', 'You must select an image to replace the background with.')): - background = QtGui.QColor(QtCore.QSettings().value( + background = QtGui.QColor(Settings().value( self.settingsSection + u'/background color', QtCore.QVariant(u'#000000'))) item = self.listView.selectedIndexes()[0] diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py index c7ec1a61b..5a9543642 100644 --- a/openlp/plugins/media/lib/mediatab.py +++ b/openlp/plugins/media/lib/mediatab.py @@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate, Receiver from openlp.core.lib.ui import UiStrings, create_button +from openlp.core.lib.settings import Settings from openlp.core.ui.media import get_media_players, set_media_players class MediaQCheckBox(QtGui.QCheckBox): """ @@ -186,7 +187,7 @@ class MediaTab(SettingsTab): else: checkbox.setChecked(False) self.updatePlayerList() - self.overridePlayerCheckBox.setChecked(QtCore.QSettings().value( + self.overridePlayerCheckBox.setChecked(Settings().value( self.settingsSection + u'/override player', QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]) @@ -200,9 +201,9 @@ class MediaTab(SettingsTab): player_string_changed = True override_changed = True setting_key = self.settingsSection + u'/override player' - if QtCore.QSettings().value(setting_key).toInt()[0] != \ + if Settings().value(setting_key).toInt()[0] != \ self.overridePlayerCheckBox.checkState(): - QtCore.QSettings().setValue(setting_key, + Settings().setValue(setting_key, QtCore.QVariant(self.overridePlayerCheckBox.checkState())) override_changed = True if override_changed: diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 13c636e83..08d7f1983 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -30,6 +30,7 @@ import logging from PyQt4 import QtCore from openlp.core.lib import Plugin, StringContent, build_icon, translate +from openlp.core.lib.settings import Settings from openlp.plugins.media.lib import MediaMediaItem, MediaTab log = logging.getLogger(__name__) @@ -126,7 +127,7 @@ class MediaPlugin(Plugin): we want to check if we have the old "Use Phonon" setting, and convert it to "enable Phonon" and "make it the first one in the list". """ - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) if settings.contains(u'use phonon'): log.info(u'Found old Phonon setting') diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 68eea809b..b98c2d093 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -36,6 +36,7 @@ from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \ validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_horizontal_adjusting_combo_box +from openlp.core.lib.settings import Settings from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -149,7 +150,7 @@ class PresentationMediaItem(MediaManagerItem): if self.displayTypeComboBox.count() > 1: self.displayTypeComboBox.insertItem(0, self.Automatic) self.displayTypeComboBox.setCurrentIndex(0) - if QtCore.QSettings().value(self.settingsSection + u'/override app', + if Settings().value(self.settingsSection + u'/override app', QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked: self.presentationWidget.show() else: diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 7702f19cd..3bda3e069 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -33,6 +33,7 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \ validate_thumb +from openlp.core.lib.settings import Settings from openlp.core.utils import AppLocation log = logging.getLogger(__name__) @@ -392,7 +393,7 @@ class PresentationController(object): """ Return whether the controller is currently enabled """ - if QtCore.QSettings().value( + if Settings().value( self.settings_section + u'/' + self.name, QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \ QtCore.Qt.Checked: diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index 1b9fa04d9..312f2b55a 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsTab, translate from openlp.core.lib.ui import UiStrings +from openlp.core.lib.settings import Settings class PresentationTab(SettingsTab): """ @@ -102,10 +103,10 @@ class PresentationTab(SettingsTab): for key in self.controllers: controller = self.controllers[key] checkbox = self.PresenterCheckboxes[controller.name] - checkbox.setChecked(QtCore.QSettings().value( + checkbox.setChecked(Settings().value( self.settingsSection + u'/' + controller.name, QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0]) - self.OverrideAppCheckBox.setChecked(QtCore.QSettings().value( + self.OverrideAppCheckBox.setChecked(Settings().value( self.settingsSection + u'/override app', QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]) @@ -123,19 +124,19 @@ class PresentationTab(SettingsTab): if controller.is_available(): checkbox = self.PresenterCheckboxes[controller.name] setting_key = self.settingsSection + u'/' + controller.name - if QtCore.QSettings().value(setting_key) != \ + if Settings().value(setting_key) != \ checkbox.checkState(): changed = True - QtCore.QSettings().setValue(setting_key, + Settings().setValue(setting_key, QtCore.QVariant(checkbox.checkState())) if checkbox.isChecked(): controller.start_process() else: controller.kill() setting_key = self.settingsSection + u'/override app' - if QtCore.QSettings().value(setting_key) != \ + if Settings().value(setting_key) != \ self.OverrideAppCheckBox.checkState(): - QtCore.QSettings().setValue(setting_key, + Settings().setValue(setting_key, QtCore.QVariant(self.OverrideAppCheckBox.checkState())) changed = True if changed: diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index 43afebb41..4bae0a901 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -122,6 +122,7 @@ from PyQt4 import QtCore, QtNetwork from mako.template import Template from openlp.core.lib import Receiver, PluginStatus, StringContent +from openlp.core.lib.settings import Settings from openlp.core.utils import AppLocation, translate log = logging.getLogger(__name__) @@ -169,10 +170,10 @@ class HttpServer(object): clients. Listen out for socket connections. """ log.debug(u'Start TCP server') - port = QtCore.QSettings().value( + port = Settings().value( self.plugin.settingsSection + u'/port', QtCore.QVariant(4316)).toInt()[0] - address = QtCore.QSettings().value( + address = Settings().value( self.plugin.settingsSection + u'/ip address', QtCore.QVariant(u'0.0.0.0')).toString() self.server = QtNetwork.QTcpServer() @@ -404,7 +405,7 @@ class HttpConnection(object): u'slide': self.parent.current_slide or 0, u'item': self.parent.current_item._uuid \ if self.parent.current_item else u'', - u'twelve':QtCore.QSettings().value( + u'twelve':Settings().value( u'remotes/twelve hour', QtCore.QVariant(True)).toBool(), u'blank': self.parent.plugin.liveController.blankScreen.\ isChecked(), diff --git a/openlp/plugins/remotes/lib/remotetab.py b/openlp/plugins/remotes/lib/remotetab.py index bae2a7090..5130ee65e 100644 --- a/openlp/plugins/remotes/lib/remotetab.py +++ b/openlp/plugins/remotes/lib/remotetab.py @@ -28,6 +28,7 @@ from PyQt4 import QtCore, QtGui, QtNetwork from openlp.core.lib import SettingsTab, translate, Receiver +from openlp.core.lib.settings import Settings ZERO_URL = u'0.0.0.0' @@ -149,12 +150,12 @@ class RemoteTab(SettingsTab): def load(self): self.portSpinBox.setValue( - QtCore.QSettings().value(self.settingsSection + u'/port', + Settings().value(self.settingsSection + u'/port', QtCore.QVariant(4316)).toInt()[0]) self.addressEdit.setText( - QtCore.QSettings().value(self.settingsSection + u'/ip address', + Settings().value(self.settingsSection + u'/ip address', QtCore.QVariant(ZERO_URL)).toString()) - self.twelveHour = QtCore.QSettings().value( + self.twelveHour = Settings().value( self.settingsSection + u'/twelve hour', QtCore.QVariant(True)).toBool() self.twelveHourCheckBox.setChecked(self.twelveHour) @@ -162,16 +163,16 @@ class RemoteTab(SettingsTab): def save(self): changed = False - if QtCore.QSettings().value(self.settingsSection + u'/ip address', + if Settings().value(self.settingsSection + u'/ip address', QtCore.QVariant(ZERO_URL).toString() != self.addressEdit.text() or - QtCore.QSettings().value(self.settingsSection + u'/port', + Settings().value(self.settingsSection + u'/port', QtCore.QVariant(4316).toInt()[0]) != self.portSpinBox.value()): changed = True - QtCore.QSettings().setValue(self.settingsSection + u'/port', + Settings().setValue(self.settingsSection + u'/port', QtCore.QVariant(self.portSpinBox.value())) - QtCore.QSettings().setValue(self.settingsSection + u'/ip address', + Settings().setValue(self.settingsSection + u'/ip address', QtCore.QVariant(self.addressEdit.text())) - QtCore.QSettings().setValue(self.settingsSection + u'/twelve hour', + Settings().setValue(self.settingsSection + u'/twelve hour', QtCore.QVariant(self.twelveHour)) if changed: Receiver.send_message(u'remotes_config_updated') diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4a44c30ef..966a749dd 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.lib.settings import Settings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.plugins.songs.lib.importer import SongFormat @@ -373,7 +374,7 @@ class SongImportForm(OpenLPWizard): return True elif self.currentPage() == self.sourcePage: source_format = self.formatComboBox.currentIndex() - QtCore.QSettings().setValue(u'songs/last import type', + Settings().setValue(u'songs/last import type', source_format) if source_format == SongFormat.OpenLP2: if self.openLP2FilenameEdit.text().isEmpty(): @@ -704,7 +705,7 @@ class SongImportForm(OpenLPWizard): self.restart() self.finishButton.setVisible(False) self.cancelButton.setVisible(True) - last_import_type = QtCore.QSettings().value( + last_import_type = Settings().value( u'songs/last import type').toInt()[0] if last_import_type < 0 or \ last_import_type >= self.formatComboBox.count(): diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 51158a954..ca3c76353 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -37,6 +37,7 @@ from sqlalchemy.sql import or_ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ translate, check_item_selected, PluginStatus, create_separated_list from openlp.core.lib.ui import UiStrings, create_widget_action +from openlp.core.lib.settings import Settings from openlp.core.utils import AppLocation from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm @@ -131,13 +132,13 @@ class SongMediaItem(MediaManagerItem): self.searchTextEdit.setFocus() def configUpdated(self): - self.searchAsYouType = QtCore.QSettings().value( + self.searchAsYouType = Settings().value( self.settingsSection + u'/search as type', QtCore.QVariant(u'False')).toBool() - self.updateServiceOnEdit = QtCore.QSettings().value( + self.updateServiceOnEdit = Settings().value( self.settingsSection + u'/update service on edit', QtCore.QVariant(u'False')).toBool() - self.addSongFromService = QtCore.QSettings().value( + self.addSongFromService = Settings().value( self.settingsSection + u'/add song from service', QtCore.QVariant(u'True')).toBool() @@ -168,14 +169,14 @@ class SongMediaItem(MediaManagerItem): (SongSearch.Themes, u':/slides/slide_theme.png', UiStrings().Themes, UiStrings().SearchThemes) ]) - self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( + self.searchTextEdit.setCurrentSearchType(Settings().value( u'%s/last search type' % self.settingsSection, QtCore.QVariant(SongSearch.Entire)).toInt()[0]) self.configUpdated() def onSearchTextButtonClicked(self): # Save the current search type to the configuration. - QtCore.QSettings().setValue(u'%s/last search type' % + Settings().setValue(u'%s/last search type' % self.settingsSection, QtCore.QVariant(self.searchTextEdit.currentSearchType())) # Reload the list considering the new search type. @@ -516,11 +517,11 @@ class SongMediaItem(MediaManagerItem): service_item.raw_footer.append(song.title) service_item.raw_footer.append(create_separated_list(author_list)) service_item.raw_footer.append(song.copyright) - if QtCore.QSettings().value(u'general/ccli number', + if Settings().value(u'general/ccli number', QtCore.QVariant(u'')).toString(): service_item.raw_footer.append(unicode( translate('SongsPlugin.MediaItem', 'CCLI License: ') + - QtCore.QSettings().value(u'general/ccli number', + Settings().value(u'general/ccli number', QtCore.QVariant(u'')).toString())) service_item.audit = [ song.title, author_list, song.copyright, unicode(song.ccli_number) diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 9d6de087f..ca646cd5f 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -28,6 +28,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate +from openlp.core.lib.settings import Settings class SongsTab(SettingsTab): """ @@ -110,7 +111,7 @@ class SongsTab(SettingsTab): self.update_load = True def load(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) self.song_search = settings.value( u'search as type', QtCore.QVariant(False)).toBool() @@ -127,7 +128,7 @@ class SongsTab(SettingsTab): settings.endGroup() def save(self): - settings = QtCore.QSettings() + settings = Settings() settings.beginGroup(self.settingsSection) settings.setValue(u'search as type', QtCore.QVariant(self.song_search)) settings.setValue(u'display songbar', QtCore.QVariant(self.tool_bar)) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index 363455ea5..1ad6fceef 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -33,6 +33,7 @@ from sqlalchemy.sql import and_ from openlp.core.lib import SettingsManager, translate, Receiver, \ check_directory_exists +from openlp.core.lib.settings import Settings from openlp.plugins.songusage.lib.db import SongUsageItem from songusagedetaildialog import Ui_SongUsageDetailDialog @@ -59,10 +60,10 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): year = QtCore.QDate().currentDate().year() if QtCore.QDate().currentDate().month() < 9: year -= 1 - toDate = QtCore.QSettings().value( + toDate = Settings().value( u'songusage/to date', QtCore.QVariant(QtCore.QDate(year, 8, 31))).toDate() - fromDate = QtCore.QSettings().value( + fromDate = Settings().value( u'songusage/from date', QtCore.QVariant(QtCore.QDate(year - 1, 9, 1))).toDate() self.fromDate.setSelectedDate(fromDate) @@ -103,9 +104,9 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): 'usage_detail_%s_%s.txt')) % ( self.fromDate.selectedDate().toString(u'ddMMyyyy'), self.toDate.selectedDate().toString(u'ddMMyyyy')) - QtCore.QSettings().setValue(u'songusage/from date', + Settings().setValue(u'songusage/from date', QtCore.QVariant(self.fromDate.selectedDate())) - QtCore.QSettings().setValue(u'songusage/to date', + Settings().setValue(u'songusage/to date', QtCore.QVariant(self.toDate.selectedDate())) usage = self.plugin.manager.get_all_objects( SongUsageItem, and_( diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 7746f9b28..3b6f66fe5 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -34,6 +34,7 @@ from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \ translate from openlp.core.lib.db import Manager from openlp.core.lib.ui import create_action +from openlp.core.lib.settings import Settings from openlp.core.utils.actions import ActionList from openlp.plugins.songusage.forms import SongUsageDetailForm, \ SongUsageDeleteForm @@ -125,7 +126,7 @@ class SongUsagePlugin(Plugin): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'print_service_started'), self.printSongUsage) - self.songUsageActive = QtCore.QSettings().value( + self.songUsageActive = Settings().value( self.settingsSection + u'/active', QtCore.QVariant(False)).toBool() # Set the button and checkbox state @@ -168,7 +169,7 @@ class SongUsagePlugin(Plugin): the UI when necessary, """ self.songUsageActive = not self.songUsageActive - QtCore.QSettings().setValue(self.settingsSection + u'/active', + Settings().setValue(self.settingsSection + u'/active', QtCore.QVariant(self.songUsageActive)) self.setButtonState() From 2f38d55261e6c5f8e7c609a36b406394f7871e0c Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Fri, 11 May 2012 14:37:57 -0400 Subject: [PATCH 05/46] Changes to accomodate correct directory structure --- openlp/core/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index e3dc92af7..d5cdeb198 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -264,13 +264,14 @@ def main(args=None): # Get location OpenLPPortable.ini app_path = AppLocation.get_directory(AppLocation.AppDir) portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', - u'Data', u'Settings', u'OpenLPPortable.ini')) + u'..', u'Data', u'settings', u'OpenLPPortable.ini')) # Make this our settings file log.info(u'INI file: %s' % portable_settings_file) Settings.setFilename(portable_settings_file) portable_settings = Settings() # Set our data path - data_path = os.path.abspath(os.path.join(app_path, u'..', u'Data',)) + data_path = os.path.abspath(os.path.join(app_path, + u'..', u'..', u'Data',)) log.info(u'Data path: %s' % data_path) # Point to our data path portable_settings.setValue(u'advanced/data path',data_path) From eb58ee10e87a18f9cdd2d32d9c2f433a0c97b610 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Mon, 14 May 2012 23:17:20 -0400 Subject: [PATCH 06/46] Changed name of settings INI to conform to PortableApps Standards Disabled data path change when running portable --- openlp/core/__init__.py | 3 ++- openlp/core/ui/advancedtab.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index d5cdeb198..efbe40bab 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -264,7 +264,7 @@ def main(args=None): # Get location OpenLPPortable.ini app_path = AppLocation.get_directory(AppLocation.AppDir) portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', - u'..', u'Data', u'settings', u'OpenLPPortable.ini')) + u'..', u'Data', u'settings', u'OpenLP.ini')) # Make this our settings file log.info(u'INI file: %s' % portable_settings_file) Settings.setFilename(portable_settings_file) @@ -275,6 +275,7 @@ def main(args=None): log.info(u'Data path: %s' % data_path) # Point to our data path portable_settings.setValue(u'advanced/data path',data_path) + portable_settings.setValue(u'advanced/is portable',True) portable_settings.sync() else: app.setApplicationName(u'OpenLP') diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 21cb42a7e..58be29126 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -543,6 +543,9 @@ class AdvancedTab(SettingsTab): os.path.join(self.currentDataPath, u'..'))) self.defaultColorButton.setStyleSheet( u'background-color: %s' % self.defaultColor) + # Don't allow data directory change if running portable + if Settings().contains(u'advanced/is portable'): + self.dataDirectoryGroupBox.hide() def save(self): """ From a7fc64f0c3788d27a116b25a0c76d656bb14e00d Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 17 May 2012 15:23:58 -0400 Subject: [PATCH 07/46] Fixed problem with Import settings. --- openlp/core/ui/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index d38bf9569..9b75e33b2 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -966,7 +966,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): for plugin in self.pluginManager.plugins: setting_sections.extend([plugin.name]) settings = Settings() - import_settings = Settings(import_file_name, + import_settings = QtCore.QSettings(import_file_name, Settings.IniFormat) import_keys = import_settings.allKeys() for section_key in import_keys: From aa5805863a3f90487264369b48ae945f50a118d2 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 17 May 2012 23:24:49 -0400 Subject: [PATCH 08/46] Moved location of settings ini file to ..\Data --- openlp/core/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index efbe40bab..4403926c8 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -264,7 +264,7 @@ def main(args=None): # Get location OpenLPPortable.ini app_path = AppLocation.get_directory(AppLocation.AppDir) portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', - u'..', u'Data', u'settings', u'OpenLP.ini')) + u'..', u'Data', u'OpenLP.ini')) # Make this our settings file log.info(u'INI file: %s' % portable_settings_file) Settings.setFilename(portable_settings_file) From f239cdcdad8bb2de5d10eb2e1be6b0788620287d Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sun, 20 May 2012 15:29:08 -0400 Subject: [PATCH 09/46] Various changes --- openlp/core/ui/advancedtab.py | 270 +-------------------------------- openlp/core/ui/mainwindow.py | 38 ----- openlp/core/ui/settingsform.py | 2 - 3 files changed, 3 insertions(+), 307 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 58be29126..1947f741d 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -31,16 +31,11 @@ from datetime import datetime, timedelta from PyQt4 import QtCore, QtGui -import logging -import os -import sys from openlp.core.lib import SettingsTab, translate, build_icon, Receiver -from openlp.core.lib.ui import UiStrings from openlp.core.lib.settings import Settings -from openlp.core.utils import get_images_filter, AppLocation +from openlp.core.lib.ui import UiStrings from openlp.core.lib import SlideLimits - -log = logging.getLogger(__name__) +from openlp.core.utils import get_images_filter class AdvancedTab(SettingsTab): """ @@ -65,7 +60,6 @@ class AdvancedTab(SettingsTab): '#strftime-strptime-behavior for more information.')) self.defaultImage = u':/graphics/openlp-splash-screen.png' self.defaultColor = u'#ffffff' - self.dataExists = False self.iconPath = u':/system/system_settings.png' advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') SettingsTab.__init__(self, parent, u'Advanced', advanced_translated) @@ -158,70 +152,6 @@ class AdvancedTab(SettingsTab): self.serviceNameLayout.addRow(self.serviceNameExampleLabel, self.serviceNameExample) self.leftLayout.addWidget(self.serviceNameGroupBox) - # Data Directory - self.dataDirectoryGroupBox = QtGui.QGroupBox(self.leftColumn) - self.dataDirectoryGroupBox.setObjectName(u'dataDirectoryGroupBox') - self.dataDirectoryLayout = QtGui.QFormLayout(self.dataDirectoryGroupBox) - self.dataDirectoryLayout.setObjectName(u'dataDirectoryLayout') - self.dataDirectoryCurrentLabel = QtGui.QLabel(self.dataDirectoryGroupBox) - self.dataDirectoryCurrentLabel.setObjectName( - u'dataDirectoryCurrentLabel') - self.dataDirectoryLabel = QtGui.QLabel(self.dataDirectoryGroupBox) - self.dataDirectoryLabel.setObjectName(u'dataDirectoryLabel') - self.dataDirectoryNewLabel = QtGui.QLabel(self.dataDirectoryGroupBox) - self.dataDirectoryNewLabel.setObjectName(u'dataDirectoryCurrentLabel') - self.newDataDirectoryEdit = QtGui.QLineEdit(self.dataDirectoryGroupBox) - self.newDataDirectoryEdit.setObjectName(u'newDataDirectoryEdit') - self.newDataDirectoryEdit.setReadOnly(True) - self.newDataDirectoryHasFilesLabel = QtGui.QLabel( - self.dataDirectoryGroupBox) - self.newDataDirectoryHasFilesLabel.setObjectName( - u'newDataDirectoryHasFilesLabel') - self.newDataDirectoryHasFilesLabel.setWordWrap(True) - self.newDataDirectoryLabelHBox = QtGui.QHBoxLayout() - self.newDataDirectoryLabelHBox.setObjectName( - u'newDataDirectoryLabelHBox') - self.dataDirectoryBrowseButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryBrowseButton.setObjectName( - u'dataDirectoryBrowseButton') - self.dataDirectoryBrowseButton.setIcon( - build_icon(u':/general/general_open.png')) - self.dataDirectoryDefaultButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryDefaultButton.setObjectName( - u'dataDirectoryDefaultButton') - self.dataDirectoryDefaultButton.setIcon( - build_icon(u':/general/general_revert.png')) - self.dataDirectoryCancelButton = QtGui.QPushButton( - self.dataDirectoryGroupBox) - self.dataDirectoryCancelButton.setObjectName( - u'dataDirectoryCancelButton') - self.dataDirectoryCancelButton.setIcon( - build_icon(u':/general/general_delete.png')) - self.newDataDirectoryLabelHBox.addWidget(self.newDataDirectoryEdit) - self.newDataDirectoryLabelHBox.addWidget( - self.dataDirectoryBrowseButton) - self.newDataDirectoryLabelHBox.addWidget( - self.dataDirectoryDefaultButton) - self.dataDirectoryCopyCheckHBox = QtGui.QHBoxLayout() - self.dataDirectoryCopyCheckHBox.setObjectName( - u'dataDirectoryCopyCheckHBox') - self.dataDirectoryCopyCheckBox = QtGui.QCheckBox( - self.dataDirectoryGroupBox) - self.dataDirectoryCopyCheckBox.setObjectName( - u'dataDirectoryCopyCheckBox') - self.dataDirectoryCopyCheckHBox.addWidget( - self.dataDirectoryCopyCheckBox) - self.dataDirectoryCopyCheckHBox.addWidget( - self.dataDirectoryCancelButton) - self.dataDirectoryLayout.addRow(self.dataDirectoryCurrentLabel, - self.dataDirectoryLabel) - self.dataDirectoryLayout.addRow(self.dataDirectoryNewLabel, - self.newDataDirectoryLabelHBox) - self.dataDirectoryLayout.addRow(self.dataDirectoryCopyCheckHBox) - self.dataDirectoryLayout.addRow(self.newDataDirectoryHasFilesLabel) - self.leftLayout.addWidget(self.dataDirectoryGroupBox) self.leftLayout.addStretch() # Default Image self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) @@ -290,6 +220,7 @@ class AdvancedTab(SettingsTab): self.x11Layout.addWidget(self.x11BypassCheckBox) self.rightLayout.addWidget(self.x11GroupBox) self.rightLayout.addStretch() + self.shouldUpdateServiceNameExample = False QtCore.QObject.connect(self.serviceNameCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled) @@ -313,18 +244,6 @@ class AdvancedTab(SettingsTab): QtCore.SIGNAL(u'clicked()'), self.onDefaultRevertButtonClicked) QtCore.QObject.connect(self.x11BypassCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled) - QtCore.QObject.connect(self.dataDirectoryBrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onDataDirectoryBrowseButtonClicked) - QtCore.QObject.connect(self.dataDirectoryDefaultButton, - QtCore.SIGNAL(u'clicked()'), - self.onDataDirectoryDefaultButtonClicked) - QtCore.QObject.connect(self.dataDirectoryCancelButton, - QtCore.SIGNAL(u'clicked()'), - self.onDataDirectoryCancelButtonClicked) - QtCore.QObject.connect(self.dataDirectoryCopyCheckBox, - QtCore.SIGNAL(u'toggled(bool)'), - self.onDataDirectoryCopyCheckBoxToggled) QtCore.QObject.connect(self.endSlideRadioButton, QtCore.SIGNAL(u'clicked()'), self.onEndSlideButtonClicked) QtCore.QObject.connect(self.wrapSlideRadioButton, @@ -339,8 +258,6 @@ class AdvancedTab(SettingsTab): self.tabTitleVisible = UiStrings().Advanced self.uiGroupBox.setTitle( translate('OpenLP.AdvancedTab', 'UI Settings')) - self.dataDirectoryGroupBox.setTitle( - translate('OpenLP.AdvancedTab', 'Data Location')) self.recentLabel.setText( translate('OpenLP.AdvancedTab', 'Number of recent files to display:')) @@ -404,32 +321,6 @@ class AdvancedTab(SettingsTab): 'Browse for an image file to display.')) self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', 'Revert to the default OpenLP logo.')) - self.dataDirectoryCurrentLabel.setText(translate('OpenLP.AdvancedTab', - 'Current:')) - self.dataDirectoryNewLabel.setText(translate('OpenLP.AdvancedTab', - 'New:')) - self.dataDirectoryBrowseButton.setToolTip( - translate('OpenLP.AdvancedTab', - 'Browse for new data file location.')) - self.dataDirectoryDefaultButton.setToolTip( - translate('OpenLP.AdvancedTab', - 'Set the data location to the default.')) - self.dataDirectoryCancelButton.setText( - translate('OpenLP.AdvancedTab', - 'Cancel Location Change')) - self.dataDirectoryCancelButton.setToolTip( - translate('OpenLP.AdvancedTab', - 'Cancel OpenLP data directory location change.')) - self.dataDirectoryCopyCheckBox.setText( - translate('OpenLP.AdvancedTab', - 'Copy data to new location.')) - self.dataDirectoryCopyCheckBox.setToolTip( - translate('OpenLP.AdvancedTab', - 'Copy the OpenLP data files to the new location.')) - self.newDataDirectoryHasFilesLabel.setText( - translate('OpenLP.AdvancedTab', - 'WARNING: New data directory location contains' - 'OpenLP data files. These files WILL be replaced during a copy.')) self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11')) self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab', @@ -507,45 +398,8 @@ class AdvancedTab(SettingsTab): else: self.nextItemRadioButton.setChecked(True) settings.endGroup() - self.dataDirectoryCopyCheckBox.hide() - self.newDataDirectoryHasFilesLabel.hide() - self.dataDirectoryCancelButton.hide() - # Since data location can be changed, make sure the path is present. - self.currentDataPath = AppLocation.get_data_path() - if not os.path.exists(self.currentDataPath): - log.error(u'Data path not found %s' % self.currentDataPath) - answer = QtGui.QMessageBox.critical(self, - translate('OpenLP.AdvancedTab', - 'Data Directory Error'), - translate('OpenLP.AdvancedTab', - 'OpenLP data directory was not found\n\n%s\n\n' - 'This data directory was previously changed from the OpenLP ' - 'default location. If the new location was on removable ' - 'media, that media needs to be made available.\n\n' - 'Click "No" to stop loading OpenLP. allowing you to fix ' - 'the the problem.\n\n' - 'Click "Yes" to reset the data directory to the default ' - 'location.' % self.currentDataPath), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if answer == QtGui.QMessageBox.No: - log.info(u'User requested termination') - Receiver.send_message(u'cleanup') - sys.exit() - # Set data location to default. - settings.remove(u'advanced/data path') - self.currentDataPath = AppLocation.get_data_path() - log.warning(u'User requested data path set to default %s' - % self.currentDataPath) - self.dataDirectoryLabel.setText(os.path.abspath( - os.path.join(self.currentDataPath, u'..'))) self.defaultColorButton.setStyleSheet( u'background-color: %s' % self.defaultColor) - # Don't allow data directory change if running portable - if Settings().contains(u'advanced/is portable'): - self.dataDirectoryGroupBox.hide() def save(self): """ @@ -654,124 +508,6 @@ class AdvancedTab(SettingsTab): self.defaultFileEdit.setText(filename) self.defaultFileEdit.setFocus() - def onDataDirectoryBrowseButtonClicked(self): - """ - Browse for a new data directory location. - """ - old_root_path = unicode(self.dataDirectoryLabel.text()) - # Get the new directory location. - new_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, - translate('OpenLP.AdvancedTab', - 'Select Data Directory Location'), old_root_path, - options = QtGui.QFileDialog.ShowDirsOnly)) - # Set the new data path. - new_data_path = os.path.join(new_path, 'openlp_data') - if new_path: - if self.currentDataPath.lower() == new_data_path.lower(): - self.onDataDirectoryCancelButtonClicked() - return - else: - return - # Make sure they want to change the data. - answer = QtGui.QMessageBox.question(self, - translate('OpenLP.AdvancedTab', 'Confirm Data Directory Change'), - translate('OpenLP.AdvancedTab', - 'Are you sure you want to change the location of the OpenLP ' - 'data directory to:\n\n%s\n\n' - 'The data directory will be changed when OpenLP is closed.' - % new_path), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if answer != QtGui.QMessageBox.Yes: - return - # Check if data already exists here. - self.checkDataOverwrite(new_data_path) - # Save the new location. - Receiver.send_message(u'set_new_data_path', new_data_path) - self.newDataDirectoryEdit.setText(new_path) - self.dataDirectoryCancelButton.show() - - def onDataDirectoryDefaultButtonClicked(self): - """ - Re-set the data directory location to the 'default' location. - """ - new_data_path = AppLocation.get_directory(AppLocation.DataDir) - if self.currentDataPath.lower() != new_data_path.lower(): - # Make sure they want to change the data location back to the default. - answer = QtGui.QMessageBox.question(self, - translate('OpenLP.AdvancedTab', 'Reset Data Directory'), - translate('OpenLP.AdvancedTab', - 'Are you sure you want to change the location of the OpenLP ' - 'data directory to the default location?\n\n' - 'This location will be used after OpenLP is closed.'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if answer != QtGui.QMessageBox.Yes: - return - self.checkDataOverwrite(new_data_path) - # Save the new location. - Receiver.send_message(u'set_new_data_path', new_data_path) - self.newDataDirectoryEdit.setText(os.path.abspath( - os.path.join(new_data_path, u'..'))) - self.dataDirectoryCancelButton.show() - else: - # We cancel the change in case user changed their mind. - self.onDataDirectoryCancelButtonClicked() - - def onDataDirectoryCopyCheckBoxToggled(self): - Receiver.send_message(u'set_copy_data', - self.dataDirectoryCopyCheckBox.isChecked()) - if self.dataExists: - if self.dataDirectoryCopyCheckBox.isChecked(): - self.newDataDirectoryHasFilesLabel.show() - else: - self.newDataDirectoryHasFilesLabel.hide() - - def checkDataOverwrite(self, data_path ): - test_path = os.path.join(data_path, u'songs') - self.dataDirectoryCopyCheckBox.show() - if os.path.exists(test_path): - self.dataExists = True - # Check is they want to replace existing data. - answer = QtGui.QMessageBox.warning(self, - translate('OpenLP.AdvancedTab', 'Overwrite Existing Data'), - translate('OpenLP.AdvancedTab', - 'WARNING: \n\n' - 'The location you have selected \n\n%s\n\n' - 'appears to contain OpenLP data files. Do you wish to replace ' - 'these files with the current data files?' - % os.path.abspath(os.path.join(data_path, u'..'))), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if answer == QtGui.QMessageBox.Yes: - self.dataDirectoryCopyCheckBox.setChecked(True) - self.newDataDirectoryHasFilesLabel.show() - else: - self.dataDirectoryCopyCheckBox.setChecked(False) - self.newDataDirectoryHasFilesLabel.hide() - else: - self.dataExists = False - self.dataDirectoryCopyCheckBox.setChecked(True) - self.newDataDirectoryHasFilesLabel.hide() - - def onDataDirectoryCancelButtonClicked(self): - """ - Cancel the data directory location change - """ - self.newDataDirectoryEdit.clear() - self.dataDirectoryCopyCheckBox.setChecked(False) - Receiver.send_message(u'set_new_data_path', u'') - Receiver.send_message(u'set_copy_data', False) - self.dataDirectoryCopyCheckBox.hide() - self.dataDirectoryCancelButton.hide() - self.newDataDirectoryHasFilesLabel.hide() - def onDefaultRevertButtonClicked(self): self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png') self.defaultFileEdit.setFocus() diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 9b75e33b2..0d5b1482a 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1200,9 +1200,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.pluginManager.finalise_plugins() # Save settings self.saveSettings() - # Check if we need to change the data directory - if self.newDataPath: - self.changeDataDirectory() # Close down the display self.liveController.display.close() @@ -1484,38 +1481,3 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def setCopyData(self, copy_data): self.copyData = copy_data - def changeDataDirectory(self): - log.info(u'Changing data path to %s' % self.newDataPath ) - old_data_path = unicode(AppLocation.get_data_path()) - # Copy OpenLP data to new location if requested. - if self.copyData: - log.info(u'Copying data to new path') - try: - Receiver.send_message(u'openlp_process_events') - Receiver.send_message(u'cursor_busy') - self.showStatusMessage( - translate('OpenLP.MainWindow', - 'Copying OpenLP data to new data directory location - %s ' - '- Please wait for copy to finish' - % os.path.abspath(os.path.join(self.newDataPath, u'..')))) - dir_util.copy_tree(old_data_path, self.newDataPath) - log.info(u'Copy sucessful') - except (IOError, os.error, DistutilsFileError), why: - Receiver.send_message(u'cursor_normal') - log.exception(u'Data copy failed %s' % unicode(why)) - QtGui.QMessageBox.critical(self, - translate('OpenLP.MainWindow', 'New Data Directory Error'), - translate('OpenLP.MainWindow', - 'OpenLP Data directory copy failed\n\n%s' - % unicode(why)), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Ok)) - return False - else: - log.info(u'No data copy requested') - # Change the location of data directory in config file. - settings = Settings() - settings.setValue(u'advanced/data path', self.newDataPath) - # Check if the new data path is our default. - if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir): - settings.remove(u'advanced/data path') diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 03f5c93a5..d183d9d4a 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -102,8 +102,6 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Process the form saving the settings """ - # Dialogue was cancelled, remove any pending data path change. - self.advancedTab.onDataDirectoryCancelButtonClicked(); for tabIndex in range(self.stackedLayout.count()): self.stackedLayout.widget(tabIndex).cancel() return QtGui.QDialog.reject(self) From 0548bfb34599039957aac0602ea3b0f74465035d Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sun, 20 May 2012 21:23:50 -0400 Subject: [PATCH 10/46] Modified code to use the directory choosen by user, don't append a sub-dir --- openlp/core/ui/advancedtab.py | 16 +++++++--------- openlp/core/ui/mainwindow.py | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index a623c6a40..f2f0389b3 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -539,7 +539,7 @@ class AdvancedTab(SettingsTab): log.warning(u'User requested data path set to default %s' % self.currentDataPath) self.dataDirectoryLabel.setText(os.path.abspath( - os.path.join(self.currentDataPath, u'..'))) + self.currentDataPath)) self.defaultColorButton.setStyleSheet( u'background-color: %s' % self.defaultColor) @@ -656,13 +656,12 @@ class AdvancedTab(SettingsTab): """ old_root_path = unicode(self.dataDirectoryLabel.text()) # Get the new directory location. - new_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, + new_data_path = unicode(QtGui.QFileDialog.getExistingDirectory(self, translate('OpenLP.AdvancedTab', 'Select Data Directory Location'), old_root_path, options = QtGui.QFileDialog.ShowDirsOnly)) # Set the new data path. - new_data_path = os.path.join(new_path, 'openlp_data') - if new_path: + if new_data_path: if self.currentDataPath.lower() == new_data_path.lower(): self.onDataDirectoryCancelButtonClicked() return @@ -675,7 +674,7 @@ class AdvancedTab(SettingsTab): 'Are you sure you want to change the location of the OpenLP ' 'data directory to:\n\n%s\n\n' 'The data directory will be changed when OpenLP is closed.' - % new_path), + % new_data_path), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), @@ -686,7 +685,7 @@ class AdvancedTab(SettingsTab): self.checkDataOverwrite(new_data_path) # Save the new location. Receiver.send_message(u'set_new_data_path', new_data_path) - self.newDataDirectoryEdit.setText(new_path) + self.newDataDirectoryEdit.setText(new_data_path) self.dataDirectoryCancelButton.show() def onDataDirectoryDefaultButtonClicked(self): @@ -711,8 +710,7 @@ class AdvancedTab(SettingsTab): self.checkDataOverwrite(new_data_path) # Save the new location. Receiver.send_message(u'set_new_data_path', new_data_path) - self.newDataDirectoryEdit.setText(os.path.abspath( - os.path.join(new_data_path, u'..'))) + self.newDataDirectoryEdit.setText(os.path.abspath(new_data_path)) self.dataDirectoryCancelButton.show() else: # We cancel the change in case user changed their mind. @@ -740,7 +738,7 @@ class AdvancedTab(SettingsTab): 'The location you have selected \n\n%s\n\n' 'appears to contain OpenLP data files. Do you wish to replace ' 'these files with the current data files?' - % os.path.abspath(os.path.join(data_path, u'..'))), + % os.path.abspath(data_path,)), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index fdcacd3d8..f19b04174 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1490,7 +1490,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - %s ' '- Please wait for copy to finish' - % os.path.abspath(os.path.join(self.newDataPath, u'..')))) + % self.newDataPath)) dir_util.copy_tree(old_data_path, self.newDataPath) log.info(u'Copy sucessful') except (IOError, os.error, DistutilsFileError), why: From 357f8763317f352b4438e2108b084f278b14caac Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Mon, 21 May 2012 08:41:33 -0400 Subject: [PATCH 11/46] Removed unused import qtcore --- openlp/core/ui/aboutdialog.py | 2 +- openlp/core/ui/firsttimelanguagedialog.py | 2 +- openlp/core/ui/serviceitemeditdialog.py | 2 +- openlp/core/ui/servicenoteform.py | 2 +- openlp/core/ui/settingsform.py | 2 +- openlp/core/ui/themelayoutdialog.py | 2 +- openlp/plugins/alerts/forms/alertdialog.py | 2 +- openlp/plugins/bibles/forms/languagedialog.py | 2 +- openlp/plugins/bibles/lib/__init__.py | 2 -- openlp/plugins/custom/forms/editcustomdialog.py | 2 +- openlp/plugins/custom/forms/editcustomslidedialog.py | 2 +- openlp/plugins/songs/forms/authorsdialog.py | 2 +- openlp/plugins/songs/forms/songbookdialog.py | 2 +- openlp/plugins/songs/forms/topicsdialog.py | 2 +- 14 files changed, 13 insertions(+), 15 deletions(-) diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py index f0908b729..211bdfb0a 100644 --- a/openlp/core/ui/aboutdialog.py +++ b/openlp/core/ui/aboutdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import build_icon, translate from openlp.core.lib.ui import UiStrings, create_button, create_button_box diff --git a/openlp/core/ui/firsttimelanguagedialog.py b/openlp/core/ui/firsttimelanguagedialog.py index f07d7bd15..51b077039 100644 --- a/openlp/core/ui/firsttimelanguagedialog.py +++ b/openlp/core/ui/firsttimelanguagedialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py index 8410f4491..7a3bdf448 100644 --- a/openlp/core/ui/serviceitemeditdialog.py +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box, create_button diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py index fb173ee43..b115cfd40 100644 --- a/openlp/core/ui/servicenoteform.py +++ b/openlp/core/ui/servicenoteform.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate, SpellTextEdit from openlp.core.lib.ui import create_button_box diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index d183d9d4a..7dd02826c 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -29,7 +29,7 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings """ import logging -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import Receiver, build_icon, PluginStatus from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab diff --git a/openlp/core/ui/themelayoutdialog.py b/openlp/core/ui/themelayoutdialog.py index cab9d13fd..3aa9b0ede 100644 --- a/openlp/core/ui/themelayoutdialog.py +++ b/openlp/core/ui/themelayoutdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index b211a3aa4..f4144602f 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import build_icon, translate from openlp.core.lib.ui import create_button, create_button_box diff --git a/openlp/plugins/bibles/forms/languagedialog.py b/openlp/plugins/bibles/forms/languagedialog.py index f3c831410..b4a5b4d6c 100644 --- a/openlp/plugins/bibles/forms/languagedialog.py +++ b/openlp/plugins/bibles/forms/languagedialog.py @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index 9d4d62bf8..d81c0f770 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -31,8 +31,6 @@ plugin. import logging import re -from PyQt4 import QtCore - from openlp.core.lib import translate from openlp.core.lib.settings import Settings from openlp.plugins.bibles.lib.db import BiblesResourcesDB diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index bd4fb78fa..28edce0d8 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import build_icon, translate from openlp.core.lib.ui import UiStrings, create_button_box, create_button diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py index 381917e8c..7bc00d4ca 100644 --- a/openlp/plugins/custom/forms/editcustomslidedialog.py +++ b/openlp/plugins/custom/forms/editcustomslidedialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate, SpellTextEdit, build_icon from openlp.core.lib.ui import UiStrings, create_button, create_button_box diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index f5cc69aa5..a7e798bf8 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 5c62514ad..073151d1d 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index edd8df9f9..a609478fc 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import create_button_box From 7bc4c5f318b4e2e6865def0793fcf39e40e83146 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Wed, 23 May 2012 13:13:22 -0400 Subject: [PATCH 12/46] Settings to set default as ini format --- openlp/core/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 381af3671..6ebf1232c 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -260,7 +260,7 @@ def main(args=None): if options.portable: log.info(u'Running portable') app.setApplicationName(u'OpenLPPortable') - QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat) + Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini app_path = AppLocation.get_directory(AppLocation.AppDir) portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', From ec27884d396204f5c6f9f263f4e85bc7807126d0 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Thu, 24 May 2012 07:02:01 -0400 Subject: [PATCH 13/46] Removed last Qtcore.Qsetting usage --- openlp/core/lib/settings.py | 9 ++++----- openlp/core/ui/mainwindow.py | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/openlp/core/lib/settings.py b/openlp/core/lib/settings.py index cf98896a9..0bd498df9 100644 --- a/openlp/core/lib/settings.py +++ b/openlp/core/lib/settings.py @@ -42,8 +42,8 @@ class Settings(QtCore.QSettings): * Exposes all the methods of QSettings. * Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to ``IniFormat``, and the path to the Ini file is set using ``setFilename``, - then the Settings constructor will create a Settings object for accessing - settings stored in that Ini file. + then the Settings constructor (without any arguments) will create a Settings + object for accessing settings stored in that Ini file. """ FilePath = u'' @@ -56,11 +56,10 @@ class Settings(QtCore.QSettings): Does not affect existing Settings objects. """ Settings.FilePath = filepath - log.info(u'Set Settings file: %s' % filepath) def __init__(self, *args): - if Settings.FilePath and (Settings.defaultFormat() == - Settings.IniFormat): + if not args and Settings.FilePath and (Settings.defaultFormat() == + Settings.IniFormat): QtCore.QSettings.__init__(self, Settings.FilePath, Settings.IniFormat) else: diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 8e55bfec8..a2551d7f1 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -956,7 +956,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): for plugin in self.pluginManager.plugins: setting_sections.extend([plugin.name]) settings = Settings() - import_settings = QtCore.QSettings(import_file_name, + import_settings = Settings(import_file_name, Settings.IniFormat) import_keys = import_settings.allKeys() for section_key in import_keys: @@ -1046,7 +1046,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): settings.remove(self.headerSection) # Get the settings. keys = settings.allKeys() - export_settings = QtCore.QSettings(temp_file, + export_settings = Settings(temp_file, Settings.IniFormat) # Add a header section. # This is to insure it's our conf file for import. From fc87e58a3c92b081609a47e781145fb800612de6 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 24 May 2012 22:12:48 +1000 Subject: [PATCH 14/46] Changed ZionWorxImport to parse CSV database dump (XML had invalid syntax) --- openlp/plugins/bibles/lib/csvbible.py | 2 +- openlp/plugins/songs/lib/zionworximport.py | 109 ++++++++++++++------- 2 files changed, 75 insertions(+), 36 deletions(-) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index cd4b921a1..e61ae9164 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -73,7 +73,7 @@ class CSVBible(BibleDB): def __init__(self, parent, **kwargs): """ - Loads a Bible from a set of CVS files. + Loads a Bible from a set of CSV files. This class assumes the files contain all the information and a clean bible is being loaded. """ diff --git a/openlp/plugins/songs/lib/zionworximport.py b/openlp/plugins/songs/lib/zionworximport.py index 485845d2a..8d715ab71 100644 --- a/openlp/plugins/songs/lib/zionworximport.py +++ b/openlp/plugins/songs/lib/zionworximport.py @@ -28,10 +28,8 @@ The :mod:`zionworximport` module provides the functionality for importing ZionWorx songs into the OpenLP database. """ +import csv import logging -import re - -from lxml import etree from openlp.core.lib import translate from openlp.plugins.songs.lib.songimport import SongImport @@ -40,40 +38,81 @@ log = logging.getLogger(__name__) class ZionWorxImport(SongImport): """ - The :class:`ZionWorxImport` class provides the ability to import... + The :class:`ZionWorxImport` class provides the ability to import songs + from ZionWorx, via a dump of the ZionWorx database to a CSV file. + + ZionWorx song database fields: + + * ``SongNum`` Song ID. Discarded by importer. + * ``Title1`` Main Title. + * ``Title2`` Alternate Title. + * ``Lyrics`` Song verses, separated by blank lines. + * ``Writer`` Song author(s). + * ``Copyright`` Copyright information + * ``Keywords`` Discarded by importer. + * ``DefaultStyle`` Discarded by importer. + + ZionWorx has no native export function; it uses the proprietary TurboDB + database engine. The TurboDB vendor, dataWeb, provides tools which can + export TurboDB tables to other formats, such as freeware console tool + TurboDB Data Exchange which is available for Windows and Linux. This command + exports the ZionWorx songs table to a CSV file: + + ``tdbdatax MainTable.dat songstable.csv -fsdf -s, -qd`` + + * ``-f`` Table format: ``sdf`` denotes text file. + * ``-s`` Separator character between fields. + * ``-q`` Quote character surrounding fields. ``d`` denotes double-quote. + + CSV format expected by importer: + + * Fields separated by comma ``,`` + * Fields surrounded by double-quotes ``"``. This enables fields (such as + Lyrics) to include new-lines and commas. Double-quotes within a field + are denoted by two double-quotes ``""`` + * Note: This is the default format of the Python ``csv`` module. + """ def doImport(self): """ - Receive ... to import. + Receive a CSV file (from a ZionWorx database dump) to import. """ - #open xml file - with open(self.importSource, 'rb') as f: - songs_xml = unicode(f.read(), u'utf-8') - # check single xml file - if not re.match(ur' *<\?xml[^<>]*\?>', songs_xml): - # Error: invalid file (no XML declaration) - print u'Error: invalid file (no XML declaration)' - else: - # clean invalid XML - # remove DefaultStyle attribute if non-empty - songs_xml = re.sub(ur'DefaultStyle=".+" />', u'/>', songs_xml) - # replace & with & (skip existing entities) - songs_xml = re.sub(ur'&(?![a-zA-Z#][a-zA-Z0-9]*;)', u'&', - songs_xml) - # replace < with < (skip known ) - songs_xml = re.sub(ur'<(?![?DMFR/])', u'<', songs_xml) - # replace " within Lyrics attribute with " - songs_xml = re.sub(ur'(?<=Lyrics=")([^<]*)(?=" Writer=)', - self._escapeQuotes, songs_xml) - print songs_xml - - # parse XML - tree = etree.fromstring(songs_xml.encode(u'utf-8')) - for song in tree[1].iterchildren(): - for attrib, value in song.attrib.items(): - print attrib + ':', value - print '' - - def _escapeQuotes(self, m): - return m.group(0).replace('"', '"') \ No newline at end of file + if not os.path.isfile(self.importSource): + self.logError(unicode(translate('SongsPlugin.ZionWorxImport', + 'No songs to import.')), + unicode(translate('SongsPlugin.ZionWorxImport', + 'No %s CSV file found.' % WizardStrings.ZW))) + return + with open(self.importSource, 'rb') as songs_file: + songs_reader = csv.reader(songs_file) + try: + num_records = sum(1 for _ in songs_reader) + except csv.Error, e: + self.logError(unicode(translate('SongsPlugin.ZionWorxImport', + 'Error reading CSV file.')), + unicode(translate('SongsPlugin.ZionWorxImport', + 'Line %d: %s' % songs_reader.line_num, e))) + log.debug(u'%s records found in CSV file' % num_records) + self.importWizard.progressBar.setMaximum(num_records) + fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics', + u'Writer', u'Copyright', u'Keywords', u'DefaultStyle'] + songs_reader_dict= csv.DictReader(songs_file, fieldnames) + try: + for record in songs_reader_dict: + if self.stopImportFlag: + return + self.setDefaults() + self.title = unicode(record[u'Title1']) + if record[u'Title2']: + self.alternateTitle = unicode(record[u'Title2']) + self.parseAuthor(unicode(record[u'Writer'])) + self.addCopyright(unicode(record[u'Copyright'])) + self.processSongText(unicode(record[u'Lyrics'])) + if not self.finish(): + self.logError(self.title) + except csv.Error, e: + self.logError(unicode(translate('SongsPlugin.ZionWorxImport', + 'Error reading CSV file.')), + unicode(translate('SongsPlugin.ZionWorxImport', + 'Line %d: %s' % songs_reader_dict.line_num, e))) From 465aecc61c5ec6c9109873fa9388a371c1698e28 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 30 May 2012 02:26:50 +1000 Subject: [PATCH 15/46] Mostly complete attempt at refactor. Tidy ups needed. --- openlp/plugins/songs/forms/songimportform.py | 824 +++++-------------- openlp/plugins/songs/lib/importer.py | 254 ++++-- openlp/plugins/songs/songsplugin.py | 4 +- 3 files changed, 390 insertions(+), 692 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4bdabd1a2..73d6cc59a 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -36,7 +36,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.plugins.songs.lib.importer import SongFormat +from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttribute, \ + SongFormatSelect log = logging.getLogger(__name__) @@ -58,6 +59,8 @@ class SongImportForm(OpenLPWizard): The songs plugin. """ self.clipboard = plugin.formParent.clipboard + self.activeFormat = None + self.formatWidgets = dict([(f, {}) for f in SongFormat.get_formats()]) OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp') @@ -66,7 +69,8 @@ class SongImportForm(OpenLPWizard): Set up the song wizard UI. """ OpenLPWizard.setupUi(self, image) - self.formatStack.setCurrentIndex(0) + self.activeFormat = SongFormat.OpenLyrics + self.formatStack.setCurrentIndex(self.activeFormat) QtCore.QObject.connect(self.formatComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onCurrentIndexChanged) @@ -77,103 +81,39 @@ class SongImportForm(OpenLPWizard): the import is available and accordingly to disable or enable the next button. """ - self.formatStack.setCurrentIndex(index) + self.activeFormat = index + self.formatStack.setCurrentIndex(self.activeFormat) next_button = self.button(QtGui.QWizard.NextButton) - next_button.setEnabled(SongFormat.get_availability(index)) + next_button.setEnabled(SongFormatAttribute.get(self.activeFormat, + SongFormatAttribute.availability)) def customInit(self): """ Song wizard specific initialisation. """ - if not SongFormat.get_availability(SongFormat.OpenLP1): - self.openLP1DisabledWidget.setVisible(True) - self.openLP1ImportWidget.setVisible(False) - if not SongFormat.get_availability(SongFormat.SongsOfFellowship): - self.songsOfFellowshipDisabledWidget.setVisible(True) - self.songsOfFellowshipImportWidget.setVisible(False) - if not SongFormat.get_availability(SongFormat.Generic): - self.genericDisabledWidget.setVisible(True) - self.genericImportWidget.setVisible(False) + for format in SongFormat.get_formats(): + if not SongFormatAttribute.get(format, + SongFormatAttribute.availability): + self.formatWidgets[format][u'disabledWidget'].setVisible(True) + self.formatWidgets[format][u'importWidget'].setVisible(False) def customSignals(self): """ Song wizard specific signals. """ - QtCore.QObject.connect(self.openLP2BrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenLP2BrowseButtonClicked) - QtCore.QObject.connect(self.openLP1BrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenLP1BrowseButtonClicked) - QtCore.QObject.connect(self.powerSongBrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onPowerSongBrowseButtonClicked) - QtCore.QObject.connect(self.openLyricsAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenLyricsAddButtonClicked) - QtCore.QObject.connect(self.openLyricsRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenLyricsRemoveButtonClicked) - QtCore.QObject.connect(self.openSongAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenSongAddButtonClicked) - QtCore.QObject.connect(self.openSongRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onOpenSongRemoveButtonClicked) - QtCore.QObject.connect(self.wordsOfWorshipAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onWordsOfWorshipAddButtonClicked) - QtCore.QObject.connect(self.wordsOfWorshipRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onWordsOfWorshipRemoveButtonClicked) - QtCore.QObject.connect(self.ccliAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onCCLIAddButtonClicked) - QtCore.QObject.connect(self.ccliRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onCCLIRemoveButtonClicked) - QtCore.QObject.connect(self.dreamBeamAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onDreamBeamAddButtonClicked) - QtCore.QObject.connect(self.dreamBeamRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onDreamBeamRemoveButtonClicked) - QtCore.QObject.connect(self.songsOfFellowshipAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongsOfFellowshipAddButtonClicked) - QtCore.QObject.connect(self.songsOfFellowshipRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongsOfFellowshipRemoveButtonClicked) - QtCore.QObject.connect(self.genericAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onGenericAddButtonClicked) - QtCore.QObject.connect(self.genericRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onGenericRemoveButtonClicked) - QtCore.QObject.connect(self.easySlidesBrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onEasySlidesBrowseButtonClicked) - QtCore.QObject.connect(self.ewBrowseButton, - QtCore.SIGNAL(u'clicked()'), - self.onEWBrowseButtonClicked) - QtCore.QObject.connect(self.songBeamerAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongBeamerAddButtonClicked) - QtCore.QObject.connect(self.songBeamerRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongBeamerRemoveButtonClicked) - QtCore.QObject.connect(self.songShowPlusAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongShowPlusAddButtonClicked) - QtCore.QObject.connect(self.songShowPlusRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onSongShowPlusRemoveButtonClicked) - QtCore.QObject.connect(self.foilPresenterAddButton, - QtCore.SIGNAL(u'clicked()'), - self.onFoilPresenterAddButtonClicked) - QtCore.QObject.connect(self.foilPresenterRemoveButton, - QtCore.SIGNAL(u'clicked()'), - self.onFoilPresenterRemoveButtonClicked) + for format in SongFormat.get_formats(): + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + if select_mode == SongFormatSelect.MultipleFiles: + QtCore.QObject.connect(self.formatWidgets[format][u'addButton'], + QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked) + QtCore.QObject.connect( + self.formatWidgets[format][u'removeButton'], + QtCore.SIGNAL(u'clicked()'), self.onRemoveButtonClicked) + else: + QtCore.QObject.connect( + self.formatWidgets[format][u'browseButton'], + QtCore.SIGNAL(u'clicked()'), self.onBrowseButtonClicked) def addCustomPages(self): """ @@ -200,38 +140,9 @@ class SongImportForm(OpenLPWizard): QtGui.QSizePolicy.Expanding) self.formatStack = QtGui.QStackedLayout() self.formatStack.setObjectName(u'FormatStack') - # OpenLyrics - self.addFileSelectItem(u'openLyrics', u'OpenLyrics', True) - # OpenLP 2.0 - self.addFileSelectItem(u'openLP2', single_select=True) - # openlp.org 1.x - self.addFileSelectItem(u'openLP1', None, True, True) - # Generic Document/Presentation import - self.addFileSelectItem(u'generic', None, True) - # CCLI File import - self.addFileSelectItem(u'ccli') - # DreamBeam - self.addFileSelectItem(u'dreamBeam') - # EasySlides - self.addFileSelectItem(u'easySlides', single_select=True) - # EasyWorship - self.addFileSelectItem(u'ew', single_select=True) - # Foilpresenter - self.addFileSelectItem(u'foilPresenter') - # Open Song - self.addFileSelectItem(u'openSong', u'OpenSong') - # PowerSong - self.addFileSelectItem(u'powerSong', single_select=True) - # SongBeamer - self.addFileSelectItem(u'songBeamer') - # Song Show Plus - self.addFileSelectItem(u'songShowPlus') - # Songs of Fellowship - self.addFileSelectItem(u'songsOfFellowship', None, True) - # Words of Worship - self.addFileSelectItem(u'wordsOfWorship') -# Commented out for future use. -# self.addFileSelectItem(u'csv', u'CSV', single_select=True) + self.disablableFormats = [] + for self.activeFormat in SongFormat.get_formats(): + self.addFileSelectItem() self.sourceLayout.addLayout(self.formatStack) self.addPage(self.sourcePage) @@ -251,107 +162,31 @@ class SongImportForm(OpenLPWizard): self.sourcePage.setTitle(WizardStrings.ImportSelect) self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) - self.formatComboBox.setItemText(SongFormat.OpenLyrics, - translate('SongsPlugin.ImportWizardForm', - 'OpenLyrics or OpenLP 2.0 Exported Song')) - self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2) - self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1) - self.formatComboBox.setItemText(SongFormat.Generic, - translate('SongsPlugin.ImportWizardForm', - 'Generic Document/Presentation')) - self.formatComboBox.setItemText(SongFormat.CCLI, WizardStrings.CCLI) - self.formatComboBox.setItemText( - SongFormat.DreamBeam, WizardStrings.DB) - self.formatComboBox.setItemText( - SongFormat.EasySlides, WizardStrings.ES) - self.formatComboBox.setItemText( - SongFormat.EasyWorship, WizardStrings.EW) - self.formatComboBox.setItemText( - SongFormat.FoilPresenter, WizardStrings.FP) - self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS) - self.formatComboBox.setItemText( - SongFormat.PowerSong, WizardStrings.PS) - self.formatComboBox.setItemText( - SongFormat.SongBeamer, WizardStrings.SB) - self.formatComboBox.setItemText( - SongFormat.SongShowPlus, WizardStrings.SSP) - self.formatComboBox.setItemText( - SongFormat.SongsOfFellowship, WizardStrings.SoF) - self.formatComboBox.setItemText( - SongFormat.WordsOfWorship, WizardStrings.WoW) -# self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV) - self.openLP2FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP2BrowseButton.setText(UiStrings().Browse) - self.openLP1FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP1BrowseButton.setText(UiStrings().Browse) - self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite) - self.powerSongFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Folder:')) - self.powerSongBrowseButton.setText(UiStrings().Browse) - self.openLyricsAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.openLyricsRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.openLyricsDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics ' - 'importer has not yet been developed, but as you can see, we are ' - 'still intending to do so. Hopefully it will be in the next ' - 'release.')) - self.openSongAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.openSongRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.wordsOfWorshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.wordsOfWorshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.ccliAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.ccliRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.dreamBeamAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.dreamBeamRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songsOfFellowshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The Songs of ' - 'Fellowship importer has been disabled because OpenLP cannot ' - 'access OpenOffice or LibreOffice.')) - self.genericAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.genericRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.genericDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The generic document/' - 'presentation importer has been disabled because OpenLP cannot ' - 'access OpenOffice or LibreOffice.')) - self.easySlidesFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.easySlidesBrowseButton.setText(UiStrings().Browse) - self.ewFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.ewBrowseButton.setText(UiStrings().Browse) - self.songBeamerAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songBeamerRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songShowPlusAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songShowPlusRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.foilPresenterAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.foilPresenterRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) -# self.csvFilenameLabel.setText( -# translate('SongsPlugin.ImportWizardForm', 'Filename:')) -# self.csvBrowseButton.setText(UiStrings().Browse) + + for format in SongFormat.get_formats(): + self.formatComboBox.setItemText(format, SongFormatAttribute.get( + format, SongFormatAttribute.combo_box_text)) + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + if select_mode == SongFormatSelect.MultipleFiles: + self.formatWidgets[format][u'addButton'].setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.formatWidgets[format][u'removeButton'].setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + else: + if select_mode == SongFormatSelect.SingleFile: + label = 'Filename:' + elif select_mode == SongFormatSelect.SingleFolder: + label = 'Folder:' + self.formatWidgets[format][u'browseButton'].setText( + UiStrings().Browse) + self.formatWidgets[format][u'filepathLabel'].setText( + translate('SongsPlugin.ImportWizardForm', label)) + for format in self.disablableFormats: + self.formatWidgets[format][u'disabledLabel'].setText( + SongFormatAttribute.get(format, + SongFormatAttribute.disabled_label_text)) + self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('SongsPlugin.ImportWizardForm', @@ -382,104 +217,48 @@ class SongImportForm(OpenLPWizard): if self.currentPage() == self.welcomePage: return True elif self.currentPage() == self.sourcePage: - source_format = self.formatComboBox.currentIndex() + #source_format = self.formatComboBox.currentIndex() + format = self.activeFormat QtCore.QSettings().setValue(u'songs/last import type', - source_format) - import_class = SongFormat.get_class(source_format) - if source_format == SongFormat.OpenLP2: - if self.openLP2FilenameEdit.text().isEmpty(): - critical_error_message_box(UiStrings().NFSs, - WizardStrings.YouSpecifyFile % UiStrings().OLPV2) - self.openLP2BrowseButton.setFocus() + format) + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + format_name = SongFormatAttribute.get(format, + SongFormatAttribute.name) + class_ = SongFormatAttribute.get(format, + SongFormatAttribute.class_) + if select_mode == SongFormatSelect.MultipleFiles: + fileListWidget = self.formatWidgets[format][u'fileListWidget'] + if fileListWidget.count() == 0 or not class_.isValidSource( + filenames=self.getListOfFiles(fileListWidget)): + critical_error_message_box(UiStrings().NFSp, + WizardStrings.YouSpecifyFile % format_name) + self.formatWidgets[format][u'addButton'].setFocus() return False - elif source_format == SongFormat.OpenLP1: - if self.openLP1FilenameEdit.text().isEmpty(): + elif select_mode == SongFormatSelect.SingleFile: + filepathEdit = self.formatWidgets[format][u'filepathEdit'] + if filepathEdit.text().isEmpty() or not class_.isValidSource( + filename=filepathEdit.text()): critical_error_message_box(UiStrings().NFSs, - WizardStrings.YouSpecifyFile % UiStrings().OLPV1) - self.openLP1BrowseButton.setFocus() + WizardStrings.YouSpecifyFile % format_name) + self.formatWidgets[format][u'browseButton'].setFocus() return False - elif source_format == SongFormat.PowerSong: - if self.powerSongFilenameEdit.text().isEmpty() or \ - not import_class.isValidSource( - folder=self.powerSongFilenameEdit.text()): + elif select_mode == SongFormatSelect.SingleFolder: + filepathEdit = self.formatWidgets[format][u'filepathEdit'] + if filepathEdit.text().isEmpty() or not class_.isValidSource( + folder=filepathEdit.text()): critical_error_message_box(UiStrings().NFdSs, - WizardStrings.YouSpecifyFolder % WizardStrings.PS) - self.powerSongBrowseButton.setFocus() - return False - elif source_format == SongFormat.OpenLyrics: - if self.openLyricsFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.OL) - self.openLyricsAddButton.setFocus() - return False - elif source_format == SongFormat.OpenSong: - if self.openSongFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.OS) - self.openSongAddButton.setFocus() - return False - elif source_format == SongFormat.WordsOfWorship: - if self.wordsOfWorshipFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.WoW) - self.wordsOfWorshipAddButton.setFocus() - return False - elif source_format == SongFormat.CCLI: - if self.ccliFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.CCLI) - self.ccliAddButton.setFocus() - return False - elif source_format == SongFormat.DreamBeam: - if self.dreamBeamFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.DB) - self.dreamBeamAddButton.setFocus() - return False - elif source_format == SongFormat.SongsOfFellowship: - if self.songsOfFellowshipFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.SoF) - self.songsOfFellowshipAddButton.setFocus() - return False - elif source_format == SongFormat.Generic: - if self.genericFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - translate('SongsPlugin.ImportWizardForm', - 'You need to specify at least one document or ' - 'presentation file to import from.')) - self.genericAddButton.setFocus() - return False - elif source_format == SongFormat.EasySlides: - if self.easySlidesFilenameEdit.text().isEmpty(): - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.ES) - self.easySlidesBrowseButton.setFocus() - return False - elif source_format == SongFormat.EasyWorship: - if self.ewFilenameEdit.text().isEmpty(): - critical_error_message_box(UiStrings().NFSs, - WizardStrings.YouSpecifyFile % WizardStrings.EW) - self.ewBrowseButton.setFocus() - return False - elif source_format == SongFormat.SongBeamer: - if self.songBeamerFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.SB) - self.songBeamerAddButton.setFocus() - return False - elif source_format == SongFormat.SongShowPlus: - if self.songShowPlusFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.SSP) - self.songShowPlusAddButton.setFocus() - return False - elif source_format == SongFormat.FoilPresenter: - if self.foilPresenterFileListWidget.count() == 0: - critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % WizardStrings.FP) - self.foilPresenterAddButton.setFocus() + WizardStrings.YouSpecifyFolder % format_name) + self.formatWidgets[format][u'browseButton'].setFocus() return False +# elif source_format == SongFormat.Generic: +# if self.genericFileListWidget.count() == 0: +# critical_error_message_box(UiStrings().NFSp, +# translate('SongsPlugin.ImportWizardForm', +# 'You need to specify at least one document or ' +# 'presentation file to import from.')) +# self.genericAddButton.setFocus() +# return False return True elif self.currentPage() == self.progressPage: return True @@ -525,203 +304,46 @@ class SongImportForm(OpenLPWizard): item = listbox.takeItem(listbox.row(item)) del item - def onOpenLP2BrowseButtonClicked(self): - """ - Get OpenLP v2 song database file - """ - self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV2, - self.openLP2FilenameEdit, u'%s (*.sqlite)' - % (translate('SongsPlugin.ImportWizardForm', - 'OpenLP 2.0 Databases')) - ) + def onBrowseButtonClicked(self): + format = self.activeFormat + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + name = SongFormatAttribute.get(format, + SongFormatAttribute.name) + filter = SongFormatAttribute.get(format, + SongFormatAttribute.filter) + filepathEdit = self.formatWidgets[format][u'filepathEdit'] + if select_mode == SongFormatSelect.SingleFile: + self.getFileName(WizardStrings.OpenTypeFile % name, filepathEdit, + filter) + elif select_mode == SongFormatSelect.SingleFolder: + self.getFolder(WizardStrings.OpenTypeFile % name, filepathEdit) - def onOpenLP1BrowseButtonClicked(self): - """ - Get OpenLP v1 song database file - """ - self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1, - self.openLP1FilenameEdit, u'%s (*.olp)' - % translate('SongsPlugin.ImportWizardForm', - 'openlp.org v1.x Databases') - ) + def onAddButtonClicked(self): + format = self.activeFormat + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + name = SongFormatAttribute.get(format, + SongFormatAttribute.name) + filter = SongFormatAttribute.get(format, + SongFormatAttribute.filter) + if select_mode == SongFormatSelect.MultipleFiles: + self.getFiles(WizardStrings.OpenTypeFile % name, + self.formatWidgets[format][u'FileListWidget'], filter) - def onPowerSongBrowseButtonClicked(self): - """ - Get PowerSong song database folder - """ - self.getFolder(WizardStrings.OpenTypeFolder % WizardStrings.PS, - self.powerSongFilenameEdit) + def onRemoveButtonClicked(self): + self.removeSelectedItems( + self.formatWidgets[self.activeFormat][u'FileListWidget']) - def onOpenLyricsAddButtonClicked(self): - """ - Get OpenLyrics song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL, - self.openLyricsFileListWidget, u'%s (*.xml)' % - translate('SongsPlugin.ImportWizardForm', 'OpenLyrics Files')) - - def onOpenLyricsRemoveButtonClicked(self): - """ - Remove selected OpenLyrics files from the import list - """ - self.removeSelectedItems(self.openLyricsFileListWidget) - - def onOpenSongAddButtonClicked(self): - """ - Get OpenSong song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OS, - self.openSongFileListWidget) - - def onOpenSongRemoveButtonClicked(self): - """ - Remove selected OpenSong files from the import list - """ - self.removeSelectedItems(self.openSongFileListWidget) - - def onWordsOfWorshipAddButtonClicked(self): - """ - Get Words of Worship song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.WoW, - self.wordsOfWorshipFileListWidget, u'%s (*.wsg *.wow-song)' - % translate('SongsPlugin.ImportWizardForm', - 'Words Of Worship Song Files') - ) - - def onWordsOfWorshipRemoveButtonClicked(self): - """ - Remove selected Words of Worship files from the import list - """ - self.removeSelectedItems(self.wordsOfWorshipFileListWidget) - - def onCCLIAddButtonClicked(self): - """ - Get CCLI song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.CCLI, - self.ccliFileListWidget, u'%s (*.usr *.txt)' - % translate('SongsPlugin.ImportWizardForm', - 'CCLI SongSelect Files')) - - def onCCLIRemoveButtonClicked(self): - """ - Remove selected CCLI files from the import list - """ - self.removeSelectedItems(self.ccliFileListWidget) - - def onDreamBeamAddButtonClicked(self): - """ - Get DreamBeam song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.DB, - self.dreamBeamFileListWidget, u'%s (*.xml)' - % translate('SongsPlugin.ImportWizardForm', - 'DreamBeam Song Files') - ) - - def onDreamBeamRemoveButtonClicked(self): - """ - Remove selected DreamBeam files from the import list - """ - self.removeSelectedItems(self.dreamBeamFileListWidget) - - def onSongsOfFellowshipAddButtonClicked(self): - """ - Get Songs of Fellowship song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SoF, - self.songsOfFellowshipFileListWidget, u'%s (*.rtf)' - % translate('SongsPlugin.ImportWizardForm', - 'Songs Of Fellowship Song Files') - ) - - def onSongsOfFellowshipRemoveButtonClicked(self): - """ - Remove selected Songs of Fellowship files from the import list - """ - self.removeSelectedItems(self.songsOfFellowshipFileListWidget) - - def onGenericAddButtonClicked(self): - """ - Get song database files - """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select Document/Presentation Files'), - self.genericFileListWidget - ) - - def onGenericRemoveButtonClicked(self): - """ - Remove selected files from the import list - """ - self.removeSelectedItems(self.genericFileListWidget) - - def onEasySlidesBrowseButtonClicked(self): - """ - Get EasySlides song database file - """ - self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.ES, - self.easySlidesFilenameEdit, u'%s (*.xml)' - % translate('SongsPlugin.ImportWizardForm', - 'EasySlides XML File')) - - def onEWBrowseButtonClicked(self): - """ - Get EasyWorship song database files - """ - self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.EW, - self.ewFilenameEdit, u'%s (*.db)' - % translate('SongsPlugin.ImportWizardForm', - 'EasyWorship Song Database')) - - def onSongBeamerAddButtonClicked(self): - """ - Get SongBeamer song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SB, - self.songBeamerFileListWidget, u'%s (*.sng)' % - translate('SongsPlugin.ImportWizardForm', 'SongBeamer Files') - ) - - def onSongBeamerRemoveButtonClicked(self): - """ - Remove selected SongBeamer files from the import list - """ - self.removeSelectedItems(self.songBeamerFileListWidget) - - def onSongShowPlusAddButtonClicked(self): - """ - Get SongShow Plus song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SSP, - self.songShowPlusFileListWidget, u'%s (*.sbsong)' - % translate('SongsPlugin.ImportWizardForm', - 'SongShow Plus Song Files') - ) - - def onSongShowPlusRemoveButtonClicked(self): - """ - Remove selected SongShow Plus files from the import list - """ - self.removeSelectedItems(self.songShowPlusFileListWidget) - - def onFoilPresenterAddButtonClicked(self): - """ - Get FoilPresenter song database files - """ - self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.FP, - self.foilPresenterFileListWidget, u'%s (*.foil)' - % translate('SongsPlugin.ImportWizardForm', - 'Foilpresenter Song Files') - ) - - def onFoilPresenterRemoveButtonClicked(self): - """ - Remove selected FoilPresenter files from the import list - """ - self.removeSelectedItems(self.foilPresenterFileListWidget) +# def onGenericAddButtonClicked(self): +# """ +# Get song database files +# """ +# self.getFiles( +# translate('SongsPlugin.ImportWizardForm', +# 'Select Document/Presentation Files'), +# self.genericFileListWidget +# ) def setDefaults(self): """ @@ -736,22 +358,13 @@ class SongImportForm(OpenLPWizard): last_import_type >= self.formatComboBox.count(): last_import_type = 0 self.formatComboBox.setCurrentIndex(last_import_type) - self.openLP2FilenameEdit.setText(u'') - self.openLP1FilenameEdit.setText(u'') - self.powerSongFilenameEdit.setText(u'') - self.openLyricsFileListWidget.clear() - self.openSongFileListWidget.clear() - self.wordsOfWorshipFileListWidget.clear() - self.ccliFileListWidget.clear() - self.dreamBeamFileListWidget.clear() - self.songsOfFellowshipFileListWidget.clear() - self.genericFileListWidget.clear() - self.easySlidesFilenameEdit.setText(u'') - self.ewFilenameEdit.setText(u'') - self.songBeamerFileListWidget.clear() - self.songShowPlusFileListWidget.clear() - self.foilPresenterFileListWidget.clear() - #self.csvFilenameEdit.setText(u'') + for format in SongFormat.get_formats(): + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) + if select_mode == SongFormatSelect.MultipleFiles: + self.formatWidgets[format][u'fileListWidget'].clear() + else: + self.formatWidgets[format][u'filepathEdit'].setText(u'') self.errorReportTextEdit.clear() self.errorReportTextEdit.setHidden(True) self.errorCopyToButton.setHidden(True) @@ -771,87 +384,21 @@ class SongImportForm(OpenLPWizard): class, and then runs the ``doImport`` method of the importer to do the actual importing. """ - source_format = self.formatComboBox.currentIndex() - importer = None - if source_format == SongFormat.OpenLP2: - # Import an OpenLP 2.0 database - importer = self.plugin.importSongs(SongFormat.OpenLP2, - filename=unicode(self.openLP2FilenameEdit.text()) - ) - elif source_format == SongFormat.OpenLP1: - # Import an openlp.org database - importer = self.plugin.importSongs(SongFormat.OpenLP1, - filename=unicode(self.openLP1FilenameEdit.text()), - plugin=self.plugin - ) - elif source_format == SongFormat.PowerSong: - # Import PowerSong folder - importer = self.plugin.importSongs(SongFormat.PowerSong, - folder=unicode(self.powerSongFilenameEdit.text()) - ) - elif source_format == SongFormat.OpenLyrics: - # Import OpenLyrics songs - importer = self.plugin.importSongs(SongFormat.OpenLyrics, - filenames=self.getListOfFiles(self.openLyricsFileListWidget) - ) - elif source_format == SongFormat.OpenSong: - # Import OpenSong songs - importer = self.plugin.importSongs(SongFormat.OpenSong, - filenames=self.getListOfFiles(self.openSongFileListWidget) - ) - elif source_format == SongFormat.WordsOfWorship: - # Import Words Of Worship songs - importer = self.plugin.importSongs(SongFormat.WordsOfWorship, + source_format = self.activeFormat + select_mode = SongFormatAttribute.get(source_format, + SongFormatAttribute.select_mode) + if select_mode == SongFormatSelect.SingleFile: + importer = self.plugin.importSongs(source_format, + filename=unicode( + self.formatWidgets[source_format][u'filepathEdit'].text())) + elif select_mode == SongFormatSelect.MultipleFiles: + importer = self.plugin.importSongs(source_format, filenames=self.getListOfFiles( - self.wordsOfWorshipFileListWidget) - ) - elif source_format == SongFormat.CCLI: - # Import Words Of Worship songs - importer = self.plugin.importSongs(SongFormat.CCLI, - filenames=self.getListOfFiles(self.ccliFileListWidget) - ) - elif source_format == SongFormat.DreamBeam: - # Import DreamBeam songs - importer = self.plugin.importSongs(SongFormat.DreamBeam, - filenames=self.getListOfFiles( - self.dreamBeamFileListWidget) - ) - elif source_format == SongFormat.SongsOfFellowship: - # Import a Songs of Fellowship RTF file - importer = self.plugin.importSongs(SongFormat.SongsOfFellowship, - filenames=self.getListOfFiles( - self.songsOfFellowshipFileListWidget) - ) - elif source_format == SongFormat.Generic: - # Import a generic document or presentation - importer = self.plugin.importSongs(SongFormat.Generic, - filenames=self.getListOfFiles(self.genericFileListWidget) - ) - elif source_format == SongFormat.EasySlides: - # Import an EasySlides export file - importer = self.plugin.importSongs(SongFormat.EasySlides, - filename=unicode(self.easySlidesFilenameEdit.text()) - ) - elif source_format == SongFormat.EasyWorship: - # Import an EasyWorship database - importer = self.plugin.importSongs(SongFormat.EasyWorship, - filename=unicode(self.ewFilenameEdit.text()) - ) - elif source_format == SongFormat.SongBeamer: - # Import SongBeamer songs - importer = self.plugin.importSongs(SongFormat.SongBeamer, - filenames=self.getListOfFiles(self.songBeamerFileListWidget) - ) - elif source_format == SongFormat.SongShowPlus: - # Import ShongShow Plus songs - importer = self.plugin.importSongs(SongFormat.SongShowPlus, - filenames=self.getListOfFiles(self.songShowPlusFileListWidget) - ) - elif source_format == SongFormat.FoilPresenter: - # Import Foilpresenter songs - importer = self.plugin.importSongs(SongFormat.FoilPresenter, - filenames=self.getListOfFiles(self.foilPresenterFileListWidget) - ) + self.formatWidgets[source_format][u'fileListWidget'])) + elif select_mode == SongFormatSelect.SingleFolder: + importer = self.plugin.importSongs(source_format, + folder=unicode( + self.formatWidgets[source_format][u'filepathEdit'].text())) importer.doImport() self.progressLabel.setText(WizardStrings.FinishedImport) @@ -873,8 +420,15 @@ class SongImportForm(OpenLPWizard): report_file.write(self.errorReportTextEdit.toPlainText()) report_file.close() - def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False, - single_select=False): + def addFileSelectItem(self): + format = self.activeFormat + prefix = SongFormatAttribute.get(format, SongFormatAttribute.prefix) + obj_prefix = SongFormatAttribute.get(format, + SongFormatAttribute.obj_prefix) + can_disable = SongFormatAttribute.get(format, + SongFormatAttribute.can_disable) + select_mode = SongFormatAttribute.get(format, + SongFormatAttribute.select_mode) if not obj_prefix: obj_prefix = prefix page = QtGui.QWidget() @@ -886,22 +440,23 @@ class SongImportForm(OpenLPWizard): importLayout = QtGui.QVBoxLayout(importWidget) importLayout.setMargin(0) importLayout.setObjectName(obj_prefix + u'ImportLayout') - if single_select: - fileLayout = QtGui.QHBoxLayout() - fileLayout.setObjectName(obj_prefix + u'FileLayout') - filenameLabel = QtGui.QLabel(importWidget) - filenameLabel.setObjectName(obj_prefix + u'FilenameLabel') - fileLayout.addWidget(filenameLabel) - filenameEdit = QtGui.QLineEdit(importWidget) - filenameEdit.setObjectName(obj_prefix + u'FilenameEdit') - fileLayout.addWidget(filenameEdit) + if select_mode == SongFormatSelect.SingleFile or \ + select_mode == SongFormatSelect.SingleFolder: + filepathLayout = QtGui.QHBoxLayout() + filepathLayout.setObjectName(obj_prefix + u'FilepathLayout') + filepathLabel = QtGui.QLabel(importWidget) + filepathLabel.setObjectName(obj_prefix + u'FilepathLabel') + filepathLayout.addWidget(filepathLabel) + filepathEdit = QtGui.QLineEdit(importWidget) + filepathEdit.setObjectName(obj_prefix + u'FilepathEdit') + filepathLayout.addWidget(filepathEdit) browseButton = QtGui.QToolButton(importWidget) browseButton.setIcon(self.openIcon) browseButton.setObjectName(obj_prefix + u'BrowseButton') - fileLayout.addWidget(browseButton) - importLayout.addLayout(fileLayout) + filepathLayout.addWidget(browseButton) + importLayout.addLayout(filepathLayout) importLayout.addSpacerItem(self.stackSpacer) - else: + elif select_mode == SongFormatSelect.MultipleFiles: fileListWidget = QtGui.QListWidget(importWidget) fileListWidget.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) @@ -920,21 +475,24 @@ class SongImportForm(OpenLPWizard): buttonLayout.addWidget(removeButton) importLayout.addLayout(buttonLayout) self.formatStack.addWidget(page) - setattr(self, prefix + u'Page', page) - if single_select: - setattr(self, prefix + u'FilenameLabel', filenameLabel) - setattr(self, prefix + u'FileLayout', fileLayout) - setattr(self, prefix + u'FilenameEdit', filenameEdit) - setattr(self, prefix + u'BrowseButton', browseButton) + #setattr(self, prefix + u'Page', page) + if select_mode == SongFormatSelect.SingleFile or \ + select_mode == SongFormatSelect.SingleFolder: + self.formatWidgets[format][u'filepathLabel'] = filepathLabel + #setattr(self, prefix + u'FileLayout', fileLayout) + self.formatWidgets[format][u'filepathEdit'] = filepathEdit + self.formatWidgets[format][u'browseButton'] = browseButton else: - setattr(self, prefix + u'FileListWidget', fileListWidget) - setattr(self, prefix + u'ButtonLayout', buttonLayout) - setattr(self, prefix + u'AddButton', addButton) - setattr(self, prefix + u'RemoveButton', removeButton) - setattr(self, prefix + u'ImportLayout', importLayout) + self.formatWidgets[format][u'fileListWidget'] = fileListWidget + #setattr(self, prefix + u'ButtonLayout', buttonLayout) + self.formatWidgets[format][u'addButton'] = addButton + self.formatWidgets[format][u'removeButton'] = removeButton + #setattr(self, prefix + u'ImportLayout', importLayout) self.formatComboBox.addItem(u'') def disablableWidget(self, page, prefix, obj_prefix): + format = self.activeFormat + self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) layout.setMargin(0) layout.setSpacing(0) @@ -954,9 +512,9 @@ class SongImportForm(OpenLPWizard): importWidget = QtGui.QWidget(page) importWidget.setObjectName(obj_prefix + u'ImportWidget') layout.addWidget(importWidget) - setattr(self, prefix + u'Layout', layout) - setattr(self, prefix + u'DisabledWidget', disabledWidget) - setattr(self, prefix + u'DisabledLayout', disabledLayout) - setattr(self, prefix + u'DisabledLabel', disabledLabel) - setattr(self, prefix + u'ImportWidget', importWidget) + #setattr(self, prefix + u'Layout', layout) + self.formatWidgets[format][u'disabledWidget'] = disabledWidget + #setattr(self, prefix + u'DisabledLayout', disabledLayout) + self.formatWidgets[format][u'disabledLabel'] = disabledLabel + self.formatWidgets[format][u'importWidget'] = importWidget return importWidget diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 16d943a73..59343afe4 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -29,6 +29,8 @@ The :mod:`importer` modules provides the general song import functionality. """ import logging +from openlp.core.lib.ui import UiStrings +from openlp.core.ui.wizard import WizardStrings from opensongimport import OpenSongImport from easyslidesimport import EasySlidesImport from olpimport import OpenLPSongImport @@ -68,7 +70,6 @@ class SongFormat(object): plus a few helper functions to facilitate generic handling of song types for importing. """ - _format_availability = {} Unknown = -1 OpenLyrics = 0 OpenLP2 = 1 @@ -88,47 +89,7 @@ class SongFormat(object): #CSV = 15 @staticmethod - def get_class(format): - """ - Return the appropriate implementation class. - - ``format`` - The song format. - """ - if format == SongFormat.OpenLP2: - return OpenLPSongImport - elif format == SongFormat.OpenLP1: - return OpenLP1SongImport - elif format == SongFormat.OpenLyrics: - return OpenLyricsImport - elif format == SongFormat.OpenSong: - return OpenSongImport - elif format == SongFormat.SongsOfFellowship: - return SofImport - elif format == SongFormat.WordsOfWorship: - return WowImport - elif format == SongFormat.Generic: - return OooImport - elif format == SongFormat.CCLI: - return CCLIFileImport - elif format == SongFormat.DreamBeam: - return DreamBeamImport - elif format == SongFormat.PowerSong: - return PowerSongImport - elif format == SongFormat.EasySlides: - return EasySlidesImport - elif format == SongFormat.EasyWorship: - return EasyWorshipSongImport - elif format == SongFormat.SongBeamer: - return SongBeamerImport - elif format == SongFormat.SongShowPlus: - return SongShowPlusImport - elif format == SongFormat.FoilPresenter: - return FoilPresenterImport - return None - - @staticmethod - def get_formats_list(): + def get_formats(): """ Return a list of the supported song formats. """ @@ -138,7 +99,7 @@ class SongFormat(object): SongFormat.OpenLP1, SongFormat.Generic, SongFormat.CCLI, - SongFormat.DreamBeam, + SongFormat.DreamBeam, SongFormat.EasySlides, SongFormat.EasyWorship, SongFormat.FoilPresenter, @@ -150,23 +111,202 @@ class SongFormat(object): SongFormat.WordsOfWorship ] - @staticmethod - def set_availability(format, available): - """ - Set the availability for a given song format. - """ - SongFormat._format_availability[format] = available +class SongFormatAttribute(object): + # Required attributes: + class_ = 0 + name = 1 + prefix = 2 + # Optional attributes: + obj_prefix = 10 + can_disable = 11 + availability = 12 + select_mode = 13 + # Required widget Text: + combo_box_text = 20 + # Optional widget Text + disabled_label_text = 30 + filter = 31 + + # Set attribute defaults (if not specified here, default is None) + _defaults = { + obj_prefix: None, + can_disable: False, + availability: True, + select_mode: SongFormatSelect.MultipleFiles, + disabled_label_text: u'', + filter: u'' + } + + # Set attribute values + _attributes = { + SongFormat.OpenLyrics: { + class_: OpenLyricsImport, + name: WizardStrings.OL, + prefix: u'openLyrics', + obj_prefix: u'OpenLyrics', + can_disable: True, + combo_box_text: translate('SongsPlugin.ImportWizardForm', + 'OpenLyrics or OpenLP 2.0 Exported Song'), + disabled_label_text: translate('SongsPlugin.ImportWizardForm', + 'The OpenLyrics importer has not yet been developed, but as ' + 'you can see, we are still intending to do so. Hopefully it ' + 'will be in the next release.'), + filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'OpenLyrics Files') + }, + SongFormat.OpenLP2: { + class_: OpenLPSongImport, + name: UiStrings().OLPV2, + prefix: u'openLP2', + select_mode: SongFormatSelect.SingleFile, + combo_box_text: UiStrings().OLPV2, + filter: u'%s (*.sqlite)' % (translate( + 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) + }, + SongFormat.OpenLP1: { + class_: OpenLP1SongImport, + name: UiStrings().OLPV1, + prefix: u'openLP1', + can_disable: True, + select_mode: SongFormatSelect.SingleFile, + combo_box_text: UiStrings().OLPV1, + disabled_label_text: WizardStrings.NoSqlite, + filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', + 'openlp.org v1.x Databases') + }, + SongFormat.Generic: { + class_: OooImport, +# name: , + prefix: u'generic', + can_disable: True, + combo_box_text: translate('SongsPlugin.ImportWizardForm', + 'Generic Document/Presentation'), + disabled_label_text: translate('SongsPlugin.ImportWizardForm', + 'The generic document/presentation importer has been disabled ' + 'because OpenLP cannot access OpenOffice or LibreOffice.') + }, + SongFormat.CCLI: { + class_: CCLIFileImport, + name: WizardStrings.CCLI, + prefix: u'ccli', + combo_box_text: WizardStrings.CCLI, + filter: u'%s (*.usr *.txt)' % translate( + 'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files') + }, + SongFormat.DreamBeam: { + class_: DreamBeamImport, + name: WizardStrings.DB, + prefix: u'dreamBeam', + combo_box_text: WizardStrings.DB, + filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'DreamBeam Song Files') + }, + SongFormat.EasySlides: { + class_: EasySlidesImport, + name: WizardStrings.ES, + prefix: u'easySlides', + select_mode: SongFormatSelect.SingleFile, + combo_box_text: WizardStrings.ES, + filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'EasySlides XML File') + }, + SongFormat.EasyWorship: { + class_: EasyWorshipSongImport, + name: WizardStrings.EW, + prefix: u'ew', + select_mode: SongFormatSelect.SingleFile, + combo_box_text: WizardStrings.EW, + filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', + 'EasyWorship Song Database') + }, + SongFormat.FoilPresenter: { + class_: FoilPresenterImport, + name: WizardStrings.FP, + prefix: u'foilPresenter', + combo_box_text: WizardStrings.FP, + filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', + 'Foilpresenter Song Files') + }, + SongFormat.OpenSong: { + class_: OpenSongImport, + name: WizardStrings.OS, + prefix: u'openSong', + obj_prefix: u'OpenSong', + combo_box_text: WizardStrings.OS + }, + SongFormat.PowerSong: { + class_: PowerSongImport, + name: WizardStrings.PS, + prefix: u'powerSong', + select_mode: SongFormatSelect.SingleFolder, + combo_box_text: WizardStrings.PS + }, + SongFormat.SongBeamer: { + class_: SongBeamerImport, + name: WizardStrings.SB, + prefix: u'songBeamer', + combo_box_text: WizardStrings.SB, + filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', + 'SongBeamer Files') + }, + SongFormat.SongShowPlus: { + class_: SongShowPlusImport, + name: WizardStrings.SSP, + prefix: u'songShowPlus', + combo_box_text: WizardStrings.SSP, + filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm', + 'SongShow Plus Song Files') + }, + SongFormat.SongsOfFellowship: { + class_: SofImport, + name: WizardStrings.SoF, + prefix: u'songsOfFellowship', + can_disable: True, + combo_box_text: WizardStrings.SoF, + disabled_label_text: translate('SongsPlugin.ImportWizardForm', + 'The Songs of Fellowship importer has been disabled because ' + 'OpenLP cannot access OpenOffice or LibreOffice.'), + filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', + 'Songs Of Fellowship Song Files') + }, + SongFormat.WordsOfWorship: { + class_: WowImport, + name: WizardStrings.WoW, + prefix: u'wordsOfWorship', + combo_box_text: WizardStrings.WoW, + filter: u'%s (*.wsg *.wow-song)' % translate( + 'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') +# }, +# SongFormat.CSV: { +# class_: CSVImport, +# name: WizardStrings.CSV, +# prefix: u'csv', +# obj_prefix: u'CSV', +# select_mode: SongFormatSelect.SingleFile, +# combo_box_text: WizardStrings.CSV + } + } @staticmethod - def get_availability(format): - """ - Return the availability of a given song format. - """ - return SongFormat._format_availability.get(format, True) + def get(format, attribute): + default = _defaults.get(attribute) + return SongFormat._attributes[format].get(attribute, default) -SongFormat.set_availability(SongFormat.OpenLP1, HAS_OPENLP1) -SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF) -SongFormat.set_availability(SongFormat.Generic, HAS_OOO) + @staticmethod + def set(format, attribute, value): + SongFormat._attributes[format][attribute] = value + +class SongFormatSelect(object): + SingleFile = 0 + MultipleFiles = 1 + SingleFolder = 2 + +SongFormatAttribute.set( + SongFormat.OpenLP1, SongFormatAttribute.availability, HAS_OPENLP1) +SongFormatAttribute.set( + SongFormat.SongsOfFellowship, SongFormatAttribute.availability, HAS_SOF) +SongFormatAttribute.set( + SongFormat.Generic, SongFormatAttribute.availability, HAS_OOO) __all__ = [u'SongFormat'] diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 4d59186e5..833da9be7 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -39,7 +39,7 @@ from openlp.core.utils.actions import ActionList from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \ SongsTab from openlp.plugins.songs.lib.db import init_schema, Song -from openlp.plugins.songs.lib.importer import SongFormat +from openlp.plugins.songs.lib.importer import SongFormatAttribute from openlp.plugins.songs.lib.olpimport import OpenLPSongImport log = logging.getLogger(__name__) @@ -194,7 +194,7 @@ class SongsPlugin(Plugin): self.manager.save_object(song) def importSongs(self, format, **kwargs): - class_ = SongFormat.get_class(format) + class_ = SongFormatAttribute.get(format, SongFormatAttribute.class_) importer = class_(self.manager, **kwargs) importer.register(self.mediaItem.importWizard) return importer From e88260736062f6716342966724490598e7991216 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 30 May 2012 19:11:44 +1000 Subject: [PATCH 16/46] Completed refactor of importer.py --- openlp/core/ui/wizard.py | 19 +- openlp/plugins/songs/forms/songimportform.py | 162 ++++++++--------- openlp/plugins/songs/lib/importer.py | 176 ++++++++++++------- openlp/plugins/songs/lib/powersongimport.py | 13 +- openlp/plugins/songs/songsplugin.py | 4 +- 5 files changed, 199 insertions(+), 175 deletions(-) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 0b4e8ec37..5aefa53dd 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -44,20 +44,9 @@ class WizardStrings(object): # Applications/Formats we import from or export to. These get used in # multiple places but do not need translating unless you find evidence of # the writers translating their own product name. - CCLI = u'CCLI/SongSelect' CSV = u'CSV' - DB = u'DreamBeam' - EW = u'EasyWorship' - ES = u'EasySlides' - FP = u'Foilpresenter' - OL = u'OpenLyrics' OS = u'OpenSong' OSIS = u'OSIS' - PS = u'PowerSong 1.0' - SB = u'SongBeamer' - SoF = u'Songs of Fellowship' - SSP = u'SongShow Plus' - WoW = u'Words of Worship' # These strings should need a good reason to be retranslated elsewhere. FinishedImport = translate('OpenLP.Ui', 'Finished import.') FormatLabel = translate('OpenLP.Ui', 'Format:') @@ -76,10 +65,12 @@ class WizardStrings(object): PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%')) Ready = translate('OpenLP.Ui', 'Ready.') StartingImport = translate('OpenLP.Ui', 'Starting import...') - YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at ' + YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify one ' + '%s file to import from.', 'A file type e.g. OpenSong')) + YouSpecifyFiles = unicode(translate('OpenLP.Ui', 'You need to specify at ' 'least one %s file to import from.', 'A file type e.g. OpenSong')) - YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a ' - '%s folder to import from.', 'A file type e.g. OpenSong')) + YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify one ' + '%s folder to import from.', 'A song format e.g. PowerSong')) class OpenLPWizard(QtGui.QWizard): diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 73d6cc59a..cff24f3e4 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -36,8 +36,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttribute, \ - SongFormatSelect +from openlp.plugins.songs.lib.importer import (SongFormat, SongFormatAttr, + SongFormatSelect) log = logging.getLogger(__name__) @@ -60,7 +60,7 @@ class SongImportForm(OpenLPWizard): """ self.clipboard = plugin.formParent.clipboard self.activeFormat = None - self.formatWidgets = dict([(f, {}) for f in SongFormat.get_formats()]) + self.formatWidgets = dict([(f, {}) for f in SongFormat.get_format_list()]) OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp') @@ -84,16 +84,16 @@ class SongImportForm(OpenLPWizard): self.activeFormat = index self.formatStack.setCurrentIndex(self.activeFormat) next_button = self.button(QtGui.QWizard.NextButton) - next_button.setEnabled(SongFormatAttribute.get(self.activeFormat, - SongFormatAttribute.availability)) + next_button.setEnabled(SongFormatAttr.get(self.activeFormat, + SongFormatAttr.availability)) def customInit(self): """ Song wizard specific initialisation. """ - for format in SongFormat.get_formats(): - if not SongFormatAttribute.get(format, - SongFormatAttribute.availability): + for format in SongFormat.get_format_list(): + if not SongFormatAttr.get(format, + SongFormatAttr.availability): self.formatWidgets[format][u'disabledWidget'].setVisible(True) self.formatWidgets[format][u'importWidget'].setVisible(False) @@ -101,9 +101,9 @@ class SongImportForm(OpenLPWizard): """ Song wizard specific signals. """ - for format in SongFormat.get_formats(): - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) + for format in SongFormat.get_format_list(): + select_mode = SongFormatAttr.get(format, + SongFormatAttr.select_mode) if select_mode == SongFormatSelect.MultipleFiles: QtCore.QObject.connect(self.formatWidgets[format][u'addButton'], QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked) @@ -141,7 +141,7 @@ class SongImportForm(OpenLPWizard): self.formatStack = QtGui.QStackedLayout() self.formatStack.setObjectName(u'FormatStack') self.disablableFormats = [] - for self.activeFormat in SongFormat.get_formats(): + for self.activeFormat in SongFormat.get_format_list(): self.addFileSelectItem() self.sourceLayout.addLayout(self.formatStack) self.addPage(self.sourcePage) @@ -163,11 +163,13 @@ class SongImportForm(OpenLPWizard): self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) - for format in SongFormat.get_formats(): - self.formatComboBox.setItemText(format, SongFormatAttribute.get( - format, SongFormatAttribute.combo_box_text)) - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) + for format in SongFormat.get_format_list(): + format_name, custom_combo_text, select_mode = SongFormatAttr.get( + format, SongFormatAttr.name, SongFormatAttr.combo_box_text, + SongFormatAttr.select_mode) + combo_box_text = custom_combo_text if custom_combo_text \ + else format_name + self.formatComboBox.setItemText(format, combo_box_text) if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'addButton'].setText( translate('SongsPlugin.ImportWizardForm', 'Add Files...')) @@ -175,17 +177,17 @@ class SongImportForm(OpenLPWizard): translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) else: if select_mode == SongFormatSelect.SingleFile: - label = 'Filename:' + f_label = 'Filename:' elif select_mode == SongFormatSelect.SingleFolder: - label = 'Folder:' + f_label = 'Folder:' self.formatWidgets[format][u'browseButton'].setText( UiStrings().Browse) self.formatWidgets[format][u'filepathLabel'].setText( - translate('SongsPlugin.ImportWizardForm', label)) + translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: self.formatWidgets[format][u'disabledLabel'].setText( - SongFormatAttribute.get(format, - SongFormatAttribute.disabled_label_text)) + SongFormatAttr.get(format, + SongFormatAttr.disabled_label_text)) self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( @@ -221,18 +223,19 @@ class SongImportForm(OpenLPWizard): format = self.activeFormat QtCore.QSettings().setValue(u'songs/last import type', format) - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) - format_name = SongFormatAttribute.get(format, - SongFormatAttribute.name) - class_ = SongFormatAttribute.get(format, - SongFormatAttribute.class_) + select_mode, class_, format_name, custom_error = \ + SongFormatAttr.get(format, SongFormatAttr.select_mode, + SongFormatAttr.class_, SongFormatAttr.name, + SongFormatAttr.invalid_source_msg) + error_msg = lambda str: (custom_error if custom_error + else str % format_name) if select_mode == SongFormatSelect.MultipleFiles: fileListWidget = self.formatWidgets[format][u'fileListWidget'] if fileListWidget.count() == 0 or not class_.isValidSource( filenames=self.getListOfFiles(fileListWidget)): + error_msg = error_msg if error_msg else WizardStrings.YouSpecifyFiles % format_name critical_error_message_box(UiStrings().NFSp, - WizardStrings.YouSpecifyFile % format_name) + error_msg(WizardStrings.YouSpecifyFiles)) self.formatWidgets[format][u'addButton'].setFocus() return False elif select_mode == SongFormatSelect.SingleFile: @@ -240,7 +243,7 @@ class SongImportForm(OpenLPWizard): if filepathEdit.text().isEmpty() or not class_.isValidSource( filename=filepathEdit.text()): critical_error_message_box(UiStrings().NFSs, - WizardStrings.YouSpecifyFile % format_name) + error_msg(WizardStrings.YouSpecifyFile)) self.formatWidgets[format][u'browseButton'].setFocus() return False elif select_mode == SongFormatSelect.SingleFolder: @@ -248,17 +251,9 @@ class SongImportForm(OpenLPWizard): if filepathEdit.text().isEmpty() or not class_.isValidSource( folder=filepathEdit.text()): critical_error_message_box(UiStrings().NFdSs, - WizardStrings.YouSpecifyFolder % format_name) + error_msg(WizardStrings.YouSpecifyFolder)) self.formatWidgets[format][u'browseButton'].setFocus() return False -# elif source_format == SongFormat.Generic: -# if self.genericFileListWidget.count() == 0: -# critical_error_message_box(UiStrings().NFSp, -# translate('SongsPlugin.ImportWizardForm', -# 'You need to specify at least one document or ' -# 'presentation file to import from.')) -# self.genericAddButton.setFocus() -# return False return True elif self.currentPage() == self.progressPage: return True @@ -306,12 +301,12 @@ class SongImportForm(OpenLPWizard): def onBrowseButtonClicked(self): format = self.activeFormat - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) - name = SongFormatAttribute.get(format, - SongFormatAttribute.name) - filter = SongFormatAttribute.get(format, - SongFormatAttribute.filter) + select_mode = SongFormatAttr.get(format, + SongFormatAttr.select_mode) + name = SongFormatAttr.get(format, + SongFormatAttr.name) + filter = SongFormatAttr.get(format, + SongFormatAttr.filter) filepathEdit = self.formatWidgets[format][u'filepathEdit'] if select_mode == SongFormatSelect.SingleFile: self.getFileName(WizardStrings.OpenTypeFile % name, filepathEdit, @@ -321,30 +316,20 @@ class SongImportForm(OpenLPWizard): def onAddButtonClicked(self): format = self.activeFormat - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) - name = SongFormatAttribute.get(format, - SongFormatAttribute.name) - filter = SongFormatAttribute.get(format, - SongFormatAttribute.filter) + select_mode, format_name, filter, custom_title = \ + SongFormatAttr.get(format, SongFormatAttr.select_mode, + SongFormatAttr.name, SongFormatAttr.filter, + SongFormatAttr.get_files_title) + title = custom_title if custom_title \ + else WizardStrings.OpenTypeFile % format_name if select_mode == SongFormatSelect.MultipleFiles: - self.getFiles(WizardStrings.OpenTypeFile % name, - self.formatWidgets[format][u'FileListWidget'], filter) + self.getFiles(title, self.formatWidgets[format][u'FileListWidget'], + filter) def onRemoveButtonClicked(self): self.removeSelectedItems( self.formatWidgets[self.activeFormat][u'FileListWidget']) -# def onGenericAddButtonClicked(self): -# """ -# Get song database files -# """ -# self.getFiles( -# translate('SongsPlugin.ImportWizardForm', -# 'Select Document/Presentation Files'), -# self.genericFileListWidget -# ) - def setDefaults(self): """ Set default form values for the song import wizard. @@ -358,9 +343,9 @@ class SongImportForm(OpenLPWizard): last_import_type >= self.formatComboBox.count(): last_import_type = 0 self.formatComboBox.setCurrentIndex(last_import_type) - for format in SongFormat.get_formats(): - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) + for format in SongFormat.get_format_list(): + select_mode = SongFormatAttr.get(format, + SongFormatAttr.select_mode) if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'fileListWidget'].clear() else: @@ -385,8 +370,8 @@ class SongImportForm(OpenLPWizard): the actual importing. """ source_format = self.activeFormat - select_mode = SongFormatAttribute.get(source_format, - SongFormatAttribute.select_mode) + select_mode = SongFormatAttr.get(source_format, + SongFormatAttr.select_mode) if select_mode == SongFormatSelect.SingleFile: importer = self.plugin.importSongs(source_format, filename=unicode( @@ -422,19 +407,19 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.activeFormat - prefix = SongFormatAttribute.get(format, SongFormatAttribute.prefix) - obj_prefix = SongFormatAttribute.get(format, - SongFormatAttribute.obj_prefix) - can_disable = SongFormatAttribute.get(format, - SongFormatAttribute.can_disable) - select_mode = SongFormatAttribute.get(format, - SongFormatAttribute.select_mode) + prefix = SongFormatAttr.get(format, SongFormatAttr.prefix) + obj_prefix = SongFormatAttr.get(format, + SongFormatAttr.obj_prefix) + can_disable = SongFormatAttr.get(format, + SongFormatAttr.can_disable) + select_mode = SongFormatAttr.get(format, + SongFormatAttr.select_mode) if not obj_prefix: obj_prefix = prefix page = QtGui.QWidget() page.setObjectName(obj_prefix + u'Page') if can_disable: - importWidget = self.disablableWidget(page, prefix, obj_prefix) + importWidget = self.disablableWidget(page, obj_prefix) else: importWidget = page importLayout = QtGui.QVBoxLayout(importWidget) @@ -456,6 +441,10 @@ class SongImportForm(OpenLPWizard): filepathLayout.addWidget(browseButton) importLayout.addLayout(filepathLayout) importLayout.addSpacerItem(self.stackSpacer) + self.formatWidgets[format][u'filepathLabel'] = filepathLabel + self.formatWidgets[format][u'filepathLayout'] = filepathLayout + self.formatWidgets[format][u'filepathEdit'] = filepathEdit + self.formatWidgets[format][u'browseButton'] = browseButton elif select_mode == SongFormatSelect.MultipleFiles: fileListWidget = QtGui.QListWidget(importWidget) fileListWidget.setSelectionMode( @@ -474,23 +463,16 @@ class SongImportForm(OpenLPWizard): removeButton.setObjectName(obj_prefix + u'RemoveButton') buttonLayout.addWidget(removeButton) importLayout.addLayout(buttonLayout) - self.formatStack.addWidget(page) - #setattr(self, prefix + u'Page', page) - if select_mode == SongFormatSelect.SingleFile or \ - select_mode == SongFormatSelect.SingleFolder: - self.formatWidgets[format][u'filepathLabel'] = filepathLabel - #setattr(self, prefix + u'FileLayout', fileLayout) - self.formatWidgets[format][u'filepathEdit'] = filepathEdit - self.formatWidgets[format][u'browseButton'] = browseButton - else: self.formatWidgets[format][u'fileListWidget'] = fileListWidget - #setattr(self, prefix + u'ButtonLayout', buttonLayout) + self.formatWidgets[format][u'buttonLayout'] = buttonLayout self.formatWidgets[format][u'addButton'] = addButton self.formatWidgets[format][u'removeButton'] = removeButton - #setattr(self, prefix + u'ImportLayout', importLayout) + self.formatStack.addWidget(page) + self.formatWidgets[format][u'page'] = page + self.formatWidgets[format][u'importLayout'] = importLayout self.formatComboBox.addItem(u'') - def disablableWidget(self, page, prefix, obj_prefix): + def disablableWidget(self, page, obj_prefix): format = self.activeFormat self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) @@ -512,9 +494,9 @@ class SongImportForm(OpenLPWizard): importWidget = QtGui.QWidget(page) importWidget.setObjectName(obj_prefix + u'ImportWidget') layout.addWidget(importWidget) - #setattr(self, prefix + u'Layout', layout) + self.formatWidgets[format][u'layout'] = layout self.formatWidgets[format][u'disabledWidget'] = disabledWidget - #setattr(self, prefix + u'DisabledLayout', disabledLayout) + self.formatWidgets[format][u'disabledLayout'] = disabledLayout self.formatWidgets[format][u'disabledLabel'] = disabledLabel self.formatWidgets[format][u'importWidget'] = importWidget return importWidget diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 59343afe4..040f723b7 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -66,9 +66,8 @@ except ImportError: class SongFormat(object): """ - This is a special enumeration class that holds the various types of songs, - plus a few helper functions to facilitate generic handling of song types - for importing. + This is a special enumeration class that holds the various types of song + importers and some helper functions to facilitate access. """ Unknown = -1 OpenLyrics = 0 @@ -89,7 +88,7 @@ class SongFormat(object): #CSV = 15 @staticmethod - def get_formats(): + def get_format_list(): """ Return a list of the supported song formats. """ @@ -111,55 +110,86 @@ class SongFormat(object): SongFormat.WordsOfWorship ] -class SongFormatAttribute(object): - # Required attributes: +class SongFormatAttr(object): + """ + This is a special static class that holds the attributes of each song format + to aid the importing of each song type. + + The various definable attributes are enumerated as follows: + + Required attributes for each song format: + * ``class_`` Import class, e.g. OpenLyricsImport + * ``name`` Name of this format, e.g. u'OpenLyrics' + * ``prefix`` Prefix for objects. Use camelCase, e.g. u'openLyrics' + See ``SongImportForm.addFileSelectItem()``. + + Optional attributes for each song format: + * ``obj_prefix`` Alternate prefix for objects. + See ``SongImportForm.addFileSelectItem()``. + * ``can_disable`` Whether song format is disablable. + * ``availability`` Whether song format is available. + * ``select_mode`` Whether format accepts single file, multiple files, or + single folder. + * ``filter`` File extension filter for Open File/Folder dialog. + + Optional/custom text values for SongImportForm widgets: + * ``combo_box_text`` Combo box selector (default is format name). + * ``disabled_label_text`` Required for disablable song formats. + * ``get_files_title`` Title for Open File/Folder dialog (default includes + format name). + * ``invalid_source_msg`` Message shown when source does not validate. + """ + # Required attributes class_ = 0 name = 1 prefix = 2 - # Optional attributes: + # Optional attributes obj_prefix = 10 can_disable = 11 availability = 12 select_mode = 13 - # Required widget Text: + filter = 14 + # Optional/custom text values combo_box_text = 20 - # Optional widget Text - disabled_label_text = 30 - filter = 31 + disabled_label_text = 21 + get_files_title = 22 + invalid_source_msg = 23 - # Set attribute defaults (if not specified here, default is None) + # Set optional attribute defaults _defaults = { obj_prefix: None, can_disable: False, availability: True, select_mode: SongFormatSelect.MultipleFiles, + filter: u'', + combo_box_text: None, disabled_label_text: u'', - filter: u'' + get_files_title: None, + invalid_source_msg: None } # Set attribute values _attributes = { SongFormat.OpenLyrics: { class_: OpenLyricsImport, - name: WizardStrings.OL, + name: u'OpenLyrics', prefix: u'openLyrics', obj_prefix: u'OpenLyrics', can_disable: True, + filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'OpenLyrics Files'), combo_box_text: translate('SongsPlugin.ImportWizardForm', 'OpenLyrics or OpenLP 2.0 Exported Song'), disabled_label_text: translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics importer has not yet been developed, but as ' 'you can see, we are still intending to do so. Hopefully it ' - 'will be in the next release.'), - filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', - 'OpenLyrics Files') + 'will be in the next release.') }, SongFormat.OpenLP2: { class_: OpenLPSongImport, name: UiStrings().OLPV2, prefix: u'openLP2', select_mode: SongFormatSelect.SingleFile, - combo_box_text: UiStrings().OLPV2, filter: u'%s (*.sqlite)' % (translate( 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) }, @@ -169,61 +199,59 @@ class SongFormatAttribute(object): prefix: u'openLP1', can_disable: True, select_mode: SongFormatSelect.SingleFile, - combo_box_text: UiStrings().OLPV1, - disabled_label_text: WizardStrings.NoSqlite, filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', - 'openlp.org v1.x Databases') + 'openlp.org v1.x Databases'), + disabled_label_text: WizardStrings.NoSqlite }, SongFormat.Generic: { class_: OooImport, -# name: , + name: translate('SongsPlugin.ImportWizardForm', + 'Generic Document/Presentation'), prefix: u'generic', can_disable: True, - combo_box_text: translate('SongsPlugin.ImportWizardForm', - 'Generic Document/Presentation'), disabled_label_text: translate('SongsPlugin.ImportWizardForm', 'The generic document/presentation importer has been disabled ' - 'because OpenLP cannot access OpenOffice or LibreOffice.') + 'because OpenLP cannot access OpenOffice or LibreOffice.'), + get_files_title: translate('SongsPlugin.ImportWizardForm', + 'Select Document/Presentation Files'), + invalid_source_msg: translate('SongsPlugin.ImportWizardForm', + 'You need to specify at least one document or presentation ' + 'file to import from.') }, SongFormat.CCLI: { class_: CCLIFileImport, - name: WizardStrings.CCLI, + name: u'CCLI/SongSelect', prefix: u'ccli', - combo_box_text: WizardStrings.CCLI, filter: u'%s (*.usr *.txt)' % translate( 'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files') }, SongFormat.DreamBeam: { class_: DreamBeamImport, - name: WizardStrings.DB, + name: u'DreamBeam', prefix: u'dreamBeam', - combo_box_text: WizardStrings.DB, filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'DreamBeam Song Files') }, SongFormat.EasySlides: { class_: EasySlidesImport, - name: WizardStrings.ES, + name: u'EasySlides', prefix: u'easySlides', select_mode: SongFormatSelect.SingleFile, - combo_box_text: WizardStrings.ES, filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'EasySlides XML File') }, SongFormat.EasyWorship: { class_: EasyWorshipSongImport, - name: WizardStrings.EW, + name: u'EasyWorship', prefix: u'ew', select_mode: SongFormatSelect.SingleFile, - combo_box_text: WizardStrings.EW, filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', 'EasyWorship Song Database') }, SongFormat.FoilPresenter: { class_: FoilPresenterImport, - name: WizardStrings.FP, + name: u'Foilpresenter', prefix: u'foilPresenter', - combo_box_text: WizardStrings.FP, filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files') }, @@ -231,49 +259,43 @@ class SongFormatAttribute(object): class_: OpenSongImport, name: WizardStrings.OS, prefix: u'openSong', - obj_prefix: u'OpenSong', - combo_box_text: WizardStrings.OS + obj_prefix: u'OpenSong' }, SongFormat.PowerSong: { class_: PowerSongImport, - name: WizardStrings.PS, + name: u'PowerSong 1.0', prefix: u'powerSong', - select_mode: SongFormatSelect.SingleFolder, - combo_box_text: WizardStrings.PS + select_mode: SongFormatSelect.SingleFolder }, SongFormat.SongBeamer: { class_: SongBeamerImport, - name: WizardStrings.SB, + name: u'SongBeamer', prefix: u'songBeamer', - combo_box_text: WizardStrings.SB, filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', 'SongBeamer Files') }, SongFormat.SongShowPlus: { class_: SongShowPlusImport, - name: WizardStrings.SSP, + name: u'SongShow Plus', prefix: u'songShowPlus', - combo_box_text: WizardStrings.SSP, filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm', 'SongShow Plus Song Files') }, SongFormat.SongsOfFellowship: { class_: SofImport, - name: WizardStrings.SoF, + name: u'Songs of Fellowship', prefix: u'songsOfFellowship', can_disable: True, - combo_box_text: WizardStrings.SoF, + filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', + 'Songs Of Fellowship Song Files'), disabled_label_text: translate('SongsPlugin.ImportWizardForm', 'The Songs of Fellowship importer has been disabled because ' - 'OpenLP cannot access OpenOffice or LibreOffice.'), - filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', - 'Songs Of Fellowship Song Files') + 'OpenLP cannot access OpenOffice or LibreOffice.') }, SongFormat.WordsOfWorship: { class_: WowImport, - name: WizardStrings.WoW, + name: u'Words of Worship', prefix: u'wordsOfWorship', - combo_box_text: WizardStrings.WoW, filter: u'%s (*.wsg *.wow-song)' % translate( 'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') # }, @@ -282,31 +304,59 @@ class SongFormatAttribute(object): # name: WizardStrings.CSV, # prefix: u'csv', # obj_prefix: u'CSV', -# select_mode: SongFormatSelect.SingleFile, -# combo_box_text: WizardStrings.CSV +# select_mode: SongFormatSelect.SingleFile } } @staticmethod - def get(format, attribute): - default = _defaults.get(attribute) - return SongFormat._attributes[format].get(attribute, default) + def get(format, *attributes): + """ + Return requested song format attribute(s). + + ``format`` + A song format from SongFormat. + + ``*attributes`` + Zero or more song format attributes from SongFormatAttr. + + Return type depends on number of supplied attributes: + * 0 : Return dict containing all defined attributes for the format. + * 1 : Return the attribute value. + * >1 : Return tuple of requested attribute values. + """ + if not attributes: + return SongFormat._attributes.get(format) + elif len(attributes) == 1: + default = _defaults.get(attributes[0]) + return SongFormat._attributes[format].get(attributes[0], default) + else: + values = [] + for attr in attributes: + default = _defaults.get(attr) + values.append(SongFormat._attributes[format].get(attr, default)) + return tuple(values) @staticmethod def set(format, attribute, value): + """ + Set specified song format attribute to supplied value. + """ SongFormat._attributes[format][attribute] = value class SongFormatSelect(object): + """ + This is a special enumeration class listing available file selection modes. + """ SingleFile = 0 MultipleFiles = 1 SingleFolder = 2 -SongFormatAttribute.set( - SongFormat.OpenLP1, SongFormatAttribute.availability, HAS_OPENLP1) -SongFormatAttribute.set( - SongFormat.SongsOfFellowship, SongFormatAttribute.availability, HAS_SOF) -SongFormatAttribute.set( - SongFormat.Generic, SongFormatAttribute.availability, HAS_OOO) +SongFormatAttr.set( + SongFormat.OpenLP1, SongFormatAttr.availability, HAS_OPENLP1) +SongFormatAttr.set( + SongFormat.SongsOfFellowship, SongFormatAttr.availability, HAS_SOF) +SongFormatAttr.set( + SongFormat.Generic, SongFormatAttr.availability, HAS_OOO) -__all__ = [u'SongFormat'] +__all__ = [u'SongFormat', u'SongFormatAttr', u'SongFormatSelect'] diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 9946d273d..a22ada2ed 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -33,8 +33,8 @@ import fnmatch import os from openlp.core.lib import translate -from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttr log = logging.getLogger(__name__) @@ -91,6 +91,8 @@ class PowerSongImport(SongImport): """ Receive either a list of files or a folder (unicode) to import. """ + PS_string = SongFormatAttr.get(SongFormat.PowerSong, + SongFormatAttr.name) if isinstance(self.importSource, unicode): if os.path.isdir(self.importSource): dir = self.importSource @@ -104,7 +106,7 @@ class PowerSongImport(SongImport): self.logError(unicode(translate('SongsPlugin.PowerSongImport', 'No songs to import.')), unicode(translate('SongsPlugin.PowerSongImport', - 'No %s files found.' % WizardStrings.PS))) + 'No %s files found.' % PS_string))) return self.importWizard.progressBar.setMaximum(len(self.importSource)) for file in self.importSource: @@ -124,7 +126,7 @@ class PowerSongImport(SongImport): self.logError(os.path.basename(file), unicode( translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Unexpected byte value.' - % WizardStrings.PS))) + % PS_string))) break else: if label == u'TITLE': @@ -142,15 +144,14 @@ class PowerSongImport(SongImport): if not self.title: self.logError(os.path.basename(file), unicode( translate('SongsPlugin.PowerSongImport', - 'Invalid %s file. Missing "TITLE" header.' - % WizardStrings.PS))) + 'Invalid %s file. Missing "TITLE" header.' % PS_string))) continue # Check that file had COPYRIGHTLINE label if not found_copyright: self.logError(self.title, unicode( translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Missing "COPYRIGHTLINE" ' - 'header.' % WizardStrings.PS))) + 'header.' % PS_string))) continue # Check that file had at least one verse if not self.verses: diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 833da9be7..7273aa6ff 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -39,7 +39,7 @@ from openlp.core.utils.actions import ActionList from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \ SongsTab from openlp.plugins.songs.lib.db import init_schema, Song -from openlp.plugins.songs.lib.importer import SongFormatAttribute +from openlp.plugins.songs.lib.importer import SongFormatAttr from openlp.plugins.songs.lib.olpimport import OpenLPSongImport log = logging.getLogger(__name__) @@ -194,7 +194,7 @@ class SongsPlugin(Plugin): self.manager.save_object(song) def importSongs(self, format, **kwargs): - class_ = SongFormatAttribute.get(format, SongFormatAttribute.class_) + class_ = SongFormatAttr.get(format, SongFormatAttr.class_) importer = class_(self.manager, **kwargs) importer.register(self.mediaItem.importWizard) return importer From 504145d4548762310f92a6c1828052cc6620c522 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 30 May 2012 23:53:31 +1000 Subject: [PATCH 17/46] Completed refactor of songimportform.py --- openlp/plugins/songs/forms/songimportform.py | 71 ++++++++------------ openlp/plugins/songs/lib/importer.py | 8 +-- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index cff24f3e4..c1c8f036b 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -36,8 +36,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.plugins.songs.lib.importer import (SongFormat, SongFormatAttr, - SongFormatSelect) +from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttr, \ + SongFormatSelect log = logging.getLogger(__name__) @@ -59,8 +59,6 @@ class SongImportForm(OpenLPWizard): The songs plugin. """ self.clipboard = plugin.formParent.clipboard - self.activeFormat = None - self.formatWidgets = dict([(f, {}) for f in SongFormat.get_format_list()]) OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp') @@ -68,6 +66,8 @@ class SongImportForm(OpenLPWizard): """ Set up the song wizard UI. """ + self.formatWidgets = dict([(format, {}) for format in + SongFormat.get_format_list()]) OpenLPWizard.setupUi(self, image) self.activeFormat = SongFormat.OpenLyrics self.formatStack.setCurrentIndex(self.activeFormat) @@ -82,7 +82,7 @@ class SongImportForm(OpenLPWizard): button. """ self.activeFormat = index - self.formatStack.setCurrentIndex(self.activeFormat) + self.formatStack.setCurrentIndex(index) next_button = self.button(QtGui.QWizard.NextButton) next_button.setEnabled(SongFormatAttr.get(self.activeFormat, SongFormatAttr.availability)) @@ -92,8 +92,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific initialisation. """ for format in SongFormat.get_format_list(): - if not SongFormatAttr.get(format, - SongFormatAttr.availability): + if not SongFormatAttr.get(format, SongFormatAttr.availability): self.formatWidgets[format][u'disabledWidget'].setVisible(True) self.formatWidgets[format][u'importWidget'].setVisible(False) @@ -102,8 +101,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific signals. """ for format in SongFormat.get_format_list(): - select_mode = SongFormatAttr.get(format, - SongFormatAttr.select_mode) + select_mode = SongFormatAttr.get(format, SongFormatAttr.select_mode) if select_mode == SongFormatSelect.MultipleFiles: QtCore.QObject.connect(self.formatWidgets[format][u'addButton'], QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked) @@ -156,13 +154,12 @@ class SongImportForm(OpenLPWizard): translate('OpenLP.Ui', 'Welcome to the Song Import Wizard')) self.informationLabel.setText( translate('SongsPlugin.ImportWizardForm', - 'This wizard will help you to import songs from a variety of ' - 'formats. Click the next button below to start the process by ' - 'selecting a format to import from.')) + 'This wizard will help you to import songs from a variety of ' + 'formats. Click the next button below to start the process by ' + 'selecting a format to import from.')) self.sourcePage.setTitle(WizardStrings.ImportSelect) self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) - for format in SongFormat.get_format_list(): format_name, custom_combo_text, select_mode = SongFormatAttr.get( format, SongFormatAttr.name, SongFormatAttr.combo_box_text, @@ -176,19 +173,17 @@ class SongImportForm(OpenLPWizard): self.formatWidgets[format][u'removeButton'].setText( translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) else: + self.formatWidgets[format][u'browseButton'].setText( + UiStrings().Browse) if select_mode == SongFormatSelect.SingleFile: f_label = 'Filename:' elif select_mode == SongFormatSelect.SingleFolder: f_label = 'Folder:' - self.formatWidgets[format][u'browseButton'].setText( - UiStrings().Browse) self.formatWidgets[format][u'filepathLabel'].setText( translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: self.formatWidgets[format][u'disabledLabel'].setText( - SongFormatAttr.get(format, - SongFormatAttr.disabled_label_text)) - + SongFormatAttr.get(format, SongFormatAttr.disabled_label_text)) self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('SongsPlugin.ImportWizardForm', @@ -200,8 +195,9 @@ class SongImportForm(OpenLPWizard): self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm', 'Save to File')) # Align all QFormLayouts towards each other. + filepathLabel = self.formatWidgets[SongFormat.OpenLP2][u'filepathLabel'] width = max(self.formatLabel.minimumSizeHint().width(), - self.openLP2FilenameLabel.minimumSizeHint().width()) + filepathLabel.minimumSizeHint().width()) self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) @@ -233,7 +229,6 @@ class SongImportForm(OpenLPWizard): fileListWidget = self.formatWidgets[format][u'fileListWidget'] if fileListWidget.count() == 0 or not class_.isValidSource( filenames=self.getListOfFiles(fileListWidget)): - error_msg = error_msg if error_msg else WizardStrings.YouSpecifyFiles % format_name critical_error_message_box(UiStrings().NFSp, error_msg(WizardStrings.YouSpecifyFiles)) self.formatWidgets[format][u'addButton'].setFocus() @@ -301,25 +296,22 @@ class SongImportForm(OpenLPWizard): def onBrowseButtonClicked(self): format = self.activeFormat - select_mode = SongFormatAttr.get(format, - SongFormatAttr.select_mode) - name = SongFormatAttr.get(format, - SongFormatAttr.name) - filter = SongFormatAttr.get(format, + select_mode, format_name, filter = SongFormatAttr.get(format, + SongFormatAttr.select_mode, SongFormatAttr.name, SongFormatAttr.filter) filepathEdit = self.formatWidgets[format][u'filepathEdit'] if select_mode == SongFormatSelect.SingleFile: - self.getFileName(WizardStrings.OpenTypeFile % name, filepathEdit, - filter) + self.getFileName(WizardStrings.OpenTypeFile % format_name, + filepathEdit, filter) elif select_mode == SongFormatSelect.SingleFolder: - self.getFolder(WizardStrings.OpenTypeFile % name, filepathEdit) + self.getFolder(WizardStrings.OpenTypeFolder % format_name, + filepathEdit) def onAddButtonClicked(self): format = self.activeFormat - select_mode, format_name, filter, custom_title = \ - SongFormatAttr.get(format, SongFormatAttr.select_mode, - SongFormatAttr.name, SongFormatAttr.filter, - SongFormatAttr.get_files_title) + select_mode, format_name, filter, custom_title = SongFormatAttr.get( + format, SongFormatAttr.select_mode, SongFormatAttr.name, + SongFormatAttr.filter, SongFormatAttr.get_files_title) title = custom_title if custom_title \ else WizardStrings.OpenTypeFile % format_name if select_mode == SongFormatSelect.MultipleFiles: @@ -344,8 +336,7 @@ class SongImportForm(OpenLPWizard): last_import_type = 0 self.formatComboBox.setCurrentIndex(last_import_type) for format in SongFormat.get_format_list(): - select_mode = SongFormatAttr.get(format, - SongFormatAttr.select_mode) + select_mode = SongFormatAttr.get(format, SongFormatAttr.select_mode) if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'fileListWidget'].clear() else: @@ -407,13 +398,9 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.activeFormat - prefix = SongFormatAttr.get(format, SongFormatAttr.prefix) - obj_prefix = SongFormatAttr.get(format, - SongFormatAttr.obj_prefix) - can_disable = SongFormatAttr.get(format, - SongFormatAttr.can_disable) - select_mode = SongFormatAttr.get(format, - SongFormatAttr.select_mode) + prefix, obj_prefix, can_disable, select_mode = SongFormatAttr.get( + format, SongFormatAttr.prefix, SongFormatAttr.obj_prefix, + SongFormatAttr.can_disable, SongFormatAttr.select_mode) if not obj_prefix: obj_prefix = prefix page = QtGui.QWidget() @@ -473,7 +460,6 @@ class SongImportForm(OpenLPWizard): self.formatComboBox.addItem(u'') def disablableWidget(self, page, obj_prefix): - format = self.activeFormat self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) layout.setMargin(0) @@ -494,6 +480,7 @@ class SongImportForm(OpenLPWizard): importWidget = QtGui.QWidget(page) importWidget.setObjectName(obj_prefix + u'ImportWidget') layout.addWidget(importWidget) + format = self.activeFormat self.formatWidgets[format][u'layout'] = layout self.formatWidgets[format][u'disabledWidget'] = disabledWidget self.formatWidgets[format][u'disabledLayout'] = disabledLayout diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 040f723b7..29f9cc8a8 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -130,13 +130,13 @@ class SongFormatAttr(object): * ``availability`` Whether song format is available. * ``select_mode`` Whether format accepts single file, multiple files, or single folder. - * ``filter`` File extension filter for Open File/Folder dialog. + * ``filter`` File extension filter for QFileDialog. Optional/custom text values for SongImportForm widgets: * ``combo_box_text`` Combo box selector (default is format name). * ``disabled_label_text`` Required for disablable song formats. - * ``get_files_title`` Title for Open File/Folder dialog (default includes - format name). + * ``get_files_title`` Title for QFileDialog (default includes format + name). * ``invalid_source_msg`` Message shown when source does not validate. """ # Required attributes @@ -339,7 +339,7 @@ class SongFormatAttr(object): @staticmethod def set(format, attribute, value): """ - Set specified song format attribute to supplied value. + Set specified song format attribute to the supplied value. """ SongFormat._attributes[format][attribute] = value From c4060dc04b33f8093606ce1c8d1f33fac65a0008 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 31 May 2012 00:59:54 +1000 Subject: [PATCH 18/46] First working rev. Completed basic testing. --- openlp/plugins/songs/forms/songimportform.py | 25 ++++----- openlp/plugins/songs/lib/importer.py | 55 +++++++++++--------- openlp/plugins/songs/lib/powersongimport.py | 3 +- openlp/plugins/songs/lib/songimport.py | 2 +- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index c1c8f036b..1b90a4242 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -175,9 +175,8 @@ class SongImportForm(OpenLPWizard): else: self.formatWidgets[format][u'browseButton'].setText( UiStrings().Browse) - if select_mode == SongFormatSelect.SingleFile: - f_label = 'Filename:' - elif select_mode == SongFormatSelect.SingleFolder: + f_label = 'Filename:' + if select_mode == SongFormatSelect.SingleFolder: f_label = 'Folder:' self.formatWidgets[format][u'filepathLabel'].setText( translate('SongsPlugin.ImportWizardForm', f_label)) @@ -315,12 +314,12 @@ class SongImportForm(OpenLPWizard): title = custom_title if custom_title \ else WizardStrings.OpenTypeFile % format_name if select_mode == SongFormatSelect.MultipleFiles: - self.getFiles(title, self.formatWidgets[format][u'FileListWidget'], + self.getFiles(title, self.formatWidgets[format][u'fileListWidget'], filter) def onRemoveButtonClicked(self): self.removeSelectedItems( - self.formatWidgets[self.activeFormat][u'FileListWidget']) + self.formatWidgets[self.activeFormat][u'fileListWidget']) def setDefaults(self): """ @@ -364,17 +363,15 @@ class SongImportForm(OpenLPWizard): select_mode = SongFormatAttr.get(source_format, SongFormatAttr.select_mode) if select_mode == SongFormatSelect.SingleFile: - importer = self.plugin.importSongs(source_format, - filename=unicode( + importer = self.plugin.importSongs(source_format, filename=unicode( self.formatWidgets[source_format][u'filepathEdit'].text())) - elif select_mode == SongFormatSelect.MultipleFiles: + elif select_mode == SongFormatSelect.SingleFolder: + importer = self.plugin.importSongs(source_format, folder=unicode( + self.formatWidgets[source_format][u'filepathEdit'].text())) + else: importer = self.plugin.importSongs(source_format, filenames=self.getListOfFiles( - self.formatWidgets[source_format][u'fileListWidget'])) - elif select_mode == SongFormatSelect.SingleFolder: - importer = self.plugin.importSongs(source_format, - folder=unicode( - self.formatWidgets[source_format][u'filepathEdit'].text())) + self.formatWidgets[source_format][u'fileListWidget'])) importer.doImport() self.progressLabel.setText(WizardStrings.FinishedImport) @@ -460,6 +457,7 @@ class SongImportForm(OpenLPWizard): self.formatComboBox.addItem(u'') def disablableWidget(self, page, obj_prefix): + format = self.activeFormat self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) layout.setMargin(0) @@ -480,7 +478,6 @@ class SongImportForm(OpenLPWizard): importWidget = QtGui.QWidget(page) importWidget.setObjectName(obj_prefix + u'ImportWidget') layout.addWidget(importWidget) - format = self.activeFormat self.formatWidgets[format][u'layout'] = layout self.formatWidgets[format][u'disabledWidget'] = disabledWidget self.formatWidgets[format][u'disabledLayout'] = disabledLayout diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 29f9cc8a8..6af55280e 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -29,6 +29,7 @@ The :mod:`importer` modules provides the general song import functionality. """ import logging +from openlp.core.lib import translate from openlp.core.lib.ui import UiStrings from openlp.core.ui.wizard import WizardStrings from opensongimport import OpenSongImport @@ -110,6 +111,14 @@ class SongFormat(object): SongFormat.WordsOfWorship ] +class SongFormatSelect(object): + """ + This is a special enumeration class listing available file selection modes. + """ + SingleFile = 0 + MultipleFiles = 1 + SingleFolder = 2 + class SongFormatAttr(object): """ This is a special static class that holds the attributes of each song format @@ -194,7 +203,6 @@ class SongFormatAttr(object): 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) }, SongFormat.OpenLP1: { - class_: OpenLP1SongImport, name: UiStrings().OLPV1, prefix: u'openLP1', can_disable: True, @@ -204,7 +212,6 @@ class SongFormatAttr(object): disabled_label_text: WizardStrings.NoSqlite }, SongFormat.Generic: { - class_: OooImport, name: translate('SongsPlugin.ImportWizardForm', 'Generic Document/Presentation'), prefix: u'generic', @@ -282,7 +289,6 @@ class SongFormatAttr(object): 'SongShow Plus Song Files') }, SongFormat.SongsOfFellowship: { - class_: SofImport, name: u'Songs of Fellowship', prefix: u'songsOfFellowship', can_disable: True, @@ -325,15 +331,17 @@ class SongFormatAttr(object): * >1 : Return tuple of requested attribute values. """ if not attributes: - return SongFormat._attributes.get(format) + return SongFormatAttr._attributes.get(format) elif len(attributes) == 1: - default = _defaults.get(attributes[0]) - return SongFormat._attributes[format].get(attributes[0], default) + default = SongFormatAttr._defaults.get(attributes[0]) + return SongFormatAttr._attributes[format].get(attributes[0], + default) else: values = [] for attr in attributes: - default = _defaults.get(attr) - values.append(SongFormat._attributes[format].get(attr, default)) + default = SongFormatAttr._defaults.get(attr) + values.append(SongFormatAttr._attributes[format].get(attr, + default)) return tuple(values) @staticmethod @@ -341,22 +349,21 @@ class SongFormatAttr(object): """ Set specified song format attribute to the supplied value. """ - SongFormat._attributes[format][attribute] = value + SongFormatAttr._attributes[format][attribute] = value -class SongFormatSelect(object): - """ - This is a special enumeration class listing available file selection modes. - """ - SingleFile = 0 - MultipleFiles = 1 - SingleFolder = 2 +SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.availability, HAS_OPENLP1) +if HAS_OPENLP1: + SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.class_, + OpenLP1SongImport) +SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.availability, + HAS_SOF) +if HAS_SOF: + SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.class_, + SofImport) +SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.availability, HAS_OOO) +if HAS_OOO: + SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.class_, + OooImport) -SongFormatAttr.set( - SongFormat.OpenLP1, SongFormatAttr.availability, HAS_OPENLP1) -SongFormatAttr.set( - SongFormat.SongsOfFellowship, SongFormatAttr.availability, HAS_SOF) -SongFormatAttr.set( - SongFormat.Generic, SongFormatAttr.availability, HAS_OOO) - -__all__ = [u'SongFormat', u'SongFormatAttr', u'SongFormatSelect'] +__all__ = [u'SongFormat', u'SongFormatSelect', u'SongFormatAttr'] diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index a22ada2ed..011b8709c 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -34,7 +34,6 @@ import os from openlp.core.lib import translate from openlp.plugins.songs.lib.songimport import SongImport -from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttr log = logging.getLogger(__name__) @@ -71,7 +70,6 @@ class PowerSongImport(SongImport): * .song """ - @staticmethod def isValidSource(**kwargs): """ @@ -91,6 +89,7 @@ class PowerSongImport(SongImport): """ Receive either a list of files or a folder (unicode) to import. """ + from importer import SongFormat, SongFormatAttr PS_string = SongFormatAttr.get(SongFormat.PowerSong, SongFormatAttr.name) if isinstance(self.importSource, unicode): diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index ac6818184..fed53ad20 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -55,7 +55,7 @@ class SongImport(QtCore.QObject): """ Override this method to validate the source prior to import. """ - pass + return True def __init__(self, manager, **kwargs): """ From d86caecbbf3c6f6511487152b78dca305aa946f4 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 31 May 2012 19:15:45 +1000 Subject: [PATCH 19/46] Refactored sourcePage validation: reimplemented QWizardPage.isComplete() so that Next button is disabled until source(s) are selected. validateCurrentPage gives each song format class chance to validate its input. --- openlp/core/lib/ui.py | 4 + openlp/plugins/songs/forms/songimportform.py | 118 +++++++++++-------- openlp/plugins/songs/lib/importer.py | 13 +- openlp/plugins/songs/lib/powersongimport.py | 12 +- openlp/plugins/songs/lib/songimport.py | 2 +- 5 files changed, 87 insertions(+), 62 deletions(-) diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index c0472cce8..9707886a9 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -80,6 +80,10 @@ class UiStrings(object): self.Help = translate('OpenLP.Ui', 'Help') self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours') + self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected', + 'Singular') + self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular') + self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural') self.Image = translate('OpenLP.Ui', 'Image') self.Import = translate('OpenLP.Ui', 'Import') self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:') diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 1b90a4242..9173851f9 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -69,23 +69,19 @@ class SongImportForm(OpenLPWizard): self.formatWidgets = dict([(format, {}) for format in SongFormat.get_format_list()]) OpenLPWizard.setupUi(self, image) - self.activeFormat = SongFormat.OpenLyrics - self.formatStack.setCurrentIndex(self.activeFormat) + self.currentFormat = SongFormat.OpenLyrics + self.formatStack.setCurrentIndex(self.currentFormat) QtCore.QObject.connect(self.formatComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onCurrentIndexChanged) def onCurrentIndexChanged(self, index): """ - Called when the format combo box's index changed. We have to check if - the import is available and accordingly to disable or enable the next - button. + Called when the format combo box's index changed. """ - self.activeFormat = index + self.currentFormat = index self.formatStack.setCurrentIndex(index) - next_button = self.button(QtGui.QWizard.NextButton) - next_button.setEnabled(SongFormatAttr.get(self.activeFormat, - SongFormatAttr.availability)) + self.sourcePage.emit(QtCore.SIGNAL(u'completeChanged()')) def customInit(self): """ @@ -112,13 +108,17 @@ class SongImportForm(OpenLPWizard): QtCore.QObject.connect( self.formatWidgets[format][u'browseButton'], QtCore.SIGNAL(u'clicked()'), self.onBrowseButtonClicked) + QtCore.QObject.connect( + self.formatWidgets[format][u'filepathEdit'], + QtCore.SIGNAL(u'textChanged (const QString&)'), + self.onFilepathEditTextChanged) def addCustomPages(self): """ Add song wizard specific pages. """ # Source Page - self.sourcePage = QtGui.QWizardPage() + self.sourcePage = SongImportSourcePage() self.sourcePage.setObjectName(u'SourcePage') self.sourceLayout = QtGui.QVBoxLayout(self.sourcePage) self.sourceLayout.setObjectName(u'SourceLayout') @@ -139,7 +139,7 @@ class SongImportForm(OpenLPWizard): self.formatStack = QtGui.QStackedLayout() self.formatStack.setObjectName(u'FormatStack') self.disablableFormats = [] - for self.activeFormat in SongFormat.get_format_list(): + for self.currentFormat in SongFormat.get_format_list(): self.addFileSelectItem() self.sourceLayout.addLayout(self.formatStack) self.addPage(self.sourcePage) @@ -210,44 +210,34 @@ class SongImportForm(OpenLPWizard): def validateCurrentPage(self): """ Validate the current page before moving on to the next page. + + For sourcePage, provide the song format class with a chance to validate + its input via isValidSource(). """ if self.currentPage() == self.welcomePage: return True elif self.currentPage() == self.sourcePage: - #source_format = self.formatComboBox.currentIndex() - format = self.activeFormat + format = self.currentFormat QtCore.QSettings().setValue(u'songs/last import type', format) - select_mode, class_, format_name, custom_error = \ + select_mode, class_, error_msg = \ SongFormatAttr.get(format, SongFormatAttr.select_mode, - SongFormatAttr.class_, SongFormatAttr.name, - SongFormatAttr.invalid_source_msg) - error_msg = lambda str: (custom_error if custom_error - else str % format_name) + SongFormatAttr.class_, SongFormatAttr.invalid_source_msg) if select_mode == SongFormatSelect.MultipleFiles: - fileListWidget = self.formatWidgets[format][u'fileListWidget'] - if fileListWidget.count() == 0 or not class_.isValidSource( - filenames=self.getListOfFiles(fileListWidget)): - critical_error_message_box(UiStrings().NFSp, - error_msg(WizardStrings.YouSpecifyFiles)) - self.formatWidgets[format][u'addButton'].setFocus() - return False - elif select_mode == SongFormatSelect.SingleFile: - filepathEdit = self.formatWidgets[format][u'filepathEdit'] - if filepathEdit.text().isEmpty() or not class_.isValidSource( - filename=filepathEdit.text()): - critical_error_message_box(UiStrings().NFSs, - error_msg(WizardStrings.YouSpecifyFile)) - self.formatWidgets[format][u'browseButton'].setFocus() - return False - elif select_mode == SongFormatSelect.SingleFolder: - filepathEdit = self.formatWidgets[format][u'filepathEdit'] - if filepathEdit.text().isEmpty() or not class_.isValidSource( - folder=filepathEdit.text()): - critical_error_message_box(UiStrings().NFdSs, - error_msg(WizardStrings.YouSpecifyFolder)) - self.formatWidgets[format][u'browseButton'].setFocus() - return False + import_source = self.getListOfFiles( + self.formatWidgets[format][u'fileListWidget']) + error_title = UiStrings().IFSp + focus_button = self.formatWidgets[format][u'addButton'] + else: + import_source = \ + self.formatWidgets[format][u'filepathEdit'].text() + error_title = UiStrings().IFSs if select_mode == \ + SongFormatSelect.SingleFile else UiStrings().IFdSs + focus_button = self.formatWidgets[format][u'browseButton'] + if not class_.isValidSource(import_source): + critical_error_message_box(error_title, error_msg) + focus_button.setFocus() + return False return True elif self.currentPage() == self.progressPage: return True @@ -294,7 +284,7 @@ class SongImportForm(OpenLPWizard): del item def onBrowseButtonClicked(self): - format = self.activeFormat + format = self.currentFormat select_mode, format_name, filter = SongFormatAttr.get(format, SongFormatAttr.select_mode, SongFormatAttr.name, SongFormatAttr.filter) @@ -307,7 +297,7 @@ class SongImportForm(OpenLPWizard): filepathEdit) def onAddButtonClicked(self): - format = self.activeFormat + format = self.currentFormat select_mode, format_name, filter, custom_title = SongFormatAttr.get( format, SongFormatAttr.select_mode, SongFormatAttr.name, SongFormatAttr.filter, SongFormatAttr.get_files_title) @@ -316,10 +306,18 @@ class SongImportForm(OpenLPWizard): if select_mode == SongFormatSelect.MultipleFiles: self.getFiles(title, self.formatWidgets[format][u'fileListWidget'], filter) + self.sourcePage.emit(QtCore.SIGNAL(u'completeChanged()')) def onRemoveButtonClicked(self): self.removeSelectedItems( - self.formatWidgets[self.activeFormat][u'fileListWidget']) + self.formatWidgets[self.currentFormat][u'fileListWidget']) + self.sourcePage.emit(QtCore.SIGNAL(u'completeChanged()')) + + def onFilepathEditTextChanged(self): + """ + Called when the content of the Filename/Folder edit box changes. + """ + self.sourcePage.emit(QtCore.SIGNAL(u'completeChanged()')) def setDefaults(self): """ @@ -359,7 +357,7 @@ class SongImportForm(OpenLPWizard): class, and then runs the ``doImport`` method of the importer to do the actual importing. """ - source_format = self.activeFormat + source_format = self.currentFormat select_mode = SongFormatAttr.get(source_format, SongFormatAttr.select_mode) if select_mode == SongFormatSelect.SingleFile: @@ -394,7 +392,7 @@ class SongImportForm(OpenLPWizard): report_file.close() def addFileSelectItem(self): - format = self.activeFormat + format = self.currentFormat prefix, obj_prefix, can_disable, select_mode = SongFormatAttr.get( format, SongFormatAttr.prefix, SongFormatAttr.obj_prefix, SongFormatAttr.can_disable, SongFormatAttr.select_mode) @@ -457,7 +455,7 @@ class SongImportForm(OpenLPWizard): self.formatComboBox.addItem(u'') def disablableWidget(self, page, obj_prefix): - format = self.activeFormat + format = self.currentFormat self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) layout.setMargin(0) @@ -484,3 +482,29 @@ class SongImportForm(OpenLPWizard): self.formatWidgets[format][u'disabledLabel'] = disabledLabel self.formatWidgets[format][u'importWidget'] = importWidget return importWidget + +class SongImportSourcePage(QtGui.QWizardPage): + """ + Subclass QtGui.QWizardPage in order to reimplement isComplete(). + """ + + def isComplete(self): + """ + Returns True if an available format is selected, and the + file/folder/files widget is not empty. + + When this method returns True, the wizard's Next button is enabled. + """ + wizard = self.wizard() + format = wizard.currentFormat + select_mode, format_available = SongFormatAttr.get(format, + SongFormatAttr.select_mode, SongFormatAttr.availability) + if format_available: + if select_mode == SongFormatSelect.MultipleFiles: + if wizard.formatWidgets[format][u'fileListWidget'].count() > 0: + return True + else: + filepathEdit = wizard.formatWidgets[format][u'filepathEdit'] + if not filepathEdit.text().isEmpty(): + return True + return False \ No newline at end of file diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 6af55280e..51f197a6a 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -146,7 +146,8 @@ class SongFormatAttr(object): * ``disabled_label_text`` Required for disablable song formats. * ``get_files_title`` Title for QFileDialog (default includes format name). - * ``invalid_source_msg`` Message shown when source does not validate. + * ``invalid_source_msg`` Message shown when source does not validate with + class_.isValidSource(). """ # Required attributes class_ = 0 @@ -220,10 +221,7 @@ class SongFormatAttr(object): 'The generic document/presentation importer has been disabled ' 'because OpenLP cannot access OpenOffice or LibreOffice.'), get_files_title: translate('SongsPlugin.ImportWizardForm', - 'Select Document/Presentation Files'), - invalid_source_msg: translate('SongsPlugin.ImportWizardForm', - 'You need to specify at least one document or presentation ' - 'file to import from.') + 'Select Document/Presentation Files') }, SongFormat.CCLI: { class_: CCLIFileImport, @@ -272,7 +270,9 @@ class SongFormatAttr(object): class_: PowerSongImport, name: u'PowerSong 1.0', prefix: u'powerSong', - select_mode: SongFormatSelect.SingleFolder + select_mode: SongFormatSelect.SingleFolder, + invalid_source_msg: translate('SongsPlugin.ImportWizardForm', + 'You need to specify a valid PowerSong 1.0 database folder.') }, SongFormat.SongBeamer: { class_: SongBeamerImport, @@ -366,4 +366,3 @@ if HAS_OOO: OooImport) __all__ = [u'SongFormat', u'SongFormatSelect', u'SongFormatAttr'] - diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 011b8709c..5611458ff 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -71,18 +71,16 @@ class PowerSongImport(SongImport): * .song """ @staticmethod - def isValidSource(**kwargs): + def isValidSource(import_source): """ Checks if source is a PowerSong 1.0 folder: * is a directory * contains at least one *.song file """ - if u'folder' in kwargs: - dir = kwargs[u'folder'] - if os.path.isdir(dir): - for file in os.listdir(dir): - if fnmatch.fnmatch(file, u'*.song'): - return True + if os.path.isdir(import_source): + for file in os.listdir(import_source): + if fnmatch.fnmatch(file, u'*.song'): + return True return False def doImport(self): diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index fed53ad20..dba86f3ab 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -51,7 +51,7 @@ class SongImport(QtCore.QObject): as necessary """ @staticmethod - def isValidSource(**kwargs): + def isValidSource(import_source): """ Override this method to validate the source prior to import. """ From dddd883edecfa7b99d0aab5fafcc8e8d5194de34 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 31 May 2012 22:42:44 +1000 Subject: [PATCH 20/46] Fixed alignment of filepathEdit widget by adjusting spacer size according to label width. --- openlp/plugins/songs/forms/songimportform.py | 28 ++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 9173851f9..cd875954e 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -177,7 +177,7 @@ class SongImportForm(OpenLPWizard): UiStrings().Browse) f_label = 'Filename:' if select_mode == SongFormatSelect.SingleFolder: - f_label = 'Folder:' + f_label = 'Folders:' self.formatWidgets[format][u'filepathLabel'].setText( translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: @@ -194,11 +194,19 @@ class SongImportForm(OpenLPWizard): self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm', 'Save to File')) # Align all QFormLayouts towards each other. - filepathLabel = self.formatWidgets[SongFormat.OpenLP2][u'filepathLabel'] - width = max(self.formatLabel.minimumSizeHint().width(), - filepathLabel.minimumSizeHint().width()) - self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) + formats = filter(lambda f: u'filepathLabel' in + self.formatWidgets[f], SongFormat.get_format_list()) + labels = [self.formatWidgets[f][u'filepathLabel'] for f in formats] + # Get max width of all labels + max_label_width = max(self.formatLabel.minimumSizeHint().width(), + max([label.minimumSizeHint().width() for label in labels])) + self.formatSpacer.changeSize(max_label_width, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + spacers = [self.formatWidgets[f][u'filepathSpacer'] for f in formats] + for index, spacer in enumerate(spacers): + spacer.changeSize( + max_label_width - labels[index].minimumSizeHint().width(), 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) def customPageChanged(self, pageId): """ @@ -211,8 +219,8 @@ class SongImportForm(OpenLPWizard): """ Validate the current page before moving on to the next page. - For sourcePage, provide the song format class with a chance to validate - its input via isValidSource(). + Provides each song format class with a chance to validate its input by + overriding isValidSource(). """ if self.currentPage() == self.welcomePage: return True @@ -414,6 +422,9 @@ class SongImportForm(OpenLPWizard): filepathLabel = QtGui.QLabel(importWidget) filepathLabel.setObjectName(obj_prefix + u'FilepathLabel') filepathLayout.addWidget(filepathLabel) + filepathSpacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Fixed) + filepathLayout.addSpacerItem(filepathSpacer) filepathEdit = QtGui.QLineEdit(importWidget) filepathEdit.setObjectName(obj_prefix + u'FilepathEdit') filepathLayout.addWidget(filepathEdit) @@ -424,6 +435,7 @@ class SongImportForm(OpenLPWizard): importLayout.addLayout(filepathLayout) importLayout.addSpacerItem(self.stackSpacer) self.formatWidgets[format][u'filepathLabel'] = filepathLabel + self.formatWidgets[format][u'filepathSpacer'] = filepathSpacer self.formatWidgets[format][u'filepathLayout'] = filepathLayout self.formatWidgets[format][u'filepathEdit'] = filepathEdit self.formatWidgets[format][u'browseButton'] = browseButton From 606da7ab76c2c0a8553c80c65e75c52d85770209 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 31 May 2012 23:58:10 +1000 Subject: [PATCH 21/46] Typo --- openlp/plugins/songs/forms/songimportform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4e71c18ad..6e6ac7bf4 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -177,7 +177,7 @@ class SongImportForm(OpenLPWizard): UiStrings().Browse) f_label = 'Filename:' if select_mode == SongFormatSelect.SingleFolder: - f_label = 'Folders:' + f_label = 'Folder:' self.formatWidgets[format][u'filepathLabel'].setText( translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: From d9ed9aaa5c48e00e0bfac213bb58e7591f813986 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Fri, 1 Jun 2012 00:24:24 +1000 Subject: [PATCH 22/46] Removed obj_prefix (old code from r1055 and even < r990) --- openlp/plugins/songs/forms/songimportform.py | 42 ++++++++++---------- openlp/plugins/songs/lib/importer.py | 24 +++-------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 6e6ac7bf4..46d2085fe 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -401,36 +401,34 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.currentFormat - prefix, obj_prefix, can_disable, select_mode = SongFormatAttr.get( - format, SongFormatAttr.prefix, SongFormatAttr.obj_prefix, - SongFormatAttr.can_disable, SongFormatAttr.select_mode) - if not obj_prefix: - obj_prefix = prefix + prefix, can_disable, select_mode = SongFormatAttr.get( + format, SongFormatAttr.prefix, SongFormatAttr.can_disable, + SongFormatAttr.select_mode) page = QtGui.QWidget() - page.setObjectName(obj_prefix + u'Page') + page.setObjectName(prefix + u'Page') if can_disable: - importWidget = self.disablableWidget(page, obj_prefix) + importWidget = self.disablableWidget(page, prefix) else: importWidget = page importLayout = QtGui.QVBoxLayout(importWidget) importLayout.setMargin(0) - importLayout.setObjectName(obj_prefix + u'ImportLayout') + importLayout.setObjectName(prefix + u'ImportLayout') if select_mode == SongFormatSelect.SingleFile or \ select_mode == SongFormatSelect.SingleFolder: filepathLayout = QtGui.QHBoxLayout() - filepathLayout.setObjectName(obj_prefix + u'FilepathLayout') + filepathLayout.setObjectName(prefix + u'FilepathLayout') filepathLabel = QtGui.QLabel(importWidget) - filepathLabel.setObjectName(obj_prefix + u'FilepathLabel') + filepathLabel.setObjectName(prefix + u'FilepathLabel') filepathLayout.addWidget(filepathLabel) filepathSpacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) filepathLayout.addSpacerItem(filepathSpacer) filepathEdit = QtGui.QLineEdit(importWidget) - filepathEdit.setObjectName(obj_prefix + u'FilepathEdit') + filepathEdit.setObjectName(prefix + u'FilepathEdit') filepathLayout.addWidget(filepathEdit) browseButton = QtGui.QToolButton(importWidget) browseButton.setIcon(self.openIcon) - browseButton.setObjectName(obj_prefix + u'BrowseButton') + browseButton.setObjectName(prefix + u'BrowseButton') filepathLayout.addWidget(browseButton) importLayout.addLayout(filepathLayout) importLayout.addSpacerItem(self.stackSpacer) @@ -443,18 +441,18 @@ class SongImportForm(OpenLPWizard): fileListWidget = QtGui.QListWidget(importWidget) fileListWidget.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) - fileListWidget.setObjectName(obj_prefix + u'FileListWidget') + fileListWidget.setObjectName(prefix + u'FileListWidget') importLayout.addWidget(fileListWidget) buttonLayout = QtGui.QHBoxLayout() - buttonLayout.setObjectName(obj_prefix + u'ButtonLayout') + buttonLayout.setObjectName(prefix + u'ButtonLayout') addButton = QtGui.QPushButton(importWidget) addButton.setIcon(self.openIcon) - addButton.setObjectName(obj_prefix + u'AddButton') + addButton.setObjectName(prefix + u'AddButton') buttonLayout.addWidget(addButton) buttonLayout.addStretch() removeButton = QtGui.QPushButton(importWidget) removeButton.setIcon(self.deleteIcon) - removeButton.setObjectName(obj_prefix + u'RemoveButton') + removeButton.setObjectName(prefix + u'RemoveButton') buttonLayout.addWidget(removeButton) importLayout.addLayout(buttonLayout) self.formatWidgets[format][u'fileListWidget'] = fileListWidget @@ -466,27 +464,27 @@ class SongImportForm(OpenLPWizard): self.formatWidgets[format][u'importLayout'] = importLayout self.formatComboBox.addItem(u'') - def disablableWidget(self, page, obj_prefix): + def disablableWidget(self, page, prefix): format = self.currentFormat self.disablableFormats.append(format) layout = QtGui.QVBoxLayout(page) layout.setMargin(0) layout.setSpacing(0) - layout.setObjectName(obj_prefix + u'Layout') + layout.setObjectName(prefix + u'Layout') disabledWidget = QtGui.QWidget(page) disabledWidget.setVisible(False) - disabledWidget.setObjectName(obj_prefix + u'DisabledWidget') + disabledWidget.setObjectName(prefix + u'DisabledWidget') disabledLayout = QtGui.QVBoxLayout(disabledWidget) disabledLayout.setMargin(0) - disabledLayout.setObjectName(obj_prefix + u'DisabledLayout') + disabledLayout.setObjectName(prefix + u'DisabledLayout') disabledLabel = QtGui.QLabel(disabledWidget) disabledLabel.setWordWrap(True) - disabledLabel.setObjectName(obj_prefix + u'DisabledLabel') + disabledLabel.setObjectName(prefix + u'DisabledLabel') disabledLayout.addWidget(disabledLabel) disabledLayout.addSpacerItem(self.stackSpacer) layout.addWidget(disabledWidget) importWidget = QtGui.QWidget(page) - importWidget.setObjectName(obj_prefix + u'ImportWidget') + importWidget.setObjectName(prefix + u'ImportWidget') layout.addWidget(importWidget) self.formatWidgets[format][u'layout'] = layout self.formatWidgets[format][u'disabledWidget'] = disabledWidget diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 51f197a6a..e90c3cfa3 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -133,8 +133,6 @@ class SongFormatAttr(object): See ``SongImportForm.addFileSelectItem()``. Optional attributes for each song format: - * ``obj_prefix`` Alternate prefix for objects. - See ``SongImportForm.addFileSelectItem()``. * ``can_disable`` Whether song format is disablable. * ``availability`` Whether song format is available. * ``select_mode`` Whether format accepts single file, multiple files, or @@ -154,11 +152,10 @@ class SongFormatAttr(object): name = 1 prefix = 2 # Optional attributes - obj_prefix = 10 - can_disable = 11 - availability = 12 - select_mode = 13 - filter = 14 + can_disable = 10 + availability = 11 + select_mode = 12 + filter = 13 # Optional/custom text values combo_box_text = 20 disabled_label_text = 21 @@ -167,7 +164,6 @@ class SongFormatAttr(object): # Set optional attribute defaults _defaults = { - obj_prefix: None, can_disable: False, availability: True, select_mode: SongFormatSelect.MultipleFiles, @@ -184,16 +180,10 @@ class SongFormatAttr(object): class_: OpenLyricsImport, name: u'OpenLyrics', prefix: u'openLyrics', - obj_prefix: u'OpenLyrics', - can_disable: True, filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'OpenLyrics Files'), combo_box_text: translate('SongsPlugin.ImportWizardForm', - 'OpenLyrics or OpenLP 2.0 Exported Song'), - disabled_label_text: translate('SongsPlugin.ImportWizardForm', - 'The OpenLyrics importer has not yet been developed, but as ' - 'you can see, we are still intending to do so. Hopefully it ' - 'will be in the next release.') + 'OpenLyrics or OpenLP 2.0 Exported Song') }, SongFormat.OpenLP2: { class_: OpenLPSongImport, @@ -263,8 +253,7 @@ class SongFormatAttr(object): SongFormat.OpenSong: { class_: OpenSongImport, name: WizardStrings.OS, - prefix: u'openSong', - obj_prefix: u'OpenSong' + prefix: u'openSong' }, SongFormat.PowerSong: { class_: PowerSongImport, @@ -309,7 +298,6 @@ class SongFormatAttr(object): # class_: CSVImport, # name: WizardStrings.CSV, # prefix: u'csv', -# obj_prefix: u'CSV', # select_mode: SongFormatSelect.SingleFile } } From de15cf85a39a6a45b63ac69ee0d3f5046c4cbb1f Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Fri, 1 Jun 2012 14:36:53 -0400 Subject: [PATCH 23/46] Changed some labels. Fixed GUI buttons --- openlp/core/ui/advancedtab.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index f2f0389b3..e1cfdb62d 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -177,27 +177,27 @@ class AdvancedTab(SettingsTab): self.newDataDirectoryHasFilesLabel.setObjectName( u'newDataDirectoryHasFilesLabel') self.newDataDirectoryHasFilesLabel.setWordWrap(True) - self.newDataDirectoryLabelHBox = QtGui.QHBoxLayout() - self.newDataDirectoryLabelHBox.setObjectName( - u'newDataDirectoryLabelHBox') - self.dataDirectoryBrowseButton = QtGui.QPushButton( + self.dataDirectoryBrowseButton = QtGui.QToolButton( self.dataDirectoryGroupBox) self.dataDirectoryBrowseButton.setObjectName( u'dataDirectoryBrowseButton') self.dataDirectoryBrowseButton.setIcon( build_icon(u':/general/general_open.png')) - self.dataDirectoryDefaultButton = QtGui.QPushButton( + self.dataDirectoryDefaultButton = QtGui.QToolButton( self.dataDirectoryGroupBox) self.dataDirectoryDefaultButton.setObjectName( u'dataDirectoryDefaultButton') self.dataDirectoryDefaultButton.setIcon( build_icon(u':/general/general_revert.png')) - self.dataDirectoryCancelButton = QtGui.QPushButton( + self.dataDirectoryCancelButton = QtGui.QToolButton( self.dataDirectoryGroupBox) self.dataDirectoryCancelButton.setObjectName( u'dataDirectoryCancelButton') self.dataDirectoryCancelButton.setIcon( build_icon(u':/general/general_delete.png')) + self.newDataDirectoryLabelHBox = QtGui.QHBoxLayout() + self.newDataDirectoryLabelHBox.setObjectName( + u'newDataDirectoryLabelHBox') self.newDataDirectoryLabelHBox.addWidget(self.newDataDirectoryEdit) self.newDataDirectoryLabelHBox.addWidget( self.dataDirectoryBrowseButton) @@ -212,6 +212,7 @@ class AdvancedTab(SettingsTab): u'dataDirectoryCopyCheckBox') self.dataDirectoryCopyCheckHBox.addWidget( self.dataDirectoryCopyCheckBox) + self.dataDirectoryCopyCheckHBox.addStretch() self.dataDirectoryCopyCheckHBox.addWidget( self.dataDirectoryCancelButton) self.dataDirectoryLayout.addRow(self.dataDirectoryCurrentLabel, @@ -404,9 +405,9 @@ class AdvancedTab(SettingsTab): self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', 'Revert to the default OpenLP logo.')) self.dataDirectoryCurrentLabel.setText(translate('OpenLP.AdvancedTab', - 'Current:')) + 'Current path:')) self.dataDirectoryNewLabel.setText(translate('OpenLP.AdvancedTab', - 'New:')) + 'Custom path:')) self.dataDirectoryBrowseButton.setToolTip( translate('OpenLP.AdvancedTab', 'Browse for new data file location.')) @@ -415,7 +416,7 @@ class AdvancedTab(SettingsTab): 'Set the data location to the default.')) self.dataDirectoryCancelButton.setText( translate('OpenLP.AdvancedTab', - 'Cancel Location Change')) + 'Cancel')) self.dataDirectoryCancelButton.setToolTip( translate('OpenLP.AdvancedTab', 'Cancel OpenLP data directory location change.')) @@ -427,7 +428,7 @@ class AdvancedTab(SettingsTab): 'Copy the OpenLP data files to the new location.')) self.newDataDirectoryHasFilesLabel.setText( translate('OpenLP.AdvancedTab', - 'WARNING: New data directory location contains' + 'WARNING: New data directory location contains ' 'OpenLP data files. These files WILL be replaced during a copy.')) self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab', 'X11')) From 7b97c15fc7305f2e63c68ad3421caa0f306176ec Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sun, 3 Jun 2012 23:50:57 +1000 Subject: [PATCH 24/46] Refactor SongFormatAttr into SongFormat. PascalCase for enumeration. --- openlp/plugins/songs/forms/songimportform.py | 50 +-- openlp/plugins/songs/lib/importer.py | 415 +++++++++---------- openlp/plugins/songs/lib/powersongimport.py | 6 +- openlp/plugins/songs/songsplugin.py | 4 +- 4 files changed, 231 insertions(+), 244 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 46d2085fe..9d9a1a65b 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -36,8 +36,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.plugins.songs.lib.importer import SongFormat, SongFormatAttr, \ - SongFormatSelect +from openlp.plugins.songs.lib.importer import SongFormat, SongFormatSelect log = logging.getLogger(__name__) @@ -88,7 +87,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific initialisation. """ for format in SongFormat.get_format_list(): - if not SongFormatAttr.get(format, SongFormatAttr.availability): + if not SongFormat.get(format, SongFormat.Availability): self.formatWidgets[format][u'disabledWidget'].setVisible(True) self.formatWidgets[format][u'importWidget'].setVisible(False) @@ -97,7 +96,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific signals. """ for format in SongFormat.get_format_list(): - select_mode = SongFormatAttr.get(format, SongFormatAttr.select_mode) + select_mode = SongFormat.get(format, SongFormat.SelectMode) if select_mode == SongFormatSelect.MultipleFiles: QtCore.QObject.connect(self.formatWidgets[format][u'addButton'], QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked) @@ -161,9 +160,9 @@ class SongImportForm(OpenLPWizard): self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) for format in SongFormat.get_format_list(): - format_name, custom_combo_text, select_mode = SongFormatAttr.get( - format, SongFormatAttr.name, SongFormatAttr.combo_box_text, - SongFormatAttr.select_mode) + format_name, custom_combo_text, select_mode = SongFormat.get( + format, SongFormat.Name, SongFormat.ComboBoxText, + SongFormat.SelectMode) combo_box_text = custom_combo_text if custom_combo_text \ else format_name self.formatComboBox.setItemText(format, combo_box_text) @@ -182,7 +181,7 @@ class SongImportForm(OpenLPWizard): translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: self.formatWidgets[format][u'disabledLabel'].setText( - SongFormatAttr.get(format, SongFormatAttr.disabled_label_text)) + SongFormat.get(format, SongFormat.DisabledLabelText)) self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('SongsPlugin.ImportWizardForm', @@ -194,8 +193,8 @@ class SongImportForm(OpenLPWizard): self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm', 'Save to File')) # Align all QFormLayouts towards each other. - formats = filter(lambda f: u'filepathLabel' in - self.formatWidgets[f], SongFormat.get_format_list()) + formats = filter(lambda f: u'filepathLabel' in self.formatWidgets[f], + SongFormat.get_format_list()) labels = [self.formatWidgets[f][u'filepathLabel'] for f in formats] # Get max width of all labels max_label_width = max(self.formatLabel.minimumSizeHint().width(), @@ -228,9 +227,9 @@ class SongImportForm(OpenLPWizard): format = self.currentFormat QtCore.QSettings().setValue(u'songs/last import type', format) - select_mode, class_, error_msg = \ - SongFormatAttr.get(format, SongFormatAttr.select_mode, - SongFormatAttr.class_, SongFormatAttr.invalid_source_msg) + select_mode, class_, error_msg = SongFormat.get(format, + SongFormat.SelectMode, SongFormat.Class, + SongFormat.InvalidSourceMsg) if select_mode == SongFormatSelect.MultipleFiles: import_source = self.getListOfFiles( self.formatWidgets[format][u'fileListWidget']) @@ -293,9 +292,8 @@ class SongImportForm(OpenLPWizard): def onBrowseButtonClicked(self): format = self.currentFormat - select_mode, format_name, filter = SongFormatAttr.get(format, - SongFormatAttr.select_mode, SongFormatAttr.name, - SongFormatAttr.filter) + select_mode, format_name, filter = SongFormat.get(format, + SongFormat.SelectMode, SongFormat.Name, SongFormat.Filter) filepathEdit = self.formatWidgets[format][u'filepathEdit'] if select_mode == SongFormatSelect.SingleFile: self.getFileName(WizardStrings.OpenTypeFile % format_name, @@ -306,9 +304,9 @@ class SongImportForm(OpenLPWizard): def onAddButtonClicked(self): format = self.currentFormat - select_mode, format_name, filter, custom_title = SongFormatAttr.get( - format, SongFormatAttr.select_mode, SongFormatAttr.name, - SongFormatAttr.filter, SongFormatAttr.get_files_title) + select_mode, format_name, filter, custom_title = SongFormat.get(format, + SongFormat.SelectMode, SongFormat.Name, SongFormat.Filter, + SongFormat.GetFilesTitle) title = custom_title if custom_title \ else WizardStrings.OpenTypeFile % format_name if select_mode == SongFormatSelect.MultipleFiles: @@ -341,7 +339,7 @@ class SongImportForm(OpenLPWizard): last_import_type = 0 self.formatComboBox.setCurrentIndex(last_import_type) for format in SongFormat.get_format_list(): - select_mode = SongFormatAttr.get(format, SongFormatAttr.select_mode) + select_mode = SongFormat.get(format, SongFormat.SelectMode) if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'fileListWidget'].clear() else: @@ -366,8 +364,7 @@ class SongImportForm(OpenLPWizard): the actual importing. """ source_format = self.currentFormat - select_mode = SongFormatAttr.get(source_format, - SongFormatAttr.select_mode) + select_mode = SongFormat.get(source_format, SongFormat.SelectMode) if select_mode == SongFormatSelect.SingleFile: importer = self.plugin.importSongs(source_format, filename=unicode( self.formatWidgets[source_format][u'filepathEdit'].text())) @@ -401,9 +398,8 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.currentFormat - prefix, can_disable, select_mode = SongFormatAttr.get( - format, SongFormatAttr.prefix, SongFormatAttr.can_disable, - SongFormatAttr.select_mode) + prefix, can_disable, select_mode = SongFormat.get(format, + SongFormat.Prefix, SongFormat.CanDisable, SongFormat.SelectMode) page = QtGui.QWidget() page.setObjectName(prefix + u'Page') if can_disable: @@ -507,8 +503,8 @@ class SongImportSourcePage(QtGui.QWizardPage): """ wizard = self.wizard() format = wizard.currentFormat - select_mode, format_available = SongFormatAttr.get(format, - SongFormatAttr.select_mode, SongFormatAttr.availability) + select_mode, format_available = SongFormat.get(format, + SongFormat.SelectMode, SongFormat.Availability) if format_available: if select_mode == SongFormatSelect.MultipleFiles: if wizard.formatWidgets[format][u'fileListWidget'].count() > 0: diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index e90c3cfa3..c13ce8038 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -65,11 +65,42 @@ except ImportError: log.exception('Error importing %s', 'OooImport') HAS_OOO = False +class SongFormatSelect(object): + """ + This is a special enumeration class listing available file selection modes. + """ + SingleFile = 0 + MultipleFiles = 1 + SingleFolder = 2 + class SongFormat(object): """ - This is a special enumeration class that holds the various types of song - importers and some helper functions to facilitate access. + This is a special static class that holds an enumeration of the various + song formats handled by the importer, the attributes of each song format, + and a few helper functions. + + + Required attributes for each song format: + * ``Class`` Import class, e.g. OpenLyricsImport + * ``Name`` Name of the format, e.g. u'OpenLyrics' + * ``Prefix`` Prefix for Qt objects. Use camelCase, e.g. u'openLyrics' + See ``SongImportForm.addFileSelectItem()``. + + Optional attributes for each song format: + * ``CanDisable`` Whether song format importer is disablable. + * ``Availability`` Whether song format importer is available. + * ``SelectMode`` Whether format accepts single file, multiple files, or + single folder (as per SongFormatSelect options). + * ``Filter`` File extension filter for QFileDialog. + + Optional/custom text Strings for SongImportForm widgets: + * ``ComboBoxText`` Combo box selector (default value is format Name). + * ``DisabledLabelText`` Required for disablable song formats. + * ``GetFilesTitle`` Title for QFileDialog (default includes format Name). + * ``InvalidSourceMsg`` Message displayed when source does not validate with + Class.isValidSource(). """ + # Song Formats Unknown = -1 OpenLyrics = 0 OpenLP2 = 1 @@ -88,6 +119,161 @@ class SongFormat(object): WordsOfWorship = 14 #CSV = 15 + # Required attributes + Class = -10 + Name = -11 + Prefix = -12 + # Optional attributes + CanDisable = -20 + Availability = -21 + SelectMode = -22 + Filter = -23 + # Optional/custom text values + ComboBoxText = -30 + DisabledLabelText = -31 + GetFilesTitle = -32 + InvalidSourceMsg = -33 + + # Set optional attribute defaults + _defaults = { + CanDisable: False, + Availability: True, + SelectMode: SongFormatSelect.MultipleFiles, + Filter: u'', + ComboBoxText: None, + DisabledLabelText: u'', + GetFilesTitle: None, + InvalidSourceMsg: None + } + + # Set attribute values for each Song Format + _attributes = { + OpenLyrics: { + Class: OpenLyricsImport, + Name: u'OpenLyrics', + Prefix: u'openLyrics', + Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'OpenLyrics Files'), + ComboBoxText: translate('SongsPlugin.ImportWizardForm', + 'OpenLyrics or OpenLP 2.0 Exported Song') + }, + OpenLP2: { + Class: OpenLPSongImport, + Name: UiStrings().OLPV2, + Prefix: u'openLP2', + SelectMode: SongFormatSelect.SingleFile, + Filter: u'%s (*.sqlite)' % (translate( + 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) + }, + OpenLP1: { + Name: UiStrings().OLPV1, + Prefix: u'openLP1', + CanDisable: True, + SelectMode: SongFormatSelect.SingleFile, + Filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', + 'openlp.org v1.x Databases'), + DisabledLabelText: WizardStrings.NoSqlite + }, + Generic: { + Name: translate('SongsPlugin.ImportWizardForm', + 'Generic Document/Presentation'), + Prefix: u'generic', + CanDisable: True, + DisabledLabelText: translate('SongsPlugin.ImportWizardForm', + 'The generic document/presentation importer has been disabled ' + 'because OpenLP cannot access OpenOffice or LibreOffice.'), + GetFilesTitle: translate('SongsPlugin.ImportWizardForm', + 'Select Document/Presentation Files') + }, + CCLI: { + Class: CCLIFileImport, + Name: u'CCLI/SongSelect', + Prefix: u'ccli', + Filter: u'%s (*.usr *.txt)' % translate( + 'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files') + }, + DreamBeam: { + Class: DreamBeamImport, + Name: u'DreamBeam', + Prefix: u'dreamBeam', + Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'DreamBeam Song Files') + }, + EasySlides: { + Class: EasySlidesImport, + Name: u'EasySlides', + Prefix: u'easySlides', + SelectMode: SongFormatSelect.SingleFile, + Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + 'EasySlides XML File') + }, + EasyWorship: { + Class: EasyWorshipSongImport, + Name: u'EasyWorship', + Prefix: u'ew', + SelectMode: SongFormatSelect.SingleFile, + Filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', + 'EasyWorship Song Database') + }, + FoilPresenter: { + Class: FoilPresenterImport, + Name: u'Foilpresenter', + Prefix: u'foilPresenter', + Filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', + 'Foilpresenter Song Files') + }, + OpenSong: { + Class: OpenSongImport, + Name: WizardStrings.OS, + Prefix: u'openSong' + }, + PowerSong: { + Class: PowerSongImport, + Name: u'PowerSong 1.0', + Prefix: u'powerSong', + SelectMode: SongFormatSelect.SingleFolder, + InvalidSourceMsg: translate('SongsPlugin.ImportWizardForm', + 'You need to specify a valid PowerSong 1.0 database folder.') + }, + SongBeamer: { + Class: SongBeamerImport, + Name: u'SongBeamer', + Prefix: u'songBeamer', + Filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', + 'SongBeamer Files') + }, + SongShowPlus: { + Class: SongShowPlusImport, + Name: u'SongShow Plus', + Prefix: u'songShowPlus', + Filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm', + 'SongShow Plus Song Files') + }, + SongsOfFellowship: { + Name: u'Songs of Fellowship', + Prefix: u'songsOfFellowship', + CanDisable: True, + Filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', + 'Songs Of Fellowship Song Files'), + DisabledLabelText: translate('SongsPlugin.ImportWizardForm', + 'The Songs of Fellowship importer has been disabled because ' + 'OpenLP cannot access OpenOffice or LibreOffice.') + }, + WordsOfWorship: { + Class: WowImport, + Name: u'Words of Worship', + Prefix: u'wordsOfWorship', + Filter: u'%s (*.wsg *.wow-song)' % translate( + 'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') +# }, +# CSV: { +# class_: CSVImport, +# name: WizardStrings.CSV, +# prefix: u'csv', +# select_mode: SongFormatSelect.SingleFile + } + } + @staticmethod def get_format_list(): """ @@ -110,198 +296,7 @@ class SongFormat(object): SongFormat.SongsOfFellowship, SongFormat.WordsOfWorship ] - -class SongFormatSelect(object): - """ - This is a special enumeration class listing available file selection modes. - """ - SingleFile = 0 - MultipleFiles = 1 - SingleFolder = 2 - -class SongFormatAttr(object): - """ - This is a special static class that holds the attributes of each song format - to aid the importing of each song type. - - The various definable attributes are enumerated as follows: - - Required attributes for each song format: - * ``class_`` Import class, e.g. OpenLyricsImport - * ``name`` Name of this format, e.g. u'OpenLyrics' - * ``prefix`` Prefix for objects. Use camelCase, e.g. u'openLyrics' - See ``SongImportForm.addFileSelectItem()``. - - Optional attributes for each song format: - * ``can_disable`` Whether song format is disablable. - * ``availability`` Whether song format is available. - * ``select_mode`` Whether format accepts single file, multiple files, or - single folder. - * ``filter`` File extension filter for QFileDialog. - - Optional/custom text values for SongImportForm widgets: - * ``combo_box_text`` Combo box selector (default is format name). - * ``disabled_label_text`` Required for disablable song formats. - * ``get_files_title`` Title for QFileDialog (default includes format - name). - * ``invalid_source_msg`` Message shown when source does not validate with - class_.isValidSource(). - """ - # Required attributes - class_ = 0 - name = 1 - prefix = 2 - # Optional attributes - can_disable = 10 - availability = 11 - select_mode = 12 - filter = 13 - # Optional/custom text values - combo_box_text = 20 - disabled_label_text = 21 - get_files_title = 22 - invalid_source_msg = 23 - - # Set optional attribute defaults - _defaults = { - can_disable: False, - availability: True, - select_mode: SongFormatSelect.MultipleFiles, - filter: u'', - combo_box_text: None, - disabled_label_text: u'', - get_files_title: None, - invalid_source_msg: None - } - - # Set attribute values - _attributes = { - SongFormat.OpenLyrics: { - class_: OpenLyricsImport, - name: u'OpenLyrics', - prefix: u'openLyrics', - filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', - 'OpenLyrics Files'), - combo_box_text: translate('SongsPlugin.ImportWizardForm', - 'OpenLyrics or OpenLP 2.0 Exported Song') - }, - SongFormat.OpenLP2: { - class_: OpenLPSongImport, - name: UiStrings().OLPV2, - prefix: u'openLP2', - select_mode: SongFormatSelect.SingleFile, - filter: u'%s (*.sqlite)' % (translate( - 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) - }, - SongFormat.OpenLP1: { - name: UiStrings().OLPV1, - prefix: u'openLP1', - can_disable: True, - select_mode: SongFormatSelect.SingleFile, - filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', - 'openlp.org v1.x Databases'), - disabled_label_text: WizardStrings.NoSqlite - }, - SongFormat.Generic: { - name: translate('SongsPlugin.ImportWizardForm', - 'Generic Document/Presentation'), - prefix: u'generic', - can_disable: True, - disabled_label_text: translate('SongsPlugin.ImportWizardForm', - 'The generic document/presentation importer has been disabled ' - 'because OpenLP cannot access OpenOffice or LibreOffice.'), - get_files_title: translate('SongsPlugin.ImportWizardForm', - 'Select Document/Presentation Files') - }, - SongFormat.CCLI: { - class_: CCLIFileImport, - name: u'CCLI/SongSelect', - prefix: u'ccli', - filter: u'%s (*.usr *.txt)' % translate( - 'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files') - }, - SongFormat.DreamBeam: { - class_: DreamBeamImport, - name: u'DreamBeam', - prefix: u'dreamBeam', - filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', - 'DreamBeam Song Files') - }, - SongFormat.EasySlides: { - class_: EasySlidesImport, - name: u'EasySlides', - prefix: u'easySlides', - select_mode: SongFormatSelect.SingleFile, - filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', - 'EasySlides XML File') - }, - SongFormat.EasyWorship: { - class_: EasyWorshipSongImport, - name: u'EasyWorship', - prefix: u'ew', - select_mode: SongFormatSelect.SingleFile, - filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', - 'EasyWorship Song Database') - }, - SongFormat.FoilPresenter: { - class_: FoilPresenterImport, - name: u'Foilpresenter', - prefix: u'foilPresenter', - filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', - 'Foilpresenter Song Files') - }, - SongFormat.OpenSong: { - class_: OpenSongImport, - name: WizardStrings.OS, - prefix: u'openSong' - }, - SongFormat.PowerSong: { - class_: PowerSongImport, - name: u'PowerSong 1.0', - prefix: u'powerSong', - select_mode: SongFormatSelect.SingleFolder, - invalid_source_msg: translate('SongsPlugin.ImportWizardForm', - 'You need to specify a valid PowerSong 1.0 database folder.') - }, - SongFormat.SongBeamer: { - class_: SongBeamerImport, - name: u'SongBeamer', - prefix: u'songBeamer', - filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', - 'SongBeamer Files') - }, - SongFormat.SongShowPlus: { - class_: SongShowPlusImport, - name: u'SongShow Plus', - prefix: u'songShowPlus', - filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm', - 'SongShow Plus Song Files') - }, - SongFormat.SongsOfFellowship: { - name: u'Songs of Fellowship', - prefix: u'songsOfFellowship', - can_disable: True, - filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', - 'Songs Of Fellowship Song Files'), - disabled_label_text: translate('SongsPlugin.ImportWizardForm', - 'The Songs of Fellowship importer has been disabled because ' - 'OpenLP cannot access OpenOffice or LibreOffice.') - }, - SongFormat.WordsOfWorship: { - class_: WowImport, - name: u'Words of Worship', - prefix: u'wordsOfWorship', - filter: u'%s (*.wsg *.wow-song)' % translate( - 'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') -# }, -# SongFormat.CSV: { -# class_: CSVImport, -# name: WizardStrings.CSV, -# prefix: u'csv', -# select_mode: SongFormatSelect.SingleFile - } - } - + @staticmethod def get(format, *attributes): """ @@ -311,7 +306,7 @@ class SongFormatAttr(object): A song format from SongFormat. ``*attributes`` - Zero or more song format attributes from SongFormatAttr. + Zero or more song format attributes from SongFormat. Return type depends on number of supplied attributes: * 0 : Return dict containing all defined attributes for the format. @@ -319,16 +314,16 @@ class SongFormatAttr(object): * >1 : Return tuple of requested attribute values. """ if not attributes: - return SongFormatAttr._attributes.get(format) + return SongFormat._attributes.get(format) elif len(attributes) == 1: - default = SongFormatAttr._defaults.get(attributes[0]) - return SongFormatAttr._attributes[format].get(attributes[0], + default = SongFormat._defaults.get(attributes[0]) + return SongFormat._attributes[format].get(attributes[0], default) else: values = [] for attr in attributes: - default = SongFormatAttr._defaults.get(attr) - values.append(SongFormatAttr._attributes[format].get(attr, + default = SongFormat._defaults.get(attr) + values.append(SongFormat._attributes[format].get(attr, default)) return tuple(values) @@ -337,20 +332,16 @@ class SongFormatAttr(object): """ Set specified song format attribute to the supplied value. """ - SongFormatAttr._attributes[format][attribute] = value + SongFormat._attributes[format][attribute] = value -SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.availability, HAS_OPENLP1) +SongFormat.set(SongFormat.OpenLP1, SongFormat.Availability, HAS_OPENLP1) if HAS_OPENLP1: - SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.class_, - OpenLP1SongImport) -SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.availability, - HAS_SOF) + SongFormat.set(SongFormat.OpenLP1, SongFormat.Class, OpenLP1SongImport) +SongFormat.set(SongFormat.SongsOfFellowship, SongFormat.Availability, HAS_SOF) if HAS_SOF: - SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.class_, - SofImport) -SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.availability, HAS_OOO) + SongFormat.set(SongFormat.SongsOfFellowship, SongFormat.Class, SofImport) +SongFormat.set(SongFormat.Generic, SongFormat.Availability, HAS_OOO) if HAS_OOO: - SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.class_, - OooImport) + SongFormat.set(SongFormat.Generic, SongFormat.Class, OooImport) -__all__ = [u'SongFormat', u'SongFormatSelect', u'SongFormatAttr'] +__all__ = [u'SongFormat', u'SongFormatSelect'] diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 5611458ff..37d016b6e 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -87,9 +87,9 @@ class PowerSongImport(SongImport): """ Receive either a list of files or a folder (unicode) to import. """ - from importer import SongFormat, SongFormatAttr - PS_string = SongFormatAttr.get(SongFormat.PowerSong, - SongFormatAttr.name) + from importer import SongFormat, SongFormat + PS_string = SongFormat.get(SongFormat.PowerSong, + SongFormat.Name) if isinstance(self.importSource, unicode): if os.path.isdir(self.importSource): dir = self.importSource diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 7273aa6ff..cff68f83e 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -39,7 +39,7 @@ from openlp.core.utils.actions import ActionList from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \ SongsTab from openlp.plugins.songs.lib.db import init_schema, Song -from openlp.plugins.songs.lib.importer import SongFormatAttr +from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.olpimport import OpenLPSongImport log = logging.getLogger(__name__) @@ -194,7 +194,7 @@ class SongsPlugin(Plugin): self.manager.save_object(song) def importSongs(self, format, **kwargs): - class_ = SongFormatAttr.get(format, SongFormatAttr.class_) + class_ = SongFormat.get(format, SongFormat.Class) importer = class_(self.manager, **kwargs) importer.register(self.mediaItem.importWizard) return importer From a07a81d851dbdcf756810ae214b6a2f3df05e856 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sun, 3 Jun 2012 23:52:45 +1000 Subject: [PATCH 25/46] Formatting --- openlp/plugins/songs/lib/powersongimport.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 37d016b6e..cbf4bb163 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -88,8 +88,7 @@ class PowerSongImport(SongImport): Receive either a list of files or a folder (unicode) to import. """ from importer import SongFormat, SongFormat - PS_string = SongFormat.get(SongFormat.PowerSong, - SongFormat.Name) + PS_string = SongFormat.get(SongFormat.PowerSong, SongFormat.Name) if isinstance(self.importSource, unicode): if os.path.isdir(self.importSource): dir = self.importSource From 676b0223b83ed3439f0534dc4000c56b76606b45 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 4 Jun 2012 01:32:21 +1000 Subject: [PATCH 26/46] Tidy up --- openlp/plugins/songs/lib/powersongimport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index cbf4bb163..d22d2a26b 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -87,7 +87,7 @@ class PowerSongImport(SongImport): """ Receive either a list of files or a folder (unicode) to import. """ - from importer import SongFormat, SongFormat + from importer import SongFormat PS_string = SongFormat.get(SongFormat.PowerSong, SongFormat.Name) if isinstance(self.importSource, unicode): if os.path.isdir(self.importSource): From 1c53207a77503b93d2a8d08faefaadc532482a3d Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Mon, 4 Jun 2012 09:18:46 -0400 Subject: [PATCH 27/46] Changed variable names --- openlp/core/lib/settings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openlp/core/lib/settings.py b/openlp/core/lib/settings.py index 0bd498df9..158f06f7b 100644 --- a/openlp/core/lib/settings.py +++ b/openlp/core/lib/settings.py @@ -46,21 +46,21 @@ class Settings(QtCore.QSettings): object for accessing settings stored in that Ini file. """ - FilePath = u'' + filePath = u'' @staticmethod - def setFilename(filepath): + def setFilename(iniFile): """ Sets the complete path to an Ini file to be used by Settings objects. Does not affect existing Settings objects. """ - Settings.FilePath = filepath + Settings.filePath = iniFile def __init__(self, *args): - if not args and Settings.FilePath and (Settings.defaultFormat() == + if not args and Settings.filePath and (Settings.defaultFormat() == Settings.IniFormat): - QtCore.QSettings.__init__(self, Settings.FilePath, + QtCore.QSettings.__init__(self, Settings.filePath, Settings.IniFormat) else: QtCore.QSettings.__init__(self, *args) From 2ccf92f543e12b5db2e7884a6973d5153b4d896d Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Tue, 5 Jun 2012 19:20:07 +1000 Subject: [PATCH 28/46] Improved isComplete() validation for single file/folder. --- openlp/plugins/songs/forms/songimportform.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 9d9a1a65b..0b7e24c8d 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -496,8 +496,11 @@ class SongImportSourcePage(QtGui.QWizardPage): def isComplete(self): """ - Returns True if an available format is selected, and the - file/folder/files widget is not empty. + Returns True if: + * an available format is selected, and + * if MultipleFiles mode, at least one file is selected + * or if SingleFile mode, the specified file exists + * or if SingleFolder mode, the specified folder exists When this method returns True, the wizard's Next button is enabled. """ @@ -510,7 +513,12 @@ class SongImportSourcePage(QtGui.QWizardPage): if wizard.formatWidgets[format][u'fileListWidget'].count() > 0: return True else: - filepathEdit = wizard.formatWidgets[format][u'filepathEdit'] - if not filepathEdit.text().isEmpty(): - return True + filepath = wizard.formatWidgets[format][u'filepathEdit'].text() + if not filepath.isEmpty(): + if select_mode == SongFormatSelect.SingleFile\ + and os.path.isfile(filepath): + return True + elif select_mode == SongFormatSelect.SingleFolder\ + and os.path.isdir(filepath): + return True return False From 34de12040fed12f23da91dc48d4a288ff9aabd5e Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 6 Jun 2012 00:12:19 +1000 Subject: [PATCH 29/46] Refactor exception handling --- openlp/plugins/songs/lib/zionworximport.py | 79 ++++++++++------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/openlp/plugins/songs/lib/zionworximport.py b/openlp/plugins/songs/lib/zionworximport.py index 620a2c574..364eccadc 100644 --- a/openlp/plugins/songs/lib/zionworximport.py +++ b/openlp/plugins/songs/lib/zionworximport.py @@ -88,51 +88,46 @@ class ZionWorxImport(SongImport): 'Error reading CSV file.')), unicode(translate('SongsPlugin.ZionWorxImport', 'Line %d: %s' % (songs_reader.line_num, e)))) - else: - num_records = len(records) - log.info(u'%s records found in CSV file' % num_records) - self.importWizard.progressBar.setMaximum(num_records) + return + num_records = len(records) + log.info(u'%s records found in CSV file' % num_records) + self.importWizard.progressBar.setMaximum(num_records) + for index, record in enumerate(records, 1): + if self.stopImportFlag: + return + self.setDefaults() try: - for index, record in enumerate(records, 1): - if self.stopImportFlag: - return - self.setDefaults() - try: - self.title = self._decode(record[u'Title1']) - if record[u'Title2']: - self.alternateTitle = self._decode( - record[u'Title2']) - self.parseAuthor(self._decode(record[u'Writer'])) - self.addCopyright(self._decode( - record[u'Copyright'])) - lyrics = self._decode(record[u'Lyrics']) - except UnicodeDecodeError, e: - self.logError(unicode(translate( - 'SongsPlugin.ZionWorxImport', - 'Decoding error.')), - unicode(translate('SongsPlugin.ZionWorxImport', - 'Record %d: %s' % (index, e)))) - else: - verse = u'' - for line in lyrics.splitlines(): - if line and not line.isspace(): - verse += line + u'\n' - elif verse: - self.addVerse(verse) - verse = u'' - if verse: - self.addVerse(verse) - title = self.title - if not self.finish(): - self.logError(unicode(translate( - 'SongsPlugin.ZionWorxImport', - 'Record %d' % index)) - + (u': "' + title + u'"' if title else u'')) + self.title = self._decode(record[u'Title1']) + if record[u'Title2']: + self.alternateTitle = self._decode(record[u'Title2']) + self.parseAuthor(self._decode(record[u'Writer'])) + self.addCopyright(self._decode(record[u'Copyright'])) + lyrics = self._decode(record[u'Lyrics']) + except UnicodeDecodeError, e: + self.logError(unicode(translate( + 'SongsPlugin.ZionWorxImport', 'Record %d' % index)), + unicode(translate('SongsPlugin.ZionWorxImport', + 'Decoding error: %s' % e))) + continue except TypeError, e: self.logError(unicode(translate( - 'SongsPlugin.ZionWorxImport', - 'File not valid ZionWorx CSV format.')), - u'TypeError: %s' % e) + 'SongsPlugin.ZionWorxImport', 'File not valid ZionWorx ' + 'CSV format.')), u'TypeError: %s' % e) + return + verse = u'' + for line in lyrics.splitlines(): + if line and not line.isspace(): + verse += line + u'\n' + elif verse: + self.addVerse(verse) + verse = u'' + if verse: + self.addVerse(verse) + title = self.title + if not self.finish(): + self.logError(unicode(translate( + 'SongsPlugin.ZionWorxImport', 'Record %d' % index)) + + (u': "' + title + u'"' if title else u'')) def _decode(self, str): """ From a79419d71564093969437790b8fe28b394861bf4 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 6 Jun 2012 00:14:50 +1000 Subject: [PATCH 30/46] Formatting --- openlp/plugins/songs/forms/songimportform.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 0b7e24c8d..4837a4b5a 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -515,10 +515,10 @@ class SongImportSourcePage(QtGui.QWizardPage): else: filepath = wizard.formatWidgets[format][u'filepathEdit'].text() if not filepath.isEmpty(): - if select_mode == SongFormatSelect.SingleFile\ - and os.path.isfile(filepath): + if select_mode == SongFormatSelect.SingleFile \ + and os.path.isfile(filepath): return True - elif select_mode == SongFormatSelect.SingleFolder\ - and os.path.isdir(filepath): + elif select_mode == SongFormatSelect.SingleFolder \ + and os.path.isdir(filepath): return True return False From 818e46fba7374f5011d351dfb01511fb36e620e3 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Wed, 6 Jun 2012 19:14:53 +1000 Subject: [PATCH 31/46] Formatting and comments --- openlp/plugins/songs/forms/songimportform.py | 17 +++--- openlp/plugins/songs/lib/importer.py | 59 +++++++++++++------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4837a4b5a..b13056b32 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -217,8 +217,7 @@ class SongImportForm(OpenLPWizard): def validateCurrentPage(self): """ Validate the current page before moving on to the next page. - - Provides each song format class with a chance to validate its input by + Provide each song format class with a chance to validate its input by overriding isValidSource(). """ if self.currentPage() == self.welcomePage: @@ -491,16 +490,16 @@ class SongImportForm(OpenLPWizard): class SongImportSourcePage(QtGui.QWizardPage): """ - Subclass QtGui.QWizardPage in order to reimplement isComplete(). + Subclass of QtGui.QWizardPage to override isComplete() for Source Page. """ - def isComplete(self): """ - Returns True if: - * an available format is selected, and - * if MultipleFiles mode, at least one file is selected - * or if SingleFile mode, the specified file exists - * or if SingleFolder mode, the specified folder exists + Return True if: + + * an available format is selected, and + * if MultipleFiles mode, at least one file is selected + * or if SingleFile mode, the specified file exists + * or if SingleFolder mode, the specified folder exists When this method returns True, the wizard's Next button is enabled. """ diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index c13ce8038..11169813b 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -79,28 +79,47 @@ class SongFormat(object): song formats handled by the importer, the attributes of each song format, and a few helper functions. - Required attributes for each song format: - * ``Class`` Import class, e.g. OpenLyricsImport - * ``Name`` Name of the format, e.g. u'OpenLyrics' - * ``Prefix`` Prefix for Qt objects. Use camelCase, e.g. u'openLyrics' - See ``SongImportForm.addFileSelectItem()``. + + ``Class`` + Import class, e.g. ``OpenLyricsImport`` + ``Name`` + Name of the format, e.g. ``u'OpenLyrics'`` + ``Prefix`` + Prefix for Qt objects. Use mixedCase, e.g. ``u'openLyrics'`` + See ``SongImportForm.addFileSelectItem()`` Optional attributes for each song format: - * ``CanDisable`` Whether song format importer is disablable. - * ``Availability`` Whether song format importer is available. - * ``SelectMode`` Whether format accepts single file, multiple files, or - single folder (as per SongFormatSelect options). - * ``Filter`` File extension filter for QFileDialog. - Optional/custom text Strings for SongImportForm widgets: - * ``ComboBoxText`` Combo box selector (default value is format Name). - * ``DisabledLabelText`` Required for disablable song formats. - * ``GetFilesTitle`` Title for QFileDialog (default includes format Name). - * ``InvalidSourceMsg`` Message displayed when source does not validate with - Class.isValidSource(). + ``CanDisable`` + Whether song format importer is disablable. + ``Availability`` + Whether song format importer is available. + ``SelectMode`` + Whether format accepts single file, multiple files, or single folder + (as per ``SongFormatSelect`` options). + ``Filter`` + File extension filter for ``QFileDialog``. + + Optional/custom text Strings for ``SongImportForm`` widgets: + + ``ComboBoxText`` + Combo box selector (default value is the format's ``Name``). + ``DisabledLabelText`` + Required for disablable song formats. + ``GetFilesTitle`` + Title for ``QFileDialog`` (default includes the format's ``Name``). + ``InvalidSourceMsg`` + Message displayed if ``Class.isValidSource()`` returns ``False``. """ - # Song Formats + # Enumeration of song formats and their attributes + # * Numerical order of song formats is significant as it determines the + # order used by formatComboBox. + # * Attribute ints are negative so they don't clash with song format ints. + # * Each group of attribute values increments by 10 to facilitate addition + # of more attributes in future. + + # Song formats (ordered alphabetically after Generic) Unknown = -1 OpenLyrics = 0 OpenLP2 = 1 @@ -309,9 +328,9 @@ class SongFormat(object): Zero or more song format attributes from SongFormat. Return type depends on number of supplied attributes: - * 0 : Return dict containing all defined attributes for the format. - * 1 : Return the attribute value. - * >1 : Return tuple of requested attribute values. + :0: Return dict containing all defined attributes for the format. + :1: Return the attribute value. + :>1: Return tuple of requested attribute values. """ if not attributes: return SongFormat._attributes.get(format) From cc900965345a463a2486897e3072928f89eeec1b Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 7 Jun 2012 22:11:47 +1000 Subject: [PATCH 32/46] Added optional descriptionLabel for song format to import wizard --- openlp/plugins/songs/forms/songimportform.py | 35 +++++++++++++++++--- openlp/plugins/songs/lib/importer.py | 12 +++++-- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 90d7d3b17..7f027fd55 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -133,6 +133,9 @@ class SongImportForm(OpenLPWizard): self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.formatSpacer) self.sourceLayout.addLayout(self.formatLayout) + self.formatHSpacing = self.formatLayout.horizontalSpacing() + self.formatVSpacing = self.formatLayout.verticalSpacing() + self.formatLayout.setVerticalSpacing(0) self.stackSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding) self.formatStack = QtGui.QStackedLayout() @@ -160,12 +163,15 @@ class SongImportForm(OpenLPWizard): self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) for format in SongFormat.get_format_list(): - format_name, custom_combo_text, select_mode = SongFormat.get( - format, SongFormat.Name, SongFormat.ComboBoxText, + format_name, custom_combo_text, description_text, select_mode = SongFormat.get( + format, SongFormat.Name, SongFormat.ComboBoxText, SongFormat.DescriptionText, SongFormat.SelectMode) combo_box_text = custom_combo_text if custom_combo_text \ else format_name self.formatComboBox.setItemText(format, combo_box_text) + if description_text is not None: + self.formatWidgets[format][u'descriptionLabel'].setText( + description_text) if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'addButton'].setText( translate('SongsPlugin.ImportWizardForm', 'Add Files...')) @@ -206,6 +212,12 @@ class SongImportForm(OpenLPWizard): spacer.changeSize( max_label_width - labels[index].minimumSizeHint().width(), 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + # Align descriptionLabels with rest of layout + for format in SongFormat.get_format_list(): + if SongFormat.get(format, SongFormat.DescriptionText) is not None: + self.formatWidgets[format][u'descriptionSpacer'].changeSize( + max_label_width + self.formatHSpacing, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) def customPageChanged(self, pageId): """ @@ -397,8 +409,9 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.currentFormat - prefix, can_disable, select_mode = SongFormat.get(format, - SongFormat.Prefix, SongFormat.CanDisable, SongFormat.SelectMode) + prefix, can_disable, description_text, select_mode = SongFormat.get( + format, SongFormat.Prefix, SongFormat.CanDisable, + SongFormat.DescriptionText, SongFormat.SelectMode) page = QtGui.QWidget() page.setObjectName(prefix + u'Page') if can_disable: @@ -408,10 +421,24 @@ class SongImportForm(OpenLPWizard): importLayout = QtGui.QVBoxLayout(importWidget) importLayout.setMargin(0) importLayout.setObjectName(prefix + u'ImportLayout') + if description_text is not None: + descriptionLayout = QtGui.QHBoxLayout() + descriptionLayout.setObjectName(prefix + u'DescriptionLayout') + descriptionSpacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Fixed) + descriptionLayout.addSpacerItem(descriptionSpacer) + descriptionLabel = QtGui.QLabel(importWidget) + descriptionLabel.setWordWrap(True) + descriptionLabel.setObjectName(prefix + u'DescriptionLabel') + descriptionLayout.addWidget(descriptionLabel) + importLayout.addLayout(descriptionLayout) + self.formatWidgets[format][u'descriptionLabel'] = descriptionLabel + self.formatWidgets[format][u'descriptionSpacer'] = descriptionSpacer if select_mode == SongFormatSelect.SingleFile or \ select_mode == SongFormatSelect.SingleFolder: filepathLayout = QtGui.QHBoxLayout() filepathLayout.setObjectName(prefix + u'FilepathLayout') + filepathLayout.setContentsMargins(0, self.formatVSpacing, 0, 0) filepathLabel = QtGui.QLabel(importWidget) filepathLabel.setObjectName(prefix + u'FilepathLabel') filepathLayout.addWidget(filepathLabel) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 01a1f0a64..cae36ce93 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -112,6 +112,8 @@ class SongFormat(object): Title for ``QFileDialog`` (default includes the format's ``Name``). ``InvalidSourceMsg`` Message displayed if ``Class.isValidSource()`` returns ``False``. + ``DescriptionText`` + Short description (1-2 lines) about the song format. """ # Enumeration of song formats and their attributes # * Numerical order of song formats is significant as it determines the @@ -154,6 +156,7 @@ class SongFormat(object): DisabledLabelText = -31 GetFilesTitle = -32 InvalidSourceMsg = -33 + DescriptionText = -34 # Set optional attribute defaults _defaults = { @@ -164,7 +167,8 @@ class SongFormat(object): ComboBoxText: None, DisabledLabelText: u'', GetFilesTitle: None, - InvalidSourceMsg: None + InvalidSourceMsg: None, + DescriptionText: None } # Set attribute values for each Song Format @@ -293,7 +297,11 @@ class SongFormat(object): Prefix: u'zionWorx', SelectMode: SongFormatSelect.SingleFile, ComboBoxText: translate('SongsPlugin.ImportWizardForm', - 'ZionWorx (CSV database dump)') + 'ZionWorx (CSV)'), + DescriptionText: translate('SongsPlugin.ImportWizardForm', + 'First dump your ZionWorx database to a CSV file, using ' + 'freeware tool "TurboDB Data Exchange" (TdbDataX) from dataWeb ' + '(see the User Manual).') # }, # CSV: { # class_: CSVImport, From c219665e1cd2f0c72f6821a20f5db1c8da828e14 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 7 Jun 2012 22:30:41 +1000 Subject: [PATCH 33/46] Formatting --- openlp/plugins/songs/forms/songimportform.py | 14 ++++----- openlp/plugins/songs/lib/importer.py | 4 +-- openlp/plugins/songs/lib/zionworximport.py | 32 ++++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 7f027fd55..f97b2579b 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -163,11 +163,11 @@ class SongImportForm(OpenLPWizard): self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.formatLabel.setText(WizardStrings.FormatLabel) for format in SongFormat.get_format_list(): - format_name, custom_combo_text, description_text, select_mode = SongFormat.get( - format, SongFormat.Name, SongFormat.ComboBoxText, SongFormat.DescriptionText, - SongFormat.SelectMode) - combo_box_text = custom_combo_text if custom_combo_text \ - else format_name + format_name, custom_combo_text, description_text, select_mode = \ + SongFormat.get(format, SongFormat.Name, SongFormat.ComboBoxText, + SongFormat.DescriptionText, SongFormat.SelectMode) + combo_box_text = (custom_combo_text if custom_combo_text else + format_name) self.formatComboBox.setItemText(format, combo_box_text) if description_text is not None: self.formatWidgets[format][u'descriptionLabel'].setText( @@ -249,8 +249,8 @@ class SongImportForm(OpenLPWizard): else: import_source = \ self.formatWidgets[format][u'filepathEdit'].text() - error_title = UiStrings().IFSs if select_mode == \ - SongFormatSelect.SingleFile else UiStrings().IFdSs + error_title = (UiStrings().IFSs if select_mode == + SongFormatSelect.SingleFile else UiStrings().IFdSs) focus_button = self.formatWidgets[format][u'browseButton'] if not class_.isValidSource(import_source): critical_error_message_box(error_title, error_msg) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index cae36ce93..62161656c 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -299,8 +299,8 @@ class SongFormat(object): ComboBoxText: translate('SongsPlugin.ImportWizardForm', 'ZionWorx (CSV)'), DescriptionText: translate('SongsPlugin.ImportWizardForm', - 'First dump your ZionWorx database to a CSV file, using ' - 'freeware tool "TurboDB Data Exchange" (TdbDataX) from dataWeb ' + 'First dump your ZionWorx database to a CSV text file, using ' + 'freeware tool TdbDataX "TurboDB Data Exchange" from dataWeb ' '(see the User Manual).') # }, # CSV: { diff --git a/openlp/plugins/songs/lib/zionworximport.py b/openlp/plugins/songs/lib/zionworximport.py index 364eccadc..bf68cdf3d 100644 --- a/openlp/plugins/songs/lib/zionworximport.py +++ b/openlp/plugins/songs/lib/zionworximport.py @@ -43,14 +43,14 @@ class ZionWorxImport(SongImport): ZionWorx song database fields: - * ``SongNum`` Song ID. Discarded by importer. - * ``Title1`` Main Title. - * ``Title2`` Alternate Title. - * ``Lyrics`` Song verses, separated by blank lines. - * ``Writer`` Song author(s). - * ``Copyright`` Copyright information - * ``Keywords`` Discarded by importer. - * ``DefaultStyle`` Discarded by importer. + * ``SongNum`` Song ID. (Discarded by importer) + * ``Title1`` Main Title. + * ``Title2`` Alternate Title. + * ``Lyrics`` Song verses, separated by blank lines. + * ``Writer`` Song author(s). + * ``Copyright`` Copyright information + * ``Keywords`` (Discarded by importer) + * ``DefaultStyle`` (Discarded by importer) ZionWorx has no native export function; it uses the proprietary TurboDB database engine. The TurboDB vendor, dataWeb, provides tools which can @@ -60,17 +60,17 @@ class ZionWorxImport(SongImport): ``tdbdatax MainTable.dat songstable.csv -fsdf -s, -qd`` - * ``-f`` Table format: ``sdf`` denotes text file. - * ``-s`` Separator character between fields. - * ``-q`` Quote character surrounding fields. ``d`` denotes double-quote. + * -f Table format: ``sdf`` denotes text file. + * -s Separator character between fields. + * -q Quote character surrounding fields. ``d`` denotes double-quote. CSV format expected by importer: - * Fields separated by comma ``,`` - * Fields surrounded by double-quotes ``"``. This enables fields (such as - Lyrics) to include new-lines and commas. Double-quotes within a field - are denoted by two double-quotes ``""`` - * Note: This is the default format of the Python ``csv`` module. + * Field separator character is comma ``,`` + * Fields surrounded by double-quotes ``"``. This enables fields (such as + Lyrics) to include new-lines and commas. Double-quotes within a field + are denoted by two double-quotes ``""`` + * Note: This is the default format of the Python ``csv`` module. """ def doImport(self): From 398ac5afdf5a0ba9f25f0891a8cfaca0876bd70a Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Thu, 7 Jun 2012 22:49:33 +1000 Subject: [PATCH 34/46] String correction --- openlp/plugins/songs/lib/importer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 62161656c..3c36bae65 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -300,8 +300,8 @@ class SongFormat(object): 'ZionWorx (CSV)'), DescriptionText: translate('SongsPlugin.ImportWizardForm', 'First dump your ZionWorx database to a CSV text file, using ' - 'freeware tool TdbDataX "TurboDB Data Exchange" from dataWeb ' - '(see the User Manual).') + 'freeware utility TdbDataX "TurboDB Data Exchange" from ' + 'dataWeb (see the User Manual).') # }, # CSV: { # class_: CSVImport, From f02e886976d887d6afbe3669104a81066228134d Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sat, 9 Jun 2012 04:30:34 +1000 Subject: [PATCH 35/46] Clean import strings of ASCII control chars (user's db had x07 chars) --- openlp/plugins/songs/lib/zionworximport.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/lib/zionworximport.py b/openlp/plugins/songs/lib/zionworximport.py index bf68cdf3d..8f83c4509 100644 --- a/openlp/plugins/songs/lib/zionworximport.py +++ b/openlp/plugins/songs/lib/zionworximport.py @@ -77,6 +77,9 @@ class ZionWorxImport(SongImport): """ Receive a CSV file (from a ZionWorx database dump) to import. """ + # Used to strip control chars (10=LF, 13=CR, 127=DEL) + self.control_chars_map = dict.fromkeys( + range(10) + [11, 12] + range(14,32) + [127]) with open(self.importSource, 'rb') as songs_file: fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics', u'Writer', u'Copyright', u'Keywords', u'DefaultStyle'] @@ -131,9 +134,9 @@ class ZionWorxImport(SongImport): def _decode(self, str): """ - Decodes CSV input to unicode. - - This encoding choice seems OK. ZionWorx has no option for setting the - encoding for its songs, so we assume encoding is always the same. + Decodes CSV input to unicode, stripping all control characters (except + new lines). """ - return unicode(str, u'cp1252') + # This encoding choice seems OK. ZionWorx has no option for setting the + # encoding for its songs, so we assume encoding is always the same. + return unicode(str, u'cp1252').translate(self.control_chars_map) From b8cd0dc7b3136d8cf00a2b1a86e85ee404829e68 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Fri, 8 Jun 2012 15:27:08 -0400 Subject: [PATCH 36/46] Moved cancel button call to advancedtab --- openlp/core/ui/advancedtab.py | 4 ++++ openlp/core/ui/settingsform.py | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index e1cfdb62d..061d69a35 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -590,6 +590,10 @@ class AdvancedTab(SettingsTab): self.displayChanged = False Receiver.send_message(u'slidecontroller_update_slide_limits') + def cancel(self): + # Dialogue was cancelled, remove any pending data path change. + self.onDataDirectoryCancelButtonClicked() + def serviceNameCheckBoxToggled(self, default_service_enabled): self.serviceNameDay.setEnabled(default_service_enabled) time_enabled = default_service_enabled and \ diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 03f5c93a5..d183d9d4a 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -102,8 +102,6 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Process the form saving the settings """ - # Dialogue was cancelled, remove any pending data path change. - self.advancedTab.onDataDirectoryCancelButtonClicked(); for tabIndex in range(self.stackedLayout.count()): self.stackedLayout.widget(tabIndex).cancel() return QtGui.QDialog.reject(self) From 6bf5f6d56f9a55a8eb6546ebc4b74ee333015603 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sat, 9 Jun 2012 05:30:33 +1000 Subject: [PATCH 37/46] Change attributes from enumeration to strings. Double underscore class attributes --- openlp/plugins/songs/forms/songimportform.py | 32 ++- openlp/plugins/songs/lib/importer.py | 242 +++++++++---------- openlp/plugins/songs/lib/powersongimport.py | 2 +- openlp/plugins/songs/songsplugin.py | 2 +- 4 files changed, 128 insertions(+), 150 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index b13056b32..08246a544 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -87,7 +87,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific initialisation. """ for format in SongFormat.get_format_list(): - if not SongFormat.get(format, SongFormat.Availability): + if not SongFormat.get(format, u'availability'): self.formatWidgets[format][u'disabledWidget'].setVisible(True) self.formatWidgets[format][u'importWidget'].setVisible(False) @@ -96,7 +96,7 @@ class SongImportForm(OpenLPWizard): Song wizard specific signals. """ for format in SongFormat.get_format_list(): - select_mode = SongFormat.get(format, SongFormat.SelectMode) + select_mode = SongFormat.get(format, u'selectMode') if select_mode == SongFormatSelect.MultipleFiles: QtCore.QObject.connect(self.formatWidgets[format][u'addButton'], QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked) @@ -161,8 +161,7 @@ class SongImportForm(OpenLPWizard): self.formatLabel.setText(WizardStrings.FormatLabel) for format in SongFormat.get_format_list(): format_name, custom_combo_text, select_mode = SongFormat.get( - format, SongFormat.Name, SongFormat.ComboBoxText, - SongFormat.SelectMode) + format, u'name', u'comboBoxText', u'selectMode') combo_box_text = custom_combo_text if custom_combo_text \ else format_name self.formatComboBox.setItemText(format, combo_box_text) @@ -181,7 +180,7 @@ class SongImportForm(OpenLPWizard): translate('SongsPlugin.ImportWizardForm', f_label)) for format in self.disablableFormats: self.formatWidgets[format][u'disabledLabel'].setText( - SongFormat.get(format, SongFormat.DisabledLabelText)) + SongFormat.get(format, u'disabledLabelText')) self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('SongsPlugin.ImportWizardForm', @@ -227,8 +226,7 @@ class SongImportForm(OpenLPWizard): QtCore.QSettings().setValue(u'songs/last import type', format) select_mode, class_, error_msg = SongFormat.get(format, - SongFormat.SelectMode, SongFormat.Class, - SongFormat.InvalidSourceMsg) + u'selectMode', u'class', u'invalidSourceMsg') if select_mode == SongFormatSelect.MultipleFiles: import_source = self.getListOfFiles( self.formatWidgets[format][u'fileListWidget']) @@ -291,8 +289,8 @@ class SongImportForm(OpenLPWizard): def onBrowseButtonClicked(self): format = self.currentFormat - select_mode, format_name, filter = SongFormat.get(format, - SongFormat.SelectMode, SongFormat.Name, SongFormat.Filter) + select_mode, format_name, filter = SongFormat.get(format, u'selectMode', + u'name', u'filter') filepathEdit = self.formatWidgets[format][u'filepathEdit'] if select_mode == SongFormatSelect.SingleFile: self.getFileName(WizardStrings.OpenTypeFile % format_name, @@ -304,8 +302,8 @@ class SongImportForm(OpenLPWizard): def onAddButtonClicked(self): format = self.currentFormat select_mode, format_name, filter, custom_title = SongFormat.get(format, - SongFormat.SelectMode, SongFormat.Name, SongFormat.Filter, - SongFormat.GetFilesTitle) + u'selectMode', u'name', u'filter', + u'getFilesTitle') title = custom_title if custom_title \ else WizardStrings.OpenTypeFile % format_name if select_mode == SongFormatSelect.MultipleFiles: @@ -338,7 +336,7 @@ class SongImportForm(OpenLPWizard): last_import_type = 0 self.formatComboBox.setCurrentIndex(last_import_type) for format in SongFormat.get_format_list(): - select_mode = SongFormat.get(format, SongFormat.SelectMode) + select_mode = SongFormat.get(format, u'selectMode') if select_mode == SongFormatSelect.MultipleFiles: self.formatWidgets[format][u'fileListWidget'].clear() else: @@ -363,7 +361,7 @@ class SongImportForm(OpenLPWizard): the actual importing. """ source_format = self.currentFormat - select_mode = SongFormat.get(source_format, SongFormat.SelectMode) + select_mode = SongFormat.get(source_format, u'selectMode') if select_mode == SongFormatSelect.SingleFile: importer = self.plugin.importSongs(source_format, filename=unicode( self.formatWidgets[source_format][u'filepathEdit'].text())) @@ -397,8 +395,8 @@ class SongImportForm(OpenLPWizard): def addFileSelectItem(self): format = self.currentFormat - prefix, can_disable, select_mode = SongFormat.get(format, - SongFormat.Prefix, SongFormat.CanDisable, SongFormat.SelectMode) + prefix, can_disable, select_mode = SongFormat.get(format, u'prefix', + u'canDisable', u'selectMode') page = QtGui.QWidget() page.setObjectName(prefix + u'Page') if can_disable: @@ -505,8 +503,8 @@ class SongImportSourcePage(QtGui.QWizardPage): """ wizard = self.wizard() format = wizard.currentFormat - select_mode, format_available = SongFormat.get(format, - SongFormat.SelectMode, SongFormat.Availability) + select_mode, format_available = SongFormat.get(format, u'selectMode', + u'availability') if format_available: if select_mode == SongFormatSelect.MultipleFiles: if wizard.formatWidgets[format][u'fileListWidget'].count() > 0: diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 11169813b..870a65e60 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -81,45 +81,40 @@ class SongFormat(object): Required attributes for each song format: - ``Class`` + ``u'class'`` Import class, e.g. ``OpenLyricsImport`` - ``Name`` + ``u'name'`` Name of the format, e.g. ``u'OpenLyrics'`` - ``Prefix`` + ``u'prefix'`` Prefix for Qt objects. Use mixedCase, e.g. ``u'openLyrics'`` See ``SongImportForm.addFileSelectItem()`` Optional attributes for each song format: - ``CanDisable`` + ``u'canDisable'`` Whether song format importer is disablable. - ``Availability`` + ``u'availability'`` Whether song format importer is available. - ``SelectMode`` + ``u'selectMode'`` Whether format accepts single file, multiple files, or single folder (as per ``SongFormatSelect`` options). - ``Filter`` + ``u'filter'`` File extension filter for ``QFileDialog``. Optional/custom text Strings for ``SongImportForm`` widgets: - ``ComboBoxText`` - Combo box selector (default value is the format's ``Name``). - ``DisabledLabelText`` + ``u'comboBoxText'`` + Combo box selector (default value is the format's ``u'name'``). + ``u'disabledLabelText'`` Required for disablable song formats. - ``GetFilesTitle`` - Title for ``QFileDialog`` (default includes the format's ``Name``). - ``InvalidSourceMsg`` - Message displayed if ``Class.isValidSource()`` returns ``False``. + ``u'getFilesTitle'`` + Title for ``QFileDialog`` (default includes the format's ``u'name'``). + ``u'invalidSourceMsg'`` + Message displayed if ``isValidSource()`` returns ``False``. """ - # Enumeration of song formats and their attributes + # Song formats (ordered alphabetically after Generic) # * Numerical order of song formats is significant as it determines the # order used by formatComboBox. - # * Attribute ints are negative so they don't clash with song format ints. - # * Each group of attribute values increments by 10 to facilitate addition - # of more attributes in future. - - # Song formats (ordered alphabetically after Generic) Unknown = -1 OpenLyrics = 0 OpenLP2 = 1 @@ -138,158 +133,143 @@ class SongFormat(object): WordsOfWorship = 14 #CSV = 15 - # Required attributes - Class = -10 - Name = -11 - Prefix = -12 - # Optional attributes - CanDisable = -20 - Availability = -21 - SelectMode = -22 - Filter = -23 - # Optional/custom text values - ComboBoxText = -30 - DisabledLabelText = -31 - GetFilesTitle = -32 - InvalidSourceMsg = -33 - # Set optional attribute defaults - _defaults = { - CanDisable: False, - Availability: True, - SelectMode: SongFormatSelect.MultipleFiles, - Filter: u'', - ComboBoxText: None, - DisabledLabelText: u'', - GetFilesTitle: None, - InvalidSourceMsg: None + __defaults__ = { + u'canDisable': False, + u'availability': True, + u'selectMode': SongFormatSelect.MultipleFiles, + u'filter': u'', + u'comboBoxText': None, + u'disabledLabelText': u'', + u'getFilesTitle': None, + u'invalidSourceMsg': None } # Set attribute values for each Song Format - _attributes = { + __attributes__ = { OpenLyrics: { - Class: OpenLyricsImport, - Name: u'OpenLyrics', - Prefix: u'openLyrics', - Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + u'class': OpenLyricsImport, + u'name': u'OpenLyrics', + u'prefix': u'openLyrics', + u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'OpenLyrics Files'), - ComboBoxText: translate('SongsPlugin.ImportWizardForm', + u'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'OpenLyrics or OpenLP 2.0 Exported Song') }, OpenLP2: { - Class: OpenLPSongImport, - Name: UiStrings().OLPV2, - Prefix: u'openLP2', - SelectMode: SongFormatSelect.SingleFile, - Filter: u'%s (*.sqlite)' % (translate( + u'class': OpenLPSongImport, + u'name': UiStrings().OLPV2, + u'prefix': u'openLP2', + u'selectMode': SongFormatSelect.SingleFile, + u'filter': u'%s (*.sqlite)' % (translate( 'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) }, OpenLP1: { - Name: UiStrings().OLPV1, - Prefix: u'openLP1', - CanDisable: True, - SelectMode: SongFormatSelect.SingleFile, - Filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', + u'name': UiStrings().OLPV1, + u'prefix': u'openLP1', + u'canDisable': True, + u'selectMode': SongFormatSelect.SingleFile, + u'filter': u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', 'openlp.org v1.x Databases'), - DisabledLabelText: WizardStrings.NoSqlite + u'disabledLabelText': WizardStrings.NoSqlite }, Generic: { - Name: translate('SongsPlugin.ImportWizardForm', + u'name': translate('SongsPlugin.ImportWizardForm', 'Generic Document/Presentation'), - Prefix: u'generic', - CanDisable: True, - DisabledLabelText: translate('SongsPlugin.ImportWizardForm', + u'prefix': u'generic', + u'canDisable': True, + u'disabledLabelText': translate('SongsPlugin.ImportWizardForm', 'The generic document/presentation importer has been disabled ' 'because OpenLP cannot access OpenOffice or LibreOffice.'), - GetFilesTitle: translate('SongsPlugin.ImportWizardForm', + u'getFilesTitle': translate('SongsPlugin.ImportWizardForm', 'Select Document/Presentation Files') }, CCLI: { - Class: CCLIFileImport, - Name: u'CCLI/SongSelect', - Prefix: u'ccli', - Filter: u'%s (*.usr *.txt)' % translate( + u'class': CCLIFileImport, + u'name': u'CCLI/SongSelect', + u'prefix': u'ccli', + u'filter': u'%s (*.usr *.txt)' % translate( 'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files') }, DreamBeam: { - Class: DreamBeamImport, - Name: u'DreamBeam', - Prefix: u'dreamBeam', - Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + u'class': DreamBeamImport, + u'name': u'DreamBeam', + u'prefix': u'dreamBeam', + u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'DreamBeam Song Files') }, EasySlides: { - Class: EasySlidesImport, - Name: u'EasySlides', - Prefix: u'easySlides', - SelectMode: SongFormatSelect.SingleFile, - Filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', + u'class': EasySlidesImport, + u'name': u'EasySlides', + u'prefix': u'easySlides', + u'selectMode': SongFormatSelect.SingleFile, + u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm', 'EasySlides XML File') }, EasyWorship: { - Class: EasyWorshipSongImport, - Name: u'EasyWorship', - Prefix: u'ew', - SelectMode: SongFormatSelect.SingleFile, - Filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', + u'class': EasyWorshipSongImport, + u'name': u'EasyWorship', + u'prefix': u'ew', + u'selectMode': SongFormatSelect.SingleFile, + u'filter': u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm', 'EasyWorship Song Database') }, FoilPresenter: { - Class: FoilPresenterImport, - Name: u'Foilpresenter', - Prefix: u'foilPresenter', - Filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', - 'Foilpresenter Song Files') + u'class': FoilPresenterImport, + u'name': u'Foilpresenter', + u'prefix': u'foilPresenter', + u'filter': u'%s (*.foil)' % translate( + 'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files') }, OpenSong: { - Class: OpenSongImport, - Name: WizardStrings.OS, - Prefix: u'openSong' + u'class': OpenSongImport, + u'name': WizardStrings.OS, + u'prefix': u'openSong' }, PowerSong: { - Class: PowerSongImport, - Name: u'PowerSong 1.0', - Prefix: u'powerSong', - SelectMode: SongFormatSelect.SingleFolder, - InvalidSourceMsg: translate('SongsPlugin.ImportWizardForm', + u'class': PowerSongImport, + u'name': u'PowerSong 1.0', + u'prefix': u'powerSong', + u'selectMode': SongFormatSelect.SingleFolder, + u'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm', 'You need to specify a valid PowerSong 1.0 database folder.') }, SongBeamer: { - Class: SongBeamerImport, - Name: u'SongBeamer', - Prefix: u'songBeamer', - Filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', + u'class': SongBeamerImport, + u'name': u'SongBeamer', + u'prefix': u'songBeamer', + u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', 'SongBeamer Files') }, SongShowPlus: { - Class: SongShowPlusImport, - Name: u'SongShow Plus', - Prefix: u'songShowPlus', - Filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm', - 'SongShow Plus Song Files') + u'class': SongShowPlusImport, + u'name': u'SongShow Plus', + u'prefix': u'songShowPlus', + u'filter': u'%s (*.sbsong)' % translate( + 'SongsPlugin.ImportWizardForm', 'SongShow Plus Song Files') }, SongsOfFellowship: { - Name: u'Songs of Fellowship', - Prefix: u'songsOfFellowship', - CanDisable: True, - Filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', + u'name': u'Songs of Fellowship', + u'prefix': u'songsOfFellowship', + u'canDisable': True, + u'filter': u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', 'Songs Of Fellowship Song Files'), - DisabledLabelText: translate('SongsPlugin.ImportWizardForm', + u'disabledLabelText': translate('SongsPlugin.ImportWizardForm', 'The Songs of Fellowship importer has been disabled because ' 'OpenLP cannot access OpenOffice or LibreOffice.') }, WordsOfWorship: { - Class: WowImport, - Name: u'Words of Worship', - Prefix: u'wordsOfWorship', - Filter: u'%s (*.wsg *.wow-song)' % translate( + u'class': WowImport, + u'name': u'Words of Worship', + u'prefix': u'wordsOfWorship', + u'filter': u'%s (*.wsg *.wow-song)' % translate( 'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') # }, # CSV: { -# class_: CSVImport, -# name: WizardStrings.CSV, -# prefix: u'csv', -# select_mode: SongFormatSelect.SingleFile +# u'class': CSVImport, +# u'name': WizardStrings.CSV, +# u'prefix': u'csv', +# u'selectMode': SongFormatSelect.SingleFile } } @@ -333,16 +313,16 @@ class SongFormat(object): :>1: Return tuple of requested attribute values. """ if not attributes: - return SongFormat._attributes.get(format) + return SongFormat.__attributes__.get(format) elif len(attributes) == 1: - default = SongFormat._defaults.get(attributes[0]) - return SongFormat._attributes[format].get(attributes[0], + default = SongFormat.__defaults__.get(attributes[0]) + return SongFormat.__attributes__[format].get(attributes[0], default) else: values = [] for attr in attributes: - default = SongFormat._defaults.get(attr) - values.append(SongFormat._attributes[format].get(attr, + default = SongFormat.__defaults__.get(attr) + values.append(SongFormat.__attributes__[format].get(attr, default)) return tuple(values) @@ -351,16 +331,16 @@ class SongFormat(object): """ Set specified song format attribute to the supplied value. """ - SongFormat._attributes[format][attribute] = value + SongFormat.__attributes__[format][attribute] = value -SongFormat.set(SongFormat.OpenLP1, SongFormat.Availability, HAS_OPENLP1) +SongFormat.set(SongFormat.OpenLP1, u'availability', HAS_OPENLP1) if HAS_OPENLP1: - SongFormat.set(SongFormat.OpenLP1, SongFormat.Class, OpenLP1SongImport) -SongFormat.set(SongFormat.SongsOfFellowship, SongFormat.Availability, HAS_SOF) + SongFormat.set(SongFormat.OpenLP1, u'class', OpenLP1SongImport) +SongFormat.set(SongFormat.SongsOfFellowship, u'availability', HAS_SOF) if HAS_SOF: - SongFormat.set(SongFormat.SongsOfFellowship, SongFormat.Class, SofImport) -SongFormat.set(SongFormat.Generic, SongFormat.Availability, HAS_OOO) + SongFormat.set(SongFormat.SongsOfFellowship, u'class', SofImport) +SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO) if HAS_OOO: - SongFormat.set(SongFormat.Generic, SongFormat.Class, OooImport) + SongFormat.set(SongFormat.Generic, u'class', OooImport) __all__ = [u'SongFormat', u'SongFormatSelect'] diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index d22d2a26b..d3ac766f9 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -88,7 +88,7 @@ class PowerSongImport(SongImport): Receive either a list of files or a folder (unicode) to import. """ from importer import SongFormat - PS_string = SongFormat.get(SongFormat.PowerSong, SongFormat.Name) + PS_string = SongFormat.get(SongFormat.PowerSong, u'name') if isinstance(self.importSource, unicode): if os.path.isdir(self.importSource): dir = self.importSource diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index cff68f83e..d7b36414a 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -194,7 +194,7 @@ class SongsPlugin(Plugin): self.manager.save_object(song) def importSongs(self, format, **kwargs): - class_ = SongFormat.get(format, SongFormat.Class) + class_ = SongFormat.get(format, u'class') importer = class_(self.manager, **kwargs) importer.register(self.mediaItem.importWizard) return importer From 413cfc3782d74980346306d81f15c4f17ab9f483 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sat, 9 Jun 2012 07:03:18 +1000 Subject: [PATCH 38/46] Change description label. dump->convert. Added link to manual --- openlp/plugins/songs/forms/songimportform.py | 1 + openlp/plugins/songs/lib/importer.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index ad12a40b8..41aa97b7e 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -427,6 +427,7 @@ class SongImportForm(OpenLPWizard): descriptionLayout.addSpacerItem(descriptionSpacer) descriptionLabel = QtGui.QLabel(importWidget) descriptionLabel.setWordWrap(True) + descriptionLabel.setOpenExternalLinks(True) descriptionLabel.setObjectName(prefix + u'DescriptionLabel') descriptionLayout.addWidget(descriptionLabel) importLayout.addLayout(descriptionLayout) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 5f77c9ee8..19916b97d 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -278,9 +278,9 @@ class SongFormat(object): u'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'ZionWorx (CSV)'), u'descriptionText': translate('SongsPlugin.ImportWizardForm', - 'First dump your ZionWorx database to a CSV text file, using ' - 'freeware utility TdbDataX "TurboDB Data Exchange" from ' - 'dataWeb (see the User Manual).') + 'First convert your ZionWorx database to a CSV text file, as ' + 'explained in the User Manual.') # }, # CSV: { # u'class': CSVImport, From c4d3ba55596ed7325ff2f93a62160fd5f9ea8008 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sat, 9 Jun 2012 00:32:28 -0400 Subject: [PATCH 39/46] Fixed indenting --- openlp/core/ui/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 380423432..27fdb7c2e 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1192,7 +1192,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if Settings().value(u'advanced/save current plugin', QtCore.QVariant(False)).toBool(): Settings().setValue(u'advanced/current media plugin', - QtCore.QVariant(self.mediaToolBox.currentIndex())) + QtCore.QVariant(self.mediaToolBox.currentIndex())) # Call the cleanup method to shutdown plugins. log.info(u'cleanup plugins') self.pluginManager.finalise_plugins() From 67093ed65f81e50a1dc2c2fabbf0278a2258caaf Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sat, 9 Jun 2012 08:03:47 -0400 Subject: [PATCH 40/46] Added code to call superclass cancel --- openlp/core/ui/advancedtab.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 061d69a35..1c382cf5e 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -593,6 +593,7 @@ class AdvancedTab(SettingsTab): def cancel(self): # Dialogue was cancelled, remove any pending data path change. self.onDataDirectoryCancelButtonClicked() + SettingsTab.cancel(self) def serviceNameCheckBoxToggled(self, default_service_enabled): self.serviceNameDay.setEnabled(default_service_enabled) From fcb7328cde58fa99db1ac49e285266baaef60c35 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 9 Jun 2012 17:46:01 +0200 Subject: [PATCH 41/46] various clean ups --- openlp/core/lib/eventreceiver.py | 8 +-- openlp/core/lib/pluginmanager.py | 6 +- openlp/core/lib/renderer.py | 2 +- openlp/core/ui/maindisplay.py | 6 +- openlp/core/ui/media/mediacontroller.py | 5 +- openlp/core/ui/media/phononplayer.py | 57 +++++++++-------- openlp/core/ui/media/vlcplayer.py | 25 ++++---- openlp/core/ui/media/webkitplayer.py | 72 +++++++++++----------- openlp/core/ui/pluginform.py | 6 +- openlp/core/ui/servicemanager.py | 5 +- openlp/plugins/songs/forms/editsongform.py | 9 +-- 11 files changed, 95 insertions(+), 106 deletions(-) diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index f27171db4..91149d62c 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -268,7 +268,7 @@ class Receiver(object): <> )`` """ - eventreceiver = EventReceiver() + __eventreceiver__ = EventReceiver() @staticmethod def send_message(event, msg=None): @@ -281,11 +281,11 @@ class Receiver(object): ``msg`` Defaults to *None*. The message to send with the event. """ - Receiver.eventreceiver.send_message(event, msg) + Receiver.__eventreceiver__.send_message(event, msg) @staticmethod def get_receiver(): """ - Get the global ``eventreceiver`` instance. + Get the global ``__eventreceiver__`` instance. """ - return Receiver.eventreceiver + return Receiver.__eventreceiver__ diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 80160911d..084d567a0 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -41,13 +41,13 @@ class PluginManager(object): and executes all the hooks, as and when necessary. """ log.info(u'Plugin manager loaded') - + __instance__ = None @staticmethod def get_instance(): """ Obtain a single instance of class. """ - return PluginManager.instance + return PluginManager.__instance__ def __init__(self, plugin_dir): """ @@ -58,7 +58,7 @@ class PluginManager(object): The directory to search for plugins. """ log.info(u'Plugin manager Initialising') - PluginManager.instance = self + PluginManager.__instance__ = self if not plugin_dir in sys.path: log.debug(u'Inserting %s into sys.path', plugin_dir) sys.path.insert(0, plugin_dir) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 74cdafd82..6ce51ab60 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -303,7 +303,7 @@ class Renderer(object): try: text_to_render, text = \ text.split(u'\n[---]\n', 1) - except: + except ValueError: text_to_render = text.split(u'\n[---]\n')[0] text = u'' text_to_render, raw_tags, html_tags = \ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index b642240a3..275b7a52f 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -100,9 +100,8 @@ class Display(QtGui.QGraphicsView): self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) - def resizeEvent(self, ev): - self.webView.setGeometry(0, 0, - self.width(), self.height()) + def resizeEvent(self, event): + self.webView.setGeometry(0, 0, self.width(), self.height()) def isWebLoaded(self): """ @@ -120,7 +119,6 @@ class MainDisplay(Display): Display.__init__(self, parent, live, controller) self.imageManager = imageManager self.screens = ScreenList() - self.plugins = PluginManager.get_instance().plugins self.rebuildCSS = False self.hideMode = None self.override = {} diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index b7356fcf5..493208697 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -335,8 +335,7 @@ class MediaController(object): if controller.isLive and \ (QtCore.QSettings().value(u'general/auto unblank', QtCore.QVariant(False)).toBool() or \ - controller.media_info.is_background == True) or \ - controller.isLive == False: + controller.media_info.is_background) or not controller.isLive: if not self.video_play([controller]): critical_error_message_box( translate('MediaPlugin.MediaItem', 'Unsupported File'), @@ -495,7 +494,7 @@ class MediaController(object): return controller = self.parent.liveController for display in self.curDisplayMediaPlayer.keys(): - if display.controller != controller or \ + if display.controller != controller or \ self.curDisplayMediaPlayer[display].state != MediaState.Playing: continue self.curDisplayMediaPlayer[display].pause(display) diff --git a/openlp/core/ui/media/phononplayer.py b/openlp/core/ui/media/phononplayer.py index c366fe339..9bc739f65 100644 --- a/openlp/core/ui/media/phononplayer.py +++ b/openlp/core/ui/media/phononplayer.py @@ -38,21 +38,21 @@ from openlp.core.ui.media import MediaState log = logging.getLogger(__name__) ADDITIONAL_EXT = { - u'audio/ac3': [u'.ac3'], - u'audio/flac': [u'.flac'], - u'audio/x-m4a': [u'.m4a'], - u'audio/midi': [u'.mid', u'.midi'], - u'audio/x-mp3': [u'.mp3'], - u'audio/mpeg': [u'.mp3', u'.mp2', u'.mpga', u'.mpega', u'.m4a'], - u'audio/qcelp': [u'.qcp'], - u'audio/x-wma': [u'.wma'], - u'audio/x-ms-wma': [u'.wma'], - u'video/x-flv': [u'.flv'], - u'video/x-matroska': [u'.mpv', u'.mkv'], - u'video/x-wmv': [u'.wmv'], - u'video/x-mpg': [u'.mpg'], - u'video/mpeg' : [u'.mp4', u'.mts'], - u'video/x-ms-wmv': [u'.wmv']} + u'audio/ac3': [u'.ac3'], + u'audio/flac': [u'.flac'], + u'audio/x-m4a': [u'.m4a'], + u'audio/midi': [u'.mid', u'.midi'], + u'audio/x-mp3': [u'.mp3'], + u'audio/mpeg': [u'.mp3', u'.mp2', u'.mpga', u'.mpega', u'.m4a'], + u'audio/qcelp': [u'.qcp'], + u'audio/x-wma': [u'.wma'], + u'audio/x-ms-wma': [u'.wma'], + u'video/x-flv': [u'.flv'], + u'video/x-matroska': [u'.mpv', u'.mkv'], + u'video/x-wmv': [u'.wmv'], + u'video/x-mpg': [u'.mpg'], + u'video/mpeg' : [u'.mp4', u'.mts'], + u'video/x-ms-wmv': [u'.wmv']} class PhononPlayer(MediaPlayer): @@ -101,7 +101,7 @@ class PhononPlayer(MediaPlayer): display.mediaObject = Phonon.MediaObject(display) Phonon.createPath(display.mediaObject, display.phononWidget) if display.hasAudio: - display.audio = Phonon.AudioOutput( \ + display.audio = Phonon.AudioOutput( Phonon.VideoCategory, display.mediaObject) Phonon.createPath(display.mediaObject, display.audio) display.phononWidget.raise_() @@ -148,18 +148,17 @@ class PhononPlayer(MediaPlayer): controller.media_info.start_time > 0: start_time = controller.media_info.start_time display.mediaObject.play() - if self.media_state_wait(display, Phonon.PlayingState): - if start_time > 0: - self.seek(display, controller.media_info.start_time*1000) - self.volume(display, controller.media_info.volume) - controller.media_info.length = \ - int(display.mediaObject.totalTime()/1000) - controller.seekSlider.setMaximum(controller.media_info.length*1000) - self.state = MediaState.Playing - display.phononWidget.raise_() - return True - else: + if not self.media_state_wait(display, Phonon.PlayingState): return False + if start_time > 0: + self.seek(display, controller.media_info.start_time * 1000) + self.volume(display, controller.media_info.volume) + controller.media_info.length = \ + int(display.mediaObject.totalTime() / 1000) + controller.seekSlider.setMaximum(controller.media_info.length * 1000) + self.state = MediaState.Playing + display.phononWidget.raise_() + return True def pause(self, display): display.mediaObject.pause() @@ -198,9 +197,9 @@ class PhononPlayer(MediaPlayer): controller = display.controller if controller.media_info.end_time > 0: if display.mediaObject.currentTime() > \ - controller.media_info.end_time*1000: + controller.media_info.end_time * 1000: self.stop(display) self.set_visible(display, False) if not controller.seekSlider.isSliderDown(): - controller.seekSlider.setSliderPosition( \ + controller.seekSlider.setSliderPosition( display.mediaObject.currentTime()) diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 6d26f3b34..75399574a 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -62,7 +62,7 @@ if VLC_AVAILABLE: log.debug(u'VLC could not be loaded: %s' % version) AUDIO_EXT = [ - u'*.mp3' + u'*.mp3' , u'*.wav' , u'*.ogg' ] @@ -130,9 +130,9 @@ class VlcPlayer(MediaPlayer): # this is platform specific! # you have to give the id of the QFrame (or similar object) to # vlc, different platforms have different functions for this - if sys.platform == "win32": # for Windows + if sys.platform == "win32": display.vlcMediaPlayer.set_hwnd(int(display.vlcWidget.winId())) - elif sys.platform == "darwin": # for MacOS + elif sys.platform == "darwin": display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId())) else: # for Linux using the X Server @@ -181,17 +181,16 @@ class VlcPlayer(MediaPlayer): if controller.media_info.start_time > 0: start_time = controller.media_info.start_time display.vlcMediaPlayer.play() - if self.media_state_wait(display, vlc.State.Playing): - if start_time > 0: - self.seek(display, controller.media_info.start_time * 1000) - controller.media_info.length = \ - int(display.vlcMediaPlayer.get_media().get_duration() / 1000) - controller.seekSlider.setMaximum(controller.media_info.length * 1000) - self.state = MediaState.Playing - display.vlcWidget.raise_() - return True - else: + if not self.media_state_wait(display, vlc.State.Playing): return False + if start_time > 0: + self.seek(display, controller.media_info.start_time * 1000) + controller.media_info.length = \ + int(display.vlcMediaPlayer.get_media().get_duration() / 1000) + controller.seekSlider.setMaximum(controller.media_info.length * 1000) + self.state = MediaState.Playing + display.vlcWidget.raise_() + return True def pause(self, display): if display.vlcMedia.get_state() != vlc.State.Playing: diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py index e3713d7ae..7df376187 100644 --- a/openlp/core/ui/media/webkitplayer.py +++ b/openlp/core/ui/media/webkitplayer.py @@ -227,33 +227,33 @@ FLASH_HTML = u""" """ VIDEO_EXT = [ - u'*.3gp' - , u'*.3gpp' - , u'*.3g2' - , u'*.3gpp2' - , u'*.aac' - , u'*.flv' - , u'*.f4a' - , u'*.f4b' - , u'*.f4p' - , u'*.f4v' - , u'*.mov' - , u'*.m4a' - , u'*.m4b' - , u'*.m4p' - , u'*.m4v' - , u'*.mkv' - , u'*.mp4' - , u'*.ogv' - , u'*.webm' - , u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi' - , u'*.swf' - ] + u'*.3gp' + , u'*.3gpp' + , u'*.3g2' + , u'*.3gpp2' + , u'*.aac' + , u'*.flv' + , u'*.f4a' + , u'*.f4b' + , u'*.f4p' + , u'*.f4v' + , u'*.mov' + , u'*.m4a' + , u'*.m4b' + , u'*.m4p' + , u'*.m4v' + , u'*.mkv' + , u'*.mp4' + , u'*.ogv' + , u'*.webm' + , u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi' + , u'*.swf' + ] AUDIO_EXT = [ - u'*.mp3' - , u'*.ogg' - ] + u'*.mp3' + , u'*.ogg' + ] class WebkitPlayer(MediaPlayer): @@ -339,7 +339,7 @@ class WebkitPlayer(MediaPlayer): else: display.frame.evaluateJavaScript(u'show_video("play");') if start_time > 0: - self.seek(display, controller.media_info.start_time*1000) + self.seek(display, controller.media_info.start_time * 1000) # TODO add playing check and get the correct media length controller.media_info.length = length self.state = MediaState.Playing @@ -375,11 +375,11 @@ class WebkitPlayer(MediaPlayer): controller = display.controller if controller.media_info.is_flash: seek = seekVal - display.frame.evaluateJavaScript( \ + display.frame.evaluateJavaScript( u'show_flash("seek", null, null, "%s");' % (seek)) else: - seek = float(seekVal)/1000 - display.frame.evaluateJavaScript( \ + seek = float(seekVal) / 1000 + display.frame.evaluateJavaScript( u'show_video("seek", null, null, null, "%f");' % (seek)) def reset(self, display): @@ -406,24 +406,24 @@ class WebkitPlayer(MediaPlayer): def update_ui(self, display): controller = display.controller if controller.media_info.is_flash: - currentTime = display.frame.evaluateJavaScript( \ + currentTime = display.frame.evaluateJavaScript( u'show_flash("currentTime");').toInt()[0] - length = display.frame.evaluateJavaScript( \ + length = display.frame.evaluateJavaScript( u'show_flash("length");').toInt()[0] else: - if display.frame.evaluateJavaScript( \ + if display.frame.evaluateJavaScript( u'show_video("isEnded");').toString() == 'true': self.stop(display) - (currentTime, ok) = display.frame.evaluateJavaScript( \ + (currentTime, ok) = display.frame.evaluateJavaScript( u'show_video("currentTime");').toFloat() # check if conversion was ok and value is not 'NaN' if ok and currentTime != float('inf'): - currentTime = int(currentTime*1000) - (length, ok) = display.frame.evaluateJavaScript( \ + currentTime = int(currentTime * 1000) + (length, ok) = display.frame.evaluateJavaScript( u'show_video("length");').toFloat() # check if conversion was ok and value is not 'NaN' if ok and length != float('inf'): - length = int(length*1000) + length = int(length * 1000) if currentTime > 0: controller.media_info.length = length controller.seekSlider.setMaximum(length) diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 435181568..f520bb235 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -102,9 +102,9 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): self.versionNumberLabel.setText(self.activePlugin.version) self.aboutTextBrowser.setHtml(self.activePlugin.about()) self.programaticChange = True - status = 1 + status = PluginStatus.Active if self.activePlugin.status == PluginStatus.Active: - status = 0 + status = PluginStatus.Inactive self.statusComboBox.setCurrentIndex(status) self.statusComboBox.setEnabled(True) self.programaticChange = False @@ -129,7 +129,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): def onStatusComboBoxChanged(self, status): if self.programaticChange or status == PluginStatus.Disabled: return - if status == 0: + if status == PluginStatus.Inactive: Receiver.send_message(u'cursor_busy') self.activePlugin.toggleStatus(PluginStatus.Active) Receiver.send_message(u'cursor_normal') diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 30567f2d2..3a47d6db8 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -580,10 +580,7 @@ class ServiceManager(QtGui.QWidget): return self.saveFileAs() self.mainwindow.addRecentFile(path_file_name) self.setModified(False) - try: - delete_file(temp_file_name) - except: - pass + delete_file(temp_file_name) return success def saveFileAs(self): diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 5dea45625..226d8baa1 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -172,17 +172,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def loadThemes(self, theme_list): self.themeComboBox.clear() self.themeComboBox.addItem(u'') - self.themes = [] - for theme in theme_list: - self.themeComboBox.addItem(theme) - self.themes.append(theme) + self.themes = theme_list + self.themeComboBox.addItems(theme_list) set_case_insensitive_completer(self.themes, self.themeComboBox) def loadMediaFiles(self): self.audioAddFromMediaButton.setVisible(False) for plugin in self.parent().pluginManager.plugins: - if plugin.name == u'media' and \ - plugin.status == PluginStatus.Active: + if plugin.name == u'media' and plugin.status == PluginStatus.Active: self.audioAddFromMediaButton.setVisible(True) self.mediaForm.populateFiles( plugin.mediaItem.getList(MediaType.Audio)) From 8365d6f5895e8df71a8bbddcc8b0c6f662610622 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sun, 10 Jun 2012 10:29:50 -0400 Subject: [PATCH 42/46] Fixed some cosmedics --- openlp/core/__init__.py | 4 ++-- openlp/core/lib/settings.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 98b66364c..1f2c0a2c3 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -276,8 +276,8 @@ def main(args=None): u'..', u'..', u'Data',)) log.info(u'Data path: %s' % data_path) # Point to our data path - portable_settings.setValue(u'advanced/data path',data_path) - portable_settings.setValue(u'advanced/is portable',True) + portable_settings.setValue(u'advanced/data path', data_path) + portable_settings.setValue(u'advanced/is portable', True) portable_settings.sync() else: app.setApplicationName(u'OpenLP') diff --git a/openlp/core/lib/settings.py b/openlp/core/lib/settings.py index 158f06f7b..115d7a8f0 100644 --- a/openlp/core/lib/settings.py +++ b/openlp/core/lib/settings.py @@ -59,7 +59,7 @@ class Settings(QtCore.QSettings): def __init__(self, *args): if not args and Settings.filePath and (Settings.defaultFormat() == - Settings.IniFormat): + Settings.IniFormat): QtCore.QSettings.__init__(self, Settings.filePath, Settings.IniFormat) else: From c30657330965f0f8d727f054ef9616d658055270 Mon Sep 17 00:00:00 2001 From: Stevan Pettit Date: Sun, 10 Jun 2012 15:53:46 -0400 Subject: [PATCH 43/46] Minor changes to logging, variable name --- openlp/core/__init__.py | 4 ++-- openlp/core/lib/settings.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 1f2c0a2c3..b4da78e83 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -268,13 +268,13 @@ def main(args=None): portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', u'..', u'Data', u'OpenLP.ini')) # Make this our settings file - log.info(u'INI file: %s' % portable_settings_file) + log.info(u'INI file: %s', portable_settings_file) Settings.setFilename(portable_settings_file) portable_settings = Settings() # Set our data path data_path = os.path.abspath(os.path.join(app_path, u'..', u'..', u'Data',)) - log.info(u'Data path: %s' % data_path) + log.info(u'Data path: %s', data_path) # Point to our data path portable_settings.setValue(u'advanced/data path', data_path) portable_settings.setValue(u'advanced/is portable', True) diff --git a/openlp/core/lib/settings.py b/openlp/core/lib/settings.py index 115d7a8f0..5f012c0d1 100644 --- a/openlp/core/lib/settings.py +++ b/openlp/core/lib/settings.py @@ -46,7 +46,7 @@ class Settings(QtCore.QSettings): object for accessing settings stored in that Ini file. """ - filePath = u'' + __filePath = u'' @staticmethod def setFilename(iniFile): @@ -55,12 +55,12 @@ class Settings(QtCore.QSettings): Does not affect existing Settings objects. """ - Settings.filePath = iniFile + Settings.__filePath = iniFile def __init__(self, *args): - if not args and Settings.filePath and (Settings.defaultFormat() == + if not args and Settings.__filePath and (Settings.defaultFormat() == Settings.IniFormat): - QtCore.QSettings.__init__(self, Settings.filePath, + QtCore.QSettings.__init__(self, Settings.__filePath, Settings.IniFormat) else: QtCore.QSettings.__init__(self, *args) From 913b0433f60df96d92d7957846bbf85b08d8ccf0 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Sun, 10 Jun 2012 22:45:02 +0100 Subject: [PATCH 44/46] This update is a tidy up of the code that fixed bug #927473 Changes are made due to the following issues: - the code assumed that exception OperationalError would only be thrown by mySQL temporarily disappearing. However, other dbms can throw this exception and usually for errors that mean a retry will also fail. - the code repeated the actual code of the method within the exception handler. This means code duplication and also that any new exceptions are not handled by the same exception handler so for example their transaction will not get rolled back. - not all potential dbms exceptions were caught and so in some cases the database transaction was not rolled back The solution is to retry transactions where an OperationalError is thrown. Currently these are retried up to 3 times before the error is logged and the method returns false. By retrying the transaction we ensure that the same transaction code with the same exception handlers is used each time. An additional catchall exception has been added where there is a transaction to ensure that it is rolled back. As with the OperationError this throws the exception back up the stack. --- openlp/core/lib/db.py | 267 +++++++++++++++++++++++------------------- 1 file changed, 145 insertions(+), 122 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index e097983eb..8f24288ba 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -238,27 +238,30 @@ class Manager(object): ``commit`` Commit the session with this object """ - try: - self.session.add(object_instance) - if commit: - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue - "MySQL has gone away"') - self.session.rollback() - self.session.add(object_instance) - if commit: - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Object save failed') - return False + for tryCount in range(3): + try: + self.session.add(object_instance) + if commit: + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue - "MySQL has gone away"') + self.session.rollback() + if tryCount >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object list save failed') + return False + except: + self.session.rollback() + raise def save_objects(self, object_list, commit=True): """ @@ -270,27 +273,30 @@ class Manager(object): ``commit`` Commit the session with this object """ - try: - self.session.add_all(object_list) - if commit: - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - self.session.add_all(object_list) - if commit: - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Object list save failed') - return False + for tryCount in range(3): + try: + self.session.add_all(object_list) + if commit: + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if tryCount >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object list save failed') + return False + except: + self.session.rollback() + raise def get_object(self, object_class, key=None): """ @@ -305,15 +311,18 @@ class Manager(object): if not key: return object_class() else: - try: - return self.session.query(object_class).get(key) - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return self.session.query(object_class).get(key) + for tryCount in range(3): + try: + return self.session.query(object_class).get(key) + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if tryCount >= 2: + raise def get_object_filtered(self, object_class, filter_clause): """ @@ -325,15 +334,18 @@ class Manager(object): ``filter_clause`` The criteria to select the object by """ - try: - return self.session.query(object_class).filter(filter_clause).first() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return self.session.query(object_class).filter(filter_clause).first() + for tryCount in range(3): + try: + return self.session.query(object_class).filter(filter_clause).first() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if tryCount >= 2: + raise def get_all_objects(self, object_class, filter_clause=None, order_by_ref=None): @@ -357,15 +369,18 @@ class Manager(object): query = query.order_by(*order_by_ref) elif order_by_ref is not None: query = query.order_by(order_by_ref) - try: - return query.all() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return query.all() + for tryCount in range(3): + try: + return query.all() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if tryCount >= 2: + raise def get_object_count(self, object_class, filter_clause=None): """ @@ -381,15 +396,18 @@ class Manager(object): query = self.session.query(object_class) if filter_clause is not None: query = query.filter(filter_clause) - try: - return query.count() - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - return query.count() + for tryCount in range(3): + try: + return query.count() + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + if tryCount >= 2: + raise def delete_object(self, object_class, key): """ @@ -403,25 +421,29 @@ class Manager(object): """ if key != 0: object_instance = self.get_object(object_class, key) - try: - self.session.delete(object_instance) - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - self.session.delete(object_instance) - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete object') - return False + for tryCount in range(3): + try: + self.session.delete(object_instance) + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if tryCount >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete object') + return False + except: + self.session.rollback() + raise else: return True @@ -439,31 +461,32 @@ class Manager(object): The filter governing selection of objects to return. Defaults to None. """ - try: - query = self.session.query(object_class) - if filter_clause is not None: - query = query.filter(filter_clause) - query.delete(synchronize_session=False) - self.session.commit() - self.is_dirty = True - return True - except OperationalError: - # This exception clause is for users running MySQL which likes - # to terminate connections on its own without telling anyone. - # See bug #927473 - log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - self.session.rollback() - query = self.session.query(object_class) - if filter_clause is not None: - query = query.filter(filter_clause) - query.delete(synchronize_session=False) - self.session.commit() - self.is_dirty = True - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete %s records', object_class.__name__) - return False + for tryCount in range(3): + try: + query = self.session.query(object_class) + if filter_clause is not None: + query = query.filter(filter_clause) + query.delete(synchronize_session=False) + self.session.commit() + self.is_dirty = True + return True + except OperationalError: + # This exception clause is for users running MySQL which likes + # to terminate connections on its own without telling anyone. + # See bug #927473 + # However, other dbms can raise it, usually in a non-recoverable + # way. So we only retry 3 times. + log.exception(u'Probably a MySQL issue, "MySQL has gone away"') + self.session.rollback() + if tryCount >= 2: + raise + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete %s records', object_class.__name__) + return False + except: + self.session.rollback() + raise def finalise(self): """ From b9b0d83a00a1d99d7605fdc5f71fe73912a7d86d Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 11 Jun 2012 15:11:53 +0100 Subject: [PATCH 45/46] renamed tryCount local variable to try_count --- openlp/core/lib/db.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 8f24288ba..e4cbcea0f 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -238,7 +238,7 @@ class Manager(object): ``commit`` Commit the session with this object """ - for tryCount in range(3): + for try_count in range(3): try: self.session.add(object_instance) if commit: @@ -253,7 +253,7 @@ class Manager(object): # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue - "MySQL has gone away"') self.session.rollback() - if tryCount >= 2: + if try_count >= 2: raise except InvalidRequestError: self.session.rollback() @@ -273,7 +273,7 @@ class Manager(object): ``commit`` Commit the session with this object """ - for tryCount in range(3): + for try_count in range(3): try: self.session.add_all(object_list) if commit: @@ -288,7 +288,7 @@ class Manager(object): # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') self.session.rollback() - if tryCount >= 2: + if try_count >= 2: raise except InvalidRequestError: self.session.rollback() @@ -311,7 +311,7 @@ class Manager(object): if not key: return object_class() else: - for tryCount in range(3): + for try_count in range(3): try: return self.session.query(object_class).get(key) except OperationalError: @@ -321,7 +321,7 @@ class Manager(object): # However, other dbms can raise it, usually in a non-recoverable # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - if tryCount >= 2: + if try_count >= 2: raise def get_object_filtered(self, object_class, filter_clause): @@ -334,7 +334,7 @@ class Manager(object): ``filter_clause`` The criteria to select the object by """ - for tryCount in range(3): + for try_count in range(3): try: return self.session.query(object_class).filter(filter_clause).first() except OperationalError: @@ -344,7 +344,7 @@ class Manager(object): # However, other dbms can raise it, usually in a non-recoverable # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - if tryCount >= 2: + if try_count >= 2: raise def get_all_objects(self, object_class, filter_clause=None, @@ -369,7 +369,7 @@ class Manager(object): query = query.order_by(*order_by_ref) elif order_by_ref is not None: query = query.order_by(order_by_ref) - for tryCount in range(3): + for try_count in range(3): try: return query.all() except OperationalError: @@ -379,7 +379,7 @@ class Manager(object): # However, other dbms can raise it, usually in a non-recoverable # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - if tryCount >= 2: + if try_count >= 2: raise def get_object_count(self, object_class, filter_clause=None): @@ -396,7 +396,7 @@ class Manager(object): query = self.session.query(object_class) if filter_clause is not None: query = query.filter(filter_clause) - for tryCount in range(3): + for try_count in range(3): try: return query.count() except OperationalError: @@ -406,7 +406,7 @@ class Manager(object): # However, other dbms can raise it, usually in a non-recoverable # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') - if tryCount >= 2: + if try_count >= 2: raise def delete_object(self, object_class, key): @@ -421,7 +421,7 @@ class Manager(object): """ if key != 0: object_instance = self.get_object(object_class, key) - for tryCount in range(3): + for try_count in range(3): try: self.session.delete(object_instance) self.session.commit() @@ -435,7 +435,7 @@ class Manager(object): # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') self.session.rollback() - if tryCount >= 2: + if try_count >= 2: raise except InvalidRequestError: self.session.rollback() @@ -461,7 +461,7 @@ class Manager(object): The filter governing selection of objects to return. Defaults to None. """ - for tryCount in range(3): + for try_count in range(3): try: query = self.session.query(object_class) if filter_clause is not None: @@ -478,7 +478,7 @@ class Manager(object): # way. So we only retry 3 times. log.exception(u'Probably a MySQL issue, "MySQL has gone away"') self.session.rollback() - if tryCount >= 2: + if try_count >= 2: raise except InvalidRequestError: self.session.rollback() From 4e0b9c30d3e3a93c27193a8043aa73038f5a2ae9 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Tue, 12 Jun 2012 23:25:31 +0200 Subject: [PATCH 46/46] Fixed bug #991150: BibleGateway has new HTML, so we need to change our parsing. This now parses the new HTML correctly. Fixes: https://launchpad.net/bugs/991150 --- openlp/plugins/bibles/lib/http.py | 163 ++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 54 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index fb79b26e1..3bf3e5397 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -43,6 +43,15 @@ from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \ Book +UGLY_CHARS = { + u'\u2014': u' - ', + u'\u2018': u'\'', + u'\u2019': u'\'', + u'\u201c': u'"', + u'\u201d': u'"', + u' ': u' ' +} + log = logging.getLogger(__name__) class BGExtract(object): @@ -54,6 +63,103 @@ class BGExtract(object): self.proxy_url = proxy_url socket.setdefaulttimeout(30) + def _remove_elements(self, parent, tag, class_=None): + """ + Remove a particular element from the BeautifulSoup tree. + + ``parent`` + The element from which items need to be removed. + + ``tag`` + A string of the tab type, e.g. "div" + + ``class_`` + An HTML class attribute for further qualification. + """ + if class_: + all_tags = parent.findAll(tag, class_) + else: + all_tags = parent.findAll(tag) + for element in all_tags: + element.extract() + + def _extract_verse(self, tag): + """ + Extract a verse (or part of a verse) from a tag. + + ``tag`` + The BeautifulSoup Tag element with the stuff we want. + """ + if isinstance(tag, NavigableString): + return None, unicode(tag) + elif tag.get('class') == 'versenum': + verse = unicode(tag.string)\ + .replace('[', '').replace(']', '').strip() + return verse, None + elif tag.get('class') == 'chapternum': + verse = '1' + return verse, None + else: + verse, text = None, '' + for child in tag.contents: + c_verse, c_text = self._extract_verse(child) + if c_verse: + verse = c_verse + if text and c_text: + text += c_text + elif c_text is not None: + text = c_text + return verse, text + + def _clean_soup(self, tag): + """ + Remove all the rubbish from the HTML page. + + ``tag`` + The base tag within which we want to remove stuff. + """ + self._remove_elements(tag, 'sup', 'crossreference') + self._remove_elements(tag, 'sup', 'footnote') + self._remove_elements(tag, 'div', 'footnotes') + self._remove_elements(tag, 'div', 'crossrefs') + self._remove_elements(tag, 'h3') + + def _extract_verses(self, tags): + """ + Extract all the verses from a pre-prepared list of HTML tags. + + ``tags`` + A list of BeautifulSoup Tag elements. + """ + verses = [] + tags = tags[::-1] + current_text = '' + for tag in tags: + verse, text = None, '' + for child in tag.contents: + c_verse, c_text = self._extract_verse(child) + if c_verse: + verse = c_verse + if text and c_text: + text += c_text + elif c_text is not None: + text = c_text + if not verse: + current_text = text + ' ' + current_text + else: + text += ' ' + current_text + current_text = '' + if text: + for old, new in UGLY_CHARS.iteritems(): + text = text.replace(old, new) + text = u' '.join(text.split()) + if verse and text: + verses.append((int(verse.strip()), text)) + verse_list = {} + for verse, text in verses[::-1]: + verse_list[verse] = text + return verse_list + def get_bible_chapter(self, version, book_name, chapter): """ Access and decode Bibles via the BibleGateway website. @@ -80,60 +186,9 @@ class BGExtract(object): if not soup: return None Receiver.send_message(u'openlp_process_events') - footnotes = soup.findAll(u'sup', u'footnote') - if footnotes: - for footnote in footnotes: - footnote.extract() - crossrefs = soup.findAll(u'sup', u'xref') - if crossrefs: - for crossref in crossrefs: - crossref.extract() - headings = soup.findAll(u'h5') - if headings: - for heading in headings: - heading.extract() - chapter_notes = soup.findAll('div', 'footnotes') - if chapter_notes: - log.debug('Found chapter notes') - for note in chapter_notes: - note.extract() - note_comments = soup.findAll(text=u'end of footnotes') - if note_comments: - for comment in note_comments: - comment.extract() - cleanup = [(re.compile('\s+'), lambda match: ' ')] - verses = BeautifulSoup(str(soup), markupMassage=cleanup) - verse_list = {} - # Cater for inconsistent mark up in the first verse of a chapter. - first_verse = verses.find(u'versenum') - if first_verse and first_verse.contents: - verse_list[1] = unicode(first_verse.contents[0]) - for verse in verses(u'sup', u'versenum'): - raw_verse_num = verse.next - clean_verse_num = 0 - # Not all verses exist in all translations and may or may not be - # represented by a verse number. If they are not fine, if they are - # it will probably be in a format that breaks int(). We will then - # have no idea what garbage may be sucked in to the verse text so - # if we do not get a clean int() then ignore the verse completely. - try: - clean_verse_num = int(str(raw_verse_num)) - except ValueError: - log.warn(u'Illegal verse number in %s %s %s:%s', - version, book_name, chapter, unicode(raw_verse_num)) - if clean_verse_num: - verse_text = raw_verse_num.next - part = raw_verse_num.next.next - while not (isinstance(part, Tag) and part.attrMap and - part.attrMap[u'class'] == u'versenum'): - # While we are still in the same verse grab all the text. - if isinstance(part, NavigableString): - verse_text = verse_text + part - if isinstance(part.next, Tag) and part.next.name == u'div': - # Run out of verses so stop. - break - part = part.next - verse_list[clean_verse_num] = unicode(verse_text) + div = soup.find('div', 'result-text-style-normal') + self._clean_soup(div) + verse_list = self._extract_verses(div.findAll('span', 'text')) if not verse_list: log.debug(u'No content found in the BibleGateway response.') send_error_message(u'parse')