diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index c8239df57..4136e9f64 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -885,7 +885,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): export_file_name += u'.conf' temp_file = os.path.join(unicode(gettempdir(), get_filesystem_encoding()), u'openlp', u'exportConf.tmp') - self.saveSettings() + self.save_settings() setting_sections = [] # Add main sections. setting_sections.extend([self.generalSettingsSection]) @@ -1051,7 +1051,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.plugin_manager.finalise_plugins() if save_settings: # Save settings - self.saveSettings() + self.save_settings() # Check if we need to change the data directory if self.new_data_path: self.changeDataDirectory() @@ -1202,7 +1202,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.controlSplitter.restoreState(settings.value(u'main window splitter geometry')) settings.endGroup() - def saveSettings(self): + def save_settings(self): """ Save the main window settings. """ diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py index 645a2921f..83f2d298f 100644 --- a/openlp/core/ui/serviceitemeditdialog.py +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -58,9 +58,9 @@ class Ui_ServiceItemEditDialog(object): click=serviceItemEditDialog.on_delete_button_clicked) self.button_layout.addWidget(self.delete_button) self.button_layout.addStretch() - self.up_button = create_button(serviceItemEditDialog, u'upButton', role=u'up', + self.up_button = create_button(serviceItemEditDialog, u'up_button', role=u'up', click=serviceItemEditDialog.on_up_button_clicked) - self.down_button = create_button(serviceItemEditDialog, u'downButton', role=u'down', + self.down_button = create_button(serviceItemEditDialog, u'down_button', role=u'down', click=serviceItemEditDialog.on_down_button_clicked) self.button_layout.addWidget(self.up_button) self.button_layout.addWidget(self.down_button) diff --git a/openlp/plugins/bibles/forms/editbibledialog.py b/openlp/plugins/bibles/forms/editbibledialog.py index aecfb7a98..b45bb2751 100644 --- a/openlp/plugins/bibles/forms/editbibledialog.py +++ b/openlp/plugins/bibles/forms/editbibledialog.py @@ -65,7 +65,7 @@ class Ui_EditBibleDialog(object): self.copyrightLabel = QtGui.QLabel(self.licenseDetailsGroupBox) self.copyrightLabel.setObjectName(u'copyrightLabel') self.copyrightEdit = QtGui.QLineEdit(self.licenseDetailsGroupBox) - self.copyrightEdit.setObjectName(u'copyrightEdit') + self.copyrightEdit.setObjectName(u'copyright_edit') self.copyrightLabel.setBuddy(self.copyrightEdit) self.licenseDetailsLayout.addRow(self.copyrightLabel, self.copyrightEdit) self.permissionsLabel = QtGui.QLabel(self.licenseDetailsGroupBox) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 9763f249d..f57da2ba0 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -55,7 +55,7 @@ There are two acceptable formats of the verses file. They are: or "Genesis",1,2,"And the earth was without form, and void; and...." -All CSV files are expected to use a comma (',') as the delimeter and double +All CSV files are expected to use a comma (',') as the delimiter and double quotes ('"') as the quote symbol. """ import logging diff --git a/openlp/plugins/songs/forms/__init__.py b/openlp/plugins/songs/forms/__init__.py index a2e80dc54..a1c177a9d 100644 --- a/openlp/plugins/songs/forms/__init__.py +++ b/openlp/plugins/songs/forms/__init__.py @@ -52,14 +52,3 @@ This allows OpenLP to use ``self.object`` for all the GUI elements while keeping them separate from the functionality, so that it is easier to recreate the GUI from the .ui files later if necessary. """ - -from mediafilesform import MediaFilesForm -from authorsform import AuthorsForm -from topicsform import TopicsForm -from songbookform import SongBookForm -from editverseform import EditVerseForm -from editsongform import EditSongForm -from songmaintenanceform import SongMaintenanceForm -from songimportform import SongImportForm -from songexportform import SongExportForm - diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index c8f1260c9..b4ef6e71b 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -29,43 +29,56 @@ from PyQt4 import QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon from openlp.core.lib.ui import create_button_box -class Ui_AuthorsDialog(object): - def setupUi(self, authorsDialog): - authorsDialog.setObjectName(u'AuthorsDialog') - authorsDialog.resize(300, 10) - self.dialogLayout = QtGui.QVBoxLayout(authorsDialog) - self.dialogLayout.setObjectName(u'dialog_layout') - self.authorLayout = QtGui.QFormLayout() - self.authorLayout.setObjectName(u'authorLayout') - self.firstNameLabel = QtGui.QLabel(authorsDialog) - self.firstNameLabel.setObjectName(u'firstNameLabel') - self.firstNameEdit = QtGui.QLineEdit(authorsDialog) - self.firstNameEdit.setObjectName(u'firstNameEdit') - self.firstNameLabel.setBuddy(self.firstNameEdit) - self.authorLayout.addRow(self.firstNameLabel, self.firstNameEdit) - self.lastNameLabel = QtGui.QLabel(authorsDialog) - self.lastNameLabel.setObjectName(u'lastNameLabel') - self.lastNameEdit = QtGui.QLineEdit(authorsDialog) - self.lastNameEdit.setObjectName(u'lastNameEdit') - self.lastNameLabel.setBuddy(self.lastNameEdit) - self.authorLayout.addRow(self.lastNameLabel, self.lastNameEdit) - self.displayLabel = QtGui.QLabel(authorsDialog) - self.displayLabel.setObjectName(u'displayLabel') - self.displayEdit = QtGui.QLineEdit(authorsDialog) - self.displayEdit.setObjectName(u'displayEdit') - self.displayLabel.setBuddy(self.displayEdit) - self.authorLayout.addRow(self.displayLabel, self.displayEdit) - self.dialogLayout.addLayout(self.authorLayout) - self.button_box = create_button_box(authorsDialog, u'button_box', [u'cancel', u'save']) - self.dialogLayout.addWidget(self.button_box) - self.retranslateUi(authorsDialog) - authorsDialog.setMaximumHeight(authorsDialog.sizeHint().height()) - def retranslateUi(self, authorsDialog): - authorsDialog.setWindowTitle(translate('SongsPlugin.AuthorsForm', 'Author Maintenance')) - self.displayLabel.setText(translate('SongsPlugin.AuthorsForm', 'Display name:')) - self.firstNameLabel.setText(translate('SongsPlugin.AuthorsForm', 'First name:')) - self.lastNameLabel.setText(translate('SongsPlugin.AuthorsForm', 'Last name:')) +class Ui_AuthorsDialog(object): + """ + The :class:`~openlp.plugins.songs.forms.authorsdialog.Ui_AuthorsDialog` class defines the user interface for the + AuthorsForm dialog. + """ + def setupUi(self, authors_dialog): + """ + Set up the UI for the dialog. + """ + authors_dialog.setObjectName(u'authors_dialog') + authors_dialog.resize(300, 10) + authors_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) + authors_dialog.setModal(True) + self.dialog_layout = QtGui.QVBoxLayout(authors_dialog) + self.dialog_layout.setObjectName(u'dialog_layout') + self.author_layout = QtGui.QFormLayout() + self.author_layout.setObjectName(u'authorLayout') + self.first_name_label = QtGui.QLabel(authors_dialog) + self.first_name_label.setObjectName(u'first_name_label') + self.first_name_edit = QtGui.QLineEdit(authors_dialog) + self.first_name_edit.setObjectName(u'first_name_edit') + self.first_name_label.setBuddy(self.first_name_edit) + self.author_layout.addRow(self.first_name_label, self.first_name_edit) + self.last_name_label = QtGui.QLabel(authors_dialog) + self.last_name_label.setObjectName(u'last_name_label') + self.last_name_edit = QtGui.QLineEdit(authors_dialog) + self.last_name_edit.setObjectName(u'last_name_edit') + self.last_name_label.setBuddy(self.last_name_edit) + self.author_layout.addRow(self.last_name_label, self.last_name_edit) + self.display_label = QtGui.QLabel(authors_dialog) + self.display_label.setObjectName(u'display_label') + self.display_edit = QtGui.QLineEdit(authors_dialog) + self.display_edit.setObjectName(u'display_edit') + self.display_label.setBuddy(self.display_edit) + self.author_layout.addRow(self.display_label, self.display_edit) + self.dialog_layout.addLayout(self.author_layout) + self.button_box = create_button_box(authors_dialog, u'button_box', [u'cancel', u'save']) + self.dialog_layout.addWidget(self.button_box) + self.retranslateUi(authors_dialog) + authors_dialog.setMaximumHeight(authors_dialog.sizeHint().height()) + + def retranslateUi(self, authors_dialog): + """ + Translate the UI on the fly. + """ + authors_dialog.setWindowTitle(translate('SongsPlugin.AuthorsForm', 'Author Maintenance')) + self.display_label.setText(translate('SongsPlugin.AuthorsForm', 'Display name:')) + self.first_name_label.setText(translate('SongsPlugin.AuthorsForm', 'First name:')) + self.last_name_label.setText(translate('SongsPlugin.AuthorsForm', 'Last name:')) diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index a128e28f2..2d94ad3da 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -27,12 +27,13 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtGui, QtCore +from PyQt4 import QtGui from openlp.core.lib import translate from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog + class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): """ Class to control the Maintenance of Authors Dialog @@ -43,58 +44,115 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) - self._autoDisplayName = False - self.firstNameEdit.textEdited.connect(self.onFirstNameEditTextEdited) - self.lastNameEdit.textEdited.connect(self.onLastNameEditTextEdited) + self.auto_display_name = False + self.first_name_edit.textEdited.connect(self.on_first_name_edited) + self.last_name_edit.textEdited.connect(self.on_last_name_edited) def exec_(self, clear=True): + """ + Execute the dialog. + + ``clear`` + Clear the form fields before displaying the dialog. + """ if clear: - self.firstNameEdit.clear() - self.lastNameEdit.clear() - self.displayEdit.clear() - self.firstNameEdit.setFocus() + self.first_name_edit.clear() + self.last_name_edit.clear() + self.display_edit.clear() + self.first_name_edit.setFocus() return QtGui.QDialog.exec_(self) - def onFirstNameEditTextEdited(self, display_name): - if not self._autoDisplayName: + def on_first_name_edited(self, display_name): + """ + Slot for when the first name is edited. + + When the first name is edited and the setting to automatically create a display name is True, then try to create + a display name from the first and last names. + + ``display_name`` + The text from the first_name_edit widget. + """ + if not self.auto_display_name: return - if self.lastNameEdit.text(): - display_name = display_name + u' ' + self.lastNameEdit.text() - self.displayEdit.setText(display_name) + if self.last_name_edit.text(): + display_name = display_name + u' ' + self.last_name_edit.text() + self.display_edit.setText(display_name) - def onLastNameEditTextEdited(self, display_name): - if not self._autoDisplayName: + def on_last_name_edited(self, display_name): + """ + Slot for when the last name is edited. + + When the last name is edited and the setting to automatically create a display name is True, then try to create + a display name from the first and last names. + + ``display_name`` + The text from the last_name_edit widget. + """ + if not self.auto_display_name: return - if self.firstNameEdit.text(): - display_name = self.firstNameEdit.text() + u' ' + display_name - self.displayEdit.setText(display_name) - - def autoDisplayName(self): - return self._autoDisplayName - - def setAutoDisplayName(self, on): - self._autoDisplayName = on + if self.first_name_edit.text(): + display_name = self.first_name_edit.text() + u' ' + display_name + self.display_edit.setText(display_name) def accept(self): - if not self.firstNameEdit.text(): + """ + Override the QDialog's accept() method to do some validation before the dialog can be closed. + """ + if not self.first_name_edit.text(): critical_error_message_box( message=translate('SongsPlugin.AuthorsForm', 'You need to type in the first name of the author.')) - self.firstNameEdit.setFocus() + self.first_name_edit.setFocus() return False - elif not self.lastNameEdit.text(): + elif not self.last_name_edit.text(): critical_error_message_box( message=translate('SongsPlugin.AuthorsForm', 'You need to type in the last name of the author.')) - self.lastNameEdit.setFocus() + self.last_name_edit.setFocus() return False - elif not self.displayEdit.text(): + elif not self.display_edit.text(): if critical_error_message_box( message=translate('SongsPlugin.AuthorsForm', 'You have not set a display name for the author, combine the first and last names?'), parent=self, question=True) == QtGui.QMessageBox.Yes: - self.displayEdit.setText(self.firstNameEdit.text() + u' ' + self.lastNameEdit.text()) + self.display_edit.setText(self.first_name_edit.text() + u' ' + self.last_name_edit.text()) return QtGui.QDialog.accept(self) else: - self.displayEdit.setFocus() + self.display_edit.setFocus() return False else: return QtGui.QDialog.accept(self) + + def _get_first_name(self): + """ + Get the value of the first name from the UI widget. + """ + return self.first_name_edit.text() + + def _set_first_name(self, value): + """ + Set the value of the first name in the UI widget. + """ + self.first_name_edit.setText(value) + + first_name = property(_get_first_name, _set_first_name) + + def _get_last_name(self): + """ + Get the value of the last name from the UI widget. + """ + return self.last_name_edit.text() + + def _set_last_name(self, value): + """ + Set the value of the last name in the UI widget. + """ + self.last_name_edit.setText(value) + + last_name = property(_get_last_name, _set_last_name) + + def _get_display_name(self): + return self.display_edit.text() + + def _set_display_name(self, value): + self.display_edit.setText(value) + + display_name = property(_get_display_name, _set_display_name) diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index 4ea75d700..4bf2c91d9 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -33,302 +33,318 @@ from openlp.core.lib import UiStrings, build_icon, translate from openlp.core.lib.ui import create_button_box, create_button from openlp.plugins.songs.lib.ui import SongStrings -class Ui_EditSongDialog(object): - def setupUi(self, editSongDialog): - editSongDialog.setObjectName(u'editSongDialog') - editSongDialog.resize(650, 400) - editSongDialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) - editSongDialog.setModal(True) - self.dialogLayout = QtGui.QVBoxLayout(editSongDialog) - self.dialogLayout.setSpacing(8) - self.dialogLayout.setContentsMargins(8, 8, 8, 8) - self.dialogLayout.setObjectName(u'dialog_layout') - self.songTabWidget = QtGui.QTabWidget(editSongDialog) - self.songTabWidget.setObjectName(u'songTabWidget') - # lyrics tab - self.lyricsTab = QtGui.QWidget() - self.lyricsTab.setObjectName(u'lyricsTab') - self.lyricsTabLayout = QtGui.QGridLayout(self.lyricsTab) - self.lyricsTabLayout.setObjectName(u'lyricsTabLayout') - self.title_label = QtGui.QLabel(self.lyricsTab) - self.title_label.setObjectName(u'title_label') - self.lyricsTabLayout.addWidget(self.title_label, 0, 0) - self.titleEdit = QtGui.QLineEdit(self.lyricsTab) - self.titleEdit.setObjectName(u'titleEdit') - self.title_label.setBuddy(self.titleEdit) - self.lyricsTabLayout.addWidget(self.titleEdit, 0, 1, 1, 2) - self.alternative_title_label = QtGui.QLabel(self.lyricsTab) - self.alternative_title_label.setObjectName(u'alternative_title_label') - self.lyricsTabLayout.addWidget(self.alternative_title_label, 1, 0) - self.alternativeEdit = QtGui.QLineEdit(self.lyricsTab) - self.alternativeEdit.setObjectName(u'alternativeEdit') - self.alternative_title_label.setBuddy(self.alternativeEdit) - self.lyricsTabLayout.addWidget(self.alternativeEdit, 1, 1, 1, 2) - self.lyricsLabel = QtGui.QLabel(self.lyricsTab) - self.lyricsLabel.setFixedHeight(self.titleEdit.sizeHint().height()) - self.lyricsLabel.setObjectName(u'lyricsLabel') - self.lyricsTabLayout.addWidget(self.lyricsLabel, 2, 0, QtCore.Qt.AlignTop) - self.verseListWidget = SingleColumnTableWidget(self.lyricsTab) - self.verseListWidget.setAlternatingRowColors(True) - self.verseListWidget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) - self.verseListWidget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) - self.verseListWidget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.verseListWidget.setObjectName(u'verseListWidget') - self.lyricsLabel.setBuddy(self.verseListWidget) - self.lyricsTabLayout.addWidget(self.verseListWidget, 2, 1) - self.verseOrderLabel = QtGui.QLabel(self.lyricsTab) - self.verseOrderLabel.setObjectName(u'verseOrderLabel') - self.lyricsTabLayout.addWidget(self.verseOrderLabel, 3, 0) - self.verseOrderEdit = QtGui.QLineEdit(self.lyricsTab) - self.verseOrderEdit.setObjectName(u'verseOrderEdit') - self.verseOrderLabel.setBuddy(self.verseOrderEdit) - self.lyricsTabLayout.addWidget(self.verseOrderEdit, 3, 1, 1, 2) - self.verseButtonsLayout = QtGui.QVBoxLayout() - self.verseButtonsLayout.setObjectName(u'verseButtonsLayout') - self.verseAddButton = QtGui.QPushButton(self.lyricsTab) - self.verseAddButton.setObjectName(u'verseAddButton') - self.verseButtonsLayout.addWidget(self.verseAddButton) - self.verseEditButton = QtGui.QPushButton(self.lyricsTab) - self.verseEditButton.setObjectName(u'verseEditButton') - self.verseButtonsLayout.addWidget(self.verseEditButton) - self.verseEditAllButton = QtGui.QPushButton(self.lyricsTab) - self.verseEditAllButton.setObjectName(u'verseEditAllButton') - self.verseButtonsLayout.addWidget(self.verseEditAllButton) - self.verseDeleteButton = QtGui.QPushButton(self.lyricsTab) - self.verseDeleteButton.setObjectName(u'verseDeleteButton') - self.verseButtonsLayout.addWidget(self.verseDeleteButton) - self.verseButtonsLayout.addStretch() - self.lyricsTabLayout.addLayout(self.verseButtonsLayout, 2, 2) - self.songTabWidget.addTab(self.lyricsTab, u'') - # authors tab - self.authorsTab = QtGui.QWidget() - self.authorsTab.setObjectName(u'authorsTab') - self.authorsTabLayout = QtGui.QHBoxLayout(self.authorsTab) - self.authorsTabLayout.setObjectName(u'authorsTabLayout') - self.authorsLeftLayout = QtGui.QVBoxLayout() - self.authorsLeftLayout.setObjectName(u'authorsLeftLayout') - self.authorsGroupBox = QtGui.QGroupBox(self.authorsTab) - self.authorsGroupBox.setObjectName(u'authorsGroupBox') - self.authorsLayout = QtGui.QVBoxLayout(self.authorsGroupBox) - self.authorsLayout.setObjectName(u'authorsLayout') - self.authorAddLayout = QtGui.QHBoxLayout() - self.authorAddLayout.setObjectName(u'authorAddLayout') - self.authorsComboBox = editSongDialogComboBox(self.authorsGroupBox, u'authorsComboBox') - self.authorAddLayout.addWidget(self.authorsComboBox) - self.authorAddButton = QtGui.QPushButton(self.authorsGroupBox) - self.authorAddButton.setObjectName(u'authorAddButton') - self.authorAddLayout.addWidget(self.authorAddButton) - self.authorsLayout.addLayout(self.authorAddLayout) - self.authorsListView = QtGui.QListWidget(self.authorsGroupBox) - self.authorsListView.setAlternatingRowColors(True) - self.authorsListView.setObjectName(u'authorsListView') - self.authorsLayout.addWidget(self.authorsListView) - self.authorRemoveLayout = QtGui.QHBoxLayout() - self.authorRemoveLayout.setObjectName(u'authorRemoveLayout') - self.authorRemoveLayout.addStretch() - self.authorRemoveButton = QtGui.QPushButton(self.authorsGroupBox) - self.authorRemoveButton.setObjectName(u'authorRemoveButton') - self.authorRemoveLayout.addWidget(self.authorRemoveButton) - self.authorsLayout.addLayout(self.authorRemoveLayout) - self.authorsLeftLayout.addWidget(self.authorsGroupBox) - self.maintenanceLayout = QtGui.QHBoxLayout() - self.maintenanceLayout.setObjectName(u'maintenanceLayout') - self.maintenanceButton = QtGui.QPushButton(self.authorsTab) - self.maintenanceButton.setObjectName(u'maintenanceButton') - self.maintenanceLayout.addWidget(self.maintenanceButton) - self.maintenanceLayout.addStretch() - self.authorsLeftLayout.addLayout(self.maintenanceLayout) - self.authorsTabLayout.addLayout(self.authorsLeftLayout) - self.authorsRightLayout = QtGui.QVBoxLayout() - self.authorsRightLayout.setObjectName(u'authorsRightLayout') - self.topicsGroupBox = QtGui.QGroupBox(self.authorsTab) - self.topicsGroupBox.setObjectName(u'topicsGroupBox') - self.topicsLayout = QtGui.QVBoxLayout(self.topicsGroupBox) - self.topicsLayout.setObjectName(u'topicsLayout') - self.topicAddLayout = QtGui.QHBoxLayout() - self.topicAddLayout.setObjectName(u'topicAddLayout') - self.topicsComboBox = editSongDialogComboBox(self.topicsGroupBox, u'topicsComboBox') - self.topicAddLayout.addWidget(self.topicsComboBox) - self.topicAddButton = QtGui.QPushButton(self.topicsGroupBox) - self.topicAddButton.setObjectName(u'topicAddButton') - self.topicAddLayout.addWidget(self.topicAddButton) - self.topicsLayout.addLayout(self.topicAddLayout) - self.topicsListView = QtGui.QListWidget(self.topicsGroupBox) - self.topicsListView.setAlternatingRowColors(True) - self.topicsListView.setObjectName(u'topicsListView') - self.topicsLayout.addWidget(self.topicsListView) - self.topicRemoveLayout = QtGui.QHBoxLayout() - self.topicRemoveLayout.setObjectName(u'topicRemoveLayout') - self.topicRemoveLayout.addStretch() - self.topicRemoveButton = QtGui.QPushButton(self.topicsGroupBox) - self.topicRemoveButton.setObjectName(u'topicRemoveButton') - self.topicRemoveLayout.addWidget(self.topicRemoveButton) - self.topicsLayout.addLayout(self.topicRemoveLayout) - self.authorsRightLayout.addWidget(self.topicsGroupBox) - self.songBookGroupBox = QtGui.QGroupBox(self.authorsTab) - self.songBookGroupBox.setObjectName(u'songBookGroupBox') - self.songBookLayout = QtGui.QFormLayout(self.songBookGroupBox) - self.songBookLayout.setObjectName(u'songBookLayout') - self.songBookNameLabel = QtGui.QLabel(self.songBookGroupBox) - self.songBookNameLabel.setObjectName(u'songBookNameLabel') - self.songBookComboBox = editSongDialogComboBox(self.songBookGroupBox, u'songBookComboBox') - self.songBookNameLabel.setBuddy(self.songBookComboBox) - self.songBookLayout.addRow(self.songBookNameLabel, self.songBookComboBox) - self.songBookNumberLabel = QtGui.QLabel(self.songBookGroupBox) - self.songBookNumberLabel.setObjectName(u'songBookNumberLabel') - self.songBookNumberEdit = QtGui.QLineEdit(self.songBookGroupBox) - self.songBookNumberEdit.setObjectName(u'songBookNumberEdit') - self.songBookNumberLabel.setBuddy(self.songBookNumberEdit) - self.songBookLayout.addRow(self.songBookNumberLabel, self.songBookNumberEdit) - self.authorsRightLayout.addWidget(self.songBookGroupBox) - self.authorsTabLayout.addLayout(self.authorsRightLayout) - self.songTabWidget.addTab(self.authorsTab, u'') - # theme tab - self.themeTab = QtGui.QWidget() - self.themeTab.setObjectName(u'themeTab') - self.themeTabLayout = QtGui.QHBoxLayout(self.themeTab) - self.themeTabLayout.setObjectName(u'themeTabLayout') - self.themeLeftLayout = QtGui.QVBoxLayout() - self.themeLeftLayout.setObjectName(u'themeLeftLayout') - self.themeGroupBox = QtGui.QGroupBox(self.themeTab) - self.themeGroupBox.setObjectName(u'themeGroupBox') - self.themeLayout = QtGui.QHBoxLayout(self.themeGroupBox) - self.themeLayout.setObjectName(u'themeLayout') - self.themeComboBox = editSongDialogComboBox(self.themeGroupBox, u'themeComboBox') - self.themeLayout.addWidget(self.themeComboBox) - self.themeAddButton = QtGui.QPushButton(self.themeGroupBox) - self.themeAddButton.setObjectName(u'themeAddButton') - self.themeLayout.addWidget(self.themeAddButton) - self.themeLeftLayout.addWidget(self.themeGroupBox) - self.rightsGroupBox = QtGui.QGroupBox(self.themeTab) - self.rightsGroupBox.setObjectName(u'rightsGroupBox') - self.rightsLayout = QtGui.QVBoxLayout(self.rightsGroupBox) - self.rightsLayout.setObjectName(u'rightsLayout') - self.copyrightLayout = QtGui.QHBoxLayout() - self.copyrightLayout.setObjectName(u'copyrightLayout') - self.copyrightEdit = QtGui.QLineEdit(self.rightsGroupBox) - self.copyrightEdit.setObjectName(u'copyrightEdit') - self.copyrightLayout.addWidget(self.copyrightEdit) - self.copyrightInsertButton = QtGui.QToolButton(self.rightsGroupBox) - self.copyrightInsertButton.setObjectName(u'copyrightInsertButton') - self.copyrightLayout.addWidget(self.copyrightInsertButton) - self.rightsLayout.addLayout(self.copyrightLayout) - self.CCLILayout = QtGui.QHBoxLayout() - self.CCLILayout.setObjectName(u'CCLILayout') - self.CCLILabel = QtGui.QLabel(self.rightsGroupBox) - self.CCLILabel.setObjectName(u'CCLILabel') - self.CCLILayout.addWidget(self.CCLILabel) - self.CCLNumberEdit = QtGui.QLineEdit(self.rightsGroupBox) - self.CCLNumberEdit.setValidator(QtGui.QIntValidator()) - self.CCLNumberEdit.setObjectName(u'CCLNumberEdit') - self.CCLILayout.addWidget(self.CCLNumberEdit) - self.rightsLayout.addLayout(self.CCLILayout) - self.themeLeftLayout.addWidget(self.rightsGroupBox) - self.themeLeftLayout.addStretch() - self.themeTabLayout.addLayout(self.themeLeftLayout) - self.commentsGroupBox = QtGui.QGroupBox(self.themeTab) - self.commentsGroupBox.setObjectName(u'commentsGroupBox') - self.commentsLayout = QtGui.QVBoxLayout(self.commentsGroupBox) - self.commentsLayout.setObjectName(u'commentsLayout') - self.commentsEdit = QtGui.QTextEdit(self.commentsGroupBox) - self.commentsEdit.setObjectName(u'commentsEdit') - self.commentsLayout.addWidget(self.commentsEdit) - self.themeTabLayout.addWidget(self.commentsGroupBox) - self.songTabWidget.addTab(self.themeTab, u'') - # audio tab - self.audioTab = QtGui.QWidget() - self.audioTab.setObjectName(u'audioTab') - self.audioLayout = QtGui.QHBoxLayout(self.audioTab) - self.audioLayout.setObjectName(u'audioLayout') - self.audioListWidget = QtGui.QListWidget(self.audioTab) - self.audioListWidget.setObjectName(u'audioListWidget') - self.audioLayout.addWidget(self.audioListWidget) - self.audioButtonsLayout = QtGui.QVBoxLayout() - self.audioButtonsLayout.setObjectName(u'audioButtonsLayout') - self.audioAddFromFileButton = QtGui.QPushButton(self.audioTab) - self.audioAddFromFileButton.setObjectName(u'audioAddFromFileButton') - self.audioButtonsLayout.addWidget(self.audioAddFromFileButton) - self.audioAddFromMediaButton = QtGui.QPushButton(self.audioTab) - self.audioAddFromMediaButton.setObjectName(u'audioAddFromMediaButton') - self.audioButtonsLayout.addWidget(self.audioAddFromMediaButton) - self.audioRemoveButton = QtGui.QPushButton(self.audioTab) - self.audioRemoveButton.setObjectName(u'audioRemoveButton') - self.audioButtonsLayout.addWidget(self.audioRemoveButton) - self.audioRemoveAllButton = QtGui.QPushButton(self.audioTab) - self.audioRemoveAllButton.setObjectName(u'audioRemoveAllButton') - self.audioButtonsLayout.addWidget(self.audioRemoveAllButton) - self.audioButtonsLayout.addStretch(1) - self.upButton = create_button(self, u'upButton', role=u'up', click=self.onUpButtonClicked) - self.downButton = create_button(self, u'downButton', role=u'down', click=self.onDownButtonClicked) - self.audioButtonsLayout.addWidget(self.upButton) - self.audioButtonsLayout.addWidget(self.downButton) - self.audioLayout.addLayout(self.audioButtonsLayout) - self.songTabWidget.addTab(self.audioTab, u'') - # Last few bits - self.dialogLayout.addWidget(self.songTabWidget) - self.bottomLayout = QtGui.QHBoxLayout() - self.bottomLayout.setObjectName(u'bottomLayout') - self.warningLabel = QtGui.QLabel(editSongDialog) - self.warningLabel.setObjectName(u'warningLabel') - self.warningLabel.setVisible(False) - self.bottomLayout.addWidget(self.warningLabel) - self.button_box = create_button_box(editSongDialog, u'button_box', [u'cancel', u'save']) - self.bottomLayout.addWidget(self.button_box) - self.dialogLayout.addLayout(self.bottomLayout) - self.retranslateUi(editSongDialog) - def retranslateUi(self, editSongDialog): - editSongDialog.setWindowTitle(translate('SongsPlugin.EditSongForm', 'Song Editor')) +class Ui_EditSongDialog(object): + """ + The :class:`~openlp.plugins.songs.forms.editsongdialog.Ui_EditSongDialog` class defines the user interface for the + EditSongForm dialog. + """ + def setupUi(self, edit_song_dialog): + edit_song_dialog.setObjectName(u'edit_song_dialog') + edit_song_dialog.resize(650, 400) + edit_song_dialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) + edit_song_dialog.setModal(True) + self.dialog_layout = QtGui.QVBoxLayout(edit_song_dialog) + self.dialog_layout.setSpacing(8) + self.dialog_layout.setContentsMargins(8, 8, 8, 8) + self.dialog_layout.setObjectName(u'dialog_layout') + self.song_tab_widget = QtGui.QTabWidget(edit_song_dialog) + self.song_tab_widget.setObjectName(u'song_tab_widget') + # lyrics tab + self.lyrics_tab = QtGui.QWidget() + self.lyrics_tab.setObjectName(u'lyrics_tab') + self.lyrics_tab_layout = QtGui.QGridLayout(self.lyrics_tab) + self.lyrics_tab_layout.setObjectName(u'lyrics_tab_layout') + self.title_label = QtGui.QLabel(self.lyrics_tab) + self.title_label.setObjectName(u'title_label') + self.lyrics_tab_layout.addWidget(self.title_label, 0, 0) + self.title_edit = QtGui.QLineEdit(self.lyrics_tab) + self.title_edit.setObjectName(u'title_edit') + self.title_label.setBuddy(self.title_edit) + self.lyrics_tab_layout.addWidget(self.title_edit, 0, 1, 1, 2) + self.alternative_title_label = QtGui.QLabel(self.lyrics_tab) + self.alternative_title_label.setObjectName(u'alternative_title_label') + self.lyrics_tab_layout.addWidget(self.alternative_title_label, 1, 0) + self.alternative_edit = QtGui.QLineEdit(self.lyrics_tab) + self.alternative_edit.setObjectName(u'alternative_edit') + self.alternative_title_label.setBuddy(self.alternative_edit) + self.lyrics_tab_layout.addWidget(self.alternative_edit, 1, 1, 1, 2) + self.lyrics_label = QtGui.QLabel(self.lyrics_tab) + self.lyrics_label.setFixedHeight(self.title_edit.sizeHint().height()) + self.lyrics_label.setObjectName(u'lyrics_label') + self.lyrics_tab_layout.addWidget(self.lyrics_label, 2, 0, QtCore.Qt.AlignTop) + self.verse_list_widget = SingleColumnTableWidget(self.lyrics_tab) + self.verse_list_widget.setAlternatingRowColors(True) + self.verse_list_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + self.verse_list_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) + self.verse_list_widget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.verse_list_widget.setObjectName(u'verse_list_widget') + self.lyrics_label.setBuddy(self.verse_list_widget) + self.lyrics_tab_layout.addWidget(self.verse_list_widget, 2, 1) + self.verse_order_label = QtGui.QLabel(self.lyrics_tab) + self.verse_order_label.setObjectName(u'verse_order_label') + self.lyrics_tab_layout.addWidget(self.verse_order_label, 3, 0) + self.verse_order_edit = QtGui.QLineEdit(self.lyrics_tab) + self.verse_order_edit.setObjectName(u'verse_order_edit') + self.verse_order_label.setBuddy(self.verse_order_edit) + self.lyrics_tab_layout.addWidget(self.verse_order_edit, 3, 1, 1, 2) + self.verse_buttons_layout = QtGui.QVBoxLayout() + self.verse_buttons_layout.setObjectName(u'verse_buttons_layout') + self.verse_add_button = QtGui.QPushButton(self.lyrics_tab) + self.verse_add_button.setObjectName(u'verse_add_button') + self.verse_buttons_layout.addWidget(self.verse_add_button) + self.verse_edit_button = QtGui.QPushButton(self.lyrics_tab) + self.verse_edit_button.setObjectName(u'verse_edit_button') + self.verse_buttons_layout.addWidget(self.verse_edit_button) + self.verse_edit_all_button = QtGui.QPushButton(self.lyrics_tab) + self.verse_edit_all_button.setObjectName(u'verse_edit_all_button') + self.verse_buttons_layout.addWidget(self.verse_edit_all_button) + self.verse_delete_button = QtGui.QPushButton(self.lyrics_tab) + self.verse_delete_button.setObjectName(u'verse_delete_button') + self.verse_buttons_layout.addWidget(self.verse_delete_button) + self.verse_buttons_layout.addStretch() + self.lyrics_tab_layout.addLayout(self.verse_buttons_layout, 2, 2) + self.song_tab_widget.addTab(self.lyrics_tab, u'') + # authors tab + self.authors_tab = QtGui.QWidget() + self.authors_tab.setObjectName(u'authors_tab') + self.authors_tab_layout = QtGui.QHBoxLayout(self.authors_tab) + self.authors_tab_layout.setObjectName(u'authors_tab_layout') + self.authors_left_layout = QtGui.QVBoxLayout() + self.authors_left_layout.setObjectName(u'authors_left_layout') + self.authors_group_box = QtGui.QGroupBox(self.authors_tab) + self.authors_group_box.setObjectName(u'authors_group_box') + self.authors_layout = QtGui.QVBoxLayout(self.authors_group_box) + self.authors_layout.setObjectName(u'authors_layout') + self.author_add_layout = QtGui.QHBoxLayout() + self.author_add_layout.setObjectName(u'author_add_layout') + self.authors_combo_box = create_combo_box(self.authors_group_box, u'authors_combo_box') + self.author_add_layout.addWidget(self.authors_combo_box) + self.author_add_button = QtGui.QPushButton(self.authors_group_box) + self.author_add_button.setObjectName(u'author_add_button') + self.author_add_layout.addWidget(self.author_add_button) + self.authors_layout.addLayout(self.author_add_layout) + self.authors_list_view = QtGui.QListWidget(self.authors_group_box) + self.authors_list_view.setAlternatingRowColors(True) + self.authors_list_view.setObjectName(u'authors_list_view') + self.authors_layout.addWidget(self.authors_list_view) + self.author_remove_layout = QtGui.QHBoxLayout() + self.author_remove_layout.setObjectName(u'author_remove_layout') + self.author_remove_layout.addStretch() + self.author_remove_button = QtGui.QPushButton(self.authors_group_box) + self.author_remove_button.setObjectName(u'author_remove_button') + self.author_remove_layout.addWidget(self.author_remove_button) + self.authors_layout.addLayout(self.author_remove_layout) + self.authors_left_layout.addWidget(self.authors_group_box) + self.maintenance_layout = QtGui.QHBoxLayout() + self.maintenance_layout.setObjectName(u'maintenance_layout') + self.maintenance_button = QtGui.QPushButton(self.authors_tab) + self.maintenance_button.setObjectName(u'maintenance_button') + self.maintenance_layout.addWidget(self.maintenance_button) + self.maintenance_layout.addStretch() + self.authors_left_layout.addLayout(self.maintenance_layout) + self.authors_tab_layout.addLayout(self.authors_left_layout) + self.authors_right_layout = QtGui.QVBoxLayout() + self.authors_right_layout.setObjectName(u'authors_right_layout') + self.topics_group_box = QtGui.QGroupBox(self.authors_tab) + self.topics_group_box.setObjectName(u'topics_group_box') + self.topics_layout = QtGui.QVBoxLayout(self.topics_group_box) + self.topics_layout.setObjectName(u'topics_layout') + self.topic_add_layout = QtGui.QHBoxLayout() + self.topic_add_layout.setObjectName(u'topic_add_layout') + self.topicsComboBox = create_combo_box(self.topics_group_box, u'topicsComboBox') + self.topic_add_layout.addWidget(self.topicsComboBox) + self.topic_add_button = QtGui.QPushButton(self.topics_group_box) + self.topic_add_button.setObjectName(u'topic_add_button') + self.topic_add_layout.addWidget(self.topic_add_button) + self.topics_layout.addLayout(self.topic_add_layout) + self.topics_list_view = QtGui.QListWidget(self.topics_group_box) + self.topics_list_view.setAlternatingRowColors(True) + self.topics_list_view.setObjectName(u'topics_list_view') + self.topics_layout.addWidget(self.topics_list_view) + self.topic_remove_layout = QtGui.QHBoxLayout() + self.topic_remove_layout.setObjectName(u'topic_remove_layout') + self.topic_remove_layout.addStretch() + self.topic_remove_button = QtGui.QPushButton(self.topics_group_box) + self.topic_remove_button.setObjectName(u'topic_remove_button') + self.topic_remove_layout.addWidget(self.topic_remove_button) + self.topics_layout.addLayout(self.topic_remove_layout) + self.authors_right_layout.addWidget(self.topics_group_box) + self.song_book_group_box = QtGui.QGroupBox(self.authors_tab) + self.song_book_group_box.setObjectName(u'song_book_group_box') + self.song_book_layout = QtGui.QFormLayout(self.song_book_group_box) + self.song_book_layout.setObjectName(u'song_book_layout') + self.song_book_name_label = QtGui.QLabel(self.song_book_group_box) + self.song_book_name_label.setObjectName(u'song_book_name_label') + self.song_book_combo_box = create_combo_box(self.song_book_group_box, u'song_book_combo_box') + self.song_book_name_label.setBuddy(self.song_book_combo_box) + self.song_book_layout.addRow(self.song_book_name_label, self.song_book_combo_box) + self.song_book_number_label = QtGui.QLabel(self.song_book_group_box) + self.song_book_number_label.setObjectName(u'song_book_number_label') + self.song_book_number_edit = QtGui.QLineEdit(self.song_book_group_box) + self.song_book_number_edit.setObjectName(u'song_book_number_edit') + self.song_book_number_label.setBuddy(self.song_book_number_edit) + self.song_book_layout.addRow(self.song_book_number_label, self.song_book_number_edit) + self.authors_right_layout.addWidget(self.song_book_group_box) + self.authors_tab_layout.addLayout(self.authors_right_layout) + self.song_tab_widget.addTab(self.authors_tab, u'') + # theme tab + self.theme_tab = QtGui.QWidget() + self.theme_tab.setObjectName(u'theme_tab') + self.theme_tab_layout = QtGui.QHBoxLayout(self.theme_tab) + self.theme_tab_layout.setObjectName(u'theme_tab_layout') + self.theme_left_layout = QtGui.QVBoxLayout() + self.theme_left_layout.setObjectName(u'theme_left_layout') + self.theme_group_box = QtGui.QGroupBox(self.theme_tab) + self.theme_group_box.setObjectName(u'theme_group_box') + self.theme_layout = QtGui.QHBoxLayout(self.theme_group_box) + self.theme_layout.setObjectName(u'theme_layout') + self.theme_combo_box = create_combo_box(self.theme_group_box, u'theme_combo_box') + self.theme_layout.addWidget(self.theme_combo_box) + self.theme_add_button = QtGui.QPushButton(self.theme_group_box) + self.theme_add_button.setObjectName(u'theme_add_button') + self.theme_layout.addWidget(self.theme_add_button) + self.theme_left_layout.addWidget(self.theme_group_box) + self.rights_group_box = QtGui.QGroupBox(self.theme_tab) + self.rights_group_box.setObjectName(u'rights_group_box') + self.rights_layout = QtGui.QVBoxLayout(self.rights_group_box) + self.rights_layout.setObjectName(u'rights_layout') + self.copyright_layout = QtGui.QHBoxLayout() + self.copyright_layout.setObjectName(u'copyright_layout') + self.copyright_edit = QtGui.QLineEdit(self.rights_group_box) + self.copyright_edit.setObjectName(u'copyright_edit') + self.copyright_layout.addWidget(self.copyright_edit) + self.copyright_insert_button = QtGui.QToolButton(self.rights_group_box) + self.copyright_insert_button.setObjectName(u'copyright_insert_button') + self.copyright_layout.addWidget(self.copyright_insert_button) + self.rights_layout.addLayout(self.copyright_layout) + self.ccli_layout = QtGui.QHBoxLayout() + self.ccli_layout.setObjectName(u'ccli_layout') + self.ccli_label = QtGui.QLabel(self.rights_group_box) + self.ccli_label.setObjectName(u'ccli_label') + self.ccli_layout.addWidget(self.ccli_label) + self.ccli_number_edit = QtGui.QLineEdit(self.rights_group_box) + self.ccli_number_edit.setValidator(QtGui.QIntValidator()) + self.ccli_number_edit.setObjectName(u'ccli_number_edit') + self.ccli_layout.addWidget(self.ccli_number_edit) + self.rights_layout.addLayout(self.ccli_layout) + self.theme_left_layout.addWidget(self.rights_group_box) + self.theme_left_layout.addStretch() + self.theme_tab_layout.addLayout(self.theme_left_layout) + self.comments_group_box = QtGui.QGroupBox(self.theme_tab) + self.comments_group_box.setObjectName(u'comments_group_box') + self.comments_layout = QtGui.QVBoxLayout(self.comments_group_box) + self.comments_layout.setObjectName(u'comments_layout') + self.comments_edit = QtGui.QTextEdit(self.comments_group_box) + self.comments_edit.setObjectName(u'comments_edit') + self.comments_layout.addWidget(self.comments_edit) + self.theme_tab_layout.addWidget(self.comments_group_box) + self.song_tab_widget.addTab(self.theme_tab, u'') + # audio tab + self.audio_tab = QtGui.QWidget() + self.audio_tab.setObjectName(u'audio_tab') + self.audio_layout = QtGui.QHBoxLayout(self.audio_tab) + self.audio_layout.setObjectName(u'audio_layout') + self.audio_list_widget = QtGui.QListWidget(self.audio_tab) + self.audio_list_widget.setObjectName(u'audio_list_widget') + self.audio_layout.addWidget(self.audio_list_widget) + self.audio_buttons_layout = QtGui.QVBoxLayout() + self.audio_buttons_layout.setObjectName(u'audio_buttons_layout') + self.from_file_button = QtGui.QPushButton(self.audio_tab) + self.from_file_button.setObjectName(u'from_file_button') + self.audio_buttons_layout.addWidget(self.from_file_button) + self.from_media_button = QtGui.QPushButton(self.audio_tab) + self.from_media_button.setObjectName(u'from_media_button') + self.audio_buttons_layout.addWidget(self.from_media_button) + self.audio_remove_button = QtGui.QPushButton(self.audio_tab) + self.audio_remove_button.setObjectName(u'audio_remove_button') + self.audio_buttons_layout.addWidget(self.audio_remove_button) + self.audio_remove_all_button = QtGui.QPushButton(self.audio_tab) + self.audio_remove_all_button.setObjectName(u'audio_remove_all_button') + self.audio_buttons_layout.addWidget(self.audio_remove_all_button) + self.audio_buttons_layout.addStretch(1) + self.up_button = create_button(self, u'up_button', role=u'up', click=self.on_up_button_clicked) + self.down_button = create_button(self, u'down_button', role=u'down', click=self.on_down_button_clicked) + self.audio_buttons_layout.addWidget(self.up_button) + self.audio_buttons_layout.addWidget(self.down_button) + self.audio_layout.addLayout(self.audio_buttons_layout) + self.song_tab_widget.addTab(self.audio_tab, u'') + # Last few bits + self.dialog_layout.addWidget(self.song_tab_widget) + self.bottom_layout = QtGui.QHBoxLayout() + self.bottom_layout.setObjectName(u'bottom_layout') + self.warning_label = QtGui.QLabel(edit_song_dialog) + self.warning_label.setObjectName(u'warning_label') + self.warning_label.setVisible(False) + self.bottom_layout.addWidget(self.warning_label) + self.button_box = create_button_box(edit_song_dialog, u'button_box', [u'cancel', u'save']) + self.bottom_layout.addWidget(self.button_box) + self.dialog_layout.addLayout(self.bottom_layout) + self.retranslateUi(edit_song_dialog) + + def retranslateUi(self, edit_song_dialog): + """ + Translate the UI on the fly. + """ + edit_song_dialog.setWindowTitle(translate('SongsPlugin.EditSongForm', 'Song Editor')) self.title_label.setText(translate('SongsPlugin.EditSongForm', '&Title:')) self.alternative_title_label.setText(translate('SongsPlugin.EditSongForm', 'Alt&ernate title:')) - self.lyricsLabel.setText(translate('SongsPlugin.EditSongForm', '&Lyrics:')) - self.verseOrderLabel.setText(translate('SongsPlugin.EditSongForm', '&Verse order:')) - self.verseAddButton.setText(UiStrings().Add) - self.verseEditButton.setText(UiStrings().Edit) - self.verseEditAllButton.setText(translate('SongsPlugin.EditSongForm', 'Ed&it All')) - self.verseDeleteButton.setText(UiStrings().Delete) - self.songTabWidget.setTabText(self.songTabWidget.indexOf(self.lyricsTab), + self.lyrics_label.setText(translate('SongsPlugin.EditSongForm', '&Lyrics:')) + self.verse_order_label.setText(translate('SongsPlugin.EditSongForm', '&Verse order:')) + self.verse_add_button.setText(UiStrings().Add) + self.verse_edit_button.setText(UiStrings().Edit) + self.verse_edit_all_button.setText(translate('SongsPlugin.EditSongForm', 'Ed&it All')) + self.verse_delete_button.setText(UiStrings().Delete) + self.song_tab_widget.setTabText(self.song_tab_widget.indexOf(self.lyrics_tab), translate('SongsPlugin.EditSongForm', 'Title && Lyrics')) - self.authorsGroupBox.setTitle(SongStrings.Authors) - self.authorAddButton.setText(translate('SongsPlugin.EditSongForm', '&Add to Song')) - self.authorRemoveButton.setText(translate('SongsPlugin.EditSongForm', '&Remove')) - self.maintenanceButton.setText(translate('SongsPlugin.EditSongForm', '&Manage Authors, Topics, Song Books')) - self.topicsGroupBox.setTitle(SongStrings.Topic) - self.topicAddButton.setText(translate('SongsPlugin.EditSongForm', 'A&dd to Song')) - self.topicRemoveButton.setText(translate('SongsPlugin.EditSongForm', 'R&emove')) - self.songBookGroupBox.setTitle(SongStrings.SongBook) - self.songBookNameLabel.setText(translate('SongsPlugin.EditSongForm', 'Book:')) - self.songBookNumberLabel.setText(translate('SongsPlugin.EditSongForm', 'Number:')) - self.songTabWidget.setTabText(self.songTabWidget.indexOf(self.authorsTab), + self.authors_group_box.setTitle(SongStrings.Authors) + self.author_add_button.setText(translate('SongsPlugin.EditSongForm', '&Add to Song')) + self.author_remove_button.setText(translate('SongsPlugin.EditSongForm', '&Remove')) + self.maintenance_button.setText(translate('SongsPlugin.EditSongForm', '&Manage Authors, Topics, Song Books')) + self.topics_group_box.setTitle(SongStrings.Topic) + self.topic_add_button.setText(translate('SongsPlugin.EditSongForm', 'A&dd to Song')) + self.topic_remove_button.setText(translate('SongsPlugin.EditSongForm', 'R&emove')) + self.song_book_group_box.setTitle(SongStrings.SongBook) + self.song_book_name_label.setText(translate('SongsPlugin.EditSongForm', 'Book:')) + self.song_book_number_label.setText(translate('SongsPlugin.EditSongForm', 'Number:')) + self.song_tab_widget.setTabText(self.song_tab_widget.indexOf(self.authors_tab), translate('SongsPlugin.EditSongForm', 'Authors, Topics && Song Book')) - self.themeGroupBox.setTitle(UiStrings().Theme) - self.themeAddButton.setText(translate('SongsPlugin.EditSongForm', 'New &Theme')) - self.rightsGroupBox.setTitle(translate('SongsPlugin.EditSongForm', 'Copyright Information')) - self.copyrightInsertButton.setText(SongStrings.CopyrightSymbol) - self.CCLILabel.setText(UiStrings().CCLINumberLabel) - self.commentsGroupBox.setTitle(translate('SongsPlugin.EditSongForm', 'Comments')) - self.songTabWidget.setTabText(self.songTabWidget.indexOf(self.themeTab), + self.theme_group_box.setTitle(UiStrings().Theme) + self.theme_add_button.setText(translate('SongsPlugin.EditSongForm', 'New &Theme')) + self.rights_group_box.setTitle(translate('SongsPlugin.EditSongForm', 'Copyright Information')) + self.copyright_insert_button.setText(SongStrings.CopyrightSymbol) + self.ccli_label.setText(UiStrings().CCLINumberLabel) + self.comments_group_box.setTitle(translate('SongsPlugin.EditSongForm', 'Comments')) + self.song_tab_widget.setTabText(self.song_tab_widget.indexOf(self.theme_tab), translate('SongsPlugin.EditSongForm', 'Theme, Copyright Info && Comments')) - self.songTabWidget.setTabText(self.songTabWidget.indexOf(self.audioTab), + self.song_tab_widget.setTabText(self.song_tab_widget.indexOf(self.audio_tab), translate('SongsPlugin.EditSongForm', 'Linked Audio')) - self.audioAddFromFileButton.setText(translate('SongsPlugin.EditSongForm', 'Add &File(s)')) - self.audioAddFromMediaButton.setText(translate('SongsPlugin.EditSongForm', 'Add &Media')) - self.audioRemoveButton.setText(translate('SongsPlugin.EditSongForm', '&Remove')) - self.audioRemoveAllButton.setText(translate('SongsPlugin.EditSongForm', 'Remove &All')) - self.warningLabel.setText( + self.from_file_button.setText(translate('SongsPlugin.EditSongForm', 'Add &File(s)')) + self.from_media_button.setText(translate('SongsPlugin.EditSongForm', 'Add &Media')) + self.audio_remove_button.setText(translate('SongsPlugin.EditSongForm', '&Remove')) + self.audio_remove_all_button.setText(translate('SongsPlugin.EditSongForm', 'Remove &All')) + self.warning_label.setText( translate('SongsPlugin.EditSongForm', 'Warning: Not all of the verses are in use.')) -def editSongDialogComboBox(parent, name): + +def create_combo_box(parent, name): """ Utility method to generate a standard combo box for this dialog. + + ``parent`` + The parent widget for this combo box. + + ``name`` + The object name. """ - comboBox = QtGui.QComboBox(parent) - comboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength) - comboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) - comboBox.setEditable(True) - comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) - comboBox.setObjectName(name) - return comboBox + combo_box = QtGui.QComboBox(parent) + combo_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength) + combo_box.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) + combo_box.setEditable(True) + combo_box.setInsertPolicy(QtGui.QComboBox.NoInsert) + combo_box.setObjectName(name) + return combo_box + class SingleColumnTableWidget(QtGui.QTableWidget): """ diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 79271e41d..80c3c45b8 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -38,19 +38,21 @@ import shutil from PyQt4 import QtCore, QtGui -from openlp.core.lib import Registry, PluginStatus, MediaType, translate, create_separated_list, \ - check_directory_exists, UiStrings -from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, \ - find_and_set_in_combo_box +from openlp.core.lib import Registry, PluginStatus, MediaType, UiStrings, translate, create_separated_list, \ + check_directory_exists +from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box from openlp.core.utils import AppLocation -from openlp.plugins.songs.forms import EditVerseForm, MediaFilesForm -from openlp.plugins.songs.lib import SongXML, VerseType, clean_song +from openlp.plugins.songs.lib import VerseType, clean_song from openlp.plugins.songs.lib.db import Book, Song, Author, Topic, MediaFile from openlp.plugins.songs.lib.ui import SongStrings +from openlp.plugins.songs.lib.xml import SongXML from openlp.plugins.songs.forms.editsongdialog import Ui_EditSongDialog +from openlp.plugins.songs.forms.editverseform import EditVerseForm +from openlp.plugins.songs.forms.mediafilesform import MediaFilesForm log = logging.getLogger(__name__) + class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ Class to manage the editing of a song @@ -68,45 +70,183 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.width = 400 self.setupUi(self) # Connecting signals and slots - self.authorAddButton.clicked.connect(self.onAuthorAddButtonClicked) - self.authorRemoveButton.clicked.connect(self.onAuthorRemoveButtonClicked) - self.authorsListView.itemClicked.connect(self.onAuthorsListViewClicked) - self.topicAddButton.clicked.connect(self.onTopicAddButtonClicked) - self.topicRemoveButton.clicked.connect(self.onTopicRemoveButtonClicked) - self.topicsListView.itemClicked.connect(self.onTopicListViewClicked) - self.copyrightInsertButton.clicked.connect(self.onCopyrightInsertButtonTriggered) - self.verseAddButton.clicked.connect(self.onVerseAddButtonClicked) - self.verseListWidget.doubleClicked.connect(self.onVerseEditButtonClicked) - self.verseEditButton.clicked.connect(self.onVerseEditButtonClicked) - self.verseEditAllButton.clicked.connect(self.onVerseEditAllButtonClicked) - self.verseDeleteButton.clicked.connect(self.onVerseDeleteButtonClicked) - self.verseListWidget.itemClicked.connect(self.onVerseListViewClicked) - self.verseOrderEdit.textChanged.connect(self.onVerseOrderTextChanged) - self.themeAddButton.clicked.connect(self.theme_manager.onAddTheme) - self.maintenanceButton.clicked.connect(self.onMaintenanceButtonClicked) - self.audioAddFromFileButton.clicked.connect(self.onAudioAddFromFileButtonClicked) - self.audioAddFromMediaButton.clicked.connect(self.onAudioAddFromMediaButtonClicked) - self.audioRemoveButton.clicked.connect(self.onAudioRemoveButtonClicked) - self.audioRemoveAllButton.clicked.connect(self.onAudioRemoveAllButtonClicked) + self.author_add_button.clicked.connect(self.on_author_add_button_clicked) + self.author_remove_button.clicked.connect(self.on_author_remove_button_clicked) + self.authors_list_view.itemClicked.connect(self.on_authors_list_view_clicked) + self.topic_add_button.clicked.connect(self.on_topic_add_button_clicked) + self.topic_remove_button.clicked.connect(self.on_topic_remove_button_clicked) + self.topics_list_view.itemClicked.connect(self.on_topic_list_view_clicked) + self.copyright_insert_button.clicked.connect(self.on_copyright_insert_button_triggered) + self.verse_add_button.clicked.connect(self.on_verse_add_button_clicked) + self.verse_list_widget.doubleClicked.connect(self.on_verse_edit_button_clicked) + self.verse_edit_button.clicked.connect(self.on_verse_edit_button_clicked) + self.verse_edit_all_button.clicked.connect(self.on_verse_edit_all_button_clicked) + self.verse_delete_button.clicked.connect(self.on_verse_delete_button_clicked) + self.verse_list_widget.itemClicked.connect(self.on_verse_list_view_clicked) + self.verse_order_edit.textChanged.connect(self.on_verse_order_text_changed) + self.theme_add_button.clicked.connect(self.theme_manager.onAddTheme) + self.maintenance_button.clicked.connect(self.on_maintenance_button_clicked) + self.from_file_button.clicked.connect(self.on_audio_add_from_file_button_clicked) + self.from_media_button.clicked.connect(self.on_audio_add_from_media_button_clicked) + self.audio_remove_button.clicked.connect(self.on_audio_remove_button_clicked) + self.audio_remove_all_button.clicked.connect(self.on_audio_remove_all_button_clicked) Registry().register_function(u'theme_update_list', self.load_themes) - self.previewButton = QtGui.QPushButton() - self.previewButton.setObjectName(u'previewButton') - self.previewButton.setText(UiStrings().SaveAndPreview) - self.button_box.addButton(self.previewButton, QtGui.QDialogButtonBox.ActionRole) - self.button_box.clicked.connect(self.onPreview) + self.preview_button = QtGui.QPushButton() + self.preview_button.setObjectName(u'preview_button') + self.preview_button.setText(UiStrings().SaveAndPreview) + self.button_box.addButton(self.preview_button, QtGui.QDialogButtonBox.ActionRole) + self.button_box.clicked.connect(self.on_preview) # Create other objects and forms self.manager = manager - self.verseForm = EditVerseForm(self) - self.mediaForm = MediaFilesForm(self) + self.verse_form = EditVerseForm(self) + self.media_form = MediaFilesForm(self) self.initialise() - self.authorsListView.setSortingEnabled(False) - self.authorsListView.setAlternatingRowColors(True) - self.topicsListView.setSortingEnabled(False) - self.topicsListView.setAlternatingRowColors(True) - self.audioListWidget.setAlternatingRowColors(True) - self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE) + self.authors_list_view.setSortingEnabled(False) + self.authors_list_view.setAlternatingRowColors(True) + self.topics_list_view.setSortingEnabled(False) + self.topics_list_view.setAlternatingRowColors(True) + self.audio_list_widget.setAlternatingRowColors(True) + self.find_verse_split = re.compile(u'---\[\]---\n', re.UNICODE) self.whitespace = re.compile(r'\W+', re.UNICODE) + def _load_objects(self, cls, combo, cache): + """ + Generically load a set of objects into a cache and a combobox. + """ + objects = self.manager.get_all_objects(cls, order_by_ref=cls.name) + combo.clear() + combo.addItem(u'') + for obj in objects: + row = combo.count() + combo.addItem(obj.name) + cache.append(obj.name) + combo.setItemData(row, obj.id) + set_case_insensitive_completer(cache, combo) + + def _add_author_to_list(self, author): + """ + Add an author to the author list. + """ + author_item = QtGui.QListWidgetItem(unicode(author.display_name)) + author_item.setData(QtCore.Qt.UserRole, author.id) + self.authors_list_view.addItem(author_item) + + def _extract_verse_order(self, verse_order): + order = [] + order_names = unicode(verse_order).split() + for item in order_names: + if len(item) == 1: + verse_index = VerseType.from_translated_tag(item, None) + if verse_index is not None: + order.append(VerseType.tags[verse_index] + u'1') + else: + # it matches no verses anyway + order.append(u'') + else: + verse_index = VerseType.from_translated_tag(item[0], None) + if verse_index is None: + # it matches no verses anyway + order.append(u'') + else: + verse_tag = VerseType.tags[verse_index] + verse_num = item[1:].lower() + order.append(verse_tag + verse_num) + return order + + def _validate_verse_list(self, verse_order, verse_count): + verses = [] + invalid_verses = [] + verse_names = [] + order_names = unicode(verse_order).split() + order = self._extract_verse_order(verse_order) + for index in range(verse_count): + verse = self.verse_list_widget.item(index, 0) + verse = verse.data(QtCore.Qt.UserRole) + if verse not in verse_names: + verses.append(verse) + verse_names.append(u'%s%s' % (VerseType.translated_tag(verse[0]), verse[1:])) + for count, item in enumerate(order): + if item not in verses: + invalid_verses.append(order_names[count]) + if invalid_verses: + valid = create_separated_list(verse_names) + if len(invalid_verses) > 1: + critical_error_message_box(message=translate('SongsPlugin.EditSongForm', + 'The verse order is invalid. There are no verses corresponding to %s. Valid entries are %s.') % + (u', '.join(invalid_verses), valid)) + else: + critical_error_message_box(message=translate('SongsPlugin.EditSongForm', + 'The verse order is invalid. There is no verse corresponding to %s. Valid entries are %s.') % + (invalid_verses[0], valid)) + return len(invalid_verses) == 0 + + def _validate_song(self): + """ + Check the validity of the song. + """ + # This checks data in the form *not* self.song. self.song is still + # None at this point. + log.debug(u'Validate Song') + # Lets be nice and assume the data is correct. + if not self.title_edit.text(): + self.song_tab_widget.setCurrentIndex(0) + self.title_edit.setFocus() + critical_error_message_box( + message=translate('SongsPlugin.EditSongForm', 'You need to type in a song title.')) + return False + if self.verse_list_widget.rowCount() == 0: + self.song_tab_widget.setCurrentIndex(0) + self.verse_list_widget.setFocus() + critical_error_message_box( + message=translate('SongsPlugin.EditSongForm', 'You need to type in at least one verse.')) + return False + if self.authors_list_view.count() == 0: + self.song_tab_widget.setCurrentIndex(1) + self.authors_list_view.setFocus() + critical_error_message_box( + message=translate('SongsPlugin.EditSongForm', 'You need to have an author for this song.')) + return False + if self.verse_order_edit.text(): + result = self._validate_verse_list(self.verse_order_edit.text(), self.verse_list_widget.rowCount()) + if not result: + return False + text = self.song_book_combo_box.currentText() + if self.song_book_combo_box.findText(text, QtCore.Qt.MatchExactly) < 0: + if QtGui.QMessageBox.question(self, translate('SongsPlugin.EditSongForm', 'Add Book'), + translate('SongsPlugin.EditSongForm', 'This song book does not exist, do you want to add it?'), + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: + book = Book.populate(name=text, publisher=u'') + self.manager.save_object(book) + else: + return False + return True + + def _process_lyrics(self): + """ + Process the lyric data entered by the user into the OpenLP XML format. + """ + # This method must only be run after the self.song = Song() assignment. + log.debug(u'_processLyrics') + sxml = None + try: + sxml = SongXML() + multiple = [] + for i in range(self.verse_list_widget.rowCount()): + item = self.verse_list_widget.item(i, 0) + verse_id = item.data(QtCore.Qt.UserRole) + verse_tag = verse_id[0] + verse_num = verse_id[1:] + sxml.add_verse_to_lyrics(verse_tag, verse_num, item.text()) + if verse_num > u'1' and verse_tag not in multiple: + multiple.append(verse_tag) + self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + for verse in multiple: + self.song.verse_order = re.sub(u'([' + verse.upper() + verse.lower() + u'])(\W|$)', + r'\g<1>1\2', self.song.verse_order) + except: + log.exception(u'Problem processing song Lyrics \n%s', sxml.dump_xml()) + raise + def keyPressEvent(self, event): """ Reimplement the keyPressEvent to react on Return/Enter keys. When some combo boxes have focus we do not want @@ -120,7 +260,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.onAuthorAddButtonClicked() return if self.topicsComboBox.hasFocus() and self.topicsComboBox.currentText(): - self.onTopicAddButtonClicked() + self.on_topic_add_button_clicked() return QtGui.QDialog.keyPressEvent(self, event) @@ -128,110 +268,95 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ Set up the form for when it is displayed. """ - self.verseEditButton.setEnabled(False) - self.verseDeleteButton.setEnabled(False) - self.authorRemoveButton.setEnabled(False) - self.topicRemoveButton.setEnabled(False) + self.verse_edit_button.setEnabled(False) + self.verse_delete_button.setEnabled(False) + self.author_remove_button.setEnabled(False) + self.topic_remove_button.setEnabled(False) - def loadAuthors(self): + def load_authors(self): """ Load the authors from the database into the combobox. """ - authors = self.manager.get_all_objects(Author, - order_by_ref=Author.display_name) - self.authorsComboBox.clear() - self.authorsComboBox.addItem(u'') + authors = self.manager.get_all_objects(Author, order_by_ref=Author.display_name) + self.authors_combo_box.clear() + self.authors_combo_box.addItem(u'') self.authors = [] for author in authors: - row = self.authorsComboBox.count() - self.authorsComboBox.addItem(author.display_name) - self.authorsComboBox.setItemData(row, author.id) + row = self.authors_combo_box.count() + self.authors_combo_box.addItem(author.display_name) + self.authors_combo_box.setItemData(row, author.id) self.authors.append(author.display_name) - set_case_insensitive_completer(self.authors, self.authorsComboBox) + set_case_insensitive_completer(self.authors, self.authors_combo_box) - def loadTopics(self): + def load_topics(self): """ Load the topics into the combobox. """ self.topics = [] - self.__loadObjects(Topic, self.topicsComboBox, self.topics) + self._load_objects(Topic, self.topicsComboBox, self.topics) - def loadBooks(self): + def load_books(self): """ Load the song books into the combobox """ self.books = [] - self.__loadObjects(Book, self.songBookComboBox, self.books) - - def __loadObjects(self, cls, combo, cache): - """ - Generically load a set of objects into a cache and a combobox. - """ - objects = self.manager.get_all_objects(cls, order_by_ref=cls.name) - combo.clear() - combo.addItem(u'') - for object in objects: - row = combo.count() - combo.addItem(object.name) - cache.append(object.name) - combo.setItemData(row, object.id) - set_case_insensitive_completer(cache, combo) + self._load_objects(Book, self.song_book_combo_box, self.books) def load_themes(self, theme_list): """ Load the themes into a combobox. """ - self.themeComboBox.clear() - self.themeComboBox.addItem(u'') + self.theme_combo_box.clear() + self.theme_combo_box.addItem(u'') self.themes = theme_list - self.themeComboBox.addItems(theme_list) - set_case_insensitive_completer(self.themes, self.themeComboBox) + self.theme_combo_box.addItems(theme_list) + set_case_insensitive_completer(self.themes, self.theme_combo_box) - def loadMediaFiles(self): + def load_media_files(self): """ Load the media files into a combobox. """ - self.audioAddFromMediaButton.setVisible(False) + self.from_media_button.setVisible(False) for plugin in self.plugin_manager.plugins: if plugin.name == u'media' and plugin.status == PluginStatus.Active: - self.audioAddFromMediaButton.setVisible(True) - self.mediaForm.populateFiles(plugin.mediaItem.getList(MediaType.Audio)) + self.from_media_button.setVisible(True) + self.media_form.populateFiles(plugin.mediaItem.getList(MediaType.Audio)) break - def newSong(self): + def new_song(self): """ Blank the edit form out in preparation for a new song. """ log.debug(u'New Song') self.song = None self.initialise() - self.songTabWidget.setCurrentIndex(0) - self.titleEdit.clear() - self.alternativeEdit.clear() - self.copyrightEdit.clear() - self.verseOrderEdit.clear() - self.commentsEdit.clear() - self.CCLNumberEdit.clear() - self.verseListWidget.clear() - self.verseListWidget.setRowCount(0) - self.authorsListView.clear() - self.topicsListView.clear() - self.audioListWidget.clear() - self.titleEdit.setFocus() - self.songBookNumberEdit.clear() - self.loadAuthors() - self.loadTopics() - self.loadBooks() - self.loadMediaFiles() - self.themeComboBox.setCurrentIndex(0) + self.song_tab_widget.setCurrentIndex(0) + self.title_edit.clear() + self.alternative_edit.clear() + self.copyright_edit.clear() + self.verse_order_edit.clear() + self.comments_edit.clear() + self.ccli_number_edit.clear() + self.verse_list_widget.clear() + self.verse_list_widget.setRowCount(0) + self.authors_list_view.clear() + self.topics_list_view.clear() + self.audio_list_widget.clear() + self.title_edit.setFocus() + self.song_book_number_edit.clear() + self.load_authors() + self.load_topics() + self.load_books() + self.load_media_files() + self.theme_combo_box.setCurrentIndex(0) # it's a new song to preview is not possible - self.previewButton.setVisible(False) + self.preview_button.setVisible(False) - def loadSong(self, id, preview=False): + def load_song(self, song_id, preview=False): """ Loads a song. - ``id`` + ``song_id`` The song id (int). ``preview`` @@ -239,27 +364,27 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ log.debug(u'Load Song') self.initialise() - self.songTabWidget.setCurrentIndex(0) - self.loadAuthors() - self.loadTopics() - self.loadBooks() - self.loadMediaFiles() - self.song = self.manager.get_object(Song, id) - self.titleEdit.setText(self.song.title) - self.alternativeEdit.setText( + self.song_tab_widget.setCurrentIndex(0) + self.load_authors() + self.load_topics() + self.load_books() + self.load_media_files() + self.song = self.manager.get_object(Song, song_id) + self.title_edit.setText(self.song.title) + self.alternative_edit.setText( self.song.alternate_title if self.song.alternate_title else u'') if self.song.song_book_id != 0: book_name = self.manager.get_object(Book, self.song.song_book_id) - find_and_set_in_combo_box(self.songBookComboBox, unicode(book_name.name)) + find_and_set_in_combo_box(self.song_book_combo_box, unicode(book_name.name)) if self.song.theme_name: - find_and_set_in_combo_box(self.themeComboBox, unicode(self.song.theme_name)) - self.copyrightEdit.setText(self.song.copyright if self.song.copyright else u'') - self.commentsEdit.setPlainText(self.song.comments if self.song.comments else u'') - self.CCLNumberEdit.setText(self.song.ccli_number if self.song.ccli_number else u'') - self.songBookNumberEdit.setText(self.song.song_number if self.song.song_number else u'') + find_and_set_in_combo_box(self.theme_combo_box, unicode(self.song.theme_name)) + self.copyright_edit.setText(self.song.copyright if self.song.copyright else u'') + self.comments_edit.setPlainText(self.song.comments if self.song.comments else u'') + self.ccli_number_edit.setText(self.song.ccli_number if self.song.ccli_number else u'') + self.song_book_number_edit.setText(self.song.song_number if self.song.song_number else u'') # lazy xml migration for now - self.verseListWidget.clear() - self.verseListWidget.setRowCount(0) + self.verse_list_widget.clear() + self.verse_list_widget.setRowCount(0) # This is just because occasionally the lyrics come back as a "buffer" if isinstance(self.song.lyrics, buffer): self.song.lyrics = unicode(self.song.lyrics) @@ -268,8 +393,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): songXML = SongXML() verse_list = songXML.get_verses(self.song.lyrics) for count, verse in enumerate(verse_list): - self.verseListWidget.setRowCount( - self.verseListWidget.rowCount() + 1) + self.verse_list_widget.setRowCount(self.verse_list_widget.rowCount() + 1) # This silently migrates from localized verse type markup. # If we trusted the database, this would be unnecessary. verse_tag = verse[0][u'type'] @@ -288,15 +412,15 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): verse_def = u'%s%s' % (verse[0][u'type'], verse[0][u'label']) item = QtGui.QTableWidgetItem(verse[1]) item.setData(QtCore.Qt.UserRole, verse_def) - self.verseListWidget.setItem(count, 0, item) + self.verse_list_widget.setItem(count, 0, item) else: verses = self.song.lyrics.split(u'\n\n') for count, verse in enumerate(verses): - self.verseListWidget.setRowCount(self.verseListWidget.rowCount() + 1) + self.verse_list_widget.setRowCount(self.verse_list_widget.rowCount() + 1) item = QtGui.QTableWidgetItem(verse) verse_def = u'%s%s' % (VerseType.tags[VerseType.Verse], unicode(count + 1)) item.setData(QtCore.Qt.UserRole, verse_def) - self.verseListWidget.setItem(count, 0, item) + self.verse_list_widget.setItem(count, 0, item) if self.song.verse_order: # we translate verse order translated = [] @@ -308,52 +432,52 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): verse_index = VerseType.from_tag(verse_def[0]) verse_tag = VerseType.translated_tags[verse_index].upper() translated.append(u'%s%s' % (verse_tag, verse_def[1:])) - self.verseOrderEdit.setText(u' '.join(translated)) + self.verse_order_edit.setText(u' '.join(translated)) else: - self.verseOrderEdit.setText(u'') - self.tagRows() + self.verse_order_edit.setText(u'') + self.tag_rows() # clear the results - self.authorsListView.clear() + self.authors_list_view.clear() for author in self.song.authors: author_name = QtGui.QListWidgetItem(unicode(author.display_name)) author_name.setData(QtCore.Qt.UserRole, author.id) - self.authorsListView.addItem(author_name) + self.authors_list_view.addItem(author_name) # clear the results - self.topicsListView.clear() + self.topics_list_view.clear() for topic in self.song.topics: topic_name = QtGui.QListWidgetItem(unicode(topic.name)) topic_name.setData(QtCore.Qt.UserRole, topic.id) - self.topicsListView.addItem(topic_name) - self.audioListWidget.clear() + self.topics_list_view.addItem(topic_name) + self.audio_list_widget.clear() for media in self.song.media_files: media_file = QtGui.QListWidgetItem(os.path.split(media.file_name)[1]) media_file.setData(QtCore.Qt.UserRole, media.file_name) - self.audioListWidget.addItem(media_file) - self.titleEdit.setFocus() + self.audio_list_widget.addItem(media_file) + self.title_edit.setFocus() # Hide or show the preview button. - self.previewButton.setVisible(preview) + self.preview_button.setVisible(preview) - def tagRows(self): + def tag_rows(self): """ Tag the Song List rows based on the verse list """ row_label = [] - for row in range(self.verseListWidget.rowCount()): - item = self.verseListWidget.item(row, 0) + for row in range(self.verse_list_widget.rowCount()): + item = self.verse_list_widget.item(row, 0) verse_def = item.data(QtCore.Qt.UserRole) verse_tag = VerseType.translated_tag(verse_def[0]) row_def = u'%s%s' % (verse_tag, verse_def[1:]) row_label.append(row_def) - self.verseListWidget.setVerticalHeaderLabels(row_label) - self.verseListWidget.resizeRowsToContents() - self.verseListWidget.repaint() + self.verse_list_widget.setVerticalHeaderLabels(row_label) + self.verse_list_widget.resizeRowsToContents() + self.verse_list_widget.repaint() - def onAuthorAddButtonClicked(self): + def on_author_add_button_clicked(self): """ Add the author to the list of authors associated with this song when the button is clicked. """ - item = int(self.authorsComboBox.currentIndex()) - text = self.authorsComboBox.currentText().strip(u' \r\n\t') + item = int(self.authors_combo_box.currentIndex()) + text = self.authors_combo_box.currentText().strip(u' \r\n\t') # This if statement is for OS X, which doesn't seem to work well with # the QCompleter autocompletion class. See bug #812628. if text in self.authors: @@ -370,52 +494,44 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): author = Author.populate(first_name=text.rsplit(u' ', 1)[0], last_name=text.rsplit(u' ', 1)[1], display_name=text) self.manager.save_object(author) - self.__addAuthorToList(author) - self.loadAuthors() - self.authorsComboBox.setCurrentIndex(0) + self._add_author_to_list(author) + self.load_authors() + self.authors_combo_box.setCurrentIndex(0) else: return elif item > 0: - item_id = (self.authorsComboBox.itemData(item)) + item_id = (self.authors_combo_box.itemData(item)) author = self.manager.get_object(Author, item_id) - if self.authorsListView.findItems(unicode(author.display_name), + if self.authors_list_view.findItems(unicode(author.display_name), QtCore.Qt.MatchExactly): critical_error_message_box( message=translate('SongsPlugin.EditSongForm', 'This author is already in the list.')) else: - self.__addAuthorToList(author) - self.authorsComboBox.setCurrentIndex(0) + self._add_author_to_list(author) + self.authors_combo_box.setCurrentIndex(0) else: QtGui.QMessageBox.warning(self, UiStrings().NISs, translate('SongsPlugin.EditSongForm', 'You have not selected a valid author. Either select an author ' 'from the list, or type in a new author and click the "Add Author to Song" button to add ' 'the new author.')) - def __addAuthorToList(self, author): - """ - Add an author to the author list. - """ - author_item = QtGui.QListWidgetItem(unicode(author.display_name)) - author_item.setData(QtCore.Qt.UserRole, author.id) - self.authorsListView.addItem(author_item) - - def onAuthorsListViewClicked(self): + def on_authors_list_view_clicked(self): """ Run a set of actions when an author in the list is selected (mainly enable the delete button). """ - if self.authorsListView.count() > 1: - self.authorRemoveButton.setEnabled(True) + if self.authors_list_view.count() > 1: + self.author_remove_button.setEnabled(True) - def onAuthorRemoveButtonClicked(self): + def on_author_remove_button_clicked(self): """ Remove the author from the list when the delete button is clicked. """ - self.authorRemoveButton.setEnabled(False) - item = self.authorsListView.currentItem() - row = self.authorsListView.row(item) - self.authorsListView.takeItem(row) + self.author_remove_button.setEnabled(False) + item = self.authors_list_view.currentItem() + row = self.authors_list_view.row(item) + self.authors_list_view.takeItem(row) - def onTopicAddButtonClicked(self): + def on_topic_add_button_clicked(self): item = int(self.topicsComboBox.currentIndex()) text = self.topicsComboBox.currentText() if item == 0 and text: @@ -426,63 +542,63 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.manager.save_object(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, topic.id) - self.topicsListView.addItem(topic_item) - self.loadTopics() + self.topics_list_view.addItem(topic_item) + self.load_topics() self.topicsComboBox.setCurrentIndex(0) else: return elif item > 0: item_id = (self.topicsComboBox.itemData(item)) topic = self.manager.get_object(Topic, item_id) - if self.topicsListView.findItems(unicode(topic.name), + if self.topics_list_view.findItems(unicode(topic.name), QtCore.Qt.MatchExactly): critical_error_message_box( message=translate('SongsPlugin.EditSongForm', 'This topic is already in the list.')) else: topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, topic.id) - self.topicsListView.addItem(topic_item) + self.topics_list_view.addItem(topic_item) self.topicsComboBox.setCurrentIndex(0) else: QtGui.QMessageBox.warning(self, UiStrings().NISs, translate('SongsPlugin.EditSongForm', 'You have not selected a valid topic. Either select a topic ' 'from the list, or type in a new topic and click the "Add Topic to Song" button to add the new topic.')) - def onTopicListViewClicked(self): - self.topicRemoveButton.setEnabled(True) + def on_topic_list_view_clicked(self): + self.topic_remove_button.setEnabled(True) - def onTopicRemoveButtonClicked(self): - self.topicRemoveButton.setEnabled(False) - item = self.topicsListView.currentItem() - row = self.topicsListView.row(item) - self.topicsListView.takeItem(row) + def on_topic_remove_button_clicked(self): + self.topic_remove_button.setEnabled(False) + item = self.topics_list_view.currentItem() + row = self.topics_list_view.row(item) + self.topics_list_view.takeItem(row) - def onVerseListViewClicked(self): - self.verseEditButton.setEnabled(True) - self.verseDeleteButton.setEnabled(True) + def on_verse_list_view_clicked(self): + self.verse_edit_button.setEnabled(True) + self.verse_delete_button.setEnabled(True) - def onVerseAddButtonClicked(self): - self.verseForm.setVerse(u'', True) - if self.verseForm.exec_(): - after_text, verse_tag, verse_num = self.verseForm.getVerse() + def on_verse_add_button_clicked(self): + self.verse_form.setVerse(u'', True) + if self.verse_form.exec_(): + after_text, verse_tag, verse_num = self.verse_form.getVerse() verse_def = u'%s%s' % (verse_tag, verse_num) item = QtGui.QTableWidgetItem(after_text) item.setData(QtCore.Qt.UserRole, verse_def) item.setText(after_text) - self.verseListWidget.setRowCount(self.verseListWidget.rowCount() + 1) - self.verseListWidget.setItem(self.verseListWidget.rowCount() - 1, 0, item) - self.tagRows() + self.verse_list_widget.setRowCount(self.verse_list_widget.rowCount() + 1) + self.verse_list_widget.setItem(self.verse_list_widget.rowCount() - 1, 0, item) + self.tag_rows() # Check if all verse tags are used. - self.onVerseOrderTextChanged(self.verseOrderEdit.text()) + self.on_verse_order_text_changed(self.verse_order_edit.text()) - def onVerseEditButtonClicked(self): - item = self.verseListWidget.currentItem() + def on_verse_edit_button_clicked(self): + item = self.verse_list_widget.currentItem() if item: temp_text = item.text() verse_id = item.data(QtCore.Qt.UserRole) - self.verseForm.setVerse(temp_text, True, verse_id) - if self.verseForm.exec_(): - after_text, verse_tag, verse_num = self.verseForm.getVerse() + self.verse_form.setVerse(temp_text, True, verse_id) + if self.verse_form.exec_(): + after_text, verse_tag, verse_num = self.verse_form.getVerse() verse_def = u'%s%s' % (verse_tag, verse_num) item.setData(QtCore.Qt.UserRole, verse_def) item.setText(after_text) @@ -490,40 +606,40 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if len(temp_text.split(u'\n')) != len(after_text.split(u'\n')): temp_list = [] temp_ids = [] - for row in range(self.verseListWidget.rowCount()): - item = self.verseListWidget.item(row, 0) + for row in range(self.verse_list_widget.rowCount()): + item = self.verse_list_widget.item(row, 0) temp_list.append(item.text()) temp_ids.append(item.data(QtCore.Qt.UserRole)) - self.verseListWidget.clear() + self.verse_list_widget.clear() for row, entry in enumerate(temp_list): item = QtGui.QTableWidgetItem(entry, 0) item.setData(QtCore.Qt.UserRole, temp_ids[row]) - self.verseListWidget.setItem(row, 0, item) - self.tagRows() + self.verse_list_widget.setItem(row, 0, item) + self.tag_rows() # Check if all verse tags are used. - self.onVerseOrderTextChanged(self.verseOrderEdit.text()) + self.on_verse_order_text_changed(self.verse_order_edit.text()) - def onVerseEditAllButtonClicked(self): + def on_verse_edit_all_button_clicked(self): verse_list = u'' - if self.verseListWidget.rowCount() > 0: - for row in range(self.verseListWidget.rowCount()): - item = self.verseListWidget.item(row, 0) + if self.verse_list_widget.rowCount() > 0: + for row in range(self.verse_list_widget.rowCount()): + item = self.verse_list_widget.item(row, 0) field = item.data(QtCore.Qt.UserRole) verse_tag = VerseType.translated_name(field[0]) verse_num = field[1:] verse_list += u'---[%s:%s]---\n' % (verse_tag, verse_num) verse_list += item.text() verse_list += u'\n' - self.verseForm.setVerse(verse_list) + self.verse_form.setVerse(verse_list) else: - self.verseForm.setVerse(u'') - if not self.verseForm.exec_(): + self.verse_form.setVerse(u'') + if not self.verse_form.exec_(): return - verse_list = self.verseForm.getVerseAll() + verse_list = self.verse_form.getVerseAll() verse_list = unicode(verse_list.replace(u'\r\n', u'\n')) - self.verseListWidget.clear() - self.verseListWidget.setRowCount(0) - for row in self.findVerseSplit.split(verse_list): + self.verse_list_widget.clear() + self.verse_list_widget.setRowCount(0) + for row in self.find_verse_split.split(verse_list): for match in row.split(u'---['): for count, parts in enumerate(match.split(u']---\n')): if count == 0: @@ -553,26 +669,26 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): parts = parts.rstrip(u'\n') item = QtGui.QTableWidgetItem(parts) item.setData(QtCore.Qt.UserRole, verse_def) - self.verseListWidget.setRowCount(self.verseListWidget.rowCount() + 1) - self.verseListWidget.setItem(self.verseListWidget.rowCount() - 1, 0, item) - self.tagRows() - self.verseEditButton.setEnabled(False) - self.verseDeleteButton.setEnabled(False) + self.verse_list_widget.setRowCount(self.verse_list_widget.rowCount() + 1) + self.verse_list_widget.setItem(self.verse_list_widget.rowCount() - 1, 0, item) + self.tag_rows() + self.verse_edit_button.setEnabled(False) + self.verse_delete_button.setEnabled(False) # Check if all verse tags are used. - self.onVerseOrderTextChanged(self.verseOrderEdit.text()) + self.on_verse_order_text_changed(self.verse_order_edit.text()) - def onVerseDeleteButtonClicked(self): - self.verseListWidget.removeRow(self.verseListWidget.currentRow()) - if not self.verseListWidget.selectedItems(): - self.verseEditButton.setEnabled(False) - self.verseDeleteButton.setEnabled(False) + def on_verse_delete_button_clicked(self): + self.verse_list_widget.removeRow(self.verse_list_widget.currentRow()) + if not self.verse_list_widget.selectedItems(): + self.verse_edit_button.setEnabled(False) + self.verse_delete_button.setEnabled(False) - def onVerseOrderTextChanged(self, text): + def on_verse_order_text_changed(self, text): verses = [] verse_names = [] - order = self.__extractVerseOrder(text) - for index in range(self.verseListWidget.rowCount()): - verse = self.verseListWidget.item(index, 0) + order = self._extract_verse_order(text) + for index in range(self.verse_list_widget.rowCount()): + verse = self.verse_list_widget.item(index, 0) verse = verse.data(QtCore.Qt.UserRole) if verse not in verse_names: verses.append(verse) @@ -581,122 +697,31 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): for verse in verses: if not verse in order: verses_not_used.append(verse) - self.warningLabel.setVisible(len(verses_not_used) > 0) + self.warning_label.setVisible(len(verses_not_used) > 0) - def __extractVerseOrder(self, verse_order): - order = [] - order_names = unicode(verse_order).split() - for item in order_names: - if len(item) == 1: - verse_index = VerseType.from_translated_tag(item, None) - if verse_index is not None: - order.append(VerseType.tags[verse_index] + u'1') - else: - # it matches no verses anyway - order.append(u'') - else: - verse_index = VerseType.from_translated_tag(item[0], None) - if verse_index is None: - # it matches no verses anyway - order.append(u'') - else: - verse_tag = VerseType.tags[verse_index] - verse_num = item[1:].lower() - order.append(verse_tag + verse_num) - return order - - def __validateVerseList(self, verse_order, verse_count): - verses = [] - invalid_verses = [] - verse_names = [] - order_names = unicode(verse_order).split() - order = self.__extractVerseOrder(verse_order) - for index in range(verse_count): - verse = self.verseListWidget.item(index, 0) - verse = verse.data(QtCore.Qt.UserRole) - if verse not in verse_names: - verses.append(verse) - verse_names.append(u'%s%s' % (VerseType.translated_tag(verse[0]), verse[1:])) - for count, item in enumerate(order): - if item not in verses: - invalid_verses.append(order_names[count]) - if invalid_verses: - valid = create_separated_list(verse_names) - if len(invalid_verses) > 1: - critical_error_message_box(message=translate('SongsPlugin.EditSongForm', - 'The verse order is invalid. There are no verses corresponding to %s. Valid entries are %s.') % - (u', '.join(invalid_verses), valid)) - else: - critical_error_message_box(message=translate('SongsPlugin.EditSongForm', - 'The verse order is invalid. There is no verse corresponding to %s. Valid entries are %s.') % - (invalid_verses[0], valid)) - return len(invalid_verses) == 0 - - def __validateSong(self): - """ - Check the validity of the song. - """ - # This checks data in the form *not* self.song. self.song is still - # None at this point. - log.debug(u'Validate Song') - # Lets be nice and assume the data is correct. - if not self.titleEdit.text(): - self.songTabWidget.setCurrentIndex(0) - self.titleEdit.setFocus() - critical_error_message_box( - message=translate('SongsPlugin.EditSongForm', 'You need to type in a song title.')) - return False - if self.verseListWidget.rowCount() == 0: - self.songTabWidget.setCurrentIndex(0) - self.verseListWidget.setFocus() - critical_error_message_box( - message=translate('SongsPlugin.EditSongForm', 'You need to type in at least one verse.')) - return False - if self.authorsListView.count() == 0: - self.songTabWidget.setCurrentIndex(1) - self.authorsListView.setFocus() - critical_error_message_box( - message=translate('SongsPlugin.EditSongForm', 'You need to have an author for this song.')) - return False - if self.verseOrderEdit.text(): - result = self.__validateVerseList(self.verseOrderEdit.text(), - self.verseListWidget.rowCount()) - if not result: - return False - text = self.songBookComboBox.currentText() - if self.songBookComboBox.findText(text, QtCore.Qt.MatchExactly) < 0: - if QtGui.QMessageBox.question(self, translate('SongsPlugin.EditSongForm', 'Add Book'), - translate('SongsPlugin.EditSongForm', 'This song book does not exist, do you want to add it?'), - QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: - book = Book.populate(name=text, publisher=u'') - self.manager.save_object(book) - else: - return False - return True - - def onCopyrightInsertButtonTriggered(self): - text = self.copyrightEdit.text() - pos = self.copyrightEdit.cursorPosition() + def on_copyright_insert_button_triggered(self): + text = self.copyright_edit.text() + pos = self.copyright_edit.cursorPosition() sign = SongStrings.CopyrightSymbol text = text[:pos] + sign + text[pos:] - self.copyrightEdit.setText(text) - self.copyrightEdit.setFocus() - self.copyrightEdit.setCursorPosition(pos + len(sign)) + self.copyright_edit.setText(text) + self.copyright_edit.setFocus() + self.copyright_edit.setCursorPosition(pos + len(sign)) - def onMaintenanceButtonClicked(self): + def on_maintenance_button_clicked(self): temp_song_book = None - item = int(self.songBookComboBox.currentIndex()) - text = self.songBookComboBox.currentText() + item = int(self.song_book_combo_box.currentIndex()) + text = self.song_book_combo_box.currentText() if item == 0 and text: temp_song_book = text self.mediaitem.songMaintenanceForm.exec_(True) - self.loadAuthors() - self.loadBooks() - self.loadTopics() + self.load_authors() + self.load_books() + self.load_topics() if temp_song_book: - self.songBookComboBox.setEditText(temp_song_book) + self.song_book_combo_box.setEditText(temp_song_book) - def onPreview(self, button): + def on_preview(self, button): """ Save and Preview button clicked. The Song is valid so as the plugin to add it to preview to see. @@ -705,11 +730,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): A button (QPushButton). """ log.debug(u'onPreview') - if button.objectName() == u'previewButton': - self.saveSong(True) + if button.objectName() == u'preview_button': + self.save_song(True) Registry().execute(u'songs_preview') - def onAudioAddFromFileButtonClicked(self): + def on_audio_add_from_file_button_clicked(self): """ Loads file(s) from the filesystem. """ @@ -719,56 +744,56 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): for filename in filenames: item = QtGui.QListWidgetItem(os.path.split(unicode(filename))[1]) item.setData(QtCore.Qt.UserRole, filename) - self.audioListWidget.addItem(item) + self.audio_list_widget.addItem(item) - def onAudioAddFromMediaButtonClicked(self): + def on_audio_add_from_media_button_clicked(self): """ Loads file(s) from the media plugin. """ - if self.mediaForm.exec_(): - for filename in self.mediaForm.getSelectedFiles(): + if self.media_form.exec_(): + for filename in self.media_form.getSelectedFiles(): item = QtGui.QListWidgetItem(os.path.split(unicode(filename))[1]) item.setData(QtCore.Qt.UserRole, filename) - self.audioListWidget.addItem(item) + self.audio_list_widget.addItem(item) - def onAudioRemoveButtonClicked(self): + def on_audio_remove_button_clicked(self): """ Removes a file from the list. """ - row = self.audioListWidget.currentRow() + row = self.audio_list_widget.currentRow() if row == -1: return - self.audioListWidget.takeItem(row) + self.audio_list_widget.takeItem(row) - def onAudioRemoveAllButtonClicked(self): + def on_audio_remove_all_button_clicked(self): """ Removes all files from the list. """ - self.audioListWidget.clear() + self.audio_list_widget.clear() - def onUpButtonClicked(self): + def on_up_button_clicked(self): """ Moves a file up when the user clicks the up button on the audio tab. """ - row = self.audioListWidget.currentRow() + row = self.audio_list_widget.currentRow() if row <= 0: return - item = self.audioListWidget.takeItem(row) - self.audioListWidget.insertItem(row - 1, item) - self.audioListWidget.setCurrentRow(row - 1) + item = self.audio_list_widget.takeItem(row) + self.audio_list_widget.insertItem(row - 1, item) + self.audio_list_widget.setCurrentRow(row - 1) - def onDownButtonClicked(self): + def on_down_button_clicked(self): """ Moves a file down when the user clicks the up button on the audio tab. """ - row = self.audioListWidget.currentRow() - if row == -1 or row > self.audioListWidget.count() - 1: + row = self.audio_list_widget.currentRow() + if row == -1 or row > self.audio_list_widget.count() - 1: return - item = self.audioListWidget.takeItem(row) - self.audioListWidget.insertItem(row + 1, item) - self.audioListWidget.setCurrentRow(row + 1) + item = self.audio_list_widget.takeItem(row) + self.audio_list_widget.insertItem(row + 1, item) + self.audio_list_widget.setCurrentRow(row + 1) - def clearCaches(self): + def clear_caches(self): """ Free up autocompletion memory on dialog exit """ @@ -783,7 +808,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Exit Dialog and do not save """ log.debug (u'SongEditForm.reject') - self.clearCaches() + self.clear_caches() QtGui.QDialog.reject(self) def accept(self): @@ -791,13 +816,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Exit Dialog and save song if valid """ log.debug(u'SongEditForm.accept') - self.clearCaches() - if self.__validateSong(): - self.saveSong() + self.clear_caches() + if self._validate_song(): + self.save_song() self.song = None QtGui.QDialog.accept(self) - def saveSong(self, preview=False): + def save_song(self, preview=False): """ Get all the data from the widgets on the form, and then save it to the database. The form has been validated and all reference items @@ -811,45 +836,45 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): # Song() is in a partially complete state. if not self.song: self.song = Song() - self.song.title = self.titleEdit.text() - self.song.alternate_title = self.alternativeEdit.text() - self.song.copyright = self.copyrightEdit.text() + self.song.title = self.title_edit.text() + self.song.alternate_title = self.alternative_edit.text() + self.song.copyright = self.copyright_edit.text() # Values will be set when cleaning the song. self.song.search_title = u'' self.song.search_lyrics = u'' self.song.verse_order = u'' - self.song.comments = self.commentsEdit.toPlainText() - ordertext = self.verseOrderEdit.text() + self.song.comments = self.comments_edit.toPlainText() + ordertext = self.verse_order_edit.text() order = [] for item in ordertext.split(): verse_tag = VerseType.tags[VerseType.from_translated_tag(item[0])] verse_num = item[1:].lower() order.append(u'%s%s' % (verse_tag, verse_num)) self.song.verse_order = u' '.join(order) - self.song.ccli_number = self.CCLNumberEdit.text() - self.song.song_number = self.songBookNumberEdit.text() - book_name = self.songBookComboBox.currentText() + self.song.ccli_number = self.ccli_number_edit.text() + self.song.song_number = self.song_book_number_edit.text() + book_name = self.song_book_combo_box.currentText() if book_name: self.song.book = self.manager.get_object_filtered(Book, Book.name == book_name) else: self.song.book = None - theme_name = self.themeComboBox.currentText() + theme_name = self.theme_combo_box.currentText() if theme_name: self.song.theme_name = theme_name else: self.song.theme_name = None - self._processLyrics() + self._process_lyrics() self.song.authors = [] - for row in xrange(self.authorsListView.count()): - item = self.authorsListView.item(row) + for row in xrange(self.authors_list_view.count()): + item = self.authors_list_view.item(row) authorId = (item.data(QtCore.Qt.UserRole)) author = self.manager.get_object(Author, authorId) if author is not None: self.song.authors.append(author) self.song.topics = [] - for row in xrange(self.topicsListView.count()): - item = self.topicsListView.item(row) + for row in xrange(self.topics_list_view.count()): + item = self.topics_list_view.item(row) topicId = (item.data(QtCore.Qt.UserRole)) topic = self.manager.get_object(Topic, topicId) if topic is not None: @@ -864,8 +889,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): check_directory_exists(save_path) self.song.media_files = [] files = [] - for row in xrange(self.audioListWidget.count()): - item = self.audioListWidget.item(row) + for row in xrange(self.audio_list_widget.count()): + item = self.audio_list_widget.item(row) filename = item.data(QtCore.Qt.UserRole) if not filename.startswith(save_path): oldfile, filename = filename, os.path.join(save_path, os.path.split(filename)[1]) @@ -891,31 +916,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.manager.save_object(self.song) self.mediaitem.autoSelectId = self.song.id - def _processLyrics(self): - """ - Process the lyric data entered by the user into the OpenLP XML format. - """ - # This method must only be run after the self.song = Song() assignment. - log.debug(u'_processLyrics') - try: - sxml = SongXML() - multiple = [] - for i in range(self.verseListWidget.rowCount()): - item = self.verseListWidget.item(i, 0) - verse_id = item.data(QtCore.Qt.UserRole) - verse_tag = verse_id[0] - verse_num = verse_id[1:] - sxml.add_verse_to_lyrics(verse_tag, verse_num, item.text()) - if verse_num > u'1' and verse_tag not in multiple: - multiple.append(verse_tag) - self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8') - for verse in multiple: - self.song.verse_order = re.sub(u'([' + verse.upper() + verse.lower() + u'])(\W|$)', r'\g<1>1\2', - self.song.verse_order) - except: - log.exception(u'Problem processing song Lyrics \n%s', sxml.dump_xml()) - raise - def _get_plugin_manager(self): """ Adds the plugin manager to the class dynamically @@ -935,4 +935,3 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): return self._theme_manager theme_manager = property(_get_theme_manager) - diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index 50deed638..e25c4a07d 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -33,13 +33,13 @@ import logging from PyQt4 import QtCore, QtGui from openlp.plugins.songs.lib import VerseType - from editversedialog import Ui_EditVerseDialog log = logging.getLogger(__name__) VERSE_REGEX = re.compile(r'---\[(.+):\D*(\d*)\D*.*\]---') + class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): """ This is the form that is used to edit the verses of the song. diff --git a/openlp/plugins/songs/forms/mediafilesform.py b/openlp/plugins/songs/forms/mediafilesform.py index 690cfe25e..49ffde644 100644 --- a/openlp/plugins/songs/forms/mediafilesform.py +++ b/openlp/plugins/songs/forms/mediafilesform.py @@ -36,6 +36,7 @@ from mediafilesdialog import Ui_MediaFilesDialog log = logging.getLogger(__name__) + class MediaFilesForm(QtGui.QDialog, Ui_MediaFilesDialog): """ Class to show a list of files from the diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 8d9ce28ab..f7941e15b 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -57,7 +57,7 @@ class Ui_SongMaintenanceDialog(object): self.authorsPage = QtGui.QWidget(songMaintenanceDialog) self.authorsPage.setObjectName(u'authorsPage') self.authorsLayout = QtGui.QVBoxLayout(self.authorsPage) - self.authorsLayout.setObjectName(u'authorsLayout') + self.authorsLayout.setObjectName(u'authors_layout') self.authorsListWidget = QtGui.QListWidget(self.authorsPage) self.authorsListWidget.setObjectName(u'authorsListWidget') self.authorsLayout.addWidget(self.authorsListWidget) @@ -82,7 +82,7 @@ class Ui_SongMaintenanceDialog(object): self.topicsPage = QtGui.QWidget(songMaintenanceDialog) self.topicsPage.setObjectName(u'topicsPage') self.topicsLayout = QtGui.QVBoxLayout(self.topicsPage) - self.topicsLayout.setObjectName(u'topicsLayout') + self.topicsLayout.setObjectName(u'topics_layout') self.topicsListWidget = QtGui.QListWidget(self.topicsPage) self.topicsListWidget.setObjectName(u'topicsListWidget') self.topicsLayout.addWidget(self.topicsListWidget) diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 4e5dd79b1..e02d4794d 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -33,7 +33,9 @@ from sqlalchemy.sql import and_ from openlp.core.lib import Registry, UiStrings, translate from openlp.core.lib.ui import critical_error_message_box -from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm +from openlp.plugins.songs.forms.authorsform import AuthorsForm +from openlp.plugins.songs.forms.topicsform import TopicsForm +from openlp.plugins.songs.forms.songbookform import SongBookForm from openlp.plugins.songs.lib.db import Author, Book, Topic, Song from songmaintenancedialog import Ui_SongMaintenanceDialog @@ -206,12 +208,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Add an author to the list. """ - self.authorform.setAutoDisplayName(True) + self.authorform.auto_display_name = True if self.authorform.exec_(): author = Author.populate( - first_name=self.authorform.firstNameEdit.text(), - last_name=self.authorform.lastNameEdit.text(), - display_name=self.authorform.displayEdit.text()) + first_name=self.authorform.first_name, + last_name=self.authorform.last_name, + display_name=self.authorform.display_name + ) if self.checkAuthor(author): if self.manager.save_object(author): self.resetAuthors() @@ -263,19 +266,19 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if author_id == -1: return author = self.manager.get_object(Author, author_id) - self.authorform.setAutoDisplayName(False) - self.authorform.firstNameEdit.setText(author.first_name) - self.authorform.lastNameEdit.setText(author.last_name) - self.authorform.displayEdit.setText(author.display_name) + self.authorform.auto_display_name = False + self.authorform.first_name_edit.setText(author.first_name) + self.authorform.last_name_edit.setText(author.last_name) + self.authorform.display_edit.setText(author.display_name) # Save the author's first and last name as well as the display name # for the case that they have to be restored. temp_first_name = author.first_name temp_last_name = author.last_name temp_display_name = author.display_name if self.authorform.exec_(False): - author.first_name = self.authorform.firstNameEdit.text() - author.last_name = self.authorform.lastNameEdit.text() - author.display_name = self.authorform.displayEdit.text() + author.first_name = self.authorform.first_name_edit.text() + author.last_name = self.authorform.last_name_edit.text() + author.display_name = self.authorform.display_edit.text() if self.checkAuthor(author, True): if self.manager.save_object(author): self.resetAuthors() diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index c6093eec7..070d322b1 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -26,6 +26,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`~openlp.plugins.songs.lib` module contains a number of library functions and classes used in the Songs plugin. +""" import re from PyQt4 import QtGui @@ -182,8 +185,10 @@ class VerseType(object): for num, tag in enumerate(VerseType.tags): if verse_tag == tag: return VerseType.translated_tags[num].upper() - if default in VerseType.translated_tags: + if len(VerseType.names) > default: return VerseType.translated_tags[default].upper() + else: + return VerseType.translated_tags[VerseType.Other].upper() @staticmethod def translated_name(verse_tag, default=Other): @@ -200,8 +205,10 @@ class VerseType(object): for num, tag in enumerate(VerseType.tags): if verse_tag == tag: return VerseType.translated_names[num] - if default in VerseType.translated_names: + if len(VerseType.names) > default: return VerseType.translated_names[default] + else: + return VerseType.translated_names[VerseType.Other] @staticmethod def from_tag(verse_tag, default=Other): @@ -218,7 +225,10 @@ class VerseType(object): for num, tag in enumerate(VerseType.tags): if verse_tag == tag: return num - return default + if len(VerseType.names) > default: + return default + else: + return VerseType.Other @staticmethod def from_translated_tag(verse_tag, default=Other): @@ -235,7 +245,10 @@ class VerseType(object): for num, tag in enumerate(VerseType.translated_tags): if verse_tag == tag: return num - return default + if len(VerseType.names) > default: + return default + else: + return VerseType.Other @staticmethod def from_string(verse_name, default=Other): @@ -611,7 +624,3 @@ def natcmp(a, b): if result != 0: return result return 1 - -from xml import OpenLyrics, SongXML -from songstab import SongsTab -from mediaitem import SongMediaItem diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 5e8f86a88..533f79a4c 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -39,10 +39,14 @@ from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, Plugin UiStrings, translate, check_item_selected, create_separated_list, check_directory_exists from openlp.core.lib.ui import create_widget_action from openlp.core.utils import AppLocation -from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, SongImportForm, SongExportForm -from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, clean_string, natcmp +from openlp.plugins.songs.forms.editsongform import EditSongForm +from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm +from openlp.plugins.songs.forms.songimportform import SongImportForm +from openlp.plugins.songs.forms.songexportform import SongExportForm +from openlp.plugins.songs.lib import VerseType, clean_string, natcmp from openlp.plugins.songs.lib.db import Author, Song, Book, MediaFile from openlp.plugins.songs.lib.ui import SongStrings +from openlp.plugins.songs.lib.xml import OpenLyrics, SongXML log = logging.getLogger(__name__) @@ -302,7 +306,7 @@ class SongMediaItem(MediaManagerItem): def onNewClick(self): log.debug(u'onNewClick') - self.editSongForm.newSong() + self.editSongForm.new_song() self.editSongForm.exec_() self.onClearTextButtonClick() self.onSelectionChange() @@ -321,7 +325,7 @@ class SongMediaItem(MediaManagerItem): song_id = int(song_id) valid = self.plugin.manager.get_object(Song, song_id) if valid: - self.editSongForm.loadSong(song_id, preview) + self.editSongForm.load_song(song_id, preview) if self.editSongForm.exec_() == QtGui.QDialog.Accepted: self.autoSelectId = -1 self.on_song_list_load() @@ -342,7 +346,7 @@ class SongMediaItem(MediaManagerItem): if check_item_selected(self.listView, UiStrings().SelectEdit): self.editItem = self.listView.currentItem() item_id = self.editItem.data(QtCore.Qt.UserRole) - self.editSongForm.loadSong(item_id, False) + self.editSongForm.load_song(item_id, False) self.editSongForm.exec_() self.autoSelectId = -1 self.on_song_list_load() diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py index 601133c03..f9ac6ebb3 100644 --- a/openlp/plugins/songs/lib/openlyricsexport.py +++ b/openlp/plugins/songs/lib/openlyricsexport.py @@ -37,10 +37,11 @@ from lxml import etree from openlp.core.lib import Registry, check_directory_exists, translate from openlp.core.utils import clean_filename -from openlp.plugins.songs.lib import OpenLyrics +from openlp.plugins.songs.lib.xml import OpenLyrics log = logging.getLogger(__name__) + class OpenLyricsExport(object): """ This provides the Openlyrics export. diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 80c01760f..d855f521e 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -39,11 +39,11 @@ from lxml import etree from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.ui import SongStrings -from openlp.plugins.songs.lib import OpenLyrics -from openlp.plugins.songs.lib.xml import OpenLyricsError +from openlp.plugins.songs.lib.xml import OpenLyrics, OpenLyricsError log = logging.getLogger(__name__) + class OpenLyricsImport(SongImport): """ This provides the Openlyrics import. diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 3652185f9..b98180f20 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -43,11 +43,13 @@ from openlp.core.lib.db import Manager from openlp.core.lib.ui import create_action from openlp.core.utils import get_filesystem_encoding from openlp.core.utils.actions import ActionList -from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, SongsTab +from openlp.plugins.songs.lib import clean_song, upgrade from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.mediaitem import SongSearch from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.olpimport import OpenLPSongImport +from openlp.plugins.songs.lib.mediaitem import SongMediaItem +from openlp.plugins.songs.lib.songstab import SongsTab log = logging.getLogger(__name__) __default_settings__ = { diff --git a/tests/functional/openlp_core_lib/test_screen.py b/tests/functional/openlp_core_lib/test_screen.py index 4b4df8e9b..007889a12 100644 --- a/tests/functional/openlp_core_lib/test_screen.py +++ b/tests/functional/openlp_core_lib/test_screen.py @@ -23,11 +23,17 @@ class TestScreenList(TestCase): """ Set up the components need for all tests. """ + # Mocked out desktop object + self.desktop = MagicMock() + self.desktop.primaryScreen.return_value = SCREEN[u'primary'] + self.desktop.screenCount.return_value = SCREEN[u'number'] + self.desktop.screenGeometry.return_value = SCREEN[u'size'] + self.application = QtGui.QApplication.instance() Registry.create() self.application.setOrganizationName(u'OpenLP-tests') self.application.setOrganizationDomain(u'openlp.org') - self.screens = ScreenList.create(self.application.desktop()) + self.screens = ScreenList.create(self.desktop) def tearDown(self): """ @@ -38,21 +44,16 @@ class TestScreenList(TestCase): def add_desktop_test(self): """ - Test the ScreenList class' - screen_count_changed method to check if new monitors are detected by OpenLP. + Test the ScreenList.screen_count_changed method to check if new monitors are detected by OpenLP. """ - # GIVEN: The screen list. - old_screens = copy.deepcopy(self.screens.screen_list) - # Mock the attributes. - self.screens.desktop.primaryScreen = MagicMock(return_value=SCREEN[u'primary']) - self.screens.desktop.screenCount = MagicMock(return_value=SCREEN[u'number'] + 1) - self.screens.desktop.screenGeometry = MagicMock(return_value=SCREEN[u'size']) + # GIVEN: The screen list at its current size + old_screen_count = len(self.screens.screen_list) - # WHEN: Add a new screen. - self.screens.screen_count_changed(len(old_screens)) + # WHEN: We add a new screen + self.desktop.screenCount.return_value = SCREEN[u'number'] + 1 + self.screens.screen_count_changed(old_screen_count) - # THEN: The screen should have been added. - new_screens = self.screens.screen_list - assert len(old_screens) + 1 == len(new_screens), u'The new_screens list should be bigger.' - - # THEN: The screens should be identical. - assert SCREEN == new_screens.pop(), u'The new screen should be identical to the screen defined above.' + # THEN: The screen should have been added and the screens should be identical + new_screen_count = len(self.screens.screen_list) + assert old_screen_count + 1 == new_screen_count, u'The new_screens list should be bigger' + assert SCREEN == self.screens.screen_list.pop(), u'The 2nd screen should be identical to the first screen' diff --git a/tests/functional/openlp_core_utils/__init__.py b/tests/functional/openlp_core_utils/__init__.py index 33507f08b..e69de29bb 100644 --- a/tests/functional/openlp_core_utils/__init__.py +++ b/tests/functional/openlp_core_utils/__init__.py @@ -1 +0,0 @@ -__author__ = 'raoul' diff --git a/tests/functional/openlp_plugins/__init__.py b/tests/functional/openlp_plugins/__init__.py new file mode 100644 index 000000000..33507f08b --- /dev/null +++ b/tests/functional/openlp_plugins/__init__.py @@ -0,0 +1 @@ +__author__ = 'raoul' diff --git a/tests/functional/openlp_plugins/songs/__init__.py b/tests/functional/openlp_plugins/songs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py new file mode 100644 index 000000000..221b54ec2 --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -0,0 +1,226 @@ +""" +This module contains tests for the lib submodule of the Songs plugin. +""" + +from unittest import TestCase + +from mock import patch + +from openlp.plugins.songs.lib import VerseType, clean_string, clean_title + + +class TestLib(TestCase): + """ + Test the functions in the :mod:`lib` module. + """ + def clean_string_test(self): + """ + Test the clean_string() function + """ + # GIVEN: A "dirty" string + dirty_string = u'Ain\'t gonna find\t you there.' + + # WHEN: We run the string through the function + result = clean_string(dirty_string) + + # THEN: The string should be cleaned up and lower-cased + self.assertEqual(result, u'aint gonna find you there ', u'The string should be cleaned up properly') + + def clean_title_test(self): + """ + Test the clean_title() function + """ + # GIVEN: A "dirty" string + dirty_string = u'This\u0000 is a\u0014 dirty \u007Fstring\u009F' + + # WHEN: We run the string through the function + result = clean_title(dirty_string) + + # THEN: The string should be cleaned up + self.assertEqual(result, u'This is a dirty string', u'The title should be cleaned up properly: "%s"' % result) + + +class TestVerseType(TestCase): + """ + This is a test case to test various methods in the VerseType enumeration class. + """ + + def translated_tag_test(self): + """ + Test that the translated_tag() method returns the correct tags + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_tag() method with a "verse" + result = VerseType.translated_tag(u'v') + + # THEN: The result should be "V" + self.assertEqual(result, u'V', u'The result should be "V"') + + # WHEN: We run the translated_tag() method with a "chorus" + result = VerseType.translated_tag(u'c') + + # THEN: The result should be "C" + self.assertEqual(result, u'C', u'The result should be "C"') + + def translated_invalid_tag_test(self): + """ + Test that the translated_tag() method returns the default tag when passed an invalid tag + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_tag() method with an invalid verse type + result = VerseType.translated_tag(u'z') + + # THEN: The result should be "O" + self.assertEqual(result, u'O', u'The result should be "O", but was "%s"' % result) + + def translated_invalid_tag_with_specified_default_test(self): + """ + Test that the translated_tag() method returns the specified default tag when passed an invalid tag + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_tag() method with an invalid verse type and specify a default + result = VerseType.translated_tag(u'q', VerseType.Bridge) + + # THEN: The result should be "B" + self.assertEqual(result, u'B', u'The result should be "B", but was "%s"' % result) + + def translated_invalid_tag_with_invalid_default_test(self): + """ + Test that the translated_tag() method returns a sane default tag when passed an invalid default + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_tag() method with an invalid verse type and an invalid default + result = VerseType.translated_tag(u'q', 29) + + # THEN: The result should be "O" + self.assertEqual(result, u'O', u'The result should be "O", but was "%s"' % result) + + def translated_name_test(self): + """ + Test that the translated_name() method returns the correct name + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_name() method with a "verse" + result = VerseType.translated_name(u'v') + + # THEN: The result should be "Verse" + self.assertEqual(result, u'Verse', u'The result should be "Verse"') + + # WHEN: We run the translated_name() method with a "chorus" + result = VerseType.translated_name(u'c') + + # THEN: The result should be "Chorus" + self.assertEqual(result, u'Chorus', u'The result should be "Chorus"') + + def translated_invalid_name_test(self): + """ + Test that the translated_name() method returns the default name when passed an invalid tag + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_name() method with an invalid verse type + result = VerseType.translated_name(u'z') + + # THEN: The result should be "Other" + self.assertEqual(result, u'Other', u'The result should be "Other", but was "%s"' % result) + + def translated_invalid_name_with_specified_default_test(self): + """ + Test that the translated_name() method returns the specified default name when passed an invalid tag + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_name() method with an invalid verse type and specify a default + result = VerseType.translated_name(u'q', VerseType.Bridge) + + # THEN: The result should be "Bridge" + self.assertEqual(result, u'Bridge', u'The result should be "Bridge", but was "%s"' % result) + + def translated_invalid_name_with_invalid_default_test(self): + """ + Test that the translated_name() method returns the specified default tag when passed an invalid tag + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the translated_name() method with an invalid verse type and specify an invalid default + result = VerseType.translated_name(u'q', 29) + + # THEN: The result should be "Other" + self.assertEqual(result, u'Other', u'The result should be "Other", but was "%s"' % result) + + def from_tag_test(self): + """ + Test that the from_tag() method returns the correct VerseType. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with a valid verse type, we get the name back + result = VerseType.from_tag(u'v') + + # THEN: The result should be VerseType.Verse + self.assertEqual(result, VerseType.Verse, u'The result should be VerseType.Verse, but was "%s"' % result) + + def from_tag_with_invalid_tag_test(self): + """ + Test that the from_tag() method returns the default VerseType when it is passed an invalid tag. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with a valid verse type, we get the name back + result = VerseType.from_tag(u'w') + + # THEN: The result should be VerseType.Other + self.assertEqual(result, VerseType.Other, u'The result should be VerseType.Other, but was "%s"' % result) + + def from_tag_with_specified_default_test(self): + """ + Test that the from_tag() method returns the specified default when passed an invalid tag. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with an invalid verse type, we get the specified default back + result = VerseType.from_tag(u'x', VerseType.Chorus) + + # THEN: The result should be VerseType.Chorus + self.assertEqual(result, VerseType.Chorus, u'The result should be VerseType.Chorus, but was "%s"' % result) + + def from_tag_with_invalid_default_test(self): + """ + Test that the from_tag() method returns a sane default when passed an invalid tag and an invalid default. + """ + # GIVEN: A mocked out translate() function that just returns what it was given + with patch(u'openlp.plugins.songs.lib.translate') as mocked_translate: + mocked_translate.side_effect = lambda x, y: y + + # WHEN: We run the from_tag() method with an invalid verse type, we get the specified default back + result = VerseType.from_tag(u'm', 29) + + # THEN: The result should be VerseType.Other + self.assertEqual(result, VerseType.Other, u'The result should be VerseType.Other, but was "%s"' % result) diff --git a/tests/interfaces/__init__.py b/tests/interfaces/__init__.py index 0b5157b46..f14948f08 100644 --- a/tests/interfaces/__init__.py +++ b/tests/interfaces/__init__.py @@ -9,5 +9,5 @@ sip.setapi(u'QVariant', 2) from PyQt4 import QtGui -# Only one QApplication can be created. Use QtGui.QApplication.instance() when you need to "create" a QApplication. +# Only one QApplication can be created. Use QtGui.QApplication.instance() when you need to "create" an QApplication. application = QtGui.QApplication([]) diff --git a/tests/interfaces/openlp_core_lib/test_pluginmanager.py b/tests/interfaces/openlp_core_lib/test_pluginmanager.py index b4b597356..6a046c80c 100644 --- a/tests/interfaces/openlp_core_lib/test_pluginmanager.py +++ b/tests/interfaces/openlp_core_lib/test_pluginmanager.py @@ -3,7 +3,8 @@ Package to test the openlp.core.lib.pluginmanager package. """ import os import sys -from tempfile import mkstemp +import shutil +from tempfile import mkstemp, mkdtemp from unittest import TestCase from mock import MagicMock @@ -23,7 +24,9 @@ class TestPluginManager(TestCase): Some pre-test setup required. """ fd, self.ini_file = mkstemp(u'.ini') + self.temp_dir = mkdtemp(u'openlp') Settings().set_filename(self.ini_file) + Settings().setValue(u'advanced/data path', self.temp_dir) Registry.create() Registry().register(u'service_list', MagicMock()) self.app = QtGui.QApplication.instance() @@ -31,9 +34,11 @@ class TestPluginManager(TestCase): Registry().register(u'main_window', self.main_window) def tearDown(self): - os.unlink(self.ini_file) del self.app del self.main_window + Settings().remove(u'advanced/data path') + shutil.rmtree(self.temp_dir) + os.unlink(self.ini_file) def find_plugins_test(self): """ diff --git a/tests/interfaces/openlp_core_ui/test_servicenotedialog.py b/tests/interfaces/openlp_core_ui/test_servicenotedialog.py index e04f9975d..5a305b79c 100644 --- a/tests/interfaces/openlp_core_ui/test_servicenotedialog.py +++ b/tests/interfaces/openlp_core_ui/test_servicenotedialog.py @@ -1,5 +1,5 @@ """ - Package to test the openlp.core.ui package. +Package to test the openlp.core.ui package. """ from unittest import TestCase from mock import patch @@ -10,6 +10,7 @@ from openlp.core.lib import Registry from openlp.core.ui import servicenoteform + class TestStartNoteDialog(TestCase): def setUp(self): diff --git a/tests/interfaces/openlp_core_ui/test_starttimedialog.py b/tests/interfaces/openlp_core_ui/test_starttimedialog.py index c09426a1f..e096b46a5 100644 --- a/tests/interfaces/openlp_core_ui/test_starttimedialog.py +++ b/tests/interfaces/openlp_core_ui/test_starttimedialog.py @@ -1,5 +1,5 @@ """ - Package to test the openlp.core.ui package. +Package to test the openlp.core.ui package. """ from unittest import TestCase from mock import MagicMock, patch @@ -10,6 +10,7 @@ from openlp.core.lib import Registry from openlp.core.ui import starttimeform + class TestStartTimeDialog(TestCase): def setUp(self): diff --git a/tests/interfaces/openlp_plugins_songs_forms/__init__.py b/tests/interfaces/openlp_plugins_songs_forms/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/interfaces/openlp_plugins_songs_forms/test_authorsform.py b/tests/interfaces/openlp_plugins_songs_forms/test_authorsform.py new file mode 100644 index 000000000..5d48c4de3 --- /dev/null +++ b/tests/interfaces/openlp_plugins_songs_forms/test_authorsform.py @@ -0,0 +1,117 @@ +""" +Package to test the openlp.plugins.songs.forms.authorsform package. +""" +from unittest import TestCase + +from PyQt4 import QtGui + +from openlp.core.lib import Registry +from openlp.plugins.songs.forms.authorsform import AuthorsForm + + +class TestAuthorsForm(TestCase): + + def setUp(self): + """ + Create the UI + """ + Registry.create() + self.app = QtGui.QApplication.instance() + self.main_window = QtGui.QMainWindow() + Registry().register(u'main_window', self.main_window) + self.form = AuthorsForm() + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + del self.form + del self.main_window + del self.app + + def ui_defaults_test(self): + """ + Test the AuthorForm defaults are correct + """ + self.assertEqual(self.form.first_name_edit.text(), u'', u'The first name edit should be empty') + self.assertEqual(self.form.last_name_edit.text(), u'', u'The last name edit should be empty') + self.assertEqual(self.form.display_edit.text(), u'', u'The display name edit should be empty') + + def get_first_name_property_test(self): + """ + Test that getting the first name property on the AuthorForm works correctly. + """ + # GIVEN: A first name to set + first_name = u'John' + + # WHEN: The first_name_edit's text is set + self.form.first_name_edit.setText(first_name) + + # THEN: The first_name property should have the correct value + self.assertEqual(self.form.first_name, first_name, u'The first name property should be correct') + + def set_first_name_property_test(self): + """ + Test that setting the first name property on the AuthorForm works correctly. + """ + # GIVEN: A first name to set + first_name = u'James' + + # WHEN: The first_name property is set + self.form.first_name = first_name + + # THEN: The first_name_edit should have the correct value + self.assertEqual(self.form.first_name_edit.text(), first_name, u'The first name should be set correctly') + + def get_last_name_property_test(self): + """ + Test that getting the last name property on the AuthorForm works correctly. + """ + # GIVEN: A last name to set + last_name = u'Smith' + + # WHEN: The last_name_edit's text is set + self.form.last_name_edit.setText(last_name) + + # THEN: The last_name property should have the correct value + self.assertEqual(self.form.last_name, last_name, u'The last name property should be correct') + + def set_last_name_property_test(self): + """ + Test that setting the last name property on the AuthorForm works correctly. + """ + # GIVEN: A last name to set + last_name = u'Potter' + + # WHEN: The last_name property is set + self.form.last_name = last_name + + # THEN: The last_name_edit should have the correct value + self.assertEqual(self.form.last_name_edit.text(), last_name, u'The last name should be set correctly') + + def get_display_name_property_test(self): + """ + Test that getting the display name property on the AuthorForm works correctly. + """ + # GIVEN: A display name to set + display_name = u'John' + + # WHEN: The display_name_edit's text is set + self.form.display_edit.setText(display_name) + + # THEN: The display_name property should have the correct value + self.assertEqual(self.form.display_name, display_name, u'The display name property should be correct') + + def set_display_name_property_test(self): + """ + Test that setting the display name property on the AuthorForm works correctly. + """ + # GIVEN: A display name to set + display_name = u'John' + + # WHEN: The display_name property is set + self.form.display_name = display_name + + # THEN: The display_name_edit should have the correct value + self.assertEqual(self.form.display_edit.text(), display_name, u'The display name should be set correctly') + diff --git a/tests/interfaces/openlp_plugins_songs_forms/test_editsongform.py b/tests/interfaces/openlp_plugins_songs_forms/test_editsongform.py new file mode 100644 index 000000000..a84eb6e67 --- /dev/null +++ b/tests/interfaces/openlp_plugins_songs_forms/test_editsongform.py @@ -0,0 +1,40 @@ +""" +Package to test the openlp.plugins.songs.forms.editsongform package. +""" +from mock import MagicMock +from unittest import TestCase + +from PyQt4 import QtGui + +from openlp.core.lib import Registry +from openlp.plugins.songs.forms.editsongform import EditSongForm + + +class TestEditSongForm(TestCase): + def setUp(self): + """ + Create the UI + """ + Registry.create() + self.app = QtGui.QApplication.instance() + self.main_window = QtGui.QMainWindow() + Registry().register(u'main_window', self.main_window) + Registry().register(u'theme_manager', MagicMock()) + self.form = EditSongForm(MagicMock(), self.main_window, MagicMock()) + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + del self.form + del self.main_window + del self.app + + def ui_defaults_test(self): + """ + Test that the EditSongForm defaults are correct + """ + self.assertFalse(self.form.verse_edit_button.isEnabled(), u'The verse edit button should not be enabled') + self.assertFalse(self.form.verse_delete_button.isEnabled(), u'The verse delete button should not be enabled') + self.assertFalse(self.form.author_remove_button.isEnabled(), u'The author remove button should not be enabled') + self.assertFalse(self.form.topic_remove_button.isEnabled(), u'The topic remove button should not be enabled') diff --git a/tests/interfaces/openlp_plugins_songs_forms/test_editverseform.py b/tests/interfaces/openlp_plugins_songs_forms/test_editverseform.py new file mode 100644 index 000000000..cfd5ed0ef --- /dev/null +++ b/tests/interfaces/openlp_plugins_songs_forms/test_editverseform.py @@ -0,0 +1,35 @@ +""" +Package to test the openlp.plugins.songs.forms.editverseform package. +""" +from unittest import TestCase + +from PyQt4 import QtGui + +from openlp.core.lib import Registry +from openlp.plugins.songs.forms.editverseform import EditVerseForm + + +class TestEditVerseForm(TestCase): + def setUp(self): + """ + Create the UI + """ + Registry.create() + self.app = QtGui.QApplication.instance() + self.main_window = QtGui.QMainWindow() + Registry().register(u'main_window', self.main_window) + self.form = EditVerseForm() + + def tearDown(self): + """ + Delete all the C++ objects at the end so that we don't have a segfault + """ + del self.form + del self.main_window + del self.app + + def ui_defaults_test(self): + """ + Test the EditVerseForm defaults are correct + """ + self.assertEqual(self.form.verseTextEdit.toPlainText(), u'', u'The verse edit box is empty.')