Source code for openlp.plugins.songs.forms.songexportform
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2017 OpenLP Developers #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`songexportform` module provides the wizard for exporting songs to the
OpenLyrics format.
"""
import logging
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import Registry, UiStrings, translate
from openlp.core.lib import create_separated_list, build_icon
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
from openlp.plugins.songs.lib.db import Song
from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
log = logging.getLogger(__name__)
[docs]class SongExportForm(OpenLPWizard):
"""
This is the Song Export Wizard, which allows easy exporting of Songs to the
OpenLyrics format.
"""
log.info('SongExportForm loaded')
def __init__(self, parent, plugin):
"""
Instantiate the wizard, and run any extra setup we need to.
: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_song.bmp')
self.stop_export_flag = False
Registry().register_function('openlp_stop_wizard', self.stop_export)
[docs] def stop_export(self):
"""
Sets the flag for the exporter to stop the export.
"""
log.debug('Stopping songs export')
self.stop_export_flag = True
[docs] def setupUi(self, image):
"""
Set up the song wizard UI.
"""
super(SongExportForm, self).setupUi(image)
[docs] def custom_signals(self):
"""
Song wizard specific signals.
"""
self.available_list_widget.itemActivated.connect(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)
[docs] def add_custom_pages(self):
"""
Add song wizard specific pages.
"""
# The page with all available songs.
self.available_songs_page = QtWidgets.QWizardPage()
self.available_songs_page.setObjectName('available_songs_page')
self.available_songs_layout = QtWidgets.QHBoxLayout(self.available_songs_page)
self.available_songs_layout.setObjectName('available_songs_layout')
self.vertical_layout = QtWidgets.QVBoxLayout()
self.vertical_layout.setObjectName('vertical_layout')
self.available_list_widget = QtWidgets.QListWidget(self.available_songs_page)
self.available_list_widget.setObjectName('available_list_widget')
self.vertical_layout.addWidget(self.available_list_widget)
self.horizontal_layout = QtWidgets.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
self.search_label = QtWidgets.QLabel(self.available_songs_page)
self.search_label.setObjectName('search_label')
self.horizontal_layout.addWidget(self.search_label)
self.search_line_edit = QtWidgets.QLineEdit(self.available_songs_page)
self.search_line_edit.setObjectName('search_line_edit')
self.horizontal_layout.addWidget(self.search_line_edit)
spacer_item = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontal_layout.addItem(spacer_item)
self.uncheck_button = QtWidgets.QPushButton(self.available_songs_page)
self.uncheck_button.setObjectName('uncheck_button')
self.horizontal_layout.addWidget(self.uncheck_button)
self.check_button = QtWidgets.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.export_song_page = QtWidgets.QWizardPage()
self.export_song_page.setObjectName('available_songs_page')
self.export_song_layout = QtWidgets.QHBoxLayout(self.export_song_page)
self.export_song_layout.setObjectName('export_song_layout')
self.grid_layout = QtWidgets.QGridLayout()
self.grid_layout.setObjectName('range_layout')
self.selected_list_widget = QtWidgets.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 = QtWidgets.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
self.directory_label = QtWidgets.QLabel(self.export_song_page)
self.directory_label.setObjectName('directory_label')
self.horizontal_layout.addWidget(self.directory_label)
self.directory_line_edit = QtWidgets.QLineEdit(self.export_song_page)
self.directory_line_edit.setObjectName('directory_line_edit')
self.horizontal_layout.addWidget(self.directory_line_edit)
self.directory_button = QtWidgets.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)
[docs] def retranslateUi(self):
"""
Song wizard localisation.
"""
self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
# TODO: Verify format() with template variables
self.title_label.setText(WizardStrings.HeaderStyle %
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.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('{text}:'.format(text=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.'))
self.progress_label.setText(WizardStrings.Ready)
self.progress_bar.setFormat(WizardStrings.PercentSymbolFormat)
[docs] def validateCurrentPage(self):
"""
Validate the current page before moving on to the next page.
"""
if self.currentPage() == self.welcome_page:
return True
elif self.currentPage() == self.available_songs_page:
items = [
item for item in find_list_widget_items(self.available_list_widget) if item.checkState()
]
if not items:
critical_error_message_box(
UiStrings().NISp,
translate('SongsPlugin.ExportWizardForm', 'You need to add at least one Song to export.'))
return False
self.selected_list_widget.clear()
# Add the songs to the list of selected songs.
for item in items:
song = QtWidgets.QListWidgetItem(item.text())
song.setData(QtCore.Qt.UserRole, item.data(QtCore.Qt.UserRole))
song.setFlags(QtCore.Qt.ItemIsEnabled)
self.selected_list_widget.addItem(song)
return True
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.available_list_widget.clear()
self.selected_list_widget.clear()
return True
[docs] def set_defaults(self):
"""
Set default form values for the song export wizard.
"""
def get_song_key(song):
"""Get the key to sort by"""
return song.sort_key
self.restart()
self.finish_button.setVisible(False)
self.cancel_button.setVisible(True)
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)
songs.sort(key=get_song_key)
for song in songs:
# No need to export temporary songs.
if song.temporary:
continue
authors = create_separated_list([author.display_name for author in song.authors])
title = '{title} ({author})'.format(title=song.title, author=authors)
item = QtWidgets.QListWidgetItem(title)
item.setData(QtCore.Qt.UserRole, song)
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)
self.available_list_widget.addItem(item)
self.application.set_normal_cursor()
[docs] def pre_wizard(self):
"""
Perform pre export tasks.
"""
super(SongExportForm, self).pre_wizard()
self.progress_label.setText(translate('SongsPlugin.ExportWizardForm', 'Starting export...'))
self.application.process_events()
[docs] def perform_wizard(self):
"""
Perform the actual export. This creates an *openlyricsexport* instance and calls the *do_export* method.
"""
songs = [
song.data(QtCore.Qt.UserRole)
for song in find_list_widget_items(self.selected_list_widget)
]
exporter = OpenLyricsExport(self, songs, self.directory_line_edit.text())
try:
if exporter.do_export():
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.'))
except OSError as ose:
self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed because this '
'error occurred: {error}').format(error=ose.strerror))
[docs] def on_search_line_edit_changed(self, text):
"""
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!
:param text: The text of the *search_line_edit*.
"""
search_result = [
song for song in find_list_widget_items(self.available_list_widget, text)
]
for item in find_list_widget_items(self.available_list_widget):
item.setHidden(item not in search_result)
[docs] def on_uncheck_button_clicked(self):
"""
The *uncheck_button* has been clicked. Set all visible songs unchecked.
"""
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)
[docs] def on_check_button_clicked(self):
"""
The *check_button* has been clicked. Set all visible songs checked.
"""
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)
[docs] def on_directory_button_clicked(self):
"""
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.directory_line_edit, 'last directory export')
[docs]def find_list_widget_items(list_widget, text=''):
"""
Returns a list of *QListWidgetItem*s of the ``list_widget``. Note, that hidden items are included.
: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 list_widget.findItems(text, QtCore.Qt.MatchContains)
]
[docs]def on_item_activated(item):
"""
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.
:param item: The *QListWidgetItem* which was triggered.
"""
item.setCheckState(QtCore.Qt.Unchecked if item.checkState() else QtCore.Qt.Checked)