Update Songs forms

This commit is contained in:
Tim Bentley 2014-03-04 18:49:30 +00:00
parent 873286df9a
commit 43f156d9fe
22 changed files with 549 additions and 499 deletions

View File

@ -63,7 +63,7 @@ class ServiceNoteForm(QtGui.QDialog):
self.dialog_layout = QtGui.QVBoxLayout(self)
self.dialog_layout.setContentsMargins(8, 8, 8, 8)
self.dialog_layout.setSpacing(8)
self.dialog_layout.setObjectName('verticalLayout')
self.dialog_layout.setObjectName('vertical_layout')
self.text_edit = SpellTextEdit(self, False)
self.text_edit.setObjectName('textEdit')
self.dialog_layout.addWidget(self.text_edit)

View File

@ -215,7 +215,7 @@ class OpenLPWizard(QtGui.QWizard):
"""
if self.with_progress_page and self.page(pageId) == self.progress_page:
self.pre_wizard()
self.performWizard()
self.perform_wizard()
self.post_wizard()
else:
self.custom_page_changed(pageId)
@ -294,8 +294,8 @@ class OpenLPWizard(QtGui.QWizard):
if filters:
filters += ';;'
filters += '%s (*)' % UiStrings().AllFiles
filename = QtGui.QFileDialog.getOpenFileName(self, title,
os.path.dirname(Settings().value(self.plugin.settings_section + '/' + setting_name)), filters)
filename = QtGui.QFileDialog.getOpenFileName(
self, title, os.path.dirname(Settings().value(self.plugin.settings_section + '/' + setting_name)), filters)
if filename:
editbox.setText(filename)
Settings().setValue(self.plugin.settings_section + '/' + setting_name, filename)
@ -313,8 +313,9 @@ class OpenLPWizard(QtGui.QWizard):
``setting_name``
The place where to save the last opened directory.
"""
folder = QtGui.QFileDialog.getExistingDirectory(self, title,
Settings().value(self.plugin.settings_section + '/' + setting_name), QtGui.QFileDialog.ShowDirsOnly)
folder = QtGui.QFileDialog.getExistingDirectory(
self, title, Settings().value(self.plugin.settings_section + '/' + setting_name),
QtGui.QFileDialog.ShowDirsOnly)
if folder:
editbox.setText(folder)
Settings().setValue(self.plugin.settings_section + '/' + setting_name, folder)

View File

@ -524,7 +524,7 @@ class BibleImportForm(OpenLPWizard):
self.progress_label.setText(WizardStrings.StartingImport)
self.application.process_events()
def performWizard(self):
def perform_wizard(self):
"""
Perform the actual import.
"""

View File

@ -107,7 +107,7 @@ class BibleUpgradeForm(OpenLPWizard):
"""
if self.page(pageId) == self.progress_page:
self.pre_wizard()
self.performWizard()
self.perform_wizard()
self.post_wizard()
elif self.page(pageId) == self.selectPage and not self.files:
self.next()
@ -312,7 +312,7 @@ class BibleUpgradeForm(OpenLPWizard):
"""
Set default values for the wizard pages.
"""
log.debug('BibleUpgrade setDefaults')
log.debug('BibleUpgrade set_defaults')
settings = Settings()
settings.beginGroup(self.plugin.settings_section)
self.stop_import_flag = False
@ -338,7 +338,7 @@ class BibleUpgradeForm(OpenLPWizard):
self.progress_label.setText(translate('BiblesPlugin.UpgradeWizardForm', 'Starting upgrade...'))
self.application.process_events()
def performWizard(self):
def perform_wizard(self):
"""
Perform the actual upgrade.
"""

View File

@ -43,16 +43,15 @@ from openlp.plugins.presentations.lib import PresentationController, Presentatio
log = logging.getLogger(__name__)
__default_settings__ = {
'presentations/override app': QtCore.Qt.Unchecked,
'presentations/enable_pdf_program': QtCore.Qt.Unchecked,
'presentations/pdf_program': '',
'presentations/Impress': QtCore.Qt.Checked,
'presentations/Powerpoint': QtCore.Qt.Checked,
'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
'presentations/Pdf': QtCore.Qt.Checked,
'presentations/presentations files': []
}
__default_settings__ = {'presentations/override app': QtCore.Qt.Unchecked,
'presentations/enable_pdf_program': QtCore.Qt.Unchecked,
'presentations/pdf_program': '',
'presentations/Impress': QtCore.Qt.Checked,
'presentations/Powerpoint': QtCore.Qt.Checked,
'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
'presentations/Pdf': QtCore.Qt.Checked,
'presentations/presentations files': []
}
class PresentationPlugin(Plugin):
@ -147,10 +146,10 @@ class PresentationPlugin(Plugin):
Return information about this plugin.
"""
about_text = translate('PresentationPlugin', '<strong>Presentation '
'Plugin</strong><br />The presentation plugin provides the '
'ability to show presentations using a number of different '
'programs. The choice of available presentation programs is '
'available to the user in a drop down box.')
'Plugin</strong><br />The presentation plugin provides the '
'ability to show presentations using a number of different '
'programs. The choice of available presentation programs is '
'available to the user in a drop down box.')
return about_text
def set_plugin_text_strings(self):

View File

@ -111,8 +111,8 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
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:
'You have not set a display name for the author, combine the first and last names?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.display_edit.setText(self.first_name_edit.text() + ' ' + self.last_name_edit.text())
return QtGui.QDialog.accept(self)
else:

View File

@ -47,8 +47,8 @@ log = logging.getLogger(__name__)
class DuplicateSongRemovalForm(OpenLPWizard):
"""
This is the Duplicate Song Removal Wizard. It provides functionality to
search for and remove duplicate songs in the database.
This is the Duplicate Song Removal Wizard. It provides functionality to search for and remove duplicate songs
in the database.
"""
log.info('DuplicateSongRemovalForm loaded')
@ -56,19 +56,16 @@ class DuplicateSongRemovalForm(OpenLPWizard):
"""
Instantiate the wizard, and run any extra setup we need to.
``parent``
The QWidget-derived parent of the wizard.
``plugin``
The songs plugin.
:param plugin: The songs plugin.
"""
self.duplicate_song_list = []
self.review_current_count = 0
self.review_total_count = 0
# Used to interrupt ongoing searches when cancel is clicked.
self.break_search = False
super(DuplicateSongRemovalForm, self).__init__(Registry().get('main_window'),
plugin, 'duplicateSongRemovalWizard', ':/wizards/wizard_duplicateremoval.bmp', False)
super(DuplicateSongRemovalForm, self).__init__(
Registry().get('main_window'), plugin, 'duplicateSongRemovalWizard', ':/wizards/wizard_duplicateremoval.bmp'
, False)
self.setMinimumWidth(730)
def custom_signals(self):
@ -127,30 +124,31 @@ class DuplicateSongRemovalForm(OpenLPWizard):
"""
self.setWindowTitle(translate('Wizard', 'Wizard'))
self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
'Welcome to the Duplicate Song Removal Wizard'))
self.information_label.setText(translate("Wizard",
'This wizard will help you to remove duplicate songs from the song database. You will have a chance to '
'review every potential duplicate song before it is deleted. So no songs will be deleted without your '
'explicit approval.'))
'Welcome to the Duplicate Song Removal Wizard'))
self.information_label.setText(
translate("Wizard",
'This wizard will help you to remove duplicate songs from the song database. You will have a '
'chance to review every potential duplicate song before it is deleted. So no songs will be '
'deleted without your explicit approval.'))
self.searching_page.setTitle(translate('Wizard', 'Searching for duplicate songs.'))
self.searching_page.setSubTitle(translate('Wizard', 'Please wait while your songs database is analyzed.'))
self.update_review_counter_text()
self.review_page.setSubTitle(translate('Wizard',
'Here you can decide which songs to remove and which ones to keep.'))
'Here you can decide which songs to remove and which ones to keep.'))
def update_review_counter_text(self):
"""
Set the wizard review page header text.
"""
self.review_page.setTitle(translate('Wizard', 'Review duplicate songs (%s/%s)') % \
(self.review_current_count, self.review_total_count))
self.review_page.setTitle(
translate('Wizard', 'Review duplicate songs (%s/%s)') %
(self.review_current_count, self.review_total_count))
def custom_page_changed(self, page_id):
"""
Called when changing the wizard page.
``page_id``
ID of the page the wizard changed to.
:param page_id: ID of the page the wizard changed to.
"""
# Hide back button.
self.button(QtGui.QWizard.BackButton).hide()
@ -172,11 +170,11 @@ class DuplicateSongRemovalForm(OpenLPWizard):
for outer_song_counter in range(max_songs - 1):
for inner_song_counter in range(outer_song_counter + 1, max_songs):
if songs_probably_equal(songs[outer_song_counter], songs[inner_song_counter]):
duplicate_added = self.add_duplicates_to_song_list(songs[outer_song_counter],
songs[inner_song_counter])
duplicate_added = self.add_duplicates_to_song_list(
songs[outer_song_counter], songs[inner_song_counter])
if duplicate_added:
self.found_duplicates_edit.appendPlainText(songs[outer_song_counter].title + " = " +
songs[inner_song_counter].title)
self.found_duplicates_edit.appendPlainText(
songs[outer_song_counter].title + " = " + songs[inner_song_counter].title)
self.duplicate_search_progress_bar.setValue(self.duplicate_search_progress_bar.value() + 1)
# The call to process_events() will keep the GUI responsive.
self.application.process_events()
@ -200,23 +198,20 @@ class DuplicateSongRemovalForm(OpenLPWizard):
self.button(QtGui.QWizard.FinishButton).setEnabled(True)
self.button(QtGui.QWizard.NextButton).hide()
self.button(QtGui.QWizard.CancelButton).hide()
QtGui.QMessageBox.information(self, translate('Wizard', 'Information'),
QtGui.QMessageBox.information(
self, translate('Wizard', 'Information'),
translate('Wizard', 'No duplicate songs have been found in the database.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
def add_duplicates_to_song_list(self, search_song, duplicate_song):
"""
Inserts a song duplicate (two similar songs) to the duplicate song list.
If one of the two songs is already part of the duplicate song list,
don't add another duplicate group but add the other song to that group.
Returns True if at least one of the songs was added, False if both were already
member of a group.
If one of the two songs is already part of the duplicate song list, don't add another duplicate group but
add the other song to that group.
Returns True if at least one of the songs was added, False if both were already member of a group.
``search_song``
The song we searched the duplicate for.
``duplicate_song``
The duplicate song.
:param search_song: The song we searched the duplicate for.
:param duplicate_song: The duplicate song.
"""
duplicate_group_found = False
duplicate_added = False
@ -259,8 +254,8 @@ class DuplicateSongRemovalForm(OpenLPWizard):
def validateCurrentPage(self):
"""
Controls whether we should switch to the next wizard page. This method loops
on the review page as long as there are more song duplicates to review.
Controls whether we should switch to the next wizard page. This method loops on the review page as long as
there are more song duplicates to review.
"""
if self.currentId() == self.review_page_id:
# As long as it's not the last duplicate list entry we revisit the review page.
@ -273,12 +268,10 @@ class DuplicateSongRemovalForm(OpenLPWizard):
def remove_button_clicked(self, song_review_widget):
"""
Removes a song from the database, removes the GUI element representing the
song on the review page, and disable the remove button if only one duplicate
is left.
Removes a song from the database, removes the GUI element representing the song on the review page, and
disable the remove button if only one duplicate is left.
``song_review_widget``
The SongReviewWidget whose song we should delete.
:param song_review_widget: The SongReviewWidget whose song we should delete.
"""
# Remove song from duplicate song list.
self.duplicate_song_list[-1].remove(song_review_widget.song)
@ -315,9 +308,8 @@ class DuplicateSongRemovalForm(OpenLPWizard):
def process_current_duplicate_entry(self):
"""
Update the review counter in the wizard header, add song widgets for
the current duplicate group to review, if it's the last
duplicate song group, hide the "next" button and show the "finish" button.
Update the review counter in the wizard header, add song widgets for the current duplicate group to review,
if it's the last duplicate song group, hide the "next" button and show the "finish" button.
"""
# Update the counter.
self.review_current_count = self.review_total_count - (len(self.duplicate_song_list) - 1)

View File

@ -153,8 +153,8 @@ class Ui_EditSongDialog(object):
self.topics_layout.setObjectName('topics_layout')
self.topic_add_layout = QtGui.QHBoxLayout()
self.topic_add_layout.setObjectName('topic_add_layout')
self.topicsComboBox = create_combo_box(self.topics_group_box, 'topicsComboBox')
self.topic_add_layout.addWidget(self.topicsComboBox)
self.topics_combo_box = create_combo_box(self.topics_group_box, 'topics_combo_box')
self.topic_add_layout.addWidget(self.topics_combo_box)
self.topic_add_button = QtGui.QPushButton(self.topics_group_box)
self.topic_add_button.setObjectName('topic_add_button')
self.topic_add_layout.addWidget(self.topic_add_button)
@ -296,7 +296,7 @@ class Ui_EditSongDialog(object):
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'))
translate('SongsPlugin.EditSongForm', 'Title && Lyrics'))
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'))
@ -308,7 +308,7 @@ class Ui_EditSongDialog(object):
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'))
translate('SongsPlugin.EditSongForm', 'Authors, Topics && Song Book'))
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'))
@ -316,9 +316,9 @@ class Ui_EditSongDialog(object):
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'))
translate('SongsPlugin.EditSongForm', 'Theme, Copyright Info && Comments'))
self.song_tab_widget.setTabText(self.song_tab_widget.indexOf(self.audio_tab),
translate('SongsPlugin.EditSongForm', 'Linked Audio'))
translate('SongsPlugin.EditSongForm', 'Linked Audio'))
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'))

View File

@ -131,6 +131,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.authors_list_view.addItem(author_item)
def _extract_verse_order(self, verse_order):
"""
Split out the verse order
:param verse_order: The starting verse order
:return: revised order
"""
order = []
order_names = str(verse_order).split()
for item in order_names:
@ -153,6 +159,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
return order
def _validate_verse_list(self, verse_order, verse_count):
"""
Check the verse order list has valid verses
:param verse_order: Verse order
:param verse_count: number of verses
:return: Count of invalid verses
"""
verses = []
invalid_verses = []
verse_names = []
@ -171,12 +184,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
valid = create_separated_list(verse_names)
if len(invalid_verses) > 1:
msg = translate('SongsPlugin.EditSongForm', 'There are no verses corresponding to "%(invalid)s".'
'Valid entries are %(valid)s.\nPlease enter the verses seperated by spaces.') \
% {'invalid' : ', '.join(invalid_verses), 'valid' : valid}
'Valid entries are %(valid)s.\nPlease enter the verses separated by spaces.') % \
{'invalid': ', '.join(invalid_verses), 'valid' : valid}
else:
msg = translate('SongsPlugin.EditSongForm', 'There is no verse corresponding to "%(invalid)s".'
'Valid entries are %(valid)s.\nPlease enter the verses seperated by spaces.') \
% {'invalid' : invalid_verses[0], 'valid' : valid}
'Valid entries are %(valid)s.\nPlease enter the verses separated by spaces.') % \
{'invalid': invalid_verses[0], 'valid' : valid}
critical_error_message_box(title=translate('SongsPlugin.EditSongForm', 'Invalid Verse Order'),
message=msg)
return len(invalid_verses) == 0
@ -213,7 +226,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
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'),
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='')
@ -250,17 +264,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def keyPressEvent(self, event):
"""
Reimplement the keyPressEvent to react on Return/Enter keys. When some combo boxes have focus we do not want
Re-implement the keyPressEvent to react on Return/Enter keys. When some combo boxes have focus we do not want
dialog's default action be triggered but instead our own.
``event``
A QtGui.QKeyEvent event.
:param event: A QtGui.QKeyEvent event.
"""
if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
if self.authors_combo_box.hasFocus() and self.authors_combo_box.currentText():
self.on_author_add_button_clicked()
return
if self.topicsComboBox.hasFocus() and self.topicsComboBox.currentText():
if self.topics_combo_box.hasFocus() and self.topics_combo_box.currentText():
self.on_topic_add_button_clicked()
return
QtGui.QDialog.keyPressEvent(self, event)
@ -294,7 +307,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
Load the topics into the combobox.
"""
self.topics = []
self._load_objects(Topic, self.topicsComboBox, self.topics)
self._load_objects(Topic, self.topics_combo_box, self.topics)
def load_books(self):
"""
@ -321,7 +334,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
for plugin in self.plugin_manager.plugins:
if plugin.name == 'media' and plugin.status == PluginStatus.Active:
self.from_media_button.setVisible(True)
self.media_form.populateFiles(plugin.media_item.get_list(MediaType.Audio))
self.media_form.populate_files(plugin.media_item.get_list(MediaType.Audio))
break
def new_song(self):
@ -358,11 +371,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
"""
Loads a song.
``song_id``
The song id (int).
``preview``
Should be ``True`` if the song is also previewed (boolean).
:param song_id: The song id (int).
:param preview: Should be ``True`` if the song is also previewed (boolean).
"""
log.debug('Load Song')
self.initialise()
@ -396,8 +406,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.verse_list_widget.setRowCount(0)
verse_tags_translated = False
if self.song.lyrics.startswith('<?xml version='):
songXML = SongXML()
verse_list = songXML.get_verses(self.song.lyrics)
song_xml = SongXML()
verse_list = song_xml.get_verses(self.song.lyrics)
for count, verse in enumerate(verse_list):
self.verse_list_widget.setRowCount(self.verse_list_widget.rowCount() + 1)
# This silently migrates from localized verse type markup.
@ -487,20 +497,21 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
item = int(self.authors_combo_box.currentIndex())
text = self.authors_combo_box.currentText().strip(' \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.
# the QCompleter auto-completion class. See bug #812628.
if text in self.authors:
# Index 0 is a blank string, so add 1
item = self.authors.index(text) + 1
if item == 0 and text:
if QtGui.QMessageBox.question(self,
translate('SongsPlugin.EditSongForm', 'Add Author'),
translate('SongsPlugin.EditSongForm', 'This author does not exist, do you want to add them?'),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
if QtGui.QMessageBox.question(
self,
translate('SongsPlugin.EditSongForm', 'Add Author'),
translate('SongsPlugin.EditSongForm', 'This author does not exist, do you want to add them?'),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
if text.find(' ') == -1:
author = Author.populate(first_name='', last_name='', display_name=text)
else:
author = Author.populate(first_name=text.rsplit(' ', 1)[0],
last_name=text.rsplit(' ', 1)[1], display_name=text)
author = Author.populate(first_name=text.rsplit(' ', 1)[0], last_name=text.rsplit(' ', 1)[1],
display_name=text)
self.manager.save_object(author)
self._add_author_to_list(author)
self.load_authors()
@ -510,18 +521,18 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
elif item > 0:
item_id = (self.authors_combo_box.itemData(item))
author = self.manager.get_object(Author, item_id)
if self.authors_list_view.findItems(str(author.display_name),
QtCore.Qt.MatchExactly):
if self.authors_list_view.findItems(str(author.display_name), QtCore.Qt.MatchExactly):
critical_error_message_box(
message=translate('SongsPlugin.EditSongForm', 'This author is already in the list.'))
else:
self._add_author_to_list(author)
self.authors_combo_box.setCurrentIndex(0)
else:
QtGui.QMessageBox.warning(self, UiStrings().NISs,
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.'))
'from the list, or type in a new author and click the "Add Author to Song" button to add '
'the new author.'))
def on_authors_list_view_clicked(self):
"""
@ -540,10 +551,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.authors_list_view.takeItem(row)
def on_topic_add_button_clicked(self):
item = int(self.topicsComboBox.currentIndex())
text = self.topicsComboBox.currentText()
item = int(self.topics_combo_box.currentIndex())
text = self.topics_combo_box.currentText()
if item == 0 and text:
if QtGui.QMessageBox.question(self, translate('SongsPlugin.EditSongForm', 'Add Topic'),
if QtGui.QMessageBox.question(
self, translate('SongsPlugin.EditSongForm', 'Add Topic'),
translate('SongsPlugin.EditSongForm', 'This topic does not exist, do you want to add it?'),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
topic = Topic.populate(name=text)
@ -552,25 +564,26 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
topic_item.setData(QtCore.Qt.UserRole, topic.id)
self.topics_list_view.addItem(topic_item)
self.load_topics()
self.topicsComboBox.setCurrentIndex(0)
self.topics_combo_box.setCurrentIndex(0)
else:
return
elif item > 0:
item_id = (self.topicsComboBox.itemData(item))
item_id = (self.topics_combo_box.itemData(item))
topic = self.manager.get_object(Topic, item_id)
if self.topics_list_view.findItems(str(topic.name),
QtCore.Qt.MatchExactly):
if self.topics_list_view.findItems(str(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(str(topic.name))
topic_item.setData(QtCore.Qt.UserRole, topic.id)
self.topics_list_view.addItem(topic_item)
self.topicsComboBox.setCurrentIndex(0)
self.topics_combo_box.setCurrentIndex(0)
else:
QtGui.QMessageBox.warning(self, UiStrings().NISs,
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.'))
'from the list, or type in a new topic and click the "Add Topic to Song" button to add the '
'new topic.'))
def on_topic_list_view_clicked(self):
self.topic_remove_button.setEnabled(True)
@ -588,7 +601,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def on_verse_add_button_clicked(self):
self.verse_form.set_verse('', True)
if self.verse_form.exec_():
after_text, verse_tag, verse_num = self.verse_form.get_verse()
after_text, verse_tag, verse_num = self.verse_form.get_verse
verse_def = '%s%s' % (verse_tag, verse_num)
item = QtGui.QTableWidgetItem(after_text)
item.setData(QtCore.Qt.UserRole, verse_def)
@ -606,7 +619,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
verse_id = item.data(QtCore.Qt.UserRole)
self.verse_form.set_verse(temp_text, True, verse_id)
if self.verse_form.exec_():
after_text, verse_tag, verse_num = self.verse_form.get_verse()
after_text, verse_tag, verse_num = self.verse_form.get_verse
verse_def = '%s%s' % (verse_tag, verse_num)
item.setData(QtCore.Qt.UserRole, verse_def)
item.setText(after_text)
@ -628,6 +641,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.on_verse_order_text_changed(self.verse_order_edit.text())
def on_verse_edit_all_button_clicked(self):
"""
Verse edit all button (save) pressed
:return:
"""
verse_list = ''
if self.verse_list_widget.rowCount() > 0:
for row in range(self.verse_list_widget.rowCount()):
@ -643,7 +661,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.verse_form.set_verse('')
if not self.verse_form.exec_():
return
verse_list = self.verse_form.get_all_verses()
verse_list = self.verse_form.get_all_verses
verse_list = str(verse_list.replace('\r\n', '\n'))
self.verse_list_widget.clear()
self.verse_list_widget.setRowCount(0)
@ -686,6 +704,10 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.on_verse_order_text_changed(self.verse_order_edit.text())
def on_verse_delete_button_clicked(self):
"""
Verse Delete button pressed
"""
self.verse_list_widget.removeRow(self.verse_list_widget.currentRow())
if not self.verse_list_widget.selectedItems():
self.verse_edit_button.setEnabled(False)
@ -696,8 +718,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
Checks if the verse order is complete or missing. Shows a error message according to the state of the verse
order.
``text``
The text of the verse order edit (ignored).
:param text: The text of the verse order edit (ignored).
"""
# Extract all verses which were used in the order.
verses_in_order = self._extract_verse_order(self.verse_order_edit.text())
@ -719,6 +740,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.warning_label.setText(label_text)
def on_copyright_insert_button_triggered(self):
"""
Copyright insert button pressed
"""
text = self.copyright_edit.text()
pos = self.copyright_edit.cursorPosition()
sign = SongStrings.CopyrightSymbol
@ -728,6 +752,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.copyright_edit.setCursorPosition(pos + len(sign))
def on_maintenance_button_clicked(self):
"""
Maintenance button pressed
"""
temp_song_book = None
item = int(self.song_book_combo_box.currentIndex())
text = self.song_book_combo_box.currentText()
@ -745,8 +772,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
Save and Preview button clicked.
The Song is valid so as the plugin to add it to preview to see.
``button``
A button (QPushButton).
:param button: A button (QPushButton).
"""
log.debug('onPreview')
if button.objectName() == 'preview_button':
@ -758,9 +784,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
Loads file(s) from the filesystem.
"""
filters = '%s (*)' % UiStrings().AllFiles
filenames = FileDialog.getOpenFileNames(self,
translate('SongsPlugin.EditSongForm', 'Open File(s)'), '', filters)
for filename in filenames:
file_names = FileDialog.getOpenFileNames(self, translate('SongsPlugin.EditSongForm', 'Open File(s)'), '',
filters)
for filename in file_names:
item = QtGui.QListWidgetItem(os.path.split(str(filename))[1])
item.setData(QtCore.Qt.UserRole, filename)
self.audio_list_widget.addItem(item)
@ -770,7 +796,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
Loads file(s) from the media plugin.
"""
if self.media_form.exec_():
for filename in self.media_form.getSelectedFiles():
for filename in self.media_form.get_selected_files():
item = QtGui.QListWidgetItem(os.path.split(str(filename))[1])
item.setData(QtCore.Qt.UserRole, filename)
self.audio_list_widget.addItem(item)
@ -814,7 +840,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def clear_caches(self):
"""
Free up autocompletion memory on dialog exit
Free up auto-completion memory on dialog exit
"""
log.debug('SongEditForm.clearCaches')
self.authors = []
@ -826,7 +852,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
"""
Exit Dialog and do not save
"""
log.debug ('SongEditForm.reject')
log.debug('SongEditForm.reject')
self.clear_caches()
QtGui.QDialog.reject(self)
@ -843,13 +869,10 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
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
(Authors, Books and Topics) have been saved before this function is
called.
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 (Authors, Books and Topics) have been saved before this function is called.
``preview``
Should be ``True`` if the song is also previewed (boolean).
:param preview: Should be ``True`` if the song is also previewed (boolean).
"""
# The Song() assignment. No database calls should be made while a
# Song() is in a partially complete state.
@ -863,9 +886,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.song.search_lyrics = ''
self.song.verse_order = ''
self.song.comments = self.comments_edit.toPlainText()
ordertext = self.verse_order_edit.text()
order_text = self.verse_order_edit.text()
order = []
for item in ordertext.split():
for item in order_text.split():
verse_tag = VerseType.tags[VerseType.from_translated_tag(item[0])]
verse_num = item[1:].lower()
order.append('%s%s' % (verse_tag, verse_num))
@ -874,8 +897,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
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)
self.song.book = self.manager.get_object_filtered(Book, Book.name == book_name)
else:
self.song.book = None
theme_name = self.theme_combo_box.currentText()
@ -887,15 +909,15 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.song.authors = []
for row in range(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)
author_id = (item.data(QtCore.Qt.UserRole))
author = self.manager.get_object(Author, author_id)
if author is not None:
self.song.authors.append(author)
self.song.topics = []
for row in range(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)
topic_id = (item.data(QtCore.Qt.UserRole))
topic = self.manager.get_object(Topic, topic_id)
if topic is not None:
self.song.topics.append(topic)
# Save the song here because we need a valid id for the audio files.
@ -904,7 +926,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
audio_files = [a.file_name for a in self.song.media_files]
log.debug(audio_files)
save_path = os.path.join(AppLocation.get_section_data_path(self.media_item.plugin.name), 'audio',
str(self.song.id))
str(self.song.id))
check_directory_exists(save_path)
self.song.media_files = []
files = []
@ -912,8 +934,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
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])
shutil.copyfile(oldfile, filename)
old_file, filename = filename, os.path.join(save_path, os.path.split(filename)[1])
shutil.copyfile(old_file, filename)
files.append(filename)
media_file = MediaFile()
media_file.file_name = filename

View File

@ -86,4 +86,4 @@ class Ui_EditVerseDialog(object):
self.split_button.setToolTip(UiStrings().SplitToolTip)
self.insert_button.setText(translate('SongsPlugin.EditVerseForm', '&Insert'))
self.insert_button.setToolTip(translate('SongsPlugin.EditVerseForm',
'Split a slide into two by inserting a verse splitter.'))
'Split a slide into two by inserting a verse splitter.'))

View File

@ -50,16 +50,18 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
"""
super(EditVerseForm, self).__init__(parent)
self.setupUi(self)
self.verse_text_edit.customContextMenuRequested.connect(self.context_menu)
self.insert_button.clicked.connect(self.on_insert_button_clicked)
self.split_button.clicked.connect(self.on_split_button_clicked)
self.verse_text_edit.cursorPositionChanged.connect(self.on_cursor_position_changed)
self.verse_type_combo_box.currentIndexChanged.connect(self.on_verse_type_combo_box_changed)
def context_menu(self, point):
item = self.serviceManagerList.itemAt(point)
def insert_verse(self, verse_tag, verse_num=1):
"""
Insert a verse
:param verse_tag: The verse tag
:param verse_num: The verse number
"""
if self.verse_text_edit.textCursor().columnNumber() != 0:
self.verse_text_edit.insertPlainText('\n')
verse_tag = VerseType.translated_name(verse_tag)
@ -67,24 +69,36 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.verse_text_edit.setFocus()
def on_split_button_clicked(self):
"""
The split button has been pressed
"""
text = self.verse_text_edit.toPlainText()
position = self.verse_text_edit.textCursor().position()
insert_string = '[---]'
if position and text[position-1] != '\n':
insert_string = '\n' + insert_string
if position == len(text) or text[position] != '\n':
if position == len(text) or text[position] != '\n':
insert_string += '\n'
self.verse_text_edit.insertPlainText(insert_string)
self.verse_text_edit.setFocus()
def on_insert_button_clicked(self):
"""
The insert button has been pressed
"""
verse_type_index = self.verse_type_combo_box.currentIndex()
self.insert_verse(VerseType.tags[verse_type_index], self.verse_number_box.value())
def on_verse_type_combo_box_changed(self):
"""
The verse type combo has been changed
"""
self.update_suggested_verse_number()
def on_cursor_position_changed(self):
"""
The cursor position has been changed
"""
self.update_suggested_verse_number()
def update_suggested_verse_number(self):
@ -117,6 +131,13 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.verse_number_box.setValue(verse_num)
def set_verse(self, text, single=False, tag='%s1' % VerseType.tags[VerseType.Verse]):
"""
Save the verse
:param text: The text
:param single: is this a single verse
:param tag: The tag
"""
self.has_single_verse = single
if single:
verse_type_index = VerseType.from_tag(tag[0], None)
@ -136,10 +157,20 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.verse_text_edit.moveCursor(QtGui.QTextCursor.End)
def get_verse(self):
"""
Extract the verse text
:return: The text
"""
return self.verse_text_edit.toPlainText(), VerseType.tags[self.verse_type_combo_box.currentIndex()], \
str(self.verse_number_box.value())
def get_all_verses(self):
"""
Extract all the verses
:return: The text
"""
text = self.verse_text_edit.toPlainText()
if not text.startswith('---['):
text = '---[%s:1]---\n%s' % (VerseType.translated_names[VerseType.Verse], text)

View File

@ -69,5 +69,6 @@ class Ui_MediaFilesDialog(object):
"""
media_files_dialog.setWindowTitle(translate('SongsPlugin.MediaFilesForm', 'Select Media File(s)'))
self.select_label.setText(translate('SongsPlugin.MediaFilesForm',
'Select one or more audio files from the list below, and click OK to import them into this song.'))
'Select one or more audio files from the list below, and click OK to import them '
'into this song.'))

View File

@ -47,13 +47,13 @@ class MediaFilesForm(QtGui.QDialog, Ui_MediaFilesDialog):
super(MediaFilesForm, self).__init__()
self.setupUi(self)
def populateFiles(self, files):
def populate_files(self, files):
self.file_list_widget.clear()
for file in files:
item = QtGui.QListWidgetItem(os.path.split(file)[1])
item.setData(QtCore.Qt.UserRole, file)
self.file_list_widget.addItem(item)
def getSelectedFiles(self):
def get_selected_files(self):
return [item.data(QtCore.Qt.UserRole) for item in self.file_list_widget.selectedItems()]

View File

@ -52,8 +52,7 @@ class SongBookForm(QtGui.QDialog, Ui_SongBookDialog):
"""
Execute the song book form.
``clear``
Clear the fields on the form before displaying it.
:param clear: Clear the fields on the form before displaying it.
"""
if clear:
self.name_edit.clear()

View File

@ -55,11 +55,8 @@ class SongExportForm(OpenLPWizard):
"""
Instantiate the wizard, and run any extra setup we need to.
``parent``
The QWidget-derived parent of the wizard.
``plugin``
The songs plugin.
:param parent: The QWidget-derived parent of the wizard.
:param plugin: The songs plugin.
"""
super(SongExportForm, self).__init__(parent, plugin, 'song_export_wizard', ':/wizards/wizard_exportsong.bmp')
self.stop_export_flag = False
@ -82,71 +79,71 @@ class SongExportForm(OpenLPWizard):
"""
Song wizard specific signals.
"""
self.availableListWidget.itemActivated.connect(self.onItemActivated)
self.searchLineEdit.textEdited.connect(self.onSearchLineEditChanged)
self.uncheckButton.clicked.connect(self.onUncheckButtonClicked)
self.checkButton.clicked.connect(self.onCheckButtonClicked)
self.directoryButton.clicked.connect(self.onDirectoryButtonClicked)
self.available_list_widget.itemActivated.connect(self.on_item_activated)
self.search_line_edit.textEdited.connect(self.on_search_line_edit_changed)
self.uncheck_button.clicked.connect(self.on_uncheck_button_clicked)
self.check_button.clicked.connect(self.on_check_button_clicked)
self.directory_button.clicked.connect(self.on_directory_button_clicked)
def add_custom_pages(self):
"""
Add song wizard specific pages.
"""
# The page with all available songs.
self.availableSongsPage = QtGui.QWizardPage()
self.availableSongsPage.setObjectName('availableSongsPage')
self.availableSongsLayout = QtGui.QHBoxLayout(self.availableSongsPage)
self.availableSongsLayout.setObjectName('availableSongsLayout')
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName('verticalLayout')
self.availableListWidget = QtGui.QListWidget(self.availableSongsPage)
self.availableListWidget.setObjectName('availableListWidget')
self.verticalLayout.addWidget(self.availableListWidget)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName('horizontalLayout')
self.searchLabel = QtGui.QLabel(self.availableSongsPage)
self.searchLabel.setObjectName('searchLabel')
self.horizontalLayout.addWidget(self.searchLabel)
self.searchLineEdit = QtGui.QLineEdit(self.availableSongsPage)
self.searchLineEdit.setObjectName('searchLineEdit')
self.horizontalLayout.addWidget(self.searchLineEdit)
self.available_songs_page = QtGui.QWizardPage()
self.available_songs_page.setObjectName('available_songs_page')
self.available_songs_layout = QtGui.QHBoxLayout(self.available_songs_page)
self.available_songs_layout.setObjectName('available_songs_layout')
self.vertical_layout = QtGui.QVBoxLayout()
self.vertical_layout.setObjectName('vertical_layout')
self.available_list_widget = QtGui.QListWidget(self.available_songs_page)
self.available_list_widget.setObjectName('available_list_widget')
self.vertical_layout.addWidget(self.available_list_widget)
self.horizontal_layout = QtGui.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
self.search_label = QtGui.QLabel(self.available_songs_page)
self.search_label.setObjectName('search_label')
self.horizontal_layout.addWidget(self.search_label)
self.search_line_edit = QtGui.QLineEdit(self.available_songs_page)
self.search_line_edit.setObjectName('search_line_edit')
self.horizontal_layout.addWidget(self.search_line_edit)
spacer_item = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacer_item)
self.uncheckButton = QtGui.QPushButton(self.availableSongsPage)
self.uncheckButton.setObjectName('uncheckButton')
self.horizontalLayout.addWidget(self.uncheckButton)
self.checkButton = QtGui.QPushButton(self.availableSongsPage)
self.checkButton.setObjectName('selectButton')
self.horizontalLayout.addWidget(self.checkButton)
self.verticalLayout.addLayout(self.horizontalLayout)
self.availableSongsLayout.addLayout(self.verticalLayout)
self.addPage(self.availableSongsPage)
self.horizontal_layout.addItem(spacer_item)
self.uncheck_button = QtGui.QPushButton(self.available_songs_page)
self.uncheck_button.setObjectName('uncheck_button')
self.horizontal_layout.addWidget(self.uncheck_button)
self.check_button = QtGui.QPushButton(self.available_songs_page)
self.check_button.setObjectName('selectButton')
self.horizontal_layout.addWidget(self.check_button)
self.vertical_layout.addLayout(self.horizontal_layout)
self.available_songs_layout.addLayout(self.vertical_layout)
self.addPage(self.available_songs_page)
# The page with the selected songs.
self.exportSongPage = QtGui.QWizardPage()
self.exportSongPage.setObjectName('availableSongsPage')
self.exportSongLayout = QtGui.QHBoxLayout(self.exportSongPage)
self.exportSongLayout.setObjectName('exportSongLayout')
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName('gridLayout')
self.selectedListWidget = QtGui.QListWidget(self.exportSongPage)
self.selectedListWidget.setObjectName('selectedListWidget')
self.gridLayout.addWidget(self.selectedListWidget, 1, 0, 1, 1)
# FIXME: self.horizontalLayout is already defined above?!?!?
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName('horizontalLayout')
self.directoryLabel = QtGui.QLabel(self.exportSongPage)
self.directoryLabel.setObjectName('directoryLabel')
self.horizontalLayout.addWidget(self.directoryLabel)
self.directoryLineEdit = QtGui.QLineEdit(self.exportSongPage)
self.directoryLineEdit.setObjectName('directoryLineEdit')
self.horizontalLayout.addWidget(self.directoryLineEdit)
self.directoryButton = QtGui.QToolButton(self.exportSongPage)
self.directoryButton.setIcon(build_icon(':/exports/export_load.png'))
self.directoryButton.setObjectName('directoryButton')
self.horizontalLayout.addWidget(self.directoryButton)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.exportSongLayout.addLayout(self.gridLayout)
self.addPage(self.exportSongPage)
self.export_song_page = QtGui.QWizardPage()
self.export_song_page.setObjectName('available_songs_page')
self.export_song_layout = QtGui.QHBoxLayout(self.export_song_page)
self.export_song_layout.setObjectName('export_song_layout')
self.grid_layout = QtGui.QGridLayout()
self.grid_layout.setObjectName('grid_layout')
self.selected_list_widget = QtGui.QListWidget(self.export_song_page)
self.selected_list_widget.setObjectName('selected_list_widget')
self.grid_layout.addWidget(self.selected_list_widget, 1, 0, 1, 1)
# FIXME: self.horizontal_layout is already defined above?!?!?
self.horizontal_layout = QtGui.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
self.directory_label = QtGui.QLabel(self.export_song_page)
self.directory_label.setObjectName('directory_label')
self.horizontal_layout.addWidget(self.directory_label)
self.directory_line_edit = QtGui.QLineEdit(self.export_song_page)
self.directory_line_edit.setObjectName('directory_line_edit')
self.horizontal_layout.addWidget(self.directory_line_edit)
self.directory_button = QtGui.QToolButton(self.export_song_page)
self.directory_button.setIcon(build_icon(':/exports/export_load.png'))
self.directory_button.setObjectName('directory_button')
self.horizontal_layout.addWidget(self.directory_button)
self.grid_layout.addLayout(self.horizontal_layout, 0, 0, 1, 1)
self.export_song_layout.addLayout(self.grid_layout)
self.addPage(self.export_song_page)
def retranslateUi(self):
"""
@ -154,22 +151,23 @@ class SongExportForm(OpenLPWizard):
"""
self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
self.title_label.setText(WizardStrings.HeaderStyle %
translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
self.information_label.setText(translate('SongsPlugin.ExportWizardForm', 'This wizard will help to'
' export your songs to the open and free <strong>OpenLyrics </strong> worship song format.'))
self.availableSongsPage.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
self.availableSongsPage.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Check the songs you want to export.'))
self.searchLabel.setText('%s:' % UiStrings().Search)
self.uncheckButton.setText(translate('SongsPlugin.ExportWizardForm', 'Uncheck All'))
self.checkButton.setText(translate('SongsPlugin.ExportWizardForm', 'Check All'))
self.exportSongPage.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Directory'))
self.exportSongPage.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Select the directory where you want the songs to be saved.'))
self.directoryLabel.setText(translate('SongsPlugin.ExportWizardForm', 'Directory:'))
' export your songs to the open and free <strong>OpenLyrics </strong> worship '
'song format.'))
self.available_songs_page.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
self.available_songs_page.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Check the songs you want to export.'))
self.search_label.setText('%s:' % UiStrings().Search)
self.uncheck_button.setText(translate('SongsPlugin.ExportWizardForm', 'Uncheck All'))
self.check_button.setText(translate('SongsPlugin.ExportWizardForm', 'Check All'))
self.export_song_page.setTitle(translate('SongsPlugin.ExportWizardForm', 'Select Directory'))
self.export_song_page.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Select the directory where you want the songs to be saved.'))
self.directory_label.setText(translate('SongsPlugin.ExportWizardForm', 'Directory:'))
self.progress_page.setTitle(translate('SongsPlugin.ExportWizardForm', 'Exporting'))
self.progress_page.setSubTitle(translate('SongsPlugin.ExportWizardForm',
'Please wait while your songs are exported.'))
'Please wait while your songs are exported.'))
self.progress_label.setText(WizardStrings.Ready)
self.progress_bar.setFormat(WizardStrings.PercentSymbolFormat)
@ -179,46 +177,46 @@ class SongExportForm(OpenLPWizard):
"""
if self.currentPage() == self.welcome_page:
return True
elif self.currentPage() == self.availableSongsPage:
elif self.currentPage() == self.available_songs_page:
items = [
item for item in self._findListWidgetItems(
self.availableListWidget) if item.checkState()
item for item in self._find_list_widget_items(self.available_list_widget) if item.checkState()
]
if not items:
critical_error_message_box(UiStrings().NISp,
critical_error_message_box(
UiStrings().NISp,
translate('SongsPlugin.ExportWizardForm', 'You need to add at least one Song to export.'))
return False
self.selectedListWidget.clear()
self.selected_list_widget.clear()
# Add the songs to the list of selected songs.
for item in items:
song = QtGui.QListWidgetItem(item.text())
song.setData(QtCore.Qt.UserRole, item.data(QtCore.Qt.UserRole))
song.setFlags(QtCore.Qt.ItemIsEnabled)
self.selectedListWidget.addItem(song)
self.selected_list_widget.addItem(song)
return True
elif self.currentPage() == self.exportSongPage:
if not self.directoryLineEdit.text():
elif self.currentPage() == self.export_song_page:
if not self.directory_line_edit.text():
critical_error_message_box(
translate('SongsPlugin.ExportWizardForm', 'No Save Location specified'),
translate('SongsPlugin.ExportWizardForm', 'You need to specify a directory.'))
return False
return True
elif self.currentPage() == self.progress_page:
self.availableListWidget.clear()
self.selectedListWidget.clear()
self.available_list_widget.clear()
self.selected_list_widget.clear()
return True
def setDefaults(self):
def set_defaults(self):
"""
Set default form values for the song export wizard.
"""
self.restart()
self.finish_button.setVisible(False)
self.cancel_button.setVisible(True)
self.availableListWidget.clear()
self.selectedListWidget.clear()
self.directoryLineEdit.clear()
self.searchLineEdit.clear()
self.available_list_widget.clear()
self.selected_list_widget.clear()
self.directory_line_edit.clear()
self.search_line_edit.clear()
# Load the list of songs.
self.application.set_busy_cursor()
songs = self.plugin.manager.get_all_objects(Song)
@ -233,7 +231,7 @@ class SongExportForm(OpenLPWizard):
item.setData(QtCore.Qt.UserRole, song)
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)
self.availableListWidget.addItem(item)
self.available_list_widget.addItem(item)
self.application.set_normal_cursor()
def pre_wizard(self):
@ -244,86 +242,81 @@ class SongExportForm(OpenLPWizard):
self.progress_label.setText(translate('SongsPlugin.ExportWizardForm', 'Starting export...'))
self.application.process_events()
def performWizard(self):
def perform_wizard(self):
"""
Perform the actual export. This creates an *openlyricsexport* instance
and calls the *do_export* method.
Perform the actual export. This creates an *openlyricsexport* instance and calls the *do_export* method.
"""
songs = [
song.data(QtCore.Qt.UserRole)
for song in self._findListWidgetItems(self.selectedListWidget)
for song in self._find_list_widget_items(self.selected_list_widget)
]
exporter = OpenLyricsExport(self, songs, self.directoryLineEdit.text())
exporter = OpenLyricsExport(self, songs, self.directory_line_edit.text())
if exporter.do_export():
self.progress_label.setText(translate('SongsPlugin.SongExportForm',
'Finished export. To import these files use the <strong>OpenLyrics</strong> importer.'))
self.progress_label.setText(
translate('SongsPlugin.SongExportForm',
'Finished export. To import these files use the <strong>OpenLyrics</strong> importer.'))
else:
self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed.'))
def _findListWidgetItems(self, listWidget, text=''):
def _find_list_widget_items(self, list_widget, text=''):
"""
Returns a list of *QListWidgetItem*s of the ``listWidget``. Note, that
hidden items are included.
Returns a list of *QListWidgetItem*s of the ``list_widget``. Note, that hidden items are included.
``listWidget``
The widget to get all items from. (QListWidget)
``text``
The text to search for. (unicode string)
:param list_widget: The widget to get all items from. (QListWidget)
:param text: The text to search for. (unicode string)
"""
return [
item for item in listWidget.findItems(text, QtCore.Qt.MatchContains)
item for item in list_widget.findItems(text, QtCore.Qt.MatchContains)
]
def onItemActivated(self, item):
def on_item_activated(self, item):
"""
Called, when an item in the *availableListWidget* has been triggered.
Called, when an item in the *available_list_widget* has been triggered.
The item is check if it was not checked, whereas it is unchecked when it
was checked.
``item``
The *QListWidgetItem* which was triggered.
:param item: The *QListWidgetItem* which was triggered.
"""
item.setCheckState(
QtCore.Qt.Unchecked if item.checkState() else QtCore.Qt.Checked)
def onSearchLineEditChanged(self, text):
def on_search_line_edit_changed(self, text):
"""
The *searchLineEdit*'s text has been changed. Update the list of
The *search_line_edit*'s text has been changed. Update the list of
available songs. Note that any song, which does not match the ``text``
will be hidden, but not unchecked!
``text``
The text of the *searchLineEdit*.
:param text: The text of the *search_line_edit*.
"""
search_result = [
song for song in self._findListWidgetItems(self.availableListWidget, text)
song for song in self._find_list_widget_items(self.available_list_widget, text)
]
for item in self._findListWidgetItems(self.availableListWidget):
for item in self._find_list_widget_items(self.available_list_widget):
item.setHidden(item not in search_result)
def onUncheckButtonClicked(self):
def on_uncheck_button_clicked(self):
"""
The *uncheckButton* has been clicked. Set all visible songs unchecked.
The *uncheck_button* has been clicked. Set all visible songs unchecked.
"""
for row in range(self.availableListWidget.count()):
item = self.availableListWidget.item(row)
for row in range(self.available_list_widget.count()):
item = self.available_list_widget.item(row)
if not item.isHidden():
item.setCheckState(QtCore.Qt.Unchecked)
def onCheckButtonClicked(self):
def on_check_button_clicked(self):
"""
The *checkButton* has been clicked. Set all visible songs checked.
The *check_button* has been clicked. Set all visible songs checked.
"""
for row in range(self.availableListWidget.count()):
item = self.availableListWidget.item(row)
for row in range(self.available_list_widget.count()):
item = self.available_list_widget.item(row)
if not item.isHidden():
item.setCheckState(QtCore.Qt.Checked)
def onDirectoryButtonClicked(self):
def on_directory_button_clicked(self):
"""
Called when the *directoryButton* was clicked. Opens a dialog and writes
the path to *directoryLineEdit*.
Called when the *directory_button* was clicked. Opens a dialog and writes
the path to *directory_line_edit*.
"""
self.get_folder(translate('SongsPlugin.ExportWizardForm', 'Select Destination Folder'),
self.directoryLineEdit, 'last directory export')
self.get_folder(
translate('SongsPlugin.ExportWizardForm', 'Select Destination Folder'),
self.directory_line_edit, 'last directory export')

View File

@ -55,11 +55,8 @@ class SongImportForm(OpenLPWizard):
"""
Instantiate the wizard, and run any extra setup we need to.
``parent``
The QWidget-derived parent of the wizard.
``plugin``
The songs plugin.
:param parent: The QWidget-derived parent of the wizard.
:param plugin: The songs plugin.
"""
super(SongImportForm, self).__init__(parent, plugin, 'songImportWizard', ':/wizards/wizard_importsong.bmp')
self.clipboard = self.main_window.clipboard
@ -72,9 +69,9 @@ class SongImportForm(OpenLPWizard):
super(SongImportForm, self).setupUi(image)
self.current_format = SongFormat.OpenLyrics
self.format_stack.setCurrentIndex(self.current_format)
self.format_combo_box.currentIndexChanged.connect(self.onCurrentIndexChanged)
self.format_combo_box.currentIndexChanged.connect(self.on_current_index_changed)
def onCurrentIndexChanged(self, index):
def on_current_index_changed(self, index):
"""
Called when the format combo box's index changed.
"""
@ -99,10 +96,10 @@ class SongImportForm(OpenLPWizard):
select_mode = SongFormat.get(song_format, 'selectMode')
if select_mode == SongFormatSelect.MultipleFiles:
self.format_widgets[song_format]['addButton'].clicked.connect(self.on_add_button_clicked)
self.format_widgets[song_format]['removeButton'].clicked.connect(self.onRemoveButtonClicked)
self.format_widgets[song_format]['removeButton'].clicked.connect(self.on_remove_button_clicked)
else:
self.format_widgets[song_format]['browseButton'].clicked.connect(self.on_browse_button_clicked)
self.format_widgets[song_format]['file_path_edit'].textChanged.connect(self.onFilepathEditTextChanged)
self.format_widgets[song_format]['file_path_edit'].textChanged.connect(self.on_filepath_edit_text_changed)
def add_custom_pages(self):
"""
@ -131,7 +128,7 @@ class SongImportForm(OpenLPWizard):
self.format_stack.setObjectName('format_stack')
self.disablable_formats = []
for self.current_format in SongFormat.get_format_list():
self.addFileSelectItem()
self.add_file_select_item()
self.source_layout.addLayout(self.format_stack)
self.addPage(self.source_page)
@ -140,33 +137,35 @@ class SongImportForm(OpenLPWizard):
Song wizard localisation.
"""
self.setWindowTitle(translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard'))
self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui', 'Welcome to the Song Import Wizard'))
self.information_label.setText(translate('SongsPlugin.ImportWizardForm',
'This wizard will help you to import songs from a variety of '
'formats. Click the next button below to start the process by selecting a format to import from.'))
self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
'Welcome to the Song Import Wizard'))
self.information_label.setText(
translate('SongsPlugin.ImportWizardForm',
'This wizard will help you to import songs from a variety of formats. Click the next button '
'below to start the process by selecting a format to import from.'))
self.source_page.setTitle(WizardStrings.ImportSelect)
self.source_page.setSubTitle(WizardStrings.ImportSelectLong)
self.format_label.setText(WizardStrings.FormatLabel)
for format in SongFormat.get_format_list():
for format_list in SongFormat.get_format_list():
format_name, custom_combo_text, description_text, select_mode = \
SongFormat.get(format, 'name', 'comboBoxText', 'descriptionText', 'selectMode')
SongFormat.get(format_list, 'name', 'comboBoxText', 'descriptionText', 'selectMode')
combo_box_text = (custom_combo_text if custom_combo_text else format_name)
self.format_combo_box.setItemText(format, combo_box_text)
self.format_combo_box.setItemText(format_list, combo_box_text)
if description_text is not None:
self.format_widgets[format]['description_label'].setText(description_text)
self.format_widgets[format_list]['description_label'].setText(description_text)
if select_mode == SongFormatSelect.MultipleFiles:
self.format_widgets[format]['addButton'].setText(
self.format_widgets[format_list]['addButton'].setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.format_widgets[format]['removeButton'].setText(
self.format_widgets[format_list]['removeButton'].setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
else:
self.format_widgets[format]['browseButton'].setText(UiStrings().Browse)
self.format_widgets[format_list]['browseButton'].setText(UiStrings().Browse)
f_label = 'Filename:'
if select_mode == SongFormatSelect.SingleFolder:
f_label = 'Folder:'
self.format_widgets[format]['filepathLabel'].setText(translate('SongsPlugin.ImportWizardForm', f_label))
for format in self.disablable_formats:
self.format_widgets[format]['disabled_label'].setText(SongFormat.get(format, 'disabledLabelText'))
self.format_widgets[format_list]['filepathLabel'].setText(translate('SongsPlugin.ImportWizardForm', f_label))
for format_list in self.disablable_formats:
self.format_widgets[format_list]['disabled_label'].setText(SongFormat.get(format_list, 'disabledLabelText'))
self.progress_page.setTitle(WizardStrings.Importing)
self.progress_page.setSubTitle(
translate('SongsPlugin.ImportWizardForm', 'Please wait while your songs are imported.'))
@ -179,7 +178,7 @@ class SongImportForm(OpenLPWizard):
labels = [self.format_widgets[f]['filepathLabel'] for f in formats]
# Get max width of all labels
max_label_width = max(self.format_label.minimumSizeHint().width(),
max([label.minimumSizeHint().width() for label in labels]))
max([label.minimumSizeHint().width() for label in labels]))
self.format_spacer.changeSize(max_label_width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
spacers = [self.format_widgets[f]['filepathSpacer'] for f in formats]
for index, spacer in enumerate(spacers):
@ -187,9 +186,9 @@ class SongImportForm(OpenLPWizard):
max_label_width - labels[index].minimumSizeHint().width(), 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
# Align descriptionLabels with rest of layout
for format in SongFormat.get_format_list():
if SongFormat.get(format, 'descriptionText') is not None:
self.format_widgets[format]['descriptionSpacer'].changeSize(
for format_list in SongFormat.get_format_list():
if SongFormat.get(format_list, 'descriptionText') is not None:
self.format_widgets[format_list]['descriptionSpacer'].changeSize(
max_label_width + self.format_h_spacing, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
def custom_page_changed(self, page_id):
@ -197,11 +196,11 @@ class SongImportForm(OpenLPWizard):
Called when changing to a page other than the progress page.
"""
if self.page(page_id) == self.source_page:
self.onCurrentIndexChanged(self.format_stack.currentIndex())
self.on_current_index_changed(self.format_stack.currentIndex())
def validateCurrentPage(self):
"""
Re-implement te validateCurrentPage() method. Validate the current page before moving on to the next page.
Re-implement the validateCurrentPage() method. Validate the current page before moving on to the next page.
Provide each song format class with a chance to validate its input by overriding isValidSource().
"""
if self.currentPage() == self.welcome_page:
@ -230,37 +229,36 @@ class SongImportForm(OpenLPWizard):
"""
Opens a QFileDialog and writes the filenames to the given listbox.
``title``
The title of the dialog (unicode).
``listbox``
A listbox (QListWidget).
``filters``
The file extension filters. It should contain the file descriptions
:param title: The title of the dialog (unicode).
:param listbox: A listbox (QListWidget).
:param filters: The file extension filters. It should contain the file descriptions
as well as the file extensions. For example::
u'SongBeamer Files (*.sng)'
"""
if filters:
filters += ';;'
filters += '%s (*)' % UiStrings().AllFiles
filenames = FileDialog.getOpenFileNames(self, title,
file_names = FileDialog.getOpenFileNames(
self, title,
Settings().value(self.plugin.settings_section + '/last directory import'), filters)
if filenames:
listbox.addItems(filenames)
if file_names:
listbox.addItems(file_names)
Settings().setValue(self.plugin.settings_section + '/last directory import',
os.path.split(str(filenames[0]))[0])
os.path.split(str(file_names[0]))[0])
def get_list_of_files(self, listbox):
def get_list_of_files(self, list_box):
"""
Return a list of file from the listbox
Return a list of file from the list_box
:param list_box: The source list box
"""
return [listbox.item(i).text() for i in range(listbox.count())]
return [list_box.item(i).text() for i in range(list_box.count())]
def remove_selected_items(self, list_box):
"""
Remove selected list_box items
:param list_box: the source list box
"""
for item in list_box.selectedItems():
item = list_box.takeItem(list_box.row(item))
@ -291,14 +289,14 @@ class SongImportForm(OpenLPWizard):
self.get_files(title, self.format_widgets[this_format]['file_list_widget'], ext_filter)
self.source_page.emit(QtCore.SIGNAL('completeChanged()'))
def onRemoveButtonClicked(self):
def on_remove_button_clicked(self):
"""
Remove a file from the list.
"""
self.remove_selected_items(self.format_widgets[self.current_format]['file_list_widget'])
self.source_page.emit(QtCore.SIGNAL('completeChanged()'))
def onFilepathEditTextChanged(self):
def on_filepath_edit_text_changed(self):
"""
Called when the content of the Filename/Folder edit box changes.
"""
@ -315,12 +313,12 @@ class SongImportForm(OpenLPWizard):
if last_import_type < 0 or last_import_type >= self.format_combo_box.count():
last_import_type = 0
self.format_combo_box.setCurrentIndex(last_import_type)
for format in SongFormat.get_format_list():
select_mode = SongFormat.get(format, 'selectMode')
for format_list in SongFormat.get_format_list():
select_mode = SongFormat.get(format_list, 'selectMode')
if select_mode == SongFormatSelect.MultipleFiles:
self.format_widgets[format]['file_list_widget'].clear()
self.format_widgets[format_list]['file_list_widget'].clear()
else:
self.format_widgets[format]['file_path_edit'].setText('')
self.format_widgets[format_list]['file_path_edit'].setText('')
self.error_report_text_edit.clear()
self.error_report_text_edit.setHidden(True)
self.error_copy_to_button.setHidden(True)
@ -334,22 +332,22 @@ class SongImportForm(OpenLPWizard):
self.progress_label.setText(WizardStrings.StartingImport)
self.application.process_events()
def performWizard(self):
def perform_wizard(self):
"""
Perform the actual import. This method pulls in the correct importer
class, and then runs the ``doImport`` method of the importer to do
the actual importing.
Perform the actual import. This method pulls in the correct importer class, and then runs the ``doImport``
method of the importer to do the actual importing.
"""
source_format = self.current_format
select_mode = SongFormat.get(source_format, 'selectMode')
if select_mode == SongFormatSelect.SingleFile:
importer = self.plugin.importSongs(source_format,
filename=self.format_widgets[source_format]['file_path_edit'].text())
importer = self.plugin.import_songs(source_format,
filename=self.format_widgets[source_format]['file_path_edit'].text())
elif select_mode == SongFormatSelect.SingleFolder:
importer = self.plugin.importSongs(source_format,
folder=self.format_widgets[source_format]['file_path_edit'].text())
importer = self.plugin.import_songs(source_format,
folder=self.format_widgets[source_format]['file_path_edit'].text())
else:
importer = self.plugin.importSongs(source_format,
importer = self.plugin.import_songs(
source_format,
filenames=self.get_list_of_files(self.format_widgets[source_format]['file_list_widget']))
importer.doImport()
self.progress_label.setText(WizardStrings.FinishedImport)
@ -364,15 +362,15 @@ class SongImportForm(OpenLPWizard):
"""
Save the error report to a file.
"""
filename = QtGui.QFileDialog.getSaveFileName(self,
Settings().value(self.plugin.settings_section + '/last directory import'))
filename = QtGui.QFileDialog.getSaveFileName(
self, Settings().value(self.plugin.settings_section + '/last directory import'))
if not filename:
return
report_file = codecs.open(filename, 'w', 'utf-8')
report_file.write(self.error_report_text_edit.toPlainText())
report_file.close()
def addFileSelectItem(self):
def add_file_select_item(self):
"""
Add a file selection page.
"""
@ -382,75 +380,75 @@ class SongImportForm(OpenLPWizard):
page = QtGui.QWidget()
page.setObjectName(prefix + 'Page')
if can_disable:
importWidget = self.disablableWidget(page, prefix)
import_widget = self.disablable_widget(page, prefix)
else:
importWidget = page
importLayout = QtGui.QVBoxLayout(importWidget)
importLayout.setMargin(0)
importLayout.setObjectName(prefix + 'ImportLayout')
import_widget = page
import_layout = QtGui.QVBoxLayout(import_widget)
import_layout.setMargin(0)
import_layout.setObjectName(prefix + 'ImportLayout')
if description_text is not None:
descriptionLayout = QtGui.QHBoxLayout()
descriptionLayout.setObjectName(prefix + 'DescriptionLayout')
descriptionSpacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
descriptionLayout.addSpacerItem(descriptionSpacer)
description_label = QtGui.QLabel(importWidget)
description_layout = QtGui.QHBoxLayout()
description_layout.setObjectName(prefix + 'DescriptionLayout')
description_spacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
description_layout.addSpacerItem(description_spacer)
description_label = QtGui.QLabel(import_widget)
description_label.setWordWrap(True)
description_label.setOpenExternalLinks(True)
description_label.setObjectName(prefix + '_description_label')
descriptionLayout.addWidget(description_label)
importLayout.addLayout(descriptionLayout)
description_layout.addWidget(description_label)
import_layout.addLayout(description_layout)
self.format_widgets[this_format]['description_label'] = description_label
self.format_widgets[this_format]['descriptionSpacer'] = descriptionSpacer
self.format_widgets[this_format]['descriptionSpacer'] = description_spacer
if select_mode == SongFormatSelect.SingleFile or select_mode == SongFormatSelect.SingleFolder:
file_path_layout = QtGui.QHBoxLayout()
file_path_layout.setObjectName(prefix + '_file_path_layout')
file_path_layout.setContentsMargins(0, self.format_v_spacing, 0, 0)
filepathLabel = QtGui.QLabel(importWidget)
filepathLabel.setObjectName(prefix + 'FilepathLabel')
file_path_layout.addWidget(filepathLabel)
filepathSpacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
file_path_layout.addSpacerItem(filepathSpacer)
file_path_edit = QtGui.QLineEdit(importWidget)
file_path_label = QtGui.QLabel(import_widget)
file_path_label.setObjectName(prefix + 'FilepathLabel')
file_path_layout.addWidget(file_path_label)
file_path_spacer = QtGui.QSpacerItem(0, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
file_path_layout.addSpacerItem(file_path_spacer)
file_path_edit = QtGui.QLineEdit(import_widget)
file_path_edit.setObjectName(prefix + '_file_path_edit')
file_path_layout.addWidget(file_path_edit)
browseButton = QtGui.QToolButton(importWidget)
browseButton.setIcon(self.open_icon)
browseButton.setObjectName(prefix + 'BrowseButton')
file_path_layout.addWidget(browseButton)
importLayout.addLayout(file_path_layout)
importLayout.addSpacerItem(self.stack_spacer)
self.format_widgets[this_format]['filepathLabel'] = filepathLabel
self.format_widgets[this_format]['filepathSpacer'] = filepathSpacer
browse_button = QtGui.QToolButton(import_widget)
browse_button.setIcon(self.open_icon)
browse_button.setObjectName(prefix + 'BrowseButton')
file_path_layout.addWidget(browse_button)
import_layout.addLayout(file_path_layout)
import_layout.addSpacerItem(self.stack_spacer)
self.format_widgets[this_format]['filepathLabel'] = file_path_label
self.format_widgets[this_format]['filepathSpacer'] = file_path_spacer
self.format_widgets[this_format]['file_path_layout'] = file_path_layout
self.format_widgets[this_format]['file_path_edit'] = file_path_edit
self.format_widgets[this_format]['browseButton'] = browseButton
self.format_widgets[this_format]['browseButton'] = browse_button
elif select_mode == SongFormatSelect.MultipleFiles:
fileListWidget = QtGui.QListWidget(importWidget)
fileListWidget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
fileListWidget.setObjectName(prefix + 'FileListWidget')
importLayout.addWidget(fileListWidget)
file_list_widget = QtGui.QListWidget(import_widget)
file_list_widget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
file_list_widget.setObjectName(prefix + 'FileListWidget')
import_layout.addWidget(file_list_widget)
button_layout = QtGui.QHBoxLayout()
button_layout.setObjectName(prefix + '_button_layout')
addButton = QtGui.QPushButton(importWidget)
addButton.setIcon(self.open_icon)
addButton.setObjectName(prefix + 'AddButton')
button_layout.addWidget(addButton)
add_button = QtGui.QPushButton(import_widget)
add_button.setIcon(self.open_icon)
add_button.setObjectName(prefix + 'AddButton')
button_layout.addWidget(add_button)
button_layout.addStretch()
removeButton = QtGui.QPushButton(importWidget)
removeButton.setIcon(self.delete_icon)
removeButton.setObjectName(prefix + 'RemoveButton')
button_layout.addWidget(removeButton)
importLayout.addLayout(button_layout)
self.format_widgets[this_format]['file_list_widget'] = fileListWidget
remove_button = QtGui.QPushButton(import_widget)
remove_button.setIcon(self.delete_icon)
remove_button.setObjectName(prefix + 'RemoveButton')
button_layout.addWidget(remove_button)
import_layout.addLayout(button_layout)
self.format_widgets[this_format]['file_list_widget'] = file_list_widget
self.format_widgets[this_format]['button_layout'] = button_layout
self.format_widgets[this_format]['addButton'] = addButton
self.format_widgets[this_format]['removeButton'] = removeButton
self.format_widgets[this_format]['addButton'] = add_button
self.format_widgets[this_format]['removeButton'] = remove_button
self.format_stack.addWidget(page)
self.format_widgets[this_format]['page'] = page
self.format_widgets[this_format]['importLayout'] = importLayout
self.format_widgets[this_format]['importLayout'] = import_layout
self.format_combo_box.addItem('')
def disablableWidget(self, page, prefix):
def disablable_widget(self, page, prefix):
"""
Disable a widget.
"""
@ -526,10 +524,10 @@ class SongImportSourcePage(QtGui.QWizardPage):
if wizard.format_widgets[this_format]['file_list_widget'].count() > 0:
return True
else:
filepath = str(wizard.format_widgets[this_format]['file_path_edit'].text())
if filepath:
if select_mode == SongFormatSelect.SingleFile and os.path.isfile(filepath):
file_path = str(wizard.format_widgets[this_format]['file_path_edit'].text())
if file_path:
if select_mode == SongFormatSelect.SingleFile and os.path.isfile(file_path):
return True
elif select_mode == SongFormatSelect.SingleFolder and os.path.isdir(filepath):
elif select_mode == SongFormatSelect.SingleFolder and os.path.isdir(file_path):
return True
return False

View File

@ -161,6 +161,7 @@ class Ui_SongMaintenanceDialog(object):
self.add_book_button.setText(UiStrings().Add)
self.edit_book_button.setText(UiStrings().Edit)
self.delete_book_button.setText(UiStrings().Delete)
typeListWidth = max(self.fontMetrics().width(SongStrings.Authors),
self.fontMetrics().width(SongStrings.Topics), self.fontMetrics().width(SongStrings.SongBooks))
self.type_list_widget.setFixedWidth(typeListWidth + self.type_list_widget.iconSize().width() + 32)
type_list_width = max(self.fontMetrics().width(SongStrings.Authors),
self.fontMetrics().width(SongStrings.Topics),
self.fontMetrics().width(SongStrings.SongBooks))
self.type_list_widget.setFixedWidth(type_list_width + self.type_list_widget.iconSize().width() + 32)

View File

@ -98,8 +98,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
"""
Get the ID of the currently selected item.
``list_widget``
The list widget to examine.
:param list_widget: The list widget to examine.
"""
item = list_widget.currentItem()
if item:
@ -163,6 +162,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def check_author_exists(self, new_author, edit=False):
"""
Returns *False* if the given Author already exists, otherwise *True*.
:param new_author: The new Author.
:param edit: Are we editing the song?
"""
authors = self.manager.get_all_objects(
Author,
@ -177,6 +179,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def check_topic_exists(self, new_topic, edit=False):
"""
Returns *False* if the given Topic already exists, otherwise *True*.
:param new_topic: The new Topic.
:param edit: Are we editing the song?
"""
topics = self.manager.get_all_objects(Topic, Topic.name == new_topic.name)
return self.__check_object_exists(topics, new_topic, edit)
@ -184,17 +189,21 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def check_song_book_exists(self, new_book, edit=False):
"""
Returns *False* if the given Topic already exists, otherwise *True*.
:param new_book: The new Book.
:param edit: Are we editing the song?
"""
books = self.manager.get_all_objects(Book,
and_(Book.name == new_book.name, Book.publisher == new_book.publisher))
books = self.manager.get_all_objects(
Book, and_(Book.name == new_book.name, Book.publisher == new_book.publisher))
return self.__check_object_exists(books, new_book, edit)
def __check_object_exists(self, existing_objects, new_object, edit):
"""
Utility method to check for an existing object.
``edit``
If we edit an item, this should be *True*.
:param existing_objects: The objects reference
:param new_object: An individual object
:param edit: If we edit an item, this should be *True*.
"""
if existing_objects:
# If we edit an existing object, we need to make sure that we do
@ -297,8 +306,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
'author %s use the existing author %s?') %
(author.display_name, temp_display_name, author.display_name), parent=self, question=True) == \
QtGui.QMessageBox.Yes:
self._merge_objects(author, self.merge_authors,
self.reset_authors)
self._merge_objects(author, self.merge_authors, self.reset_authors)
else:
# We restore the author's old first and last name as well as
# his display name.
@ -330,15 +338,16 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.'))
elif critical_error_message_box(
message=translate('SongsPlugin.SongMaintenanceForm',
'The topic %s already exists. Would you like to make songs with topic %s use the existing topic %s?') %
(topic.name, temp_name, topic.name), parent=self, question=True) == QtGui.QMessageBox.Yes:
'The topic %s already exists. Would you like to make songs with topic %s use the '
'existing topic %s?') % (topic.name, temp_name, topic.name),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self._merge_objects(topic, self.merge_topics, self.reset_topics)
else:
# We restore the topics's old name.
topic.name = temp_name
critical_error_message_box(
message=translate('SongsPlugin.SongMaintenanceForm',
'Could not save your modified topic, because it already exists.'))
'Could not save your modified topic, because it already exists.'))
def on_edit_book_button_clicked(self):
"""
@ -367,8 +376,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
message=translate('SongsPlugin.SongMaintenanceForm', 'Could not save your changes.'))
elif critical_error_message_box(
message=translate('SongsPlugin.SongMaintenanceForm',
'The book %s already exists. Would you like to make songs with book %s use the existing book %s?') %
(book.name, temp_name, book.name), parent=self, question=True) == QtGui.QMessageBox.Yes:
'The book %s already exists. Would you like to make '
'songs with book %s use the existing book %s?') % (book.name, temp_name, book.name),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self._merge_objects(book, self.merge_song_books, self.reset_song_books)
else:
# We restore the book's old name and publisher.
@ -390,8 +400,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
"""
Merges two authors into one author.
``old_author``
The object, which was edited, that will be deleted
:param old_author: The object, which was edited, that will be deleted
"""
# Find the duplicate.
existing_author = self.manager.get_object_filtered(
@ -418,15 +427,11 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
"""
Merges two topics into one topic.
``old_topic``
The object, which was edited, that will be deleted
:param old_topic: The object, which was edited, that will be deleted
"""
# Find the duplicate.
existing_topic = self.manager.get_object_filtered(
Topic,
and_(
Topic.name == old_topic.name, Topic.id != old_topic.id
)
Topic, and_(Topic.name == old_topic.name, Topic.id != old_topic.id)
)
# Find the songs, which have the old_topic as topic.
songs = self.manager.get_all_objects(Song, Song.topics.contains(old_topic))
@ -467,30 +472,34 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
Delete the author if the author is not attached to any songs.
"""
self._delete_item(Author, self.authors_list_widget, self.reset_authors,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'),
translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected author?'),
translate('SongsPlugin.SongMaintenanceForm',
'This author cannot be deleted, they are currently assigned to at least one song.'))
translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'),
translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected author?'),
translate('SongsPlugin.SongMaintenanceForm',
'This author cannot be deleted, they are currently assigned to at least one song'
'.'))
def on_delete_topic_button_clicked(self):
"""
Delete the Book if the Book is not attached to any songs.
"""
self._delete_item(Topic, self.topics_list_widget, self.reset_topics,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'),
translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected topic?'),
translate('SongsPlugin.SongMaintenanceForm',
'This topic cannot be deleted, it is currently assigned to at least one song.'))
translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'),
translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected topic?'),
translate('SongsPlugin.SongMaintenanceForm',
'This topic cannot be deleted, it is currently assigned to at least one song.'))
def on_delete_book_button_clicked(self):
"""
Delete the Book if the Book is not attached to any songs.
"""
self._delete_item(Book, self.song_books_list_widget, self.reset_song_books,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'),
translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected book?'),
translate('SongsPlugin.SongMaintenanceForm',
'This book cannot be deleted, it is currently assigned to at least one song.'))
translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'),
translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected book?'),
translate('SongsPlugin.SongMaintenanceForm',
'This book cannot be deleted, it is currently assigned to at least one song.'))
def on_authors_list_row_changed(self, row):
"""

View File

@ -186,7 +186,7 @@ class SongReviewWidget(QtGui.QWidget):
# Some pixels are missing at the bottom of the table, but all themes I tried still allowed
# to read the last verse line, so I'll just leave it at that.
self.song_info_verse_list_widget.setFixedHeight(self.song_info_verse_list_widget.verticalHeader().length() +
self.song_info_verse_list_widget.verticalHeader().offset() + 6)
self.song_info_verse_list_widget.verticalHeader().offset() + 6)
self.song_group_box_layout.addWidget(self.song_info_verse_list_widget)
self.song_group_box_layout.addStretch()
self.song_vertical_layout.addWidget(self.song_group_box)

View File

@ -62,8 +62,8 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog):
Override the inherited method to check before we close.
"""
if not self.name_edit.text():
critical_error_message_box(message=translate('SongsPlugin.TopicsForm',
'You need to type in a topic name.'))
critical_error_message_box(
message=translate('SongsPlugin.TopicsForm', 'You need to type in a topic name.'))
self.name_edit.setFocus()
return False
else:

View File

@ -107,7 +107,7 @@ class SongFormat(object):
``u'prefix'``
Prefix for Qt objects. Use mixedCase, e.g. ``u'openLyrics'``
See ``SongImportForm.addFileSelectItem()``
See ``SongImportForm.add_file_select_item()``
Optional attributes for each song format:

View File

@ -54,26 +54,23 @@ from openlp.plugins.songs.forms.duplicatesongremovalform import DuplicateSongRem
log = logging.getLogger(__name__)
__default_settings__ = {
'songs/db type': 'sqlite',
'songs/last search type': SongSearch.Entire,
'songs/last import type': SongFormat.OpenLyrics,
'songs/update service on edit': False,
'songs/search as type': False,
'songs/add song from service': True,
'songs/display songbar': True,
'songs/last directory import': '',
'songs/last directory export': ''
}
__default_settings__ = {'songs/db type': 'sqlite',
'songs/last search type': SongSearch.Entire,
'songs/last import type': SongFormat.OpenLyrics,
'songs/update service on edit': False,
'songs/search as type': False,
'songs/add song from service': True,
'songs/display songbar': True,
'songs/last directory import': '',
'songs/last directory export': ''
}
class SongsPlugin(Plugin):
"""
This is the number 1 plugin, if importance were placed on any
plugins. This plugin enables the user to create, edit and display
songs. Songs are divided into verses, and the verse order can be
specified. Authors, topics and song books can be assigned to songs
as well.
This is the number 1 plugin, if importance were placed on any plugins. This plugin enables the user to create,
edit and display songs. Songs are divided into verses, and the verse order can be specified. Authors, topics and
song books can be assigned to songs as well.
"""
log.info('Song Plugin loaded')
@ -94,6 +91,9 @@ class SongsPlugin(Plugin):
return self.manager.session is not None
def initialise(self):
"""
Lets Initialise the plugin
"""
log.info('Songs Initialising')
super(SongsPlugin, self).initialise()
self.song_import_item.setVisible(True)
@ -108,15 +108,13 @@ class SongsPlugin(Plugin):
def add_import_menu_item(self, import_menu):
"""
Give the Songs plugin the opportunity to add items to the
**Import** menu.
Give the Songs plugin the opportunity to add items to the **Import** menu.
``import_menu``
The actual **Import** menu item, so that your actions can
use it as their parent.
:param import_menu: The actual **Import** menu item, so that your actions can use it as their parent.
"""
# Main song import menu item - will eventually be the only one
self.song_import_item = create_action(import_menu, 'songImportItem',
self.song_import_item = create_action(
import_menu, 'songImportItem',
text=translate('SongsPlugin', '&Song'),
tooltip=translate('SongsPlugin', 'Import songs using the import wizard.'),
triggers=self.on_song_import_item_clicked)
@ -124,15 +122,13 @@ class SongsPlugin(Plugin):
def add_export_menu_Item(self, export_menu):
"""
Give the Songs plugin the opportunity to add items to the
**Export** menu.
Give the Songs plugin the opportunity to add items to the **Export** menu.
``export_menu``
The actual **Export** menu item, so that your actions can
use it as their parent.
:param export_menu: The actual **Export** menu item, so that your actions can use it as their parent.
"""
# Main song import menu item - will eventually be the only one
self.song_export_item = create_action(export_menu, 'songExportItem',
self.song_export_item = create_action(
export_menu, 'songExportItem',
text=translate('SongsPlugin', '&Song'),
tooltip=translate('SongsPlugin', 'Exports songs using the export wizard.'),
triggers=self.on_song_export_item_clicked)
@ -140,24 +136,22 @@ class SongsPlugin(Plugin):
def add_tools_menu_item(self, tools_menu):
"""
Give the Songs plugin the opportunity to add items to the
**Tools** menu.
Give the Songs plugin the opportunity to add items to the **Tools** menu.
``tools_menu``
The actual **Tools** menu item, so that your actions can
use it as their parent.
:param tools_menu: The actual **Tools** menu item, so that your actions can use it as their parent.
"""
log.info('add tools menu')
self.tools_reindex_item = create_action(tools_menu, 'toolsReindexItem',
self.tools_reindex_item = create_action(
tools_menu, 'toolsReindexItem',
text=translate('SongsPlugin', '&Re-index Songs'),
icon=':/plugins/plugin_songs.png',
statustip=translate('SongsPlugin', 'Re-index the songs database to improve searching and ordering.'),
visible=False, triggers=self.on_tools_reindex_item_triggered)
tools_menu.addAction(self.tools_reindex_item)
self.tools_find_duplicates = create_action(tools_menu, 'toolsFindDuplicates',
self.tools_find_duplicates = create_action(
tools_menu, 'toolsFindDuplicates',
text=translate('SongsPlugin', 'Find &Duplicate Songs'),
statustip=translate('SongsPlugin',
'Find and remove duplicate songs in the song database.'),
statustip=translate('SongsPlugin', 'Find and remove duplicate songs in the song database.'),
visible=False, triggers=self.on_tools_find_duplicates_triggered, can_shortcuts=True)
tools_menu.addAction(self.tools_find_duplicates)
@ -165,11 +159,11 @@ class SongsPlugin(Plugin):
"""
Rebuild each song.
"""
maxSongs = self.manager.get_object_count(Song)
if maxSongs == 0:
max_songs = self.manager.get_object_count(Song)
if max_songs == 0:
return
progress_dialog = QtGui.QProgressDialog(translate('SongsPlugin', 'Reindexing songs...'), UiStrings().Cancel,
0, maxSongs, self.main_window)
progress_dialog = QtGui.QProgressDialog(
translate('SongsPlugin', 'Reindexing songs...'), UiStrings().Cancel, 0, max_songs, self.main_window)
progress_dialog.setWindowTitle(translate('SongsPlugin', 'Reindexing songs'))
progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
songs = self.manager.get_all_objects(Song)
@ -186,16 +180,22 @@ class SongsPlugin(Plugin):
DuplicateSongRemovalForm(self).exec_()
def on_song_import_item_clicked(self):
"""
The song import option has been selected
"""
if self.media_item:
self.media_item.on_import_click()
def on_song_export_item_clicked(self):
"""
The song export option has been selected
"""
if self.media_item:
self.media_item.on_export_click()
def about(self):
return translate('SongsPlugin', '<strong>Songs Plugin</strong>'
'<br />The songs plugin provides the ability to display and manage songs.')
'<br />The songs plugin provides the ability to display and manage songs.')
def uses_theme(self, theme):
"""
@ -207,24 +207,27 @@ class SongsPlugin(Plugin):
return True
return False
def rename_theme(self, oldTheme, newTheme):
def rename_theme(self, old_theme, new_theme):
"""
Renames a theme the song plugin is using making the plugin use the new
name.
Renames a theme the song plugin is using making the plugin use the new name.
``oldTheme``
The name of the theme the plugin should stop using.
``newTheme``
The new name the plugin should now use.
:param old_theme: The name of the theme the plugin should stop using.
:param new_theme: The new name the plugin should now use.
"""
songsUsingTheme = self.manager.get_all_objects(Song, Song.theme_name == oldTheme)
for song in songsUsingTheme:
song.theme_name = newTheme
songs_using_theme = self.manager.get_all_objects(Song, Song.theme_name == old_theme)
for song in songs_using_theme:
song.theme_name = new_theme
self.manager.save_object(song)
def importSongs(self, format, **kwargs):
class_ = SongFormat.get(format, 'class')
def import_songs(self, import_format, **kwargs):
"""
Add the correct importer class
:param import_format: The import_format to be used
:param kwargs: The arguments
:return: the correct importer
"""
class_ = SongFormat.get(import_format, 'class')
importer = class_(self.manager, **kwargs)
importer.register(self.media_item.import_wizard)
return importer
@ -257,8 +260,7 @@ class SongsPlugin(Plugin):
def first_time(self):
"""
If the first time wizard has run, this function is run to import all the
new songs into the database.
If the first time wizard has run, this function is run to import all the new songs into the database.
"""
self.application.process_events()
self.on_tools_reindex_item_triggered()
@ -272,7 +274,7 @@ class SongsPlugin(Plugin):
if sfile.startswith('songs_') and sfile.endswith('.sqlite'):
self.application.process_events()
song_dbs.append(os.path.join(db_dir, sfile))
song_count += self._countSongs(os.path.join(db_dir, sfile))
song_count += self._count_songs(os.path.join(db_dir, sfile))
if not song_dbs:
return
self.application.process_events()
@ -319,9 +321,11 @@ class SongsPlugin(Plugin):
for song in songs:
self.manager.delete_object(Song, song.id)
def _countSongs(self, db_file):
def _count_songs(self, db_file):
"""
Provide a count of the songs in the database
:param db_file: the database name to count
"""
connection = sqlite3.connect(db_file)
cursor = connection.cursor()