From e9082eaec3c6fecfbb0f5959464ec08a269fe2de Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 23 Dec 2010 17:42:28 +0000 Subject: [PATCH 01/43] Start to add functionality to allow tags to be customised --- openlp.pyw | 2 +- openlp/core/lib/__init__.py | 56 ++-- openlp/core/lib/displaytags.py | 66 +++++ openlp/core/lib/plugin.py | 4 + openlp/core/lib/settingstab.py | 6 + openlp/core/lib/spelltextedit.py | 6 +- openlp/core/ui/__init__.py | 1 + openlp/core/ui/displaytagtab.py | 344 ++++++++++++++++++++++++ openlp/core/ui/maindisplay.py | 5 +- openlp/core/ui/pluginform.py | 2 - openlp/core/ui/settingsform.py | 17 +- resources/forms/displaytabeditdialog.ui | 209 ++++++++++++++ 12 files changed, 680 insertions(+), 38 deletions(-) create mode 100644 openlp/core/lib/displaytags.py create mode 100644 openlp/core/ui/displaytagtab.py create mode 100644 resources/forms/displaytabeditdialog.ui diff --git a/openlp.pyw b/openlp.pyw index 17743903f..8998e89b9 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -159,7 +159,7 @@ class OpenLP(QtGui.QApplication): Run the OpenLP application. """ app_version = self._get_version() - #provide a listener for widgets to reqest a screen update. + # provide a listener for widgets to reqest a screen update. QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_process_events'), self.processEvents) self.setOrganizationName(u'OpenLP') diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 956b6c787..620afe1b6 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -35,52 +35,51 @@ from PyQt4 import QtCore, QtGui log = logging.getLogger(__name__) -# TODO make external and configurable in alpha 4 via a settings dialog -html_expands = [] +base_html_expands = [] -html_expands.append({u'desc': u'Red', u'start tag': u'{r}', +base_html_expands.append({u'desc': u'Red', u'start tag': u'{r}', u'start html': u'', - u'end tag': u'{/r}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Black', u'start tag': u'{b}', + u'end tag': u'{/r}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Black', u'start tag': u'{b}', u'start html': u'', - u'end tag': u'{/b}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}', + u'end tag': u'{/b}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}', u'start html': u'', - u'end tag': u'{/bl}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}', + u'end tag': u'{/bl}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}', u'start html': u'', - u'end tag': u'{/y}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Green', u'start tag': u'{g}', + u'end tag': u'{/y}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Green', u'start tag': u'{g}', u'start html': u'', - u'end tag': u'{/g}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}', + u'end tag': u'{/g}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}', u'start html': u'', - u'end tag': u'{/pk}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Orange', u'start tag': u'{o}', + u'end tag': u'{/pk}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Orange', u'start tag': u'{o}', u'start html': u'', - u'end tag': u'{/o}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}', + u'end tag': u'{/o}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}', u'start html': u'', - u'end tag': u'{/pp}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'White', u'start tag': u'{w}', + u'end tag': u'{/pp}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'White', u'start tag': u'{w}', u'start html': u'', - u'end tag': u'{/w}', u'end html': u'', u'protected': False}) -html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}', + u'end tag': u'{/w}', u'end html': u'', u'protected': True}) +base_html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}', u'start html': u'', u'end tag': u'{/su}', u'end html': u'', u'protected': True}) -html_expands.append({u'desc': u'Subscript', u'start tag': u'{sb}', +base_html_expands.append({u'desc': u'Subscript', u'start tag': u'{sb}', u'start html': u'', u'end tag': u'{/sb}', u'end html': u'', u'protected': True}) -html_expands.append({u'desc': u'Paragraph', u'start tag': u'{p}', +base_html_expands.append({u'desc': u'Paragraph', u'start tag': u'{p}', u'start html': u'

', u'end tag': u'{/p}', u'end html': u'

', u'protected': True}) -html_expands.append({u'desc': u'Bold', u'start tag': u'{st}', +base_html_expands.append({u'desc': u'Bold', u'start tag': u'{st}', u'start html': u'', u'end tag': u'{/st}', u'end html': u'', u'protected': True}) -html_expands.append({u'desc': u'Italics', u'start tag': u'{it}', +base_html_expands.append({u'desc': u'Italics', u'start tag': u'{it}', u'start html': u'', u'end tag': u'{/it}', u'end html': u'', u'protected': True}) -html_expands.append({u'desc': u'Underline', u'start tag': u'{u}', +base_html_expands.append({u'desc': u'Underline', u'start tag': u'{u}', u'start html': u'', u'end tag': u'{/u}', u'end html': u'', u'protected': True}) @@ -292,7 +291,7 @@ def clean_tags(text): Remove Tags from text for display """ text = text.replace(u'
', u'\n') - for tag in html_expands: + for tag in DisplayTags.get_html_tags().html_expands: text = text.replace(tag[u'start tag'], u'') text = text.replace(tag[u'end tag'], u'') return text @@ -301,13 +300,14 @@ def expand_tags(text): """ Expand tags HTML for display """ - for tag in html_expands: + for tag in DisplayTags.get_html_tags().html_expands: text = text.replace(tag[u'start tag'], tag[u'start html']) text = text.replace(tag[u'end tag'], tag[u'end html']) return text from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ BackgroundType, HorizontalType, VerticalType +from displaytags import DisplayTags from spelltextedit import SpellTextEdit from eventreceiver import Receiver from imagemanager import ImageManager diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py new file mode 100644 index 000000000..2a47e2e09 --- /dev/null +++ b/openlp/core/lib/displaytags.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Provide Html Tag management and Display Tag access class +""" + +from openlp.core.lib import base_html_expands + +class HtmlTags(object): + """ + """ + def __init__(self): + self.html_expands = [] + self.eyeCatcher = "eyeCatcher" + self.reset_list() + + def reset_list(self): + """ + """ + self.html_expands = [] + for html in base_html_expands: + self.html_expands.append(html) + + def add_tag(self, html): + """ + """ + self.html_expands.append(html) + + +class DisplayTags(object): + """ + Static Class to HTML Tags to be access around the code the list is managed + by the Options Tab. + """ + html_tags = HtmlTags() + + @staticmethod + def get_html_tags(): + """ + Provide access to the HtmlTags object. + """ + return DisplayTags.html_tags + diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index f73b58735..405cd531e 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -175,6 +175,10 @@ class Plugin(QtCore.QObject): self.status = new_status QtCore.QSettings().setValue( self.settingsSection + u'/status', QtCore.QVariant(self.status)) + if new_status == PluginStatus.Active: + self.initialise() + elif new_status == PluginStatus.InActive: + self.finalise() def isActive(self): """ diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index 048751006..beb252387 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -87,6 +87,12 @@ class SettingsTab(QtGui.QWidget): """ pass + def cancel(self): + """ + Reset any settings + """ + pass + def postSetUp(self, postUpdate=False): """ Changes which need to be made after setup of application diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 76271b6a7..4aa1d37a4 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -36,7 +36,7 @@ except ImportError: # http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check from PyQt4 import QtCore, QtGui -from openlp.core.lib import html_expands, translate +from openlp.core.lib import translate, DisplayTags class SpellTextEdit(QtGui.QPlainTextEdit): """ @@ -88,7 +88,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit): popupMenu.insertMenu(popupMenu.actions()[0], spell_menu) tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Formatting Tags')) - for html in html_expands: + for html in DisplayTags.get_html_tags().html_expands: action = SpellAction( html[u'desc'], tagMenu) action.correct.connect(self.htmlTag) tagMenu.addAction(action) @@ -110,7 +110,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit): """ Replaces the selected text with word. """ - for html in html_expands: + for html in DisplayTags.get_html_tags().html_expands: if tag == html[u'desc']: cursor = self.textCursor() if self.textCursor().hasSelection(): diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 377999553..7c5991a54 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -48,6 +48,7 @@ from splashscreen import SplashScreen from generaltab import GeneralTab from themestab import ThemesTab from advancedtab import AdvancedTab +from displaytagtab import DisplayTagTab from aboutform import AboutForm from pluginform import PluginForm from settingsform import SettingsForm diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py new file mode 100644 index 000000000..56c9fd911 --- /dev/null +++ b/openlp/core/ui/displaytagtab.py @@ -0,0 +1,344 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +''' +The :mod:`DisplayTagTab` provides an Tag Edit facility. The Base set are +protected and included each time loaded. Custom tags can be defined and saved. +The Custom Tag arrays are saved in a pickle so QSettings works on them. Base +Tags cannot be changed. + +''' +import cPickle +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import SettingsTab, translate, DisplayTags + +class DisplayTagTab(SettingsTab): + ''' + The :class:`DisplayTagTab` manages the settings tab . + ''' + def __init__(self): + ''' + Initialise the settings tab + ''' + SettingsTab.__init__(self, u'Display Tags') + + def preLoad(self): + """ + Initialise values before the Load takes place + """ + # Create initial copy from master + print DisplayTags.get_html_tags().eyeCatcher + DisplayTags.get_html_tags().reset_list() + user_expands = QtCore.QSettings().value(u'displayTags/html_tags', + QtCore.QVariant(u'')).toString() + # cPickle only accepts str not unicode strings + user_tags = cPickle.loads(str(user_expands)) + # If we have some user ones added them as well + for t in user_tags: + DisplayTags.get_html_tags().add_tag(t) + self.selected = -1 + + def setupUi(self): + ''' + Configure the UI elements for the tab. + ''' + self.setObjectName(u'DisplayTagTab') + self.tabTitleVisible = translate(u'OpenLP.DisplayTagTab', 'Display Tags') + self.displayTagEdit = QtGui.QWidget(self) + self.editGroupBox = QtGui.QGroupBox(self.displayTagEdit) + self.editGroupBox.setGeometry(QtCore.QRect(10, 220, 691, 181)) + self.editGroupBox.setObjectName(u'editGroupBox') + self.updatePushButton = QtGui.QPushButton(self.editGroupBox) + self.updatePushButton.setGeometry(QtCore.QRect(600, 140, 71, 26)) + self.updatePushButton.setObjectName(u'updatePushButton') + self.layoutWidget = QtGui.QWidget(self.editGroupBox) + self.layoutWidget.setGeometry(QtCore.QRect(20, 50, 571, 114)) + self.layoutWidget.setObjectName(u'layoutWidget') + self.formLayout = QtGui.QFormLayout(self.layoutWidget) + self.formLayout.setObjectName(u'formLayout') + self.descriptionLabel = QtGui.QLabel(self.layoutWidget) + self.descriptionLabel.setAlignment(QtCore.Qt.AlignCenter) + self.descriptionLabel.setObjectName(u'descriptionLabel') + self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.descriptionLabel) + self.descriptionLineEdit = QtGui.QLineEdit(self.layoutWidget) + self.descriptionLineEdit.setObjectName(u'descriptionLineEdit') + self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.descriptionLineEdit) + self.tagLabel = QtGui.QLabel(self.layoutWidget) + self.tagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.tagLabel.setObjectName(u'tagLabel') + self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.tagLabel) + self.tagLineEdit = QtGui.QLineEdit(self.layoutWidget) + self.tagLineEdit.setMaximumSize(QtCore.QSize(50, 16777215)) + self.tagLineEdit.setMaxLength(5) + self.tagLineEdit.setObjectName(u'tagLineEdit') + self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.tagLineEdit) + self.startTagLabel = QtGui.QLabel(self.layoutWidget) + self.startTagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.startTagLabel.setObjectName(u'startTagLabel') + self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, + self.startTagLabel) + self.startTagLineEdit = QtGui.QLineEdit(self.layoutWidget) + self.startTagLineEdit.setObjectName(u'startTagLineEdit') + self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, + self.startTagLineEdit) + self.endTagLabel = QtGui.QLabel(self.layoutWidget) + self.endTagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.endTagLabel.setObjectName(u'endTagLabel') + self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, + self.endTagLabel) + self.endTagLineEdit = QtGui.QLineEdit(self.layoutWidget) + self.endTagLineEdit.setObjectName(u'endTagLineEdit') + self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, + self.endTagLineEdit) + self.defaultPushButton = QtGui.QPushButton(self.displayTagEdit) + self.defaultPushButton.setGeometry(QtCore.QRect(450, 188, 71, 26)) + self.defaultPushButton.setObjectName(u'updatePushButton') + self.deletePushButton = QtGui.QPushButton(self.displayTagEdit) + self.deletePushButton.setGeometry(QtCore.QRect(530, 188, 71, 26)) + self.deletePushButton.setObjectName(u'deletePushButton') + self.newPushButton = QtGui.QPushButton(self.displayTagEdit) + self.newPushButton.setGeometry(QtCore.QRect(610, 188, 71, 26)) + self.newPushButton.setObjectName(u'newPushButton') + self.tagTableWidget = QtGui.QTableWidget(self.displayTagEdit) + self.tagTableWidget.setGeometry(QtCore.QRect(10, 10, 691, 171)) + self.tagTableWidget.setHorizontalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOff) + self.tagTableWidget.setEditTriggers( + QtGui.QAbstractItemView.NoEditTriggers) + self.tagTableWidget.setAlternatingRowColors(True) + self.tagTableWidget.setSelectionMode( + QtGui.QAbstractItemView.SingleSelection) + self.tagTableWidget.setSelectionBehavior( + QtGui.QAbstractItemView.SelectRows) + self.tagTableWidget.setCornerButtonEnabled(False) + self.tagTableWidget.setObjectName(u'tagTableWidget') + self.tagTableWidget.setColumnCount(4) + self.tagTableWidget.setRowCount(0) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(0, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(1, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(2, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(3, item) + self.editGroupBox.setTitle( + translate('OpenLP.DisplayTagTab', 'Edit Selection')) + self.updatePushButton.setText( + translate('OpenLP.DisplayTagTab', 'Update')) + self.descriptionLabel.setText( + translate('OpenLP.DisplayTagTab', 'Description')) + self.tagLabel.setText(translate('OpenLP.DisplayTagTab', 'Tag')) + self.startTagLabel.setText( + translate('OpenLP.DisplayTagTab', 'Start tag')) + self.endTagLabel.setText(translate('OpenLP.DisplayTagTab', 'End tag')) + self.deletePushButton.setText( + translate('OpenLP.DisplayTagTab', 'Delete')) + self.defaultPushButton.setText( + translate('OpenLP.DisplayTagTab', 'Default')) + self.newPushButton.setText(translate('OpenLP.DisplayTagTab', 'New')) + self.tagTableWidget.horizontalHeaderItem(0). \ + setText(translate('OpenLP.DisplayTagTab', 'Description')) + self.tagTableWidget.horizontalHeaderItem(1). \ + setText(translate('OpenLP.DisplayTagTab', 'Tag id')) + self.tagTableWidget.horizontalHeaderItem(2). \ + setText(translate('OpenLP.DisplayTagTab', 'Start Html')) + self.tagTableWidget.horizontalHeaderItem(3). \ + setText(translate('OpenLP.DisplayTagTab', 'End Html')) + QtCore.QMetaObject.connectSlotsByName(self.displayTagEdit) + self.tagTableWidget.setColumnWidth(0, 120) + self.tagTableWidget.setColumnWidth(1, 40) + self.tagTableWidget.setColumnWidth(2, 280) + self.tagTableWidget.setColumnWidth(3, 200) + QtCore.QObject.connect(self.tagTableWidget, + QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) + QtCore.QObject.connect(self.defaultPushButton, + QtCore.SIGNAL(u'pressed()'), self.onDefaultPushed) + QtCore.QObject.connect(self.newPushButton, + QtCore.SIGNAL(u'pressed()'), self.onNewPushed) + QtCore.QObject.connect(self.updatePushButton, + QtCore.SIGNAL(u'pressed()'), self.onUpdatePushed) + QtCore.QObject.connect(self.deletePushButton, + QtCore.SIGNAL(u'pressed()'), self.onDeletePushed) + + def load(self): + """ + Load Display and set field state. + """ + self.newPushButton.setEnabled(True) + self.updatePushButton.setEnabled(False) + self.deletePushButton.setEnabled(False) + for linenumber, html in enumerate( + DisplayTags.get_html_tags().html_expands): + self.tagTableWidget.setRowCount( + self.tagTableWidget.rowCount() + 1) + self.tagTableWidget.setItem(linenumber, 0, + QtGui.QTableWidgetItem(html[u'desc'])) + self.tagTableWidget.setItem(linenumber, 1, + QtGui.QTableWidgetItem(self._strip(html[u'start tag']))) + self.tagTableWidget.setItem(linenumber, 2, + QtGui.QTableWidgetItem(html[u'start html'])) + self.tagTableWidget.setItem(linenumber, 3, + QtGui.QTableWidgetItem(html[u'end html'])) + self.tagTableWidget.resizeRowsToContents() + self.descriptionLineEdit.setText(u'') + self.tagLineEdit.setText(u'') + self.startTagLineEdit.setText(u'') + self.endTagLineEdit.setText(u'') + self.descriptionLineEdit.setEnabled(False) + self.tagLineEdit.setEnabled(False) + self.startTagLineEdit.setEnabled(False) + self.endTagLineEdit.setEnabled(False) + + def save(self): + """ + Save Custom tags in a pickle . + """ + temp = [] + for tag in DisplayTags.get_html_tags().html_expands: + if not tag[u'protected']: + temp.append(tag) + if temp: + ctemp = cPickle.dumps(temp) + QtCore.QSettings().setValue(u'displayTags/html_tags', + QtCore.QVariant(ctemp)) + else: + QtCore.QSettings().setValue(u'displayTags/html_tags', + QtCore.QVariant(u'')) + + def cancel(self): + """ + Reset Custom tags from Settings. + """ + self.preLoad() + self._resetTable() + + def onRowSelected(self): + """ + Table Row selected so display items and set field state. + """ + row = self.tagTableWidget.currentRow() + html = DisplayTags.get_html_tags().html_expands[row] + self.selected = row + self.descriptionLineEdit.setText(html[u'desc']) + self.tagLineEdit.setText(self._strip(html[u'start tag'])) + self.startTagLineEdit.setText(html[u'start html']) + self.endTagLineEdit.setText(html[u'end html']) + if html[u'protected']: + self.descriptionLineEdit.setEnabled(False) + self.tagLineEdit.setEnabled(False) + self.startTagLineEdit.setEnabled(False) + self.endTagLineEdit.setEnabled(False) + self.updatePushButton.setEnabled(False) + self.deletePushButton.setEnabled(False) + else: + self.descriptionLineEdit.setEnabled(True) + self.tagLineEdit.setEnabled(True) + self.startTagLineEdit.setEnabled(True) + self.endTagLineEdit.setEnabled(True) + self.updatePushButton.setEnabled(True) + self.deletePushButton.setEnabled(True) + + def onNewPushed(self): + """ + Add a new tag to list only if it is not a duplicate. + """ + for html in DisplayTags.get_html_tags().html_expands: + if self._strip(html[u'start tag']) == u'n': + QtGui.QMessageBox.critical(self, + translate('OpenLP.DisplayTagTab', 'Update Error'), + translate('OpenLP.DisplayTagTab', + 'Tag "n" already defined.'), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), + QtGui.QMessageBox.Ok) + return + # Add new tag to list + DisplayTags.get_html_tags().html_expands.append( + {u'desc': u'New Item', u'start tag': u'{n}', + u'start html': u'', u'end tag': u'{/n}', + u'end html': u'', u'protected': False}) + self._resetTable() + + def onDefaultPushed(self): + """ + Remove all Custom Tags and reset to base set only. + """ + DisplayTags.get_html_tags().reset_list() + self._resetTable() + + def onDeletePushed(self): + """ + Delete selected custom tag. + """ + if self.selected != -1: + DisplayTags.get_html_tags().html_expands.pop(self.selected) + self.selected = -1 + self._resetTable() + + def onUpdatePushed(self): + """ + Update Custom Tag details if not duplicate. + """ + html_expands = DisplayTags.get_html_tags().html_expands + if self.selected != -1: + html = html_expands[self.selected] + tag = unicode(self.tagLineEdit.text()) + for linenumber, html1 in enumerate(html_expands): + if self._strip(html1[u'start tag']) == tag and \ + linenumber != self.selected: + QtGui.QMessageBox.critical(self, + translate('OpenLP.DisplayTagTab', 'Update Error'), + unicode(translate('OpenLP.DisplayTagTab', + 'Tag %s already defined.')) % tag, + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), + QtGui.QMessageBox.Ok) + return + html[u'desc'] = unicode(self.descriptionLineEdit.text()) + html[u'start html'] = unicode(self.startTagLineEdit.text()) + html[u'end html'] = unicode(self.endTagLineEdit.text()) + html[u'start tag'] = u'{%s}' % tag + html[u'end tag'] = u'{/%s}' % tag + self.selected = -1 + self._resetTable() + + def _resetTable(self): + """ + Reset List for loading. + """ + self.tagTableWidget.clearContents() + self.tagTableWidget.setRowCount(0) + self.load() + + def _strip(self, tag): + """ + Remove tag wrappers for editing. + """ + tag = tag.replace(u'{', u'') + tag = tag.replace(u'}', u'') + return tag diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 69eb9305d..aa3445fbb 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -31,7 +31,8 @@ import os from PyQt4 import QtCore, QtGui, QtWebKit from PyQt4.phonon import Phonon -from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte +from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ + build_icon from openlp.core.ui import HideMode log = logging.getLogger(__name__) @@ -102,6 +103,8 @@ class MainDisplay(DisplayWidget): self.isLive = live self.alertTab = None self.hideMode = None + mainIcon = build_icon(u':/icon/openlp-logo-16x16.png') + self.setWindowIcon(mainIcon) self.setWindowTitle(u'OpenLP Display') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setWindowFlags(QtCore.Qt.FramelessWindowHint | diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 3d3a814a0..2189b38be 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -125,10 +125,8 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): return if status == 0: self.activePlugin.toggleStatus(PluginStatus.Active) - self.activePlugin.initialise() else: self.activePlugin.toggleStatus(PluginStatus.Inactive) - self.activePlugin.finalise() status_text = unicode( translate('OpenLP.PluginForm', '%s (Inactive)')) if self.activePlugin.status == PluginStatus.Active: diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index d1cf19622..15a8056c2 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -31,7 +31,7 @@ import logging from PyQt4 import QtGui from openlp.core.lib import Receiver -from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab +from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab, DisplayTagTab from settingsdialog import Ui_SettingsDialog log = logging.getLogger(__name__) @@ -55,6 +55,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): # Advanced tab self.advancedTab = AdvancedTab() self.addTab(u'Advanced', self.advancedTab) + # Edit Tags tab + displayTagTab = DisplayTagTab() + self.addTab(u'Display Tags', displayTagTab) def addTab(self, name, tab): """ @@ -68,9 +71,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): Add a tab to the form at a specific location """ log.debug(u'Inserting %s tab' % tab.tabTitle) - # 14 : There are 3 tables currently and locations starts at -10 + # 15 : There are 4 tables currently and locations starts at -10 self.settingsTabWidget.insertTab( - location + 14, tab, tab.tabTitleVisible) + location + 15, tab, tab.tabTitleVisible) def removeTab(self, tab): """ @@ -93,6 +96,14 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): Receiver.send_message(u'config_updated') return QtGui.QDialog.accept(self) + def reject(self): + """ + Process the form saving the settings + """ + for tabIndex in range(0, self.settingsTabWidget.count()): + self.settingsTabWidget.widget(tabIndex).cancel() + return QtGui.QDialog.reject(self) + def postSetUp(self): """ Run any post-setup code for the tabs on the form diff --git a/resources/forms/displaytabeditdialog.ui b/resources/forms/displaytabeditdialog.ui new file mode 100644 index 000000000..3c748594f --- /dev/null +++ b/resources/forms/displaytabeditdialog.ui @@ -0,0 +1,209 @@ + + + displayTagEdit + + + + 0 + 0 + 717 + 554 + + + + Form + + + + + 10 + 320 + 691 + 181 + + + + Edit Selection + + + + + 600 + 140 + 73 + 26 + + + + Update + + + + + + 20 + 50 + 571 + 114 + + + + + + + Description + + + Qt::AlignCenter + + + + + + + + + + Tag + + + Qt::AlignCenter + + + + + + + + 50 + 16777215 + + + + 5 + + + + + + + Start tag + + + Qt::AlignCenter + + + + + + + + + + End tag + + + Qt::AlignCenter + + + + + + + + + + + + + 540 + 510 + 162 + 26 + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 530 + 280 + 71 + 26 + + + + Delete + + + + + + 610 + 280 + 71 + 26 + + + + Add + + + + + + 10 + 10 + 691 + 271 + + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + Description + + + + + Key + + + AlignHCenter|AlignVCenter|AlignCenter + + + + + Start Tag + + + + + End Tag + + + + + + + From 67f6fceb0a1e2282dc6acebc008bbe51491cb142 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 23 Dec 2010 17:51:32 +0000 Subject: [PATCH 02/43] Allow Songs to be Searched by Theme --- openlp/plugins/songs/lib/mediaitem.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index e42cb7fa3..a3d1d24a6 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -168,6 +168,8 @@ class SongMediaItem(MediaManagerItem): translate('SongsPlugin.MediaItem', 'Lyrics')) self.SearchTypeComboBox.addItem( translate('SongsPlugin.MediaItem', 'Authors')) + self.SearchTypeComboBox.addItem( + translate('SongsPlugin.MediaItem', 'Themes')) self.configUpdated() def onSearchTextButtonClick(self): @@ -192,6 +194,12 @@ class SongMediaItem(MediaManagerItem): Author.display_name.like(u'%' + search_keywords + u'%'), Author.display_name.asc()) self.displayResultsAuthor(search_results) + elif search_type == 3: + log.debug(u'Theme Search') + search_results = self.parent.manager.get_all_objects(Song, + Song.theme_name.like(u'%' + search_keywords + u'%'), + Song.search_lyrics.asc()) + self.displayResultsSong(search_results) def onSongListLoad(self): """ From 49d8a6a2f2d38af9c61518662bdb2bb6afef1df8 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 26 Dec 2010 10:43:25 +0000 Subject: [PATCH 03/43] More changes --- openlp/core/lib/displaytags.py | 1 - openlp/core/lib/rendermanager.py | 2 +- openlp/core/ui/displaytagtab.py | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py index 2a47e2e09..ab321d6bb 100644 --- a/openlp/core/lib/displaytags.py +++ b/openlp/core/lib/displaytags.py @@ -34,7 +34,6 @@ class HtmlTags(object): """ def __init__(self): self.html_expands = [] - self.eyeCatcher = "eyeCatcher" self.reset_list() def reset_list(self): diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index fc7ba38b8..f448217ee 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -214,7 +214,7 @@ class RenderManager(object): if self.force_page: verse = verse + verse + verse else: - self.image_manager.del_image(self.theme_data.theme_name) + self.image_manager.del_image(theme_data.theme_name) footer = [] footer.append(u'Arky Arky (Unknown)' ) footer.append(u'Public Domain') diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index 56c9fd911..ec66b5028 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -50,7 +50,6 @@ class DisplayTagTab(SettingsTab): Initialise values before the Load takes place """ # Create initial copy from master - print DisplayTags.get_html_tags().eyeCatcher DisplayTags.get_html_tags().reset_list() user_expands = QtCore.QSettings().value(u'displayTags/html_tags', QtCore.QVariant(u'')).toString() @@ -66,7 +65,8 @@ class DisplayTagTab(SettingsTab): Configure the UI elements for the tab. ''' self.setObjectName(u'DisplayTagTab') - self.tabTitleVisible = translate(u'OpenLP.DisplayTagTab', 'Display Tags') + self.tabTitleVisible = \ + translate(u'OpenLP.DisplayTagTab', 'Display Tags') self.displayTagEdit = QtGui.QWidget(self) self.editGroupBox = QtGui.QGroupBox(self.displayTagEdit) self.editGroupBox.setGeometry(QtCore.QRect(10, 220, 691, 181)) From 4e58f880c357f56e374ecd8a6484ad8256cfd865 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 27 Dec 2010 08:31:20 +0000 Subject: [PATCH 04/43] More changes for next release --- openlp/core/ui/thememanager.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 477b07422..8d9581780 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -234,6 +234,9 @@ class ThemeManager(QtGui.QWidget): oldThemeData = self.getThemeData(oldThemeName) self.deleteTheme(oldThemeName) self.cloneThemeData(oldThemeData, newThemeName) + for plugin in self.parent.pluginManager.plugins: + if plugin.usesTheme(oldThemeName): + plugin.renameTheme(oldThemeName, newThemeName) def onCopyTheme(self): """ From 399970e7c755fa2dcb7adb1438a552a82be5c483 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 27 Dec 2010 10:18:09 +0000 Subject: [PATCH 05/43] More Theme Management cleanups --- openlp/core/ui/filerenameform.py | 2 +- openlp/core/ui/servicemanager.py | 8 +- openlp/core/ui/thememanager.py | 212 ++++++++++++-------------- openlp/plugins/songs/lib/mediaitem.py | 4 +- 4 files changed, 108 insertions(+), 118 deletions(-) diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py index 9ff310030..86634e3b1 100644 --- a/openlp/core/ui/filerenameform.py +++ b/openlp/core/ui/filerenameform.py @@ -52,4 +52,4 @@ class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): else: self.setWindowTitle(translate('OpenLP.FileRenameForm', 'File Rename')) - return QtGui.QDialog.exec_(self) \ No newline at end of file + return QtGui.QDialog.exec_(self) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e2c1a765b..9a3f33d88 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -108,11 +108,11 @@ class ServiceManager(QtGui.QWidget): self.suffixes = [] self.droppos = 0 self.expandTabs = False - #is a new service and has not been saved + # is a new service and has not been saved self.isNew = True self.serviceNoteForm = ServiceNoteForm(self.parent) self.serviceItemEditForm = ServiceItemEditForm(self.parent) - #start with the layout + # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) self.layout.setMargin(0) @@ -245,7 +245,7 @@ class ServiceManager(QtGui.QWidget): self.parent.serviceSettingsSection + u'/service theme', QtCore.QVariant(u'')).toString()) self.servicePath = AppLocation.get_section_data_path(u'servicemanager') - #build the drag and drop context menu + # build the drag and drop context menu self.dndMenu = QtGui.QMenu() self.newAction = self.dndMenu.addAction( translate('OpenLP.ServiceManager', '&Add New Item')) @@ -1119,4 +1119,4 @@ class ServiceManager(QtGui.QWidget): data_item[u'notes'] = unicode(service_item.notes) data_item[u'selected'] = (item == curitem) data.append(data_item) - Receiver.send_message(u'servicemanager_list_response', data) \ No newline at end of file + Receiver.send_message(u'servicemanager_list_response', data) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index f44ae7a6d..79eaadb4a 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -114,22 +114,30 @@ class ThemeManager(QtGui.QWidget): self.exportAction = self.menu.addAction( translate('OpenLP.ThemeManager', '&Export Theme')) self.exportAction.setIcon(build_icon(u':/general/general_export.png')) - #Signals + # Signals QtCore.QObject.connect(self.themeListWidget, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.changeGlobalFromScreen) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.changeGlobalFromTab) - #Variables + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_updated'), self.configUpdated) + # Variables self.themelist = [] self.path = AppLocation.get_section_data_path(self.settingsSection) - self.checkThemesExists(self.path) + self.checkDirectoryExists(self.path) self.thumbPath = os.path.join(self.path, u'thumbnails') - self.checkThemesExists(self.thumbPath) + self.checkDirectoryExists(self.thumbPath) self.themeForm.path = self.path self.oldBackgroundImage = None self.editingDefault = False # Last little bits of setting up + self.configUpdated() + + def configUpdated(self, firstTime=False): + """ + Triggered when Config dialog is updated. + """ self.global_theme = unicode(QtCore.QSettings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) @@ -215,7 +223,6 @@ class ThemeManager(QtGui.QWidget): editing form for the user to make their customisations. """ theme = ThemeXML() - self.saveThemeName = u'' self.themeForm.theme = theme self.themeForm.exec_() @@ -228,15 +235,15 @@ class ThemeManager(QtGui.QWidget): item = self.themeListWidget.currentItem() oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) self.fileRenameForm.fileNameEdit.setText(oldThemeName) - self.saveThemeName = oldThemeName if self.fileRenameForm.exec_(): newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) - oldThemeData = self.getThemeData(oldThemeName) - self.deleteTheme(oldThemeName) - self.cloneThemeData(oldThemeData, newThemeName) - for plugin in self.parent.pluginManager.plugins: - if plugin.usesTheme(oldThemeName): - plugin.renameTheme(oldThemeName, newThemeName) + if self.checkIfThemeExists(newThemeName): + oldThemeData = self.getThemeData(oldThemeName) + self.deleteTheme(oldThemeName) + self.cloneThemeData(oldThemeData, newThemeName) + for plugin in self.parent.pluginManager.plugins: + if plugin.usesTheme(oldThemeName): + plugin.renameTheme(oldThemeName, newThemeName) def onCopyTheme(self): """ @@ -245,12 +252,12 @@ class ThemeManager(QtGui.QWidget): item = self.themeListWidget.currentItem() oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) self.fileRenameForm.fileNameEdit.setText(oldThemeName) - self.saveThemeName = u'' if self.fileRenameForm.exec_(True): newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) - themeData = self.getThemeData(oldThemeName) - self.cloneThemeData(themeData, newThemeName) - self.loadThemes() + if self.checkIfThemeExists(newThemeName): + themeData = self.getThemeData(oldThemeName) + self.cloneThemeData(themeData, newThemeName) + self.loadThemes() def cloneThemeData(self, themeData, newThemeName): """ @@ -282,8 +289,6 @@ class ThemeManager(QtGui.QWidget): unicode(item.data(QtCore.Qt.UserRole).toString())) if theme.background_type == u'image': self.oldBackgroundImage = theme.background_filename - self.saveThemeName = unicode( - item.data(QtCore.Qt.UserRole).toString()) self.themeForm.theme = theme self.themeForm.exec_(True) @@ -446,7 +451,7 @@ class ThemeManager(QtGui.QWidget): else: return self.createThemeFromXml(xml, self.path) - def checkThemesExists(self, dir): + def checkDirectoryExists(self, dir): """ Check a theme directory exists and if not create it @@ -609,6 +614,20 @@ class ThemeManager(QtGui.QWidget): newtheme.display_vertical_align = vAlignCorrection return newtheme.extract_xml() + def checkIfThemeExists(self, themeName): + """ + Check if theme already exists and displays error message + """ + theme_dir = os.path.join(self.path, themeName) + if os.path.exists(theme_dir): + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Theme Exists'), + translate('OpenLP.ThemeManager', + 'A theme with this name already exists.'), + (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) + return False + return True + def saveTheme(self, theme, imageFrom, imageTo): """ Called by thememaintenance Dialog to save the theme @@ -623,77 +642,57 @@ class ThemeManager(QtGui.QWidget): theme_file = os.path.join(theme_dir, name + u'.xml') log.debug(theme_file) editedServiceTheme = False - result = QtGui.QMessageBox.Yes - if self.saveThemeName != name: - if os.path.exists(theme_file): - result = QtGui.QMessageBox.question(self, - translate('OpenLP.ThemeManager', 'Theme Exists'), - translate('OpenLP.ThemeManager', - 'A theme with this name already ' - 'exists. Would you like to overwrite it?'), - (QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), - QtGui.QMessageBox.No) - if self.saveThemeName != u'': - for plugin in self.parent.pluginManager.plugins: - if plugin.usesTheme(self.saveThemeName): - plugin.renameTheme(self.saveThemeName, name) - if unicode(self.serviceComboBox.currentText()) == name: - editedServiceTheme = True - if result == QtGui.QMessageBox.Yes: + #result = QtGui.QMessageBox.Yes + #if result == QtGui.QMessageBox.Yes: # Save the theme, overwriting the existing theme if necessary. - if imageTo and self.oldBackgroundImage and \ - imageTo != self.oldBackgroundImage: - try: - os.remove(self.oldBackgroundImage) - except OSError: - log.exception(u'Unable to remove old theme background') - outfile = None + if imageTo and self.oldBackgroundImage and \ + imageTo != self.oldBackgroundImage: try: - outfile = open(theme_file, u'w') - outfile.write(theme_pretty_xml) + os.remove(self.oldBackgroundImage) + except OSError: + log.exception(u'Unable to remove old theme background') + outfile = None + try: + outfile = open(theme_file, u'w') + outfile.write(theme_pretty_xml) + except IOError: + log.exception(u'Saving theme to file failed') + finally: + if outfile: + outfile.close() + if imageFrom and imageFrom != imageTo: + try: + encoding = get_filesystem_encoding() + shutil.copyfile( + unicode(imageFrom).encode(encoding), + unicode(imageTo).encode(encoding)) except IOError: - log.exception(u'Saving theme to file failed') - finally: - if outfile: - outfile.close() - if imageFrom and imageFrom != imageTo: - try: - encoding = get_filesystem_encoding() - shutil.copyfile( - unicode(imageFrom).encode(encoding), - unicode(imageTo).encode(encoding)) - except IOError: - log.exception(u'Failed to save theme image') - self.generateAndSaveImage(self.path, name, theme) - self.loadThemes() + log.exception(u'Failed to save theme image') + self.generateAndSaveImage(self.path, name, theme) + self.loadThemes() # Check if we need to set a new service theme - if editedServiceTheme: - newThemeIndex = self.serviceComboBox.findText(name) - if newThemeIndex != -1: - self.serviceComboBox.setCurrentIndex(newThemeIndex) - if self.editingDefault: - if self.saveThemeName != name: - newThemeItem = self.themeListWidget.findItems(name, - QtCore.Qt.MatchExactly)[0] - newThemeIndex = self.themeListWidget.indexFromItem( - newThemeItem).row() - self.global_theme = unicode( - self.themeListWidget.item(newThemeIndex).text()) - newName = unicode(translate('OpenLP.ThemeManager', - '%s (default)')) % self.global_theme - self.themeListWidget.item(newThemeIndex).setText(newName) - QtCore.QSettings().setValue( - self.settingsSection + u'/global theme', - QtCore.QVariant(self.global_theme)) - Receiver.send_message(u'theme_update_global', - self.global_theme) - self.editingDefault = False - self.pushThemes() - return True - else: - # Don't close the dialog - allow the user to change the name of - # the theme or to cancel the theme dialog completely. - return False +# if editedServiceTheme: +# newThemeIndex = self.serviceComboBox.findText(name) +# if newThemeIndex != -1: +# self.serviceComboBox.setCurrentIndex(newThemeIndex) +# if self.editingDefault: +# if self.saveThemeName != name: +# newThemeItem = self.themeListWidget.findItems(name, +# QtCore.Qt.MatchExactly)[0] +# newThemeIndex = self.themeListWidget.indexFromItem( +# newThemeItem).row() +# self.global_theme = unicode( +# self.themeListWidget.item(newThemeIndex).text()) +# newName = unicode(translate('OpenLP.ThemeManager', +# '%s (default)')) % self.global_theme +# self.themeListWidget.item(newThemeIndex).setText(newName) +# QtCore.QSettings().setValue( +# self.settingsSection + u'/global theme', +# QtCore.QVariant(self.global_theme)) +# Receiver.send_message(u'theme_update_global', +# self.global_theme) +# self.editingDefault = False + self.pushThemes() def generateAndSaveImage(self, dir, name, theme): log.debug(u'generateAndSaveImage %s %s', dir, name) @@ -758,15 +757,12 @@ class ThemeManager(QtGui.QWidget): Check to see if theme has been selected and the destructive action is allowed. """ - self.global_theme = unicode(QtCore.QSettings().value( - self.settingsSection + u'/global theme', - QtCore.QVariant(u'')).toString()) if check_item_selected(self.themeListWidget, unicode(translate('OpenLP.ThemeManager', 'You must select a theme to %s.')) % action): item = self.themeListWidget.currentItem() theme = unicode(item.text()) - # confirm deletion + # confirm destructive action answer = QtGui.QMessageBox.question(self, unicode(translate('OpenLP.ThemeManager', '%s Confirmation')) % action, @@ -776,26 +772,20 @@ class ThemeManager(QtGui.QWidget): QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: return False - # should be the same unless default - if theme != unicode(item.data(QtCore.Qt.UserRole).toString()): + # check for use in the system else where. + if testPlugin: + for plugin in self.parent.pluginManager.plugins: + if plugin.usesTheme(theme): + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Error'), + unicode(translate('OpenLP.ThemeManager', + 'Theme %s is used in the %s plugin.')) % \ + (theme, plugin.name)) + return False + if unicode(self.serviceComboBox.currentText()) == theme: QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', - 'You are unable to delete the default theme.')) - else: - if testPlugin: - for plugin in self.parent.pluginManager.plugins: - if plugin.usesTheme(theme): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used in the %s plugin.')) % \ - (theme, plugin.name)) - return False - if unicode(self.serviceComboBox.currentText()) == theme: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used by the service manager.')) % theme) - return False - return True \ No newline at end of file + unicode(translate('OpenLP.ThemeManager', + 'Theme %s is used by the service manager.')) % theme) + return False + return True diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 99d378f58..6574ed521 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -197,7 +197,7 @@ class SongMediaItem(MediaManagerItem): elif search_type == 3: log.debug(u'Theme Search') search_results = self.parent.manager.get_all_objects(Song, - Song.theme_name.like(u'%' + search_keywords + u'%'), + Song.theme_name == search_keywords, Song.search_lyrics.asc()) self.displayResultsSong(search_results) @@ -465,4 +465,4 @@ class SongMediaItem(MediaManagerItem): """ Locale aware collation of song titles """ - return locale.strcoll(unicode(song_1.title), unicode(song_2.title)) \ No newline at end of file + return locale.strcoll(unicode(song_1.title), unicode(song_2.title)) From ecc46c12c447a42a7e5156f284c7ff08468e21d2 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 28 Dec 2010 10:56:19 +0000 Subject: [PATCH 06/43] Theme manager cleanup --- openlp/core/ui/themeform.py | 10 +- openlp/core/ui/thememanager.py | 345 +++++++++++++++------------------ 2 files changed, 167 insertions(+), 188 deletions(-) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index c7854e187..673d48a07 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -600,7 +600,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) return - self.accepted = True saveFrom = None saveTo = None if self.theme.background_type == \ @@ -608,9 +607,12 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): filename = \ os.path.split(unicode(self.theme.background_filename))[1] saveTo = os.path.join(self.path, self.theme.theme_name, filename) - saveFrom = self.theme.background_filename - if self.thememanager.saveTheme(self.theme, saveFrom, saveTo): + saveFrom = self.theme.background_filename# + if self.thememanager.checkIfThemeExists(self.theme.theme_name): + self.thememanager.saveTheme(self.theme, saveFrom, saveTo) + self.accepted = True return QtGui.QDialog.accept(self) + return def _colorButton(self, field): """ @@ -620,4 +622,4 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtGui.QColor(field), self) if new_color.isValid(): field = new_color.name() - return field \ No newline at end of file + return field diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 79eaadb4a..4772994fa 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -130,7 +130,6 @@ class ThemeManager(QtGui.QWidget): self.checkDirectoryExists(self.thumbPath) self.themeForm.path = self.path self.oldBackgroundImage = None - self.editingDefault = False # Last little bits of setting up self.configUpdated() @@ -143,6 +142,10 @@ class ThemeManager(QtGui.QWidget): QtCore.QVariant(u'')).toString()) def contextMenu(self, point): + """ + Build the Right Click Context menu and set state depending on + the type of theme. + """ item = self.themeListWidget.itemAt(point) if item is None: return @@ -283,8 +286,6 @@ class ThemeManager(QtGui.QWidget): 'You must select a theme to edit.')): item = self.themeListWidget.currentItem() themeName = unicode(item.text()) - if themeName != unicode(item.data(QtCore.Qt.UserRole).toString()): - self.editingDefault = True theme = self.getThemeData( unicode(item.data(QtCore.Qt.UserRole).toString())) if theme.background_type == u'image': @@ -447,9 +448,9 @@ class ThemeManager(QtGui.QWidget): unicode(themeName) + u'.xml') xml = get_text_file_string(xmlFile) if not xml: - return self.baseTheme() + return self._baseTheme() else: - return self.createThemeFromXml(xml, self.path) + return self._createThemeFromXml(xml, self.path) def checkDirectoryExists(self, dir): """ @@ -520,7 +521,7 @@ class ThemeManager(QtGui.QWidget): outfile = open(fullpath, u'wb') outfile.write(zip.read(file)) if filexml: - theme = self.createThemeFromXml(filexml, self.path) + theme = self._createThemeFromXml(filexml, self.path) self.generateAndSaveImage(dir, themename, theme) else: QtGui.QMessageBox.critical(self, @@ -554,9 +555,161 @@ class ThemeManager(QtGui.QWidget): if tree.find(u'BackgroundType') is None: return xml_data else: - return self.migrateVersion122(xml_data) + return self._migrateVersion122(xml_data) - def migrateVersion122(self, xml_data): + def checkIfThemeExists(self, themeName): + """ + Check if theme already exists and displays error message + + ``themeName`` + Name of the Theme to test + """ + theme_dir = os.path.join(self.path, themeName) + if os.path.exists(theme_dir): + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Theme Exists'), + translate('OpenLP.ThemeManager', + 'A theme with this name already exists.'), + (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) + return False + return True + + def saveTheme(self, theme, imageFrom, imageTo): + """ + Called by thememaintenance Dialog to save the theme + and to trigger the reload of the theme list + """ + name = theme.theme_name + theme_pretty_xml = theme.extract_formatted_xml() + log.debug(u'saveTheme %s %s', name, theme_pretty_xml) + theme_dir = os.path.join(self.path, name) + if not os.path.exists(theme_dir): + os.mkdir(os.path.join(self.path, name)) + theme_file = os.path.join(theme_dir, name + u'.xml') + if imageTo and self.oldBackgroundImage and \ + imageTo != self.oldBackgroundImage: + try: + os.remove(self.oldBackgroundImage) + except OSError: + log.exception(u'Unable to remove old theme background') + outfile = None + try: + outfile = open(theme_file, u'w') + outfile.write(theme_pretty_xml) + except IOError: + log.exception(u'Saving theme to file failed') + finally: + if outfile: + outfile.close() + if imageFrom and imageFrom != imageTo: + try: + encoding = get_filesystem_encoding() + shutil.copyfile( + unicode(imageFrom).encode(encoding), + unicode(imageTo).encode(encoding)) + except IOError: + log.exception(u'Failed to save theme image') + self.generateAndSaveImage(self.path, name, theme) + self.loadThemes() + self.pushThemes() + + def generateAndSaveImage(self, dir, name, theme): + log.debug(u'generateAndSaveImage %s %s', dir, name) + theme_xml = theme.extract_xml() + frame = self.generateImage(theme) + samplepathname = os.path.join(self.path, name + u'.png') + if os.path.exists(samplepathname): + os.unlink(samplepathname) + frame.save(samplepathname, u'png') + thumb = os.path.join(self.thumbPath, u'%s.png' % name) + icon = build_icon(frame) + pixmap = icon.pixmap(QtCore.QSize(88, 50)) + pixmap.save(thumb, u'png') + log.debug(u'Theme image written to %s', samplepathname) + + def generateImage(self, themeData, forcePage=False): + """ + Call the RenderManager to build a Sample Image + + ``themeData`` + The theme to generated a preview for. + + ``forcePage`` + Flag to tell message lines per page need to be generated. + """ + log.debug(u'generateImage \n%s ', themeData) + return self.parent.renderManager.generate_preview(themeData, forcePage) + + def getPreviewImage(self, theme): + """ + Return an image representing the look of the theme + + ``theme`` + The theme to return the image for + """ + log.debug(u'getPreviewImage %s ', theme) + image = os.path.join(self.path, theme + u'.png') + return image + + def _baseTheme(self): + """ + Provide a base theme with sensible defaults + """ + log.debug(u'base theme created') + newtheme = ThemeXML() + return newtheme + + def _createThemeFromXml(self, themeXml, path): + """ + Return a theme object using information parsed from XML + + ``themeXml`` + The XML data to load into the theme + """ + theme = ThemeXML() + theme.parse(themeXml) + theme.extend_image_filename(path) + return theme + + def _validate_theme_action(self, action, testPlugin=True): + """ + Check to see if theme has been selected and the destructive action + is allowed. + """ + if check_item_selected(self.themeListWidget, + unicode(translate('OpenLP.ThemeManager', + 'You must select a theme to %s.')) % action): + item = self.themeListWidget.currentItem() + theme = unicode(item.text()) + # confirm destructive action + answer = QtGui.QMessageBox.question(self, + unicode(translate('OpenLP.ThemeManager', '%s Confirmation')) + % action, + unicode(translate('OpenLP.ThemeManager', '%s %s theme?')) + % (action, theme), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No), QtGui.QMessageBox.No) + if answer == QtGui.QMessageBox.No: + return False + # check for use in the system else where. + if testPlugin: + for plugin in self.parent.pluginManager.plugins: + if plugin.usesTheme(theme): + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Error'), + unicode(translate('OpenLP.ThemeManager', + 'Theme %s is used in the %s plugin.')) % \ + (theme, plugin.name)) + return False + if unicode(self.serviceComboBox.currentText()) == theme: + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Error'), + unicode(translate('OpenLP.ThemeManager', + 'Theme %s is used by the service manager.')) % theme) + return False + return True + + def _migrateVersion122(self, xml_data): """ Convert the xml data from version 1 format to the current format. @@ -613,179 +766,3 @@ class ThemeManager(QtGui.QWidget): newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_vertical_align = vAlignCorrection return newtheme.extract_xml() - - def checkIfThemeExists(self, themeName): - """ - Check if theme already exists and displays error message - """ - theme_dir = os.path.join(self.path, themeName) - if os.path.exists(theme_dir): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Theme Exists'), - translate('OpenLP.ThemeManager', - 'A theme with this name already exists.'), - (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) - return False - return True - - def saveTheme(self, theme, imageFrom, imageTo): - """ - Called by thememaintenance Dialog to save the theme - and to trigger the reload of the theme list - """ - name = theme.theme_name - theme_pretty_xml = theme.extract_formatted_xml() - log.debug(u'saveTheme %s %s', name, theme_pretty_xml) - theme_dir = os.path.join(self.path, name) - if not os.path.exists(theme_dir): - os.mkdir(os.path.join(self.path, name)) - theme_file = os.path.join(theme_dir, name + u'.xml') - log.debug(theme_file) - editedServiceTheme = False - #result = QtGui.QMessageBox.Yes - #if result == QtGui.QMessageBox.Yes: - # Save the theme, overwriting the existing theme if necessary. - if imageTo and self.oldBackgroundImage and \ - imageTo != self.oldBackgroundImage: - try: - os.remove(self.oldBackgroundImage) - except OSError: - log.exception(u'Unable to remove old theme background') - outfile = None - try: - outfile = open(theme_file, u'w') - outfile.write(theme_pretty_xml) - except IOError: - log.exception(u'Saving theme to file failed') - finally: - if outfile: - outfile.close() - if imageFrom and imageFrom != imageTo: - try: - encoding = get_filesystem_encoding() - shutil.copyfile( - unicode(imageFrom).encode(encoding), - unicode(imageTo).encode(encoding)) - except IOError: - log.exception(u'Failed to save theme image') - self.generateAndSaveImage(self.path, name, theme) - self.loadThemes() - # Check if we need to set a new service theme -# if editedServiceTheme: -# newThemeIndex = self.serviceComboBox.findText(name) -# if newThemeIndex != -1: -# self.serviceComboBox.setCurrentIndex(newThemeIndex) -# if self.editingDefault: -# if self.saveThemeName != name: -# newThemeItem = self.themeListWidget.findItems(name, -# QtCore.Qt.MatchExactly)[0] -# newThemeIndex = self.themeListWidget.indexFromItem( -# newThemeItem).row() -# self.global_theme = unicode( -# self.themeListWidget.item(newThemeIndex).text()) -# newName = unicode(translate('OpenLP.ThemeManager', -# '%s (default)')) % self.global_theme -# self.themeListWidget.item(newThemeIndex).setText(newName) -# QtCore.QSettings().setValue( -# self.settingsSection + u'/global theme', -# QtCore.QVariant(self.global_theme)) -# Receiver.send_message(u'theme_update_global', -# self.global_theme) -# self.editingDefault = False - self.pushThemes() - - def generateAndSaveImage(self, dir, name, theme): - log.debug(u'generateAndSaveImage %s %s', dir, name) - theme_xml = theme.extract_xml() - frame = self.generateImage(theme) - samplepathname = os.path.join(self.path, name + u'.png') - if os.path.exists(samplepathname): - os.unlink(samplepathname) - frame.save(samplepathname, u'png') - thumb = os.path.join(self.thumbPath, u'%s.png' % name) - icon = build_icon(frame) - pixmap = icon.pixmap(QtCore.QSize(88, 50)) - pixmap.save(thumb, u'png') - log.debug(u'Theme image written to %s', samplepathname) - - def generateImage(self, themeData, forcePage=False): - """ - Call the RenderManager to build a Sample Image - - ``themeData`` - The theme to generated a preview for. - - ``forcePage`` - Flag to tell message lines per page need to be generated. - """ - log.debug(u'generateImage \n%s ', themeData) - return self.parent.renderManager.generate_preview(themeData, forcePage) - - def getPreviewImage(self, theme): - """ - Return an image representing the look of the theme - - ``theme`` - The theme to return the image for - """ - log.debug(u'getPreviewImage %s ', theme) - image = os.path.join(self.path, theme + u'.png') - return image - - def baseTheme(self): - """ - Provide a base theme with sensible defaults - """ - log.debug(u'base theme created') - newtheme = ThemeXML() - return newtheme - - def createThemeFromXml(self, themeXml, path): - """ - Return a theme object using information parsed from XML - - ``themeXml`` - The XML data to load into the theme - """ - theme = ThemeXML() - theme.parse(themeXml) - theme.extend_image_filename(path) - return theme - - def _validate_theme_action(self, action, testPlugin=True): - """ - Check to see if theme has been selected and the destructive action - is allowed. - """ - if check_item_selected(self.themeListWidget, - unicode(translate('OpenLP.ThemeManager', - 'You must select a theme to %s.')) % action): - item = self.themeListWidget.currentItem() - theme = unicode(item.text()) - # confirm destructive action - answer = QtGui.QMessageBox.question(self, - unicode(translate('OpenLP.ThemeManager', '%s Confirmation')) - % action, - unicode(translate('OpenLP.ThemeManager', '%s %s theme?')) - % (action, theme), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | - QtGui.QMessageBox.No), QtGui.QMessageBox.No) - if answer == QtGui.QMessageBox.No: - return False - # check for use in the system else where. - if testPlugin: - for plugin in self.parent.pluginManager.plugins: - if plugin.usesTheme(theme): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used in the %s plugin.')) % \ - (theme, plugin.name)) - return False - if unicode(self.serviceComboBox.currentText()) == theme: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used by the service manager.')) % theme) - return False - return True From 0ce3848d0f19db7e6780a121e8f385b6af40c4c0 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 28 Dec 2010 11:07:59 +0000 Subject: [PATCH 07/43] Fix missed years --- openlp/core/lib/displaytags.py | 5 ++--- openlp/core/ui/displaytagtab.py | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py index ab321d6bb..435ebdf63 100644 --- a/openlp/core/lib/displaytags.py +++ b/openlp/core/lib/displaytags.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # # Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # # Carsten Tinggaard, Frode Woldsund # @@ -62,4 +62,3 @@ class DisplayTags(object): Provide access to the HtmlTags object. """ return DisplayTags.html_tags - diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index ec66b5028..a4415911b 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # # Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # # Carsten Tinggaard, Frode Woldsund # @@ -341,4 +341,4 @@ class DisplayTagTab(SettingsTab): """ tag = tag.replace(u'{', u'') tag = tag.replace(u'}', u'') - return tag + return tag \ No newline at end of file From 0a1118266b606e874bbb7d5036278e7f13ff0a3d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 31 Dec 2010 08:34:53 +0000 Subject: [PATCH 08/43] fix ups requested by Raoul --- openlp/core/lib/__init__.py | 6 +++--- openlp/core/lib/displaytags.py | 25 +++++++++++++++++++++++-- openlp/core/ui/displaytagtab.py | 27 +++++++++++++-------------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 1200cb21e..49d2e4522 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -291,7 +291,7 @@ def clean_tags(text): Remove Tags from text for display """ text = text.replace(u'
', u'\n') - for tag in DisplayTags.get_html_tags().html_expands: + for tag in DisplayTags.get_html_tags(): text = text.replace(tag[u'start tag'], u'') text = text.replace(tag[u'end tag'], u'') return text @@ -300,7 +300,7 @@ def expand_tags(text): """ Expand tags HTML for display """ - for tag in DisplayTags.get_html_tags().html_expands: + for tag in DisplayTags.get_html_tags(): text = text.replace(tag[u'start tag'], tag[u'start html']) text = text.replace(tag[u'end tag'], tag[u'end html']) return text @@ -325,4 +325,4 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from baselistwithdnd import BaseListWithDnD \ No newline at end of file +from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py index 435ebdf63..9e0e7b387 100644 --- a/openlp/core/lib/displaytags.py +++ b/openlp/core/lib/displaytags.py @@ -59,6 +59,27 @@ class DisplayTags(object): @staticmethod def get_html_tags(): """ - Provide access to the HtmlTags object. + Provide access to the html_expands list. """ - return DisplayTags.html_tags + return DisplayTags.html_tags.html_expands + + @staticmethod + def reset_html_tags(): + """ + Resets the html_expands list. + """ + return DisplayTags.html_tags.reset_list() + + @staticmethod + def add_html_tag(tag): + """ + Add a new tag to the list + """ + return DisplayTags.html_tags.add_tag(tag) + + @staticmethod + def remove_html_tag(id): + """ + Removes amd individual html_expands list. + """ + return DisplayTags.html_tags.html_expands.pop(id) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index a4415911b..47e3b7192 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -50,14 +50,14 @@ class DisplayTagTab(SettingsTab): Initialise values before the Load takes place """ # Create initial copy from master - DisplayTags.get_html_tags().reset_list() + DisplayTags.reset_html_tags() user_expands = QtCore.QSettings().value(u'displayTags/html_tags', QtCore.QVariant(u'')).toString() # cPickle only accepts str not unicode strings user_tags = cPickle.loads(str(user_expands)) # If we have some user ones added them as well for t in user_tags: - DisplayTags.get_html_tags().add_tag(t) + DisplayTags.add_html_tag(t) self.selected = -1 def setupUi(self): @@ -194,8 +194,7 @@ class DisplayTagTab(SettingsTab): self.newPushButton.setEnabled(True) self.updatePushButton.setEnabled(False) self.deletePushButton.setEnabled(False) - for linenumber, html in enumerate( - DisplayTags.get_html_tags().html_expands): + for linenumber, html in enumerate(DisplayTags.get_html_tags()): self.tagTableWidget.setRowCount( self.tagTableWidget.rowCount() + 1) self.tagTableWidget.setItem(linenumber, 0, @@ -221,7 +220,7 @@ class DisplayTagTab(SettingsTab): Save Custom tags in a pickle . """ temp = [] - for tag in DisplayTags.get_html_tags().html_expands: + for tag in DisplayTags.get_html_tags(): if not tag[u'protected']: temp.append(tag) if temp: @@ -244,7 +243,7 @@ class DisplayTagTab(SettingsTab): Table Row selected so display items and set field state. """ row = self.tagTableWidget.currentRow() - html = DisplayTags.get_html_tags().html_expands[row] + html = DisplayTags.get_html_tags()[row] self.selected = row self.descriptionLineEdit.setText(html[u'desc']) self.tagLineEdit.setText(self._strip(html[u'start tag'])) @@ -269,7 +268,7 @@ class DisplayTagTab(SettingsTab): """ Add a new tag to list only if it is not a duplicate. """ - for html in DisplayTags.get_html_tags().html_expands: + for html in DisplayTags.get_html_tags(): if self._strip(html[u'start tag']) == u'n': QtGui.QMessageBox.critical(self, translate('OpenLP.DisplayTagTab', 'Update Error'), @@ -279,17 +278,17 @@ class DisplayTagTab(SettingsTab): QtGui.QMessageBox.Ok) return # Add new tag to list - DisplayTags.get_html_tags().html_expands.append( - {u'desc': u'New Item', u'start tag': u'{n}', + tag = {u'desc': u'New Item', u'start tag': u'{n}', u'start html': u'', u'end tag': u'{/n}', - u'end html': u'', u'protected': False}) + u'end html': u'', u'protected': False} + DisplayTags.add_html_tag(tag) self._resetTable() def onDefaultPushed(self): """ Remove all Custom Tags and reset to base set only. """ - DisplayTags.get_html_tags().reset_list() + DisplayTags.reset_html_tags() self._resetTable() def onDeletePushed(self): @@ -297,7 +296,7 @@ class DisplayTagTab(SettingsTab): Delete selected custom tag. """ if self.selected != -1: - DisplayTags.get_html_tags().html_expands.pop(self.selected) + DisplayTags.remove_html_tag(self.selected) self.selected = -1 self._resetTable() @@ -305,7 +304,7 @@ class DisplayTagTab(SettingsTab): """ Update Custom Tag details if not duplicate. """ - html_expands = DisplayTags.get_html_tags().html_expands + html_expands = DisplayTags.get_html_tags() if self.selected != -1: html = html_expands[self.selected] tag = unicode(self.tagLineEdit.text()) @@ -341,4 +340,4 @@ class DisplayTagTab(SettingsTab): """ tag = tag.replace(u'{', u'') tag = tag.replace(u'}', u'') - return tag \ No newline at end of file + return tag From f6a8e6884c9c4617194246457b5d759d536b139e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 1 Jan 2011 17:23:24 +0000 Subject: [PATCH 09/43] Clean up directory creation --- openlp.pyw | 7 +-- openlp/core/lib/__init__.py | 11 ++++ openlp/core/ui/slidecontroller.py | 2 - openlp/core/ui/thememanager.py | 86 ++++++++------------------ openlp/plugins/images/lib/mediaitem.py | 5 +- 5 files changed, 43 insertions(+), 68 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index c1d4ae10a..d5975b1a4 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -34,7 +34,7 @@ from subprocess import Popen, PIPE from PyQt4 import QtCore, QtGui -from openlp.core.lib import Receiver +from openlp.core.lib import Receiver, checkDirectoryExists from openlp.core.resources import qInitResources from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.exceptionform import ExceptionForm @@ -216,7 +216,7 @@ class OpenLP(QtGui.QApplication): def setNormalCursor(self): """ - Sets the Normal Cursor forthe Application + Sets the Normal Cursor for the Application """ self.restoreOverrideCursor() @@ -243,8 +243,7 @@ def main(): help='Set the Qt4 style (passed directly to Qt4).') # Set up logging log_path = AppLocation.get_directory(AppLocation.CacheDir) - if not os.path.exists(log_path): - os.makedirs(log_path) + checkDirectoryExists(log_path) filename = os.path.join(log_path, u'openlp.log') logfile = logging.FileHandler(filename, u'w') logfile.setFormatter(logging.Formatter( diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index d9dae9455..dd1fb852b 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -306,6 +306,17 @@ def expand_tags(text): text = text.replace(tag[u'end tag'], tag[u'end html']) return text +def checkDirectoryExists(dir): + """ + Check a theme directory exists and if not create it + + ``dir`` + Theme directory to make sure exists + """ + log.debug(u'checkDirectoryExists') + if not os.path.exists(dir): + os.mkdir(dir) + from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ BackgroundType, HorizontalType, VerticalType from displaytags import DisplayTags diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 6a5e313f0..97a02f333 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -387,7 +387,6 @@ class SlideController(QtGui.QWidget): Settings dialog has changed the screen size of adjust output and screen previews. """ - log.debug(u'screenSizeChanged live = %s' % self.isLive) # rebuild display as screen size changed self.display = MainDisplay(self, self.screens, self.isLive) self.display.imageManager = self.parent.renderManager.image_manager @@ -403,7 +402,6 @@ class SlideController(QtGui.QWidget): Takes care of the SlidePreview's size. Is called when one of the the splitters is moved or when the screen size is changed. """ - log.debug(u'previewSizeChanged live = %s' % self.isLive) if self.ratio < float(self.PreviewFrame.width()) / float( self.PreviewFrame.height()): # We have to take the height as limit. diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 6a7f98a03..7cfdb9aae 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -36,7 +36,7 @@ from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.theme import Theme from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ build_icon, Receiver, SettingsManager, translate, check_item_selected, \ - BackgroundType, BackgroundGradientType + BackgroundType, BackgroundGradientType, checkDirectoryExists from openlp.core.utils import AppLocation, get_filesystem_encoding log = logging.getLogger(__name__) @@ -125,9 +125,9 @@ class ThemeManager(QtGui.QWidget): # Variables self.themelist = [] self.path = AppLocation.get_section_data_path(self.settingsSection) - self.checkDirectoryExists(self.path) + checkDirectoryExists(self.path) self.thumbPath = os.path.join(self.path, u'thumbnails') - self.checkDirectoryExists(self.thumbPath) + checkDirectoryExists(self.thumbPath) self.themeForm.path = self.path self.oldBackgroundImage = None # Last little bits of setting up @@ -457,17 +457,6 @@ class ThemeManager(QtGui.QWidget): else: return self._createThemeFromXml(xml, self.path) - def checkDirectoryExists(self, dir): - """ - Check a theme directory exists and if not create it - - ``dir`` - Theme directory to make sure exists - """ - log.debug(u'check themes') - if not os.path.exists(dir): - os.mkdir(dir) - def unzipTheme(self, filename, dir): """ Unzip the theme, remove the preview file if stored @@ -498,8 +487,7 @@ class ThemeManager(QtGui.QWidget): theme_dir = None if osfile.endswith(os.path.sep): theme_dir = os.path.join(dir, osfile) - if not os.path.exists(theme_dir): - os.mkdir(os.path.join(dir, osfile)) + checkDirectoryExists(theme_dir) else: fullpath = os.path.join(dir, osfile) names = osfile.split(os.path.sep) @@ -509,8 +497,7 @@ class ThemeManager(QtGui.QWidget): themename = names[0] if theme_dir is None: theme_dir = os.path.join(dir, names[0]) - if not os.path.exists(theme_dir): - os.mkdir(os.path.join(dir, names[0])) + checkDirectoryExists(theme_dir) if os.path.splitext(ucsfile)[1].lower() in [u'.xml']: xml_data = zip.read(file) try: @@ -529,16 +516,19 @@ class ThemeManager(QtGui.QWidget): theme = self._createThemeFromXml(filexml, self.path) self.generateAndSaveImage(dir, themename, theme) else: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', - 'File is not a valid theme.')) + Receiver.send_message(u'openlp_error_message', { + u'title': translate('OpenLP.ThemeManager', \ + 'Validation Error'), + u'message':translate('OpenLP.ThemeManager', + 'File is not a valid theme.')}) log.exception(u'Theme file does not contain XML data %s' % filename) except (IOError, NameError): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', 'File is not a valid theme.')) + Receiver.send_message(u'openlp_error_message', { + u'title': translate('OpenLP.ThemeManager', \ + 'Validation Error'), + u'message':translate('OpenLP.ThemeManager', + 'File is not a valid theme.')}) log.exception(u'Importing theme from zip failed %s' % filename) finally: if zip: @@ -571,11 +561,11 @@ class ThemeManager(QtGui.QWidget): """ theme_dir = os.path.join(self.path, themeName) if os.path.exists(theme_dir): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Theme Exists'), - translate('OpenLP.ThemeManager', - 'A theme with this name already exists.'), - (QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) + Receiver.send_message(u'openlp_error_message', { + u'title': translate('OpenLP.ThemeManager', \ + 'Validation Error'), + u'message':translate('OpenLP.ThemeManager', + 'A theme with this name already exists.')}) return False return True @@ -588,8 +578,7 @@ class ThemeManager(QtGui.QWidget): theme_pretty_xml = theme.extract_formatted_xml() log.debug(u'saveTheme %s %s', name, theme_pretty_xml) theme_dir = os.path.join(self.path, name) - if not os.path.exists(theme_dir): - os.mkdir(os.path.join(self.path, name)) + checkDirectoryExists(theme_dir) theme_file = os.path.join(theme_dir, name + u'.xml') if imageTo and self.oldBackgroundImage and \ imageTo != self.oldBackgroundImage: @@ -699,34 +688,13 @@ class ThemeManager(QtGui.QWidget): if testPlugin: for plugin in self.parent.pluginManager.plugins: if plugin.usesTheme(theme): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used in the %s plugin.')) % \ - (theme, plugin.name)) + Receiver.send_message(u'openlp_error_message', { + u'title': translate('OpenLP.ThemeManager', \ + 'Validation Error'), + u'message': unicode(translate('OpenLP.ThemeManager', + 'Theme %s is used in the %s plugin.')) % \ + (theme, plugin.name)}) return False - if unicode(self.serviceComboBox.currentText()) == theme: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - translate('OpenLP.ThemeManager', - 'You are unable to delete the default theme.')) - return False - else: - if testPlugin: - for plugin in self.parent.pluginManager.plugins: - if plugin.usesTheme(theme): - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used in the %s plugin.')) % \ - (theme, plugin.name)) - return False - if unicode(self.serviceComboBox.currentText()) == theme: - QtGui.QMessageBox.critical(self, - translate('OpenLP.ThemeManager', 'Error'), - unicode(translate('OpenLP.ThemeManager', - 'Theme %s is used by the service manager.')) % theme) - return False return True def _migrateVersion122(self, xml_data): diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 7281bb091..086ba3113 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ context_menu_action, ItemCapabilities, SettingsManager, translate, \ - check_item_selected, Receiver + check_item_selected, Receiver, checkDirectoryExists from openlp.core.utils import AppLocation, get_images_filter log = logging.getLogger(__name__) @@ -79,8 +79,7 @@ class ImageMediaItem(MediaManagerItem): self.servicePath = os.path.join( AppLocation.get_section_data_path(self.settingsSection), u'thumbnails') - if not os.path.exists(self.servicePath): - os.mkdir(self.servicePath) + checkDirectoryExists(self.servicePath) self.loadList(SettingsManager.load_list( self.settingsSection, self.settingsSection)) From cfb896e3b102a350fa5e4a4dd4ca23b098907e69 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 2 Jan 2011 17:42:09 +0100 Subject: [PATCH 10/43] started work on OpenLyrics importer --- openlp/plugins/songs/forms/songimportform.py | 49 +++++++++-------- .../plugins/songs/forms/songimportwizard.py | 11 ++-- openlp/plugins/songs/lib/importer.py | 6 ++- openlp/plugins/songs/lib/xml.py | 54 +++++++++++-------- 4 files changed, 65 insertions(+), 55 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 5ec7f45e1..5776dd21a 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -73,12 +73,12 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): QtCore.QObject.connect(self.openLP1BrowseButton, QtCore.SIGNAL(u'clicked()'), self.onOpenLP1BrowseButtonClicked) - #QtCore.QObject.connect(self.openLyricsAddButton, - # QtCore.SIGNAL(u'clicked()'), - # self.onOpenLyricsAddButtonClicked) - #QtCore.QObject.connect(self.openLyricsRemoveButton, - # QtCore.SIGNAL(u'clicked()'), - # self.onOpenLyricsRemoveButtonClicked) + QtCore.QObject.connect(self.openLyricsAddButton, + QtCore.SIGNAL(u'clicked()'), + self.onOpenLyricsAddButtonClicked) + QtCore.QObject.connect(self.openLyricsRemoveButton, + QtCore.SIGNAL(u'clicked()'), + self.onOpenLyricsRemoveButtonClicked) QtCore.QObject.connect(self.openSongAddButton, QtCore.SIGNAL(u'clicked()'), self.onOpenSongAddButtonClicked) @@ -167,16 +167,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.openLP1BrowseButton.setFocus() return False elif source_format == SongFormat.OpenLyrics: -# if self.openLyricsFileListWidget.count() == 0: -# QtGui.QMessageBox.critical(self, -# translate('SongsPlugin.ImportWizardForm', -# 'No OpenLyrics Files Selected'), -# translate('SongsPlugin.ImportWizardForm', -# 'You need to add at least one OpenLyrics ' -# 'song file to import from.')) -# self.openLyricsAddButton.setFocus() -# return False - return False + if self.openLyricsFileListWidget.count() == 0: + QtGui.QMessageBox.critical(self, + translate('SongsPlugin.ImportWizardForm', + 'No OpenLyrics Files Selected'), + translate('SongsPlugin.ImportWizardForm', + 'You need to add at least one OpenLyrics ' + 'song file to import from.')) + self.openLyricsAddButton.setFocus() + return False elif source_format == SongFormat.OpenSong: if self.openSongFileListWidget.count() == 0: QtGui.QMessageBox.critical(self, @@ -337,15 +336,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): 'openlp.org v1.x Databases') ) - #def onOpenLyricsAddButtonClicked(self): - # self.getFiles( - # translate('SongsPlugin.ImportWizardForm', - # 'Select OpenLyrics Files'), - # self.openLyricsFileListWidget - # ) + def onOpenLyricsAddButtonClicked(self): + self.getFiles( + translate('SongsPlugin.ImportWizardForm', + 'Select OpenLyrics Files'), + self.openLyricsFileListWidget + ) - #def onOpenLyricsRemoveButtonClicked(self): - # self.removeSelectedItems(self.openLyricsFileListWidget) + def onOpenLyricsRemoveButtonClicked(self): + self.removeSelectedItems(self.openLyricsFileListWidget) def onOpenSongAddButtonClicked(self): self.getFiles( @@ -435,7 +434,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.formatComboBox.setCurrentIndex(0) self.openLP2FilenameEdit.setText(u'') self.openLP1FilenameEdit.setText(u'') - #self.openLyricsFileListWidget.clear() + self.openLyricsFileListWidget.clear() self.openSongFileListWidget.clear() self.wordsOfWorshipFileListWidget.clear() self.ccliFileListWidget.clear() diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py index 85fbb07fe..6eccff9b4 100644 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ b/openlp/plugins/songs/forms/songimportwizard.py @@ -81,9 +81,6 @@ class Ui_SongImportWizard(object): self.addSingleFileSelectItem(u'openLP1', None, True) # OpenLyrics self.addMultiFileSelectItem(u'openLyrics', u'OpenLyrics', True) - # set OpenLyrics to disabled by default - self.openLyricsDisabledWidget.setVisible(True) - self.openLyricsImportWidget.setVisible(False) # Open Song self.addMultiFileSelectItem(u'openSong', u'OpenSong') # Words of Worship @@ -177,10 +174,10 @@ class Ui_SongImportWizard(object): 'importer has been disabled due to a missing Python module. If ' 'you want to use this importer, you will need to install the ' '"python-sqlite" module.')) - #self.openLyricsAddButton.setText( - # translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - #self.openLyricsRemoveButton.setText( - # translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.openLyricsAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.openLyricsRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) self.openLyricsDisabledLabel.setText( translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics ' 'importer has not yet been developed, but as you can see, we are ' diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index b82e14c12..128d80138 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -26,6 +26,7 @@ from opensongimport import OpenSongImport from olpimport import OpenLPSongImport +from openlyricsimport import OpenLyricsImport from wowimport import WowImport from cclifileimport import CCLIFileImport from ewimport import EasyWorshipSongImport @@ -77,8 +78,10 @@ class SongFormat(object): """ if format == SongFormat.OpenLP2: return OpenLPSongImport - if format == SongFormat.OpenLP1: + elif format == SongFormat.OpenLP1: return OpenLP1SongImport + elif format == SongFormat.OpenLyrics: + return OpenLyricsImport elif format == SongFormat.OpenSong: return OpenSongImport elif format == SongFormat.SongsOfFellowship: @@ -93,7 +96,6 @@ class SongFormat(object): return EasyWorshipSongImport elif format == SongFormat.SongBeamer: return SongBeamerImport -# else: return None @staticmethod diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index f00711bb6..a6558d669 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -80,8 +80,8 @@ class SongXMLBuilder(object): ``content`` The actual text of the verse to be stored. """ - verse = etree.Element(u'verse', type = unicode(type), - label = unicode(number)) + verse = etree.Element(u'verse', type=unicode(type), + label=unicode(number)) verse.text = etree.CDATA(content) self.lyrics.append(verse) @@ -194,9 +194,7 @@ class LyricsXML(object): text = text.replace('\r\n', '\n') verses = text.split('\n\n') self.languages = [{u'language': u'en', u'verses': []}] - counter = 0 - for verse in verses: - counter = counter + 1 + for counter, verse in enumerate(verses): self.languages[0][u'verses'].append({ u'type': u'verse', u'label': unicode(counter), @@ -245,14 +243,16 @@ class LyricsXML(object): class OpenLyricsParser(object): """ - This class represents the converter for Song to/from OpenLyrics XML. + This class represents the converter for Song to/from + `OpenLyrics `_ XML. """ + # TODO: complete OpenLyrics standard implementation! def __init__(self, manager): self.manager = manager def song_to_xml(self, song): """ - Convert the song to OpenLyrics Format + Convert the song to OpenLyrics Format. """ song_xml_parser = SongXMLParser(song.lyrics) verse_list = song_xml_parser.get_verses() @@ -286,7 +286,7 @@ class OpenLyricsParser(object): def xml_to_song(self, xml): """ - Create a Song from OpenLyrics format xml + Create and save a Song from OpenLyrics format xml. """ # No xml get out of here if not xml: @@ -299,23 +299,15 @@ class OpenLyricsParser(object): song.copyright = unicode(properties.copyright.text) if song.copyright == u'None': song.copyright = u'' - song.verse_order = unicode(properties.verseOrder.text) - if song.verse_order == u'None': - song.verse_order = u'' song.topics = [] song.book = None - theme_name = None try: song.ccli_number = unicode(properties.ccliNo.text) - except: + except AttributeError: song.ccli_number = u'' try: - theme_name = unicode(properties.themes.theme) - except: - pass - if theme_name: - song.theme_name = theme_name - else: + song.theme_name = unicode(properties.themes.theme) + except AttributeError: song.theme_name = u'' # Process Titles for title in properties.titles.title: @@ -331,6 +323,7 @@ class OpenLyricsParser(object): # Process Lyrics sxml = SongXMLBuilder() search_text = u'' + song.verse_order = u'' for lyrics in song_xml.lyrics: for verse in song_xml.lyrics.verse: text = u'' @@ -341,17 +334,36 @@ class OpenLyricsParser(object): else: text += u'\n' + line type = VerseType.expand_string(verse.attrib[u'name'][0]) + # Here we need to create the verse order for the case that the + # song does not have a verseOrder property. sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + try: + song.verse_order = unicode(properties.verseOrder.text) + except AttributeError: + # TODO: Do not allow empty verse order. + # Do not worry! + pass + if song.verse_order == u'None': + song.verse_order = u'' + # Process Comments song.comments = u'' + try: + for comment in properties.comments.comment: + if not song.comments: + song.comments = comment + else: + song.comments += u'\n' + comment + except AttributeError: + pass song.song_number = u'' # Process Authors try: for author in properties.authors.author: self._process_author(author.text, song) - except: + except AttributeError: # No Author in XML so ignore pass self.manager.save_object(song) @@ -396,4 +408,4 @@ class OpenLyricsParser(object): new_author = Author.populate(first_name=name.rsplit(u' ', 1)[0], last_name=name.rsplit(u' ', 1)[1], display_name=name) self.manager.save_object(new_author) - song.authors.append(new_author) \ No newline at end of file + song.authors.append(new_author) From 3bb309e6238128086597ae4b1beb27403e24ef60 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 2 Jan 2011 17:20:53 +0000 Subject: [PATCH 11/43] Block delete of default theme --- openlp/core/ui/thememanager.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 7cfdb9aae..94a440d81 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -684,6 +684,13 @@ class ThemeManager(QtGui.QWidget): QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: return False + # should be the same unless default + if theme != unicode(item.data(QtCore.Qt.UserRole).toString()): + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeManager', 'Error'), + translate('OpenLP.ThemeManager', + 'You are unable to delete the default theme.')) + return False # check for use in the system else where. if testPlugin: for plugin in self.parent.pluginManager.plugins: From 909fa25e7b08a6d9fc0de438c6c430b3929816c0 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 2 Jan 2011 18:24:47 +0100 Subject: [PATCH 12/43] clean ups, added missing file --- openlp/plugins/songs/lib/mediaitem.py | 13 ++-- openlp/plugins/songs/lib/openlyricsimport.py | 77 ++++++++++++++++++++ openlp/plugins/songs/lib/xml.py | 1 + 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 openlp/plugins/songs/lib/openlyricsimport.py diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index cd305877c..011373d68 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -314,15 +314,14 @@ class SongMediaItem(MediaManagerItem): translate('SongsPlugin.MediaItem', 'You must select an item to delete.')): items = self.listView.selectedIndexes() - ans = QtGui.QMessageBox.question(self, + if QtGui.QMessageBox.question(self, translate('SongsPlugin.MediaItem', 'Delete Song(s)?'), translate('SongsPlugin.MediaItem', 'Are you sure you want to delete the %n selected song(s)?', '', QtCore.QCoreApplication.CodecForTr, len(items)), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok| - QtGui.QMessageBox.Cancel), - QtGui.QMessageBox.Ok) - if ans == QtGui.QMessageBox.Cancel: + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok | + QtGui.QMessageBox.Cancel), + QtGui.QMessageBox.Ok) == QtGui.QMessageBox.Cancel: return for item in items: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] @@ -396,8 +395,8 @@ class SongMediaItem(MediaManagerItem): service_item.audit = [ song.title, author_audit, song.copyright, unicode(song.ccli_number) ] - service_item.data_string = {u'title':song.search_title, - u'authors':author_list} + service_item.data_string = {u'title': song.search_title, + u'authors': author_list} service_item.xml_version = self.openLyrics.song_to_xml(song) return True diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py new file mode 100644 index 000000000..6deb9cc09 --- /dev/null +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`openlyricsimport` module provides the functionality for importing +songs which are saved as OpenLyrics files. +""" + +#import logging +import os + +from openlp.core.lib import translate +from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib import OpenLyricsParser + +#log = logging.getLogger(__name__) + +class OpenLyricsImport(SongImport): + """ + This provides the Openlyrics import. + """ + def __init__(self, master_manager, **kwargs): + """ + Initialise the import. + """ + SongImport.__init__(self, master_manager) + self.master_manager = master_manager + self.openLyricsParser = OpenLyricsParser(master_manager) + if kwargs.has_key(u'filename'): + self.import_source = kwargs[u'filename'] + if kwargs.has_key(u'filenames'): + self.import_source = kwargs[u'filenames'] + + def do_import(self): + """ + Imports the songs. + """ + success = True + self.import_wizard.importProgressBar.setMaximum(len(self.import_source)) + for file_path in self.import_source: + if self.stop_import_flag: + success = False + break + file = open(file_path) + xml = file.read() + file.close() + self.import_wizard.incrementProgressBar(unicode(translate( + 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % + os.path.basename(file_path)) + if self.openLyricsParser.xml_to_song(xml) == 0: + success = false + break + if success: + return True + return False diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index a6558d669..65be3f5e4 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -367,6 +367,7 @@ class OpenLyricsParser(object): # No Author in XML so ignore pass self.manager.save_object(song) + # TODO: better return song itself, instead of song.id return song.id def _add_text_to_element(self, tag, parent, text=None, label=None): From 9fc113abceae1a21a3ce1747ba58b86af79edfd0 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 3 Jan 2011 08:16:21 +0100 Subject: [PATCH 13/43] fix wrong 'themes' usage (themes -> topics), improved methods, make sure a missing property does not crash openlp --- openlp/plugins/songs/lib/xml.py | 112 ++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 36 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 65be3f5e4..290d83d38 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -42,8 +42,10 @@ import logging import re from lxml import etree, objectify + +from openlp.core.lib import translate from openlp.plugins.songs.lib import VerseType -from openlp.plugins.songs.lib.db import Author, Song +from openlp.plugins.songs.lib.db import Author, Song, Topic log = logging.getLogger(__name__) @@ -246,7 +248,7 @@ class OpenLyricsParser(object): This class represents the converter for Song to/from `OpenLyrics `_ XML. """ - # TODO: complete OpenLyrics standard implementation! + # TODO: complete OpenLyrics standard implementation as fare as possible! def __init__(self, manager): self.manager = manager @@ -288,7 +290,7 @@ class OpenLyricsParser(object): """ Create and save a Song from OpenLyrics format xml. """ - # No xml get out of here + # No xml get out of here. if not xml: return 0 song = Song() @@ -296,19 +298,18 @@ class OpenLyricsParser(object): xml = xml[38:] song_xml = objectify.fromstring(xml) properties = song_xml.properties - song.copyright = unicode(properties.copyright.text) - if song.copyright == u'None': + # Process Copyright + try: + song.copyright = unicode(properties.copyright.text) + if song.copyright == u'None': + song.copyright = u'' + except AttributeError: song.copyright = u'' - song.topics = [] - song.book = None + # Process CCLI number try: song.ccli_number = unicode(properties.ccliNo.text) except AttributeError: song.ccli_number = u'' - try: - song.theme_name = unicode(properties.themes.theme) - except AttributeError: - song.theme_name = u'' # Process Titles for title in properties.titles.title: if not song.title: @@ -325,26 +326,29 @@ class OpenLyricsParser(object): search_text = u'' song.verse_order = u'' for lyrics in song_xml.lyrics: - for verse in song_xml.lyrics.verse: + for verse in lyrics.verse: text = u'' - for line in verse.lines.line: - line = unicode(line) - if not text: - text = line - else: - text += u'\n' + line - type = VerseType.expand_string(verse.attrib[u'name'][0]) - # Here we need to create the verse order for the case that the - # song does not have a verseOrder property. - sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) + # Note that the element will not be in OpenLyrics 0.8: + # http://code.google.com/p/openlyrics/issues/detail?id=8 + for line in verse.lines: + for line in line.line: + line = unicode(line) + if not text: + text = line + else: + text += u'\n' + line + type_ = VerseType.expand_string(verse.attrib[u'name'][0]) + # TODO: Here we need to create the verse order for the case that + # the song does not have a verseOrder property. + sxml.add_verse_to_lyrics(type_, verse.attrib[u'name'][1], text) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + # Process verse order try: song.verse_order = unicode(properties.verseOrder.text) except AttributeError: # TODO: Do not allow empty verse order. - # Do not worry! pass if song.verse_order == u'None': song.verse_order = u'' @@ -358,16 +362,26 @@ class OpenLyricsParser(object): song.comments += u'\n' + comment except AttributeError: pass - song.song_number = u'' # Process Authors try: for author in properties.authors.author: self._process_author(author.text, song) except AttributeError: - # No Author in XML so ignore pass + if not song.authors: + # Add "Author unknown" (can be translated) + self._process_author(translate('SongsPlugin.XML', + 'Author unknown'), song) + # Process Topcis + try: + for topic in properties.themes.theme: + self._process_topic(topic.text, song) + except AttributeError: + pass + # Properties not yet supported. + song.book = None + song.song_number = u'' self.manager.save_object(song) - # TODO: better return song itself, instead of song.id return song.id def _add_text_to_element(self, tag, parent, text=None, label=None): @@ -396,17 +410,43 @@ class OpenLyricsParser(object): def _process_author(self, name, song): """ - Find or create an Author from display_name. + Finds an existing Author or creates a new Author and adds it to the song + object. + + ``name`` + The display_name of the song (string). + + ``song`` + The song the Author will be added to. """ + if not name: + return name = unicode(name) author = self.manager.get_object_filtered(Author, Author.display_name == name) - if author: - # should only be one! so take the first - song.authors.append(author) - else: - # Need a new author - new_author = Author.populate(first_name=name.rsplit(u' ', 1)[0], - last_name=name.rsplit(u' ', 1)[1], display_name=name) - self.manager.save_object(new_author) - song.authors.append(new_author) + if author is None: + # We need to create a new author, as the author does not exist. + author = Author.populate(first_name=name.rsplit(u' ', 1)[0], + last_name=name.rsplit(u' ', 1)[1], display_name=name) + self.manager.save_object(author) + song.authors.append(author) + + def _process_topic(self, topictext, song): + """ + Finds an existing Topic or creates a new Topic and adds it to the song + object. + + ``topictext`` + The topictext we add to the song (string). + + ``song`` + The song the Topic will be added to. + """ + topictext = unicode(topictext) + # Check if topic already exists in the database. + topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) + if topic is None: + # We need to create a new topic, as the topic does not exist. + topic = Topic.populate(name=topictext) + self.manager.save_object(topic) + song.topics.append(topic) From a127019f28c3d3810cb1392f7949e0cbdb23b9ed Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 3 Jan 2011 14:43:09 +0100 Subject: [PATCH 14/43] fixed wrong use of 'theme', implemented songbooks and songnumber, continued with openlyrics implementation, clean ups --- openlp/plugins/songs/lib/mediaitem.py | 7 +- openlp/plugins/songs/lib/openlyricsimport.py | 11 +-- openlp/plugins/songs/lib/xml.py | 91 ++++++++++++++++---- 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 011373d68..d2565ad8f 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -404,11 +404,13 @@ class SongMediaItem(MediaManagerItem): """ Triggered by a song being loaded by the service item """ + # TODO: fix db flooding log.debug(u'serviceLoad') if item.data_string: + print item.data_string search_results = self.parent.manager.get_all_objects(Song, Song.search_title == - item.data_string[u'title'].split(u'@')[0].lower() , + item.data_string[u'title'].split(u'@')[0].lower(), Song.search_title.asc()) author_list = item.data_string[u'authors'].split(u', ') # The service item always has an author (at least it has u'' as @@ -417,7 +419,6 @@ class SongMediaItem(MediaManagerItem): if u'' in author_list: author_list.remove(u'') editId = 0 - uuid = item._uuid add_song = True if search_results: for song in search_results: @@ -444,7 +445,7 @@ class SongMediaItem(MediaManagerItem): # Update service with correct song id. if editId != 0: Receiver.send_message(u'service_item_update', - u'%s:%s' %(editId, uuid)) + u'%s:%s' % (editId, item._uuid)) def collateSongTitles(self, song_1, song_2): """ diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 6deb9cc09..f4f49e1b5 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -61,8 +61,7 @@ class OpenLyricsImport(SongImport): self.import_wizard.importProgressBar.setMaximum(len(self.import_source)) for file_path in self.import_source: if self.stop_import_flag: - success = False - break + return False file = open(file_path) xml = file.read() file.close() @@ -70,8 +69,6 @@ class OpenLyricsImport(SongImport): 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % os.path.basename(file_path)) if self.openLyricsParser.xml_to_song(xml) == 0: - success = false - break - if success: - return True - return False + # Importing this song failed! For now we stop import. + return False + return True diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 290d83d38..2a3ec4944 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -45,7 +45,7 @@ from lxml import etree, objectify from openlp.core.lib import translate from openlp.plugins.songs.lib import VerseType -from openlp.plugins.songs.lib.db import Author, Song, Topic +from openlp.plugins.songs.lib.db import Author, Book, Song, Topic log = logging.getLogger(__name__) @@ -265,22 +265,41 @@ class OpenLyricsParser(object): self._add_text_to_element(u'title', titles, song.title) if song.alternate_title: self._add_text_to_element(u'title', titles, song.alternate_title) - if song.theme_name: - themes = etree.SubElement(properties, u'themes') - self._add_text_to_element(u'theme', themes, song.theme_name) - self._add_text_to_element(u'copyright', properties, song.copyright) - self._add_text_to_element(u'verseOrder', properties, song.verse_order) + if song.comments: + comments = etree.SubElement(properties, u'comments') + self._add_text_to_element(u'comment', comments, song.comments) + if song.copyright: + self._add_text_to_element(u'copyright', properties, song.copyright) + if song.verse_order: + self._add_text_to_element( + u'verseOrder', properties, song.verse_order) if song.ccli_number: self._add_text_to_element(u'ccliNo', properties, song.ccli_number) - authors = etree.SubElement(properties, u'authors') - for author in song.authors: - self._add_text_to_element(u'author', authors, author.display_name) + if song.authors: + authors = etree.SubElement(properties, u'authors') + for author in song.authors: + self._add_text_to_element( + u'author', authors, author.display_name) + book = self.manager.get_object_filtered( + Book, Book.id == song.song_book_id) + if book is not None: + book = book.name + songbooks = etree.SubElement(properties, u'songbooks') + element = self._add_text_to_element( + u'songbook', songbooks, None, book) + element.set(u'entry', song.song_number) + if song.topics: + themes = etree.SubElement(properties, u'themes') + for topic in song.topics: + self._add_text_to_element(u'theme', themes, topic.name) lyrics = etree.SubElement(song_xml, u'lyrics') for verse in verse_list: verse_tag = u'%s%s' % ( verse[0][u'type'][0].lower(), verse[0][u'label']) element = \ self._add_text_to_element(u'verse', lyrics, None, verse_tag) + # Note that the element will not be in OpenLyrics 0.8: + # http://code.google.com/p/openlyrics/issues/detail?id=8 element = self._add_text_to_element(u'lines', element) for line in unicode(verse[1]).split(u'\n'): self._add_text_to_element(u'line', element, line) @@ -357,9 +376,9 @@ class OpenLyricsParser(object): try: for comment in properties.comments.comment: if not song.comments: - song.comments = comment + song.comments = unicode(comment.text) else: - song.comments += u'\n' + comment + song.comments += u'\n' + unicode(comment.text) except AttributeError: pass # Process Authors @@ -372,6 +391,18 @@ class OpenLyricsParser(object): # Add "Author unknown" (can be translated) self._process_author(translate('SongsPlugin.XML', 'Author unknown'), song) + # Process Song Book and Song Number + song.song_book_id = 0 + song.song_number = u'' + try: + for songbook in properties.songbooks.songbook: + self._process_songbook(songbook.get(u'name'), song) + if songbook.get(u'entry'): + song.song_number = unicode(songbook.get(u'entry')) + # OpenLp does only support one song book, so take the first one. + break + except AttributeError: + pass # Process Topcis try: for topic in properties.themes.theme: @@ -379,8 +410,7 @@ class OpenLyricsParser(object): except AttributeError: pass # Properties not yet supported. - song.book = None - song.song_number = u'' + song.theme_name = u'' self.manager.save_object(song) return song.id @@ -417,9 +447,10 @@ class OpenLyricsParser(object): The display_name of the song (string). ``song`` - The song the Author will be added to. + The song the object. """ if not name: + # Wrong use of XML here, as no text has been supplied. return name = unicode(name) author = self.manager.get_object_filtered(Author, @@ -433,20 +464,44 @@ class OpenLyricsParser(object): def _process_topic(self, topictext, song): """ - Finds an existing Topic or creates a new Topic and adds it to the song + Finds an existing topic or creates a new topic and adds it to the song object. ``topictext`` - The topictext we add to the song (string). + The topictext of the topic (string). ``song`` - The song the Topic will be added to. + The song object. """ + if not topictext: + # Wrong use of XML here, as no text has been supplied. + return topictext = unicode(topictext) - # Check if topic already exists in the database. topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) if topic is None: # We need to create a new topic, as the topic does not exist. topic = Topic.populate(name=topictext) self.manager.save_object(topic) song.topics.append(topic) + + def _process_songbook(self, bookname, song): + """ + Finds an existing book or creates a new book and adds it to the song + object. + + ``bookname`` + The name of the book (string). + + ``song`` + The song object. + """ + if not bookname: + # Wrong use of XML here, as no text has been supplied. + return + bookname = unicode(bookname) + book = self.manager.get_object_filtered(Book, Book.name == bookname) + if book is None: + # We need to create a new book, as the book does not exist. + book = Book.populate(name=bookname, publisher=u'') + self.manager.save_object(book) + song.song_book_id = book.id From 23d71700aa2b32d1390cc51c4ed284a1191d5f90 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 3 Jan 2011 19:47:14 +0000 Subject: [PATCH 15/43] Theme handling changes --- openlp.pyw | 6 +++--- openlp/core/ui/themeform.py | 16 +++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index d5975b1a4..bc08940bb 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -150,9 +150,9 @@ class OpenLP(QtGui.QApplication): log.info(u'Openlp version %s' % app_version[u'version']) return app_version - def notify(self, obj, evt): - #TODO needed for presentation exceptions - return QtGui.QApplication.notify(self, obj, evt) +# def notify(self, obj, evt): +# #TODO needed for presentation exceptions +# return QtGui.QApplication.notify(self, obj, evt) def run(self): """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index e0b522947..f5b119fa8 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -291,9 +291,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.updateThemeAllowed = True self.themeNameLabel.setVisible(not edit) self.themeNameEdit.setVisible(not edit) + self.edit = edit if edit: self.setWindowTitle(unicode(translate('OpenLP.ThemeWizard', - 'Edit Theme %s')) % self.theme.theme_name) + 'Edit Theme - %s')) % self.theme.theme_name) self.next() else: self.setWindowTitle(translate('OpenLP.ThemeWizard', 'New Theme')) @@ -586,12 +587,13 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): filename = \ os.path.split(unicode(self.theme.background_filename))[1] saveTo = os.path.join(self.path, self.theme.theme_name, filename) - saveFrom = self.theme.background_filename# - if self.thememanager.checkIfThemeExists(self.theme.theme_name): - self.thememanager.saveTheme(self.theme, saveFrom, saveTo) - self.accepted = True - return QtGui.QDialog.accept(self) - return + saveFrom = self.theme.background_filename + if not self.edit: + if not self.thememanager.checkIfThemeExists(self.theme.theme_name): + return + self.accepted = True + self.thememanager.saveTheme(self.theme, saveFrom, saveTo) + return QtGui.QDialog.accept(self) def _colorButton(self, field): """ From a5f73713d4192ef0ac9b961255c1f1eebbac8fda Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 3 Jan 2011 22:47:49 +0100 Subject: [PATCH 16/43] add standard verseOrder, if xml does not have any verseOrder property; added '_get' and '_text' methods which do the same as 'get' and 'text', but make sure that they never return 'None' (but u'' instead) --- openlp/plugins/songs/lib/mediaitem.py | 2 - openlp/plugins/songs/lib/openlyricsimport.py | 8 +- openlp/plugins/songs/lib/xml.py | 86 +++++++++++++------- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index d2565ad8f..93d648146 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -404,10 +404,8 @@ class SongMediaItem(MediaManagerItem): """ Triggered by a song being loaded by the service item """ - # TODO: fix db flooding log.debug(u'serviceLoad') if item.data_string: - print item.data_string search_results = self.parent.manager.get_all_objects(Song, Song.search_title == item.data_string[u'title'].split(u'@')[0].lower(), diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index f4f49e1b5..5346b5803 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -28,15 +28,12 @@ The :mod:`openlyricsimport` module provides the functionality for importing songs which are saved as OpenLyrics files. """ -#import logging import os from openlp.core.lib import translate from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib import OpenLyricsParser -#log = logging.getLogger(__name__) - class OpenLyricsImport(SongImport): """ This provides the Openlyrics import. @@ -57,14 +54,15 @@ class OpenLyricsImport(SongImport): """ Imports the songs. """ - success = True self.import_wizard.importProgressBar.setMaximum(len(self.import_source)) for file_path in self.import_source: if self.stop_import_flag: return False file = open(file_path) - xml = file.read() + lines = file.readlines() file.close() + lines = [line.strip() for line in lines] + xml = u''.join(lines) self.import_wizard.incrementProgressBar(unicode(translate( 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % os.path.basename(file_path)) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 2a3ec4944..326f97537 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -298,8 +298,6 @@ class OpenLyricsParser(object): verse[0][u'type'][0].lower(), verse[0][u'label']) element = \ self._add_text_to_element(u'verse', lyrics, None, verse_tag) - # Note that the element will not be in OpenLyrics 0.8: - # http://code.google.com/p/openlyrics/issues/detail?id=8 element = self._add_text_to_element(u'lines', element) for line in unicode(verse[1]).split(u'\n'): self._add_text_to_element(u'line', element, line) @@ -307,7 +305,10 @@ class OpenLyricsParser(object): def xml_to_song(self, xml): """ - Create and save a Song from OpenLyrics format xml. + Create and save a song from OpenLyrics format xml to the database. Since + we also export XML from external sources (e. g. OpenLyrics import), we + cannot ensure, that it completely conforms to the OpenLyrics standard. + That means, that we for example have to remove chords. """ # No xml get out of here. if not xml: @@ -315,28 +316,28 @@ class OpenLyricsParser(object): song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) properties = song_xml.properties # Process Copyright try: - song.copyright = unicode(properties.copyright.text) - if song.copyright == u'None': - song.copyright = u'' + song.copyright = self._text(properties.copyright) except AttributeError: song.copyright = u'' # Process CCLI number try: - song.ccli_number = unicode(properties.ccliNo.text) + song.ccli_number = self._text(properties.ccliNo) except AttributeError: song.ccli_number = u'' # Process Titles for title in properties.titles.title: if not song.title: - song.title = unicode(title.text) + song.title = self._text(title) song.search_title = unicode(song.title) song.alternate_title = u'' else: - song.alternate_title = unicode(title.text) + song.alternate_title = self._text(title) song.search_title += u'@' + song.alternate_title song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', unicode(song.search_title)).lower() @@ -347,8 +348,6 @@ class OpenLyricsParser(object): for lyrics in song_xml.lyrics: for verse in lyrics.verse: text = u'' - # Note that the element will not be in OpenLyrics 0.8: - # http://code.google.com/p/openlyrics/issues/detail?id=8 for line in verse.lines: for line in line.line: line = unicode(line) @@ -356,18 +355,21 @@ class OpenLyricsParser(object): text = line else: text += u'\n' + line - type_ = VerseType.expand_string(verse.attrib[u'name'][0]) - # TODO: Here we need to create the verse order for the case that - # the song does not have a verseOrder property. - sxml.add_verse_to_lyrics(type_, verse.attrib[u'name'][1], text) + type = VerseType.expand_string(verse.attrib[u'name'][0]) + sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) + # TODO: test this verse_order thing! + song.verse_order += u'%s%s ' % (type[0], + verse.attrib[u'name'][1]) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + song.verse_order = song.verse_order.strip() # Process verse order try: - song.verse_order = unicode(properties.verseOrder.text) + song.verse_order = self._text(properties.verseOrder) except AttributeError: - # TODO: Do not allow empty verse order. + # Do not worry, as the verse order has cautionary already been + # saved while creating the verses. pass if song.verse_order == u'None': song.verse_order = u'' @@ -376,29 +378,29 @@ class OpenLyricsParser(object): try: for comment in properties.comments.comment: if not song.comments: - song.comments = unicode(comment.text) + song.comments = self._text(comment) else: - song.comments += u'\n' + unicode(comment.text) + song.comments += u'\n' + self._text(comment) except AttributeError: pass # Process Authors try: for author in properties.authors.author: - self._process_author(author.text, song) + self._process_author(self._text(author), song) except AttributeError: pass if not song.authors: # Add "Author unknown" (can be translated) - self._process_author(translate('SongsPlugin.XML', - 'Author unknown'), song) + self._process_author(unicode(translate('SongsPlugin.XML', + 'Author unknown')), song) # Process Song Book and Song Number song.song_book_id = 0 song.song_number = u'' try: for songbook in properties.songbooks.songbook: - self._process_songbook(songbook.get(u'name'), song) + self._process_songbook(self._get(songbook, u'name'), song) if songbook.get(u'entry'): - song.song_number = unicode(songbook.get(u'entry')) + song.song_number = self._get(songbook, u'entry') # OpenLp does only support one song book, so take the first one. break except AttributeError: @@ -406,7 +408,7 @@ class OpenLyricsParser(object): # Process Topcis try: for topic in properties.themes.theme: - self._process_topic(topic.text, song) + self._process_topic(self._text(topic), song) except AttributeError: pass # Properties not yet supported. @@ -414,6 +416,31 @@ class OpenLyricsParser(object): self.manager.save_object(song) return song.id + def _get(self, element, attribute): + """ + This takes care of empty attributes. It returns the element's attribute. + + ``element`` + The element. + + ``attribute`` + The element's attribute (unicode). + """ + if element.get(attribute) is not None: + return element.get(attribute) + return u'' + + def _text(self, element): + """ + This takes care of empty texts. It returns the element's text. + + ``element`` + The element. + """ + if element.text is not None: + return unicode(element.text) + return u'' + def _add_text_to_element(self, tag, parent, text=None, label=None): if label: element = etree.Element(tag, name=unicode(label)) @@ -444,7 +471,7 @@ class OpenLyricsParser(object): object. ``name`` - The display_name of the song (string). + The display_name of the song (unicode). ``song`` The song the object. @@ -452,7 +479,6 @@ class OpenLyricsParser(object): if not name: # Wrong use of XML here, as no text has been supplied. return - name = unicode(name) author = self.manager.get_object_filtered(Author, Author.display_name == name) if author is None: @@ -468,7 +494,7 @@ class OpenLyricsParser(object): object. ``topictext`` - The topictext of the topic (string). + The topictext of the topic (unicode). ``song`` The song object. @@ -476,7 +502,6 @@ class OpenLyricsParser(object): if not topictext: # Wrong use of XML here, as no text has been supplied. return - topictext = unicode(topictext) topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) if topic is None: # We need to create a new topic, as the topic does not exist. @@ -490,7 +515,7 @@ class OpenLyricsParser(object): object. ``bookname`` - The name of the book (string). + The name of the book (unicode). ``song`` The song object. @@ -498,7 +523,6 @@ class OpenLyricsParser(object): if not bookname: # Wrong use of XML here, as no text has been supplied. return - bookname = unicode(bookname) book = self.manager.get_object_filtered(Book, Book.name == bookname) if book is None: # We need to create a new book, as the book does not exist. From 0494c75ce92cc05a9553a4fac8f38313aa7e1cad Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 4 Jan 2011 10:45:19 +0100 Subject: [PATCH 17/43] r1186 From 449610d50e2de222b3669dcb243b465fb1ff26a9 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 4 Jan 2011 23:06:43 +0100 Subject: [PATCH 18/43] - fixed author wihtou first_name e. g. "Luther" - open xml file properly - tweakes --- openlp/plugins/songs/lib/openlyricsimport.py | 15 ++++++--- openlp/plugins/songs/lib/xml.py | 33 ++++++++++---------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 5346b5803..27c2308f4 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -28,12 +28,17 @@ The :mod:`openlyricsimport` module provides the functionality for importing songs which are saved as OpenLyrics files. """ +import logging import os +from lxml import etree + from openlp.core.lib import translate from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib import OpenLyricsParser +log = logging.getLogger(__name__) + class OpenLyricsImport(SongImport): """ This provides the Openlyrics import. @@ -42,6 +47,7 @@ class OpenLyricsImport(SongImport): """ Initialise the import. """ + log.debug(u'initialise OpenLyricsImport') SongImport.__init__(self, master_manager) self.master_manager = master_manager self.openLyricsParser = OpenLyricsParser(master_manager) @@ -58,15 +64,14 @@ class OpenLyricsImport(SongImport): for file_path in self.import_source: if self.stop_import_flag: return False - file = open(file_path) - lines = file.readlines() - file.close() - lines = [line.strip() for line in lines] - xml = u''.join(lines) self.import_wizard.incrementProgressBar(unicode(translate( 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % os.path.basename(file_path)) + parser = etree.XMLParser(remove_blank_text=True) + file = etree.parse(file_path, parser) + xml = etree.tostring(file) if self.openLyricsParser.xml_to_song(xml) == 0: + log.debug(u'File could not be imported: %s' % file_path) # Importing this song failed! For now we stop import. return False return True diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 326f97537..4045a412a 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -248,7 +248,8 @@ class OpenLyricsParser(object): This class represents the converter for Song to/from `OpenLyrics `_ XML. """ - # TODO: complete OpenLyrics standard implementation as fare as possible! + # TODO: Complete OpenLyrics standard implementation and document what is + # supported and what not! def __init__(self, manager): self.manager = manager @@ -316,8 +317,6 @@ class OpenLyricsParser(object): song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) properties = song_xml.properties # Process Copyright @@ -349,17 +348,17 @@ class OpenLyricsParser(object): for verse in lyrics.verse: text = u'' for line in verse.lines: - for line in line.line: - line = unicode(line) - if not text: - text = line - else: - text += u'\n' + line - type = VerseType.expand_string(verse.attrib[u'name'][0]) - sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text) - # TODO: test this verse_order thing! + text = u'\n'.join([unicode(line) for line in line.line]) + # Remove chords + text = re.compile(u'').sub(u'', text) + # OpenLyrics allows e. g. "c", but we need "c1". + if self._get(verse, u'name').isalpha(): + verse.set(u'name', self._get(verse, u'name') + u'1') + type = VerseType.expand_string(self._get(verse, u'name')[0]) + sxml.add_verse_to_lyrics( + type, self._get(verse, u'name')[1], text) song.verse_order += u'%s%s ' % (type[0], - verse.attrib[u'name'][1]) + self._get(verse, u'name')[1]) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') @@ -399,7 +398,7 @@ class OpenLyricsParser(object): try: for songbook in properties.songbooks.songbook: self._process_songbook(self._get(songbook, u'name'), song) - if songbook.get(u'entry'): + if self._get(songbook, u'entry'): song.song_number = self._get(songbook, u'entry') # OpenLp does only support one song book, so take the first one. break @@ -427,7 +426,7 @@ class OpenLyricsParser(object): The element's attribute (unicode). """ if element.get(attribute) is not None: - return element.get(attribute) + return unicode(element.get(attribute)) return u'' def _text(self, element): @@ -483,8 +482,8 @@ class OpenLyricsParser(object): Author.display_name == name) if author is None: # We need to create a new author, as the author does not exist. - author = Author.populate(first_name=name.rsplit(u' ', 1)[0], - last_name=name.rsplit(u' ', 1)[1], display_name=name) + author = Author.populate(last_name=name.split(u' ')[-1], + first_name=u' '.join(name.split(u' ')[:-1]), display_name=name) self.manager.save_object(author) song.authors.append(author) From 4246c3b76ee8c3619bd201849a596a331a12550c Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 5 Jan 2011 17:31:04 +0100 Subject: [PATCH 19/43] - added documentation - commented not needed class out - split class 'OpenLyricsParser' - relocated and imporved some code in methods --- openlp/plugins/songs/lib/__init__.py | 3 +- openlp/plugins/songs/lib/mediaitem.py | 10 +- openlp/plugins/songs/lib/xml.py | 587 +++++++++++++++----------- 3 files changed, 341 insertions(+), 259 deletions(-) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 5093d6180..491c7e6c5 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -123,6 +123,7 @@ class VerseType(object): unicode(VerseType.to_string(VerseType.Other)).lower(): return VerseType.Other -from xml import LyricsXML, SongXMLBuilder, SongXMLParser, OpenLyricsParser +from xml import OpenLyricsBuilder, OpenLyricsParser, SongXMLBuilder, \ + SongXMLParser from songstab import SongsTab from mediaitem import SongMediaItem \ No newline at end of file diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 93d648146..d2776e1a4 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -35,7 +35,8 @@ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \ ItemCapabilities, translate, check_item_selected from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm -from openlp.plugins.songs.lib import SongXMLParser, OpenLyricsParser +from openlp.plugins.songs.lib import OpenLyricsBuilder, OpenLyricsParser, \ + SongXMLParser from openlp.plugins.songs.lib.db import Author, Song from openlp.core.lib.searchedit import SearchEdit @@ -58,7 +59,8 @@ class SongMediaItem(MediaManagerItem): self.ListViewWithDnD_class = SongListView MediaManagerItem.__init__(self, parent, self, icon) self.edit_song_form = EditSongForm(self, self.parent.manager) - self.openLyrics = OpenLyricsParser(self.parent.manager) + self.openLyricsParser = OpenLyricsParser(self.parent.manager) + self.openLyricsBuilder = OpenLyricsBuilder(self.parent.manager) self.singleServiceItem = False self.song_maintenance_form = SongMaintenanceForm( self.parent.manager, self) @@ -397,7 +399,7 @@ class SongMediaItem(MediaManagerItem): ] service_item.data_string = {u'title': song.search_title, u'authors': author_list} - service_item.xml_version = self.openLyrics.song_to_xml(song) + service_item.xml_version = self.openLyricsBuilder.song_to_xml(song) return True def serviceLoad(self, item): @@ -439,7 +441,7 @@ class SongMediaItem(MediaManagerItem): break if add_song: if self.addSongFromService: - editId = self.openLyrics.xml_to_song(item.xml_version) + editId = self.openLyricsParser.xml_to_song(item.xml_version) # Update service with correct song id. if editId != 0: Receiver.send_message(u'service_item_update', diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 4045a412a..4d23ebd78 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -24,9 +24,9 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`xml` module provides the XML functionality for songs +The :mod:`xml` module provides the XML functionality. -The basic XML is of the format:: +The basic XML for storing the lyrics in the song database is of the format:: @@ -36,6 +36,28 @@ The basic XML is of the format:: + + +The XML of `OpenLyrics `_ songs is of the format:: + + + + + Amazing Grace + + + + + + Amazing grace how sweet the sound + + + + """ import logging @@ -144,112 +166,109 @@ class SongXMLParser(object): return etree.dump(self.song_xml) -class LyricsXML(object): +#class LyricsXML(object): +# """ +# This class represents the XML in the ``lyrics`` field of a song. +# """ +# def __init__(self, song=None): +# if song: +# if song.lyrics.startswith(u'' % \ +# (verse[u'type'], verse[u'label'], verse[u'text']) +# lyrics_output = lyrics_output + \ +# u'%s' % \ +# (language[u'language'], verse_output) +# song_output = u'' + \ +# u'%s' % lyrics_output +# return song_output + + +class OpenLyricsBuilder(object): """ - This class represents the XML in the ``lyrics`` field of a song. + This class represents the converter for song to OpenLyrics XML. """ - def __init__(self, song=None): - if song: - if song.lyrics.startswith(u'' % \ - (verse[u'type'], verse[u'label'], verse[u'text']) - lyrics_output = lyrics_output + \ - u'%s' % \ - (language[u'language'], verse_output) - song_output = u'' + \ - u'%s' % lyrics_output - return song_output - - -class OpenLyricsParser(object): - """ - This class represents the converter for Song to/from - `OpenLyrics `_ XML. - """ - # TODO: Complete OpenLyrics standard implementation and document what is - # supported and what not! def __init__(self, manager): self.manager = manager @@ -304,6 +323,98 @@ class OpenLyricsParser(object): self._add_text_to_element(u'line', element, line) return self._extract_xml(song_xml) + def _add_text_to_element(self, tag, parent, text=None, label=None): + if label: + element = etree.Element(tag, name=unicode(label)) + else: + element = etree.Element(tag) + if text: + element.text = unicode(text) + parent.append(element) + return element + + def _extract_xml(self, xml): + """ + Extract our newly created XML song. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True) + + def _dump_xml(self, xml): + """ + Debugging aid to dump XML so that we can see what we have. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True, pretty_print=True) + + +class OpenLyricsParser(object): + """ + This class represents the converter for OpenLyrics XML to a song. + + As OpenLyrics has a rich set of different features, we cannot support them + all. The following features are supported by the :class:`OpenLyricsParser`:: + + ```` + OpenLP does not support the author ``type`` and consequently not + ``lang`` for the author of the type ``translation``. + + ```` + This property is not supported. + + ```` + The ```` property is fully supported. But comments in lyrics + are not supported. + + ```` + This property is fully supported. + + ```` + This property is not supported. + + ```` + This property is not supported. + + ```` + This property is not supported. + + ```` + The attribute ``part`` is not supported. + + ```` + This property is not supported. + + ```` + As OpenLP does only support one songbook, we cannot consider more than + one songbook. + + ```` + This property is not supported. + + ```` + Topics, as they are called in OpenLP, are fully supported, whereby only + the topic text (e. g. Grace) is considered, but neither the ``id`` nor + ``lang``. + + ```` + This property is not supported. + + ```` + This property is not supported. + + ```` + The attribute ``translit`` and ``lang`` are not supported. + This class support verse names of the format ```` and + ````. Whereas this class does not support verse names of + the format ```` as OpenLP does not support splitting + verses into different parts. + + ```` + OpenLP supports this property. + """ + def __init__(self, manager): + self.manager = manager + def xml_to_song(self, xml): """ Create and save a song from OpenLyrics format xml to the database. Since @@ -317,6 +428,8 @@ class OpenLyricsParser(object): song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) properties = song_xml.properties # Process Copyright @@ -329,41 +442,11 @@ class OpenLyricsParser(object): song.ccli_number = self._text(properties.ccliNo) except AttributeError: song.ccli_number = u'' - # Process Titles - for title in properties.titles.title: - if not song.title: - song.title = self._text(title) - song.search_title = unicode(song.title) - song.alternate_title = u'' - else: - song.alternate_title = self._text(title) - song.search_title += u'@' + song.alternate_title - song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', - unicode(song.search_title)).lower() - # Process Lyrics - sxml = SongXMLBuilder() - search_text = u'' + self._process_titles(properties, song) song.verse_order = u'' - for lyrics in song_xml.lyrics: - for verse in lyrics.verse: - text = u'' - for line in verse.lines: - text = u'\n'.join([unicode(line) for line in line.line]) - # Remove chords - text = re.compile(u'').sub(u'', text) - # OpenLyrics allows e. g. "c", but we need "c1". - if self._get(verse, u'name').isalpha(): - verse.set(u'name', self._get(verse, u'name') + u'1') - type = VerseType.expand_string(self._get(verse, u'name')[0]) - sxml.add_verse_to_lyrics( - type, self._get(verse, u'name')[1], text) - song.verse_order += u'%s%s ' % (type[0], - self._get(verse, u'name')[1]) - search_text = search_text + text - song.search_lyrics = search_text.lower() - song.lyrics = unicode(sxml.extract_xml(), u'utf-8') - song.verse_order = song.verse_order.strip() + self._process_lyrics(song_xml, song) # Process verse order + song.verse_order = song.verse_order.strip() try: song.verse_order = self._text(properties.verseOrder) except AttributeError: @@ -372,46 +455,10 @@ class OpenLyricsParser(object): pass if song.verse_order == u'None': song.verse_order = u'' - # Process Comments - song.comments = u'' - try: - for comment in properties.comments.comment: - if not song.comments: - song.comments = self._text(comment) - else: - song.comments += u'\n' + self._text(comment) - except AttributeError: - pass - # Process Authors - try: - for author in properties.authors.author: - self._process_author(self._text(author), song) - except AttributeError: - pass - if not song.authors: - # Add "Author unknown" (can be translated) - self._process_author(unicode(translate('SongsPlugin.XML', - 'Author unknown')), song) - # Process Song Book and Song Number - song.song_book_id = 0 - song.song_number = u'' - try: - for songbook in properties.songbooks.songbook: - self._process_songbook(self._get(songbook, u'name'), song) - if self._get(songbook, u'entry'): - song.song_number = self._get(songbook, u'entry') - # OpenLp does only support one song book, so take the first one. - break - except AttributeError: - pass - # Process Topcis - try: - for topic in properties.themes.theme: - self._process_topic(self._text(topic), song) - except AttributeError: - pass - # Properties not yet supported. - song.theme_name = u'' + self._process_comments(properties, song) + self._process_authors(properties, song) + self._process_songbooks(properties, song) + self._process_topics(properties, song) self.manager.save_object(song) return song.id @@ -440,91 +487,123 @@ class OpenLyricsParser(object): return unicode(element.text) return u'' - def _add_text_to_element(self, tag, parent, text=None, label=None): - if label: - element = etree.Element(tag, name=unicode(label)) - else: - element = etree.Element(tag) - if text: - element.text = unicode(text) - parent.append(element) - return element - - def _dump_xml(self, xml): - """ - Debugging aid to dump XML so that we can see what we have. - """ - return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=True) - - def _extract_xml(self, xml): - """ - Extract our newly created XML song. - """ - return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True) - - def _process_author(self, name, song): + def _process_authors(self, properties, song): """ Finds an existing Author or creates a new Author and adds it to the song object. - - ``name`` - The display_name of the song (unicode). - - ``song`` - The song the object. """ - if not name: - # Wrong use of XML here, as no text has been supplied. - return - author = self.manager.get_object_filtered(Author, - Author.display_name == name) - if author is None: - # We need to create a new author, as the author does not exist. - author = Author.populate(last_name=name.split(u' ')[-1], - first_name=u' '.join(name.split(u' ')[:-1]), display_name=name) + authors = [] + try: + for author in properties.authors.author: + display_name = self._text(author) + if display_name: + authors.append(display_name) + except AttributeError: + pass + if not authors: + # Add "Author unknown" (can be translated). + authors.append((unicode(translate('SongsPlugin.XML', + 'Author unknown')))) + for display_name in authors: + author = self.manager.get_object_filtered(Author, + Author.display_name == display_name) + if author is None: + # We need to create a new author, as the author does not exist. + author = Author.populate(display_name=display_name, + last_name=display_name.split(u' ')[-1], + first_name=u' '.join(display_name.split(u' ')[:-1])) self.manager.save_object(author) - song.authors.append(author) + song.authors.append(author) - def _process_topic(self, topictext, song): + def _process_comments(self, properties, song): """ - Finds an existing topic or creates a new topic and adds it to the song - object. - - ``topictext`` - The topictext of the topic (unicode). - - ``song`` - The song object. """ - if not topictext: - # Wrong use of XML here, as no text has been supplied. - return - topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) - if topic is None: - # We need to create a new topic, as the topic does not exist. - topic = Topic.populate(name=topictext) - self.manager.save_object(topic) - song.topics.append(topic) + try: + song.comments = u'\n'.join( + [self._text(comment) for comment in properties.comments.comment] + ) + except AttributeError: + song.comments = u'' - def _process_songbook(self, bookname, song): + def _process_lyrics(self, song_xml, song): + """ + """ + sxml = SongXMLBuilder() + search_text = u'' + for verse in song_xml.lyrics.verse: + text = u'' + for lines in verse.lines: + if text: + text += u'\n' + text += u'\n'.join([unicode(line) for line in lines.line]) + # OpenLyrics allows e. g. "c", but we need "c1". + if self._get(verse, u'name').isalpha(): + verse.set(u'name', self._get(verse, u'name') + u'1') + type = VerseType.expand_string(self._get(verse, u'name')[0]) + sxml.add_verse_to_lyrics(type, self._get(verse, u'name')[1], text) + song.verse_order += u'%s%s ' % (type[0], + self._get(verse, u'name')[1]) + search_text = search_text + text + song.search_lyrics = search_text.lower() + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + #TODO: make sure "c" becomes "c1" + + def _process_songbooks(self, properties, song): """ Finds an existing book or creates a new book and adds it to the song object. - - ``bookname`` - The name of the book (unicode). - - ``song`` - The song object. """ - if not bookname: - # Wrong use of XML here, as no text has been supplied. - return - book = self.manager.get_object_filtered(Book, Book.name == bookname) - if book is None: - # We need to create a new book, as the book does not exist. - book = Book.populate(name=bookname, publisher=u'') - self.manager.save_object(book) - song.song_book_id = book.id + song.song_book_id = 0 + song.song_number = u'' + try: + for songbook in properties.songbooks.songbook: + bookname = self._get(songbook, u'name') + if bookname: + book = self.manager.get_object_filtered(Book, + Book.name == bookname) + if book is None: + # We need to create a book, because it does not exist. + book = Book.populate(name=bookname, publisher=u'') + self.manager.save_object(book) + song.song_book_id = book.id + if self._get(songbook, u'entry'): + song.song_number = self._get(songbook, u'entry') + # We does only support one song book, so take the first one. + break + except AttributeError: + pass + + def _process_titles(self, properties, song): + """ + """ + for title in properties.titles.title: + if not song.title: + song.title = self._text(title) + song.search_title = unicode(song.title) + song.alternate_title = u'' + else: + song.alternate_title = self._text(title) + song.search_title += u'@' + song.alternate_title + song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', + unicode(song.search_title)).lower() + + def _process_topics(self, properties, song): + """ + Finds an existing topic or creates a new topic and adds it to the song + object. + """ + try: + for topictext in properties.themes.theme: + topictext = self._text(topictext) + if not topictext: + # Wrong use of XML here, as no text has been supplied. + return + topic = self.manager.get_object_filtered(Topic, + Topic.name == topictext) + if topic is None: + # We need to create a new topic, as the topic does not exist. + topic = Topic.populate(name=topictext) + self.manager.save_object(topic) + song.topics.append(topic) + except AttributeError: + pass From 09e2fb7691c79c48ef431882f06f448b34283985 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 5 Jan 2011 17:45:29 +0100 Subject: [PATCH 20/43] clean up --- openlp/plugins/songs/lib/xml.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 4d23ebd78..957c377ec 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -420,7 +420,6 @@ class OpenLyricsParser(object): Create and save a song from OpenLyrics format xml to the database. Since we also export XML from external sources (e. g. OpenLyrics import), we cannot ensure, that it completely conforms to the OpenLyrics standard. - That means, that we for example have to remove chords. """ # No xml get out of here. if not xml: @@ -453,8 +452,6 @@ class OpenLyricsParser(object): # Do not worry, as the verse order has cautionary already been # saved while creating the verses. pass - if song.verse_order == u'None': - song.verse_order = u'' self._process_comments(properties, song) self._process_authors(properties, song) self._process_songbooks(properties, song) From b6db2e3659420b6ff9ee60583465354f227b92ce Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 5 Jan 2011 16:55:28 +0000 Subject: [PATCH 21/43] Fixes --- openlp/core/lib/theme.py | 20 ++++++++++---------- openlp/core/ui/themeform.py | 4 ++++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 1e4a9854e..619d991c7 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -527,15 +527,15 @@ class ThemeXML(object): value = u'' setattr(self, tag, unicode(value).strip().lstrip()) - def __str__(self): - """ - Return a string representation of this object. - """ - theme_strings = [] - for key in dir(self): - if key[0:1] != u'_': - theme_strings.append(u'%30s: %s' % (key, getattr(self, key))) - return u'\n'.join(theme_strings) +# def __str__(self): +# """ +# Return a string representation of this object. +# """ +# theme_strings = [] +# for key in dir(self): +# if key[0:1] != u'_': +# theme_strings.append(u'%30s: %s' % (key, getattr(self, key))) +# return u'\n'.join(theme_strings) def _de_hump(self, name): """ @@ -598,4 +598,4 @@ class ThemeXML(object): self.font_footer_shadow_size) self.add_display(self.display_horizontal_align, self.display_vertical_align, - self.display_slide_transition) \ No newline at end of file + self.display_slide_transition) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index f5b119fa8..ca33cd628 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -125,8 +125,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Set up display at start of theme edit. """ + print "setdefaults 1", self.theme, self.theme.theme_name self.restart() self.accepted = False + print "setdefaults 2", self.theme, self.theme.theme_name self.setBackgroundPageValues() self.setMainAreaPageValues() self.setFooterAreaPageValues() @@ -286,6 +288,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): Run the wizard. """ log.debug(u'Editing theme %s' % self.theme.theme_name) + print "exec_", self.theme, self.theme.theme_name self.updateThemeAllowed = False self.setDefaults() self.updateThemeAllowed = True @@ -321,6 +324,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Handle the display and state of the Background page. """ + print "setBPV", self.theme, self.theme.theme_name if self.theme.background_type == \ BackgroundType.to_string(BackgroundType.Solid): self.colorButton.setStyleSheet(u'background-color: %s' % From b4dfeca4d7be4984bc128a14541355e0302dd3d0 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 5 Jan 2011 20:34:56 +0100 Subject: [PATCH 22/43] --- openlp/plugins/songs/lib/xml.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 957c377ec..8a9cc6930 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -545,6 +545,11 @@ class OpenLyricsParser(object): song.lyrics = unicode(sxml.extract_xml(), u'utf-8') #TODO: make sure "c" becomes "c1" +# name = self._get(verse, u'name') +# type = name[0] +# number = re.compile(u'[a-zA-Z]*').sub(u'', name) +# part = re.compile(u'[0-9]*').sub(u'', name[1:]) + def _process_songbooks(self, properties, song): """ Finds an existing book or creates a new book and adds it to the song From fc2142849932f289c0e4429254144188af8b8644 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 6 Jan 2011 10:34:26 +0100 Subject: [PATCH 23/43] fixed docs --- openlp/plugins/songs/lib/xml.py | 45 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 14d2f426f..4a676b1ad 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -355,57 +355,56 @@ class OpenLyricsParser(object): As OpenLyrics has a rich set of different features, we cannot support them all. The following features are supported by the :class:`OpenLyricsParser`:: - ```` - OpenLP does not support the author ``type`` and consequently not - ``lang`` for the author of the type ``translation``. + ** + OpenLP does not support the attribute *type* and *lang*. - ```` + ** This property is not supported. - ```` - The ```` property is fully supported. But comments in lyrics + ** + The ** property is fully supported. But comments in lyrics are not supported. - ```` + ** This property is fully supported. - ```` + ** This property is not supported. - ```` + ** This property is not supported. - ```` + ** This property is not supported. - ```` - The attribute ``part`` is not supported. + ** + The attribute *part* is not supported. - ```` + ** This property is not supported. - ```` + ** As OpenLP does only support one songbook, we cannot consider more than one songbook. - ```` + ** This property is not supported. - ```` + ** Topics, as they are called in OpenLP, are fully supported, whereby only - the topic text (e. g. Grace) is considered, but neither the ``id`` nor - ``lang``. + the topic text (e. g. Grace) is considered, but neither the *id* nor + *lang*. - ```` + ** This property is not supported. - ```` + ** This property is not supported. - ```` - The attribute ``translit`` and ``lang`` are not supported. + ** + The attribute *translit* and *lang* are not supported. - ```` + ** OpenLP supports this property. """ def __init__(self, manager): From 68c550cd711dab7160702645999fdfd9853bcbcd Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Thu, 6 Jan 2011 14:01:30 +0100 Subject: [PATCH 24/43] -basic work for OpenLyrics exporter (songexport wizard is missing) --- openlp/plugins/songs/lib/openlyricsexport.py | 72 ++++++++++++++++++++ openlp/plugins/songs/lib/xml.py | 8 +-- 2 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 openlp/plugins/songs/lib/openlyricsexport.py diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py new file mode 100644 index 000000000..95c96517d --- /dev/null +++ b/openlp/plugins/songs/lib/openlyricsexport.py @@ -0,0 +1,72 @@ +## -*- coding: utf-8 -*- +## vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +# +################################################################################ +## OpenLP - Open Source Lyrics Projection # +## --------------------------------------------------------------------------- # +## Copyright (c) 2008-2011 Raoul Snyman # +## Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +## Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +## Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +## Carsten Tinggaard, Frode Woldsund # +## --------------------------------------------------------------------------- # +## This program is free software; you can redistribute it and/or modify it # +## under the terms of the GNU General Public License as published by the Free # +## Software Foundation; version 2 of the License. # +## # +## This program is distributed in the hope that it will be useful, but WITHOUT # +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +## more details. # +## # +## You should have received a copy of the GNU General Public License along # +## with this program; if not, write to the Free Software Foundation, Inc., 59 # +## Temple Place, Suite 330, Boston, MA 02111-1307 USA # +################################################################################ +#""" +#The :mod:`openlyricsexport` module provides the functionality for exporting +#songs from the database. +#""" +# +#import logging +#import os +# +#from lxml import etree +# +#from openlp.core.lib import translate +#from openlp.plugins.songs.lib import OpenLyricsBuilder +#from openlp.plugins.songs.lib.songimport import SongImport +# +#log = logging.getLogger(__name__) +# +#class OpenLyricsExport(SongExport): +# """ +# This provides the Openlyrics export. +# """ +# def __init__(self, master_manager, songs=None, save_path=u''): +# """ +# Initialise the export. +# """ +# log.debug(u'initialise OpenLyricsExport') +# SongExport.__init__(self, master_manager) +# self.master_manager = master_manager +# self.songs = songs +# self.save_path = save_path +# +# def do_export(self): +# """ +# Exports the songs. +# """ +# openLyricsBuilder = OpenLyricsBuilder(self.master_manager) +# self.export_wizard.exportProgressBar.setMaximum(len(songs)) +# for song in self.songs: +# if self.stop_export_flag: +# return False +# self.import_wizard.incrementProgressBar(unicode(translate( +# 'SongsPlugin.OpenLyricsExport', 'Importing %s...')) % +# song.title) +# xml = openLyricsBuilder.song_to_xml(song, True) +# tree = etree.ElementTree(etree.fromstring(xml)) +# path = os.path.join(self.save_path, song.title) +# tree.write(path) +# return True diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 4a676b1ad..a5c8ecd06 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -272,7 +272,7 @@ class OpenLyricsBuilder(object): def __init__(self, manager): self.manager = manager - def song_to_xml(self, song): + def song_to_xml(self, song, pretty_print=False): """ Convert the song to OpenLyrics Format. """ @@ -321,7 +321,7 @@ class OpenLyricsBuilder(object): element = self._add_text_to_element(u'lines', element) for line in unicode(verse[1]).split(u'\n'): self._add_text_to_element(u'line', element, line) - return self._extract_xml(song_xml) + return self._extract_xml(song_xml, pretty_print) def _add_text_to_element(self, tag, parent, text=None, label=None): if label: @@ -333,12 +333,12 @@ class OpenLyricsBuilder(object): parent.append(element) return element - def _extract_xml(self, xml): + def _extract_xml(self, xml, pretty_print): """ Extract our newly created XML song. """ return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True) + xml_declaration=True, pretty_print=pretty_print) def _dump_xml(self, xml): """ From c2b1dd9f2f6c1062dec49a0ffa57797654b879b5 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 8 Jan 2011 02:44:12 +0000 Subject: [PATCH 25/43] More cleanups --- openlp/core/lib/__init__.py | 3 ++- openlp/core/lib/mediamanageritem.py | 3 ++- openlp/core/ui/servicemanager.py | 5 ++--- openlp/core/ui/themewizard.py | 9 ++++++--- openlp/plugins/bibles/lib/manager.py | 8 ++++---- openlp/plugins/presentations/lib/presentationtab.py | 3 ++- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index ebbe31597..2bcb25d85 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -102,7 +102,8 @@ def translate(context, text, comment=None, An identifying string for when the same text is used in different roles within the same context. """ - return QtCore.QCoreApplication.translate(context, text, comment, encoding, n) + return QtCore.QCoreApplication.translate(context, text, comment, encoding, + n) def get_text_file_string(text_file): """ diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index c92960163..2d6bcce46 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -176,7 +176,8 @@ class MediaManagerItem(QtGui.QWidget): # break compatability), but it makes sense for the icon to # come before the tooltip (as you have to have an icon, but # not neccesarily a tooltip) - return self.toolbar.addToolbarButton(title, icon, tooltip, slot, checkable) + return self.toolbar.addToolbarButton(title, icon, tooltip, slot, + checkable) def addToolbarSeparator(self): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index a9bf232d4..d918a7083 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -28,7 +28,6 @@ import os import logging import cPickle import zipfile -from pprint import pformat log = logging.getLogger(__name__) @@ -986,8 +985,8 @@ class ServiceManager(QtGui.QWidget): u'expanded':expand}) self.repaintServiceList(len(self.serviceItems) + 1, 0) else: - self.serviceItems.insert(self.dropPosition, {u'service_item': item, - u'order': self.dropPosition, + self.serviceItems.insert(self.dropPosition, + {u'service_item': item, u'order': self.dropPosition, u'expanded':expand}) self.repaintServiceList(self.dropPosition, 0) # if rebuilding list make sure live is fixed. diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 1bf0a0038..ae2a4e1bd 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -249,7 +249,8 @@ class Ui_ThemeWizard(object): self.footerSizeSpinBox.setMaximum(999) self.footerSizeSpinBox.setValue(10) self.footerSizeSpinBox.setObjectName(u'FooterSizeSpinBox') - self.footerAreaLayout.addRow(self.footerSizeLabel, self.footerSizeSpinBox) + self.footerAreaLayout.addRow(self.footerSizeLabel, + self.footerSizeSpinBox) ThemeWizard.addPage(self.footerAreaPage) # Alignment Page self.alignmentPage = QtGui.QWizardPage() @@ -317,9 +318,11 @@ class Ui_ThemeWizard(object): self.areaPositionLayout.addWidget(self.mainPositionGroupBox) self.footerPositionGroupBox = QtGui.QGroupBox(self.areaPositionPage) self.footerPositionGroupBox.setObjectName(u'FooterPositionGroupBox') - self.footerPositionLayout = QtGui.QFormLayout(self.footerPositionGroupBox) + self.footerPositionLayout = QtGui.QFormLayout( + self.footerPositionGroupBox) self.footerPositionLayout.setObjectName(u'FooterPositionLayout') - self.footerPositionCheckBox = QtGui.QCheckBox(self.footerPositionGroupBox) + self.footerPositionCheckBox = QtGui.QCheckBox(i + self.footerPositionGroupBox) self.footerPositionCheckBox.setObjectName(u'FooterPositionCheckBox') self.footerPositionLayout.addRow(self.footerPositionCheckBox) self.footerXLabel = QtGui.QLabel(self.footerPositionGroupBox) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 8e1dadd0e..63c6954fb 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -273,10 +273,10 @@ class BibleManager(object): Receiver.send_message(u'openlp_information_message', { u'title': translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'), - u'message': translate('BiblesPlugin.BibleManager', 'Your scripture ' - 'reference is either not supported by OpenLP or is invalid. ' - 'Please make sure your reference conforms to one of the ' - 'following patterns:\n\n' + u'message': translate('BiblesPlugin.BibleManager', + 'Your scripture reference is either not supported by OpenLP ' + 'or is invalid. Please make sure your reference conforms to ' + 'one of the following patterns:\n\n' 'Book Chapter\n' 'Book Chapter-Chapter\n' 'Book Chapter:Verse-Verse\n' diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index c4df4f4e1..fc82600df 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -116,7 +116,8 @@ class PresentationTab(SettingsTab): if controller.available: checkbox = self.PresenterCheckboxes[controller.name] setting_key = self.settingsSection + u'/' + controller.name - if QtCore.QSettings().value(setting_key) != checkbox.checkState(): + if QtCore.QSettings().value(setting_key) != \ + checkbox.checkState(): changed = True QtCore.QSettings().setValue(setting_key, QtCore.QVariant(checkbox.checkState())) From 04302b590be6a6a9f0e0352152b5fedfe02d5cda Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 8 Jan 2011 09:17:08 +0000 Subject: [PATCH 26/43] Fix up Settings tab following its rebuild --- openlp/core/ui/displaytagtab.py | 21 +++++++++++++-------- openlp/core/ui/settingsdialog.py | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index 47e3b7192..dce1c79d8 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -45,6 +45,9 @@ class DisplayTagTab(SettingsTab): ''' SettingsTab.__init__(self, u'Display Tags') + def resizeEvent(self, event=None): + pass + def preLoad(self): """ Initialise values before the Load takes place @@ -69,13 +72,13 @@ class DisplayTagTab(SettingsTab): translate(u'OpenLP.DisplayTagTab', 'Display Tags') self.displayTagEdit = QtGui.QWidget(self) self.editGroupBox = QtGui.QGroupBox(self.displayTagEdit) - self.editGroupBox.setGeometry(QtCore.QRect(10, 220, 691, 181)) + self.editGroupBox.setGeometry(QtCore.QRect(10, 220, 650, 181)) self.editGroupBox.setObjectName(u'editGroupBox') self.updatePushButton = QtGui.QPushButton(self.editGroupBox) - self.updatePushButton.setGeometry(QtCore.QRect(600, 140, 71, 26)) + self.updatePushButton.setGeometry(QtCore.QRect(550, 140, 71, 26)) self.updatePushButton.setObjectName(u'updatePushButton') self.layoutWidget = QtGui.QWidget(self.editGroupBox) - self.layoutWidget.setGeometry(QtCore.QRect(20, 50, 571, 114)) + self.layoutWidget.setGeometry(QtCore.QRect(5, 20, 571, 114)) self.layoutWidget.setObjectName(u'layoutWidget') self.formLayout = QtGui.QFormLayout(self.layoutWidget) self.formLayout.setObjectName(u'formLayout') @@ -117,16 +120,16 @@ class DisplayTagTab(SettingsTab): self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.endTagLineEdit) self.defaultPushButton = QtGui.QPushButton(self.displayTagEdit) - self.defaultPushButton.setGeometry(QtCore.QRect(450, 188, 71, 26)) + self.defaultPushButton.setGeometry(QtCore.QRect(430, 188, 71, 26)) self.defaultPushButton.setObjectName(u'updatePushButton') self.deletePushButton = QtGui.QPushButton(self.displayTagEdit) - self.deletePushButton.setGeometry(QtCore.QRect(530, 188, 71, 26)) + self.deletePushButton.setGeometry(QtCore.QRect(510, 188, 71, 26)) self.deletePushButton.setObjectName(u'deletePushButton') self.newPushButton = QtGui.QPushButton(self.displayTagEdit) - self.newPushButton.setGeometry(QtCore.QRect(610, 188, 71, 26)) + self.newPushButton.setGeometry(QtCore.QRect(600, 188, 71, 26)) self.newPushButton.setObjectName(u'newPushButton') self.tagTableWidget = QtGui.QTableWidget(self.displayTagEdit) - self.tagTableWidget.setGeometry(QtCore.QRect(10, 10, 691, 171)) + self.tagTableWidget.setGeometry(QtCore.QRect(10, 10, 650, 171)) self.tagTableWidget.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.tagTableWidget.setEditTriggers( @@ -174,7 +177,7 @@ class DisplayTagTab(SettingsTab): QtCore.QMetaObject.connectSlotsByName(self.displayTagEdit) self.tagTableWidget.setColumnWidth(0, 120) self.tagTableWidget.setColumnWidth(1, 40) - self.tagTableWidget.setColumnWidth(2, 280) + self.tagTableWidget.setColumnWidth(2, 240) self.tagTableWidget.setColumnWidth(3, 200) QtCore.QObject.connect(self.tagTableWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) @@ -283,6 +286,8 @@ class DisplayTagTab(SettingsTab): u'end html': u'', u'protected': False} DisplayTags.add_html_tag(tag) self._resetTable() + print self.tagTableWidget.rowCount() + self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1) def onDefaultPushed(self): """ diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index 537e99cc2..61c73961c 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -31,7 +31,7 @@ from openlp.core.lib import translate, build_icon class Ui_SettingsDialog(object): def setupUi(self, settingsDialog): settingsDialog.setObjectName(u'settingsDialog') - settingsDialog.resize(700, 300) + settingsDialog.resize(700, 500) settingsDialog.setWindowIcon( build_icon(u':/system/system_settings.png')) self.settingsLayout = QtGui.QVBoxLayout(settingsDialog) From f5ec98f79cd78c9856c40af59265e30932f68b1e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 8 Jan 2011 09:44:44 +0000 Subject: [PATCH 27/43] Remove Print add comment --- openlp/core/ui/displaytagtab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index dce1c79d8..b200f0765 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -286,7 +286,7 @@ class DisplayTagTab(SettingsTab): u'end html': u'', u'protected': False} DisplayTags.add_html_tag(tag) self._resetTable() - print self.tagTableWidget.rowCount() + # Highlight new row self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1) def onDefaultPushed(self): From ead2daeed4142392c51e806f37fbfdbb2e12fa65 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 8 Jan 2011 13:57:03 +0000 Subject: [PATCH 28/43] Cleanups --- openlp/core/lib/theme.py | 18 +++++++++--------- openlp/core/ui/themeform.py | 4 ---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 619d991c7..35b62ddda 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -527,15 +527,15 @@ class ThemeXML(object): value = u'' setattr(self, tag, unicode(value).strip().lstrip()) -# def __str__(self): -# """ -# Return a string representation of this object. -# """ -# theme_strings = [] -# for key in dir(self): -# if key[0:1] != u'_': -# theme_strings.append(u'%30s: %s' % (key, getattr(self, key))) -# return u'\n'.join(theme_strings) + def __str__(self): + """ + Return a string representation of this object. + """ + theme_strings = [] + for key in dir(self): + if key[0:1] != u'_': + theme_strings.append(u'%30s: %s' % (key, getattr(self, key))) + return u'\n'.join(theme_strings) def _de_hump(self, name): """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index c184585e6..a6e925707 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -125,10 +125,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Set up display at start of theme edit. """ - print "setdefaults 1", self.theme, self.theme.theme_name self.restart() self.accepted = False - print "setdefaults 2", self.theme, self.theme.theme_name self.setBackgroundPageValues() self.setMainAreaPageValues() self.setFooterAreaPageValues() @@ -288,7 +286,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): Run the wizard. """ log.debug(u'Editing theme %s' % self.theme.theme_name) - print "exec_", self.theme, self.theme.theme_name self.updateThemeAllowed = False self.setDefaults() self.updateThemeAllowed = True @@ -324,7 +321,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Handle the display and state of the Background page. """ - print "setBPV", self.theme, self.theme.theme_name if self.theme.background_type == \ BackgroundType.to_string(BackgroundType.Solid): self.colorButton.setStyleSheet(u'background-color: %s' % From 70f18fdfa4deee23d95ac5af6bfbfb6f6d7f9c04 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 8 Jan 2011 18:26:38 +0000 Subject: [PATCH 29/43] Fix typo --- openlp/core/ui/themewizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index ae2a4e1bd..f61a44584 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -321,7 +321,7 @@ class Ui_ThemeWizard(object): self.footerPositionLayout = QtGui.QFormLayout( self.footerPositionGroupBox) self.footerPositionLayout.setObjectName(u'FooterPositionLayout') - self.footerPositionCheckBox = QtGui.QCheckBox(i + self.footerPositionCheckBox = QtGui.QCheckBox( self.footerPositionGroupBox) self.footerPositionCheckBox.setObjectName(u'FooterPositionCheckBox') self.footerPositionLayout.addRow(self.footerPositionCheckBox) From dbfd7796ba94767de2828bdfa8d0ca2b49fb1a72 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 8 Jan 2011 18:50:06 +0000 Subject: [PATCH 30/43] Fix BibleGateway xrefs (Bug #700271) --- openlp/plugins/bibles/lib/http.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index ef663dfbe..d9210a275 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -231,6 +231,9 @@ class BGExtract(object): footnotes = soup.findAll(u'sup', u'footnote') if footnotes: [footnote.extract() for footnote in footnotes] + crossrefs = soup.findAll(u'sup', u'xref') + if crossrefs: + [crossref.extract() for crossref in crossrefs] cleanup = [(re.compile('\s+'), lambda match: ' ')] verses = BeautifulSoup(str(soup), markupMassage=cleanup) content = verses.find(u'div', u'result-text-style-normal') From d5a30294a45471206e9b36fc9e14a1dfe9be2d18 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 8 Jan 2011 19:24:56 +0000 Subject: [PATCH 31/43] Refactor out first_item --- openlp/plugins/bibles/lib/mediaitem.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index a669a51be..661a9a679 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -709,11 +709,11 @@ class BibleMediaItem(MediaManagerItem): if len(items) == 0: return False bible_text = u'' + old_item = None old_chapter = -1 raw_footer = [] raw_slides = [] raw_title = [] - first_item = True for item in items: bitem = self.listView.item(item.row()) book = self._decodeQtObject(bitem, 'book') @@ -754,9 +754,8 @@ class BibleMediaItem(MediaManagerItem): # We have to be 'Continuous'. else: bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text) - if first_item: + if not old_item: start_item = item - first_item = False elif self.checkTitle(item, old_item): raw_title.append(self.formatTitle(start_item, old_item)) start_item = item From a51ad14322efafc6966eb7a9ff680685a11178d8 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 8 Jan 2011 21:35:31 +0100 Subject: [PATCH 32/43] removed OpenLyrics export for now --- openlp/plugins/songs/lib/openlyricsexport.py | 72 -------------------- 1 file changed, 72 deletions(-) delete mode 100644 openlp/plugins/songs/lib/openlyricsexport.py diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py deleted file mode 100644 index 95c96517d..000000000 --- a/openlp/plugins/songs/lib/openlyricsexport.py +++ /dev/null @@ -1,72 +0,0 @@ -## -*- coding: utf-8 -*- -## vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 -# -################################################################################ -## OpenLP - Open Source Lyrics Projection # -## --------------------------------------------------------------------------- # -## Copyright (c) 2008-2011 Raoul Snyman # -## Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -## Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -## Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -## Carsten Tinggaard, Frode Woldsund # -## --------------------------------------------------------------------------- # -## This program is free software; you can redistribute it and/or modify it # -## under the terms of the GNU General Public License as published by the Free # -## Software Foundation; version 2 of the License. # -## # -## This program is distributed in the hope that it will be useful, but WITHOUT # -## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -## more details. # -## # -## You should have received a copy of the GNU General Public License along # -## with this program; if not, write to the Free Software Foundation, Inc., 59 # -## Temple Place, Suite 330, Boston, MA 02111-1307 USA # -################################################################################ -#""" -#The :mod:`openlyricsexport` module provides the functionality for exporting -#songs from the database. -#""" -# -#import logging -#import os -# -#from lxml import etree -# -#from openlp.core.lib import translate -#from openlp.plugins.songs.lib import OpenLyricsBuilder -#from openlp.plugins.songs.lib.songimport import SongImport -# -#log = logging.getLogger(__name__) -# -#class OpenLyricsExport(SongExport): -# """ -# This provides the Openlyrics export. -# """ -# def __init__(self, master_manager, songs=None, save_path=u''): -# """ -# Initialise the export. -# """ -# log.debug(u'initialise OpenLyricsExport') -# SongExport.__init__(self, master_manager) -# self.master_manager = master_manager -# self.songs = songs -# self.save_path = save_path -# -# def do_export(self): -# """ -# Exports the songs. -# """ -# openLyricsBuilder = OpenLyricsBuilder(self.master_manager) -# self.export_wizard.exportProgressBar.setMaximum(len(songs)) -# for song in self.songs: -# if self.stop_export_flag: -# return False -# self.import_wizard.incrementProgressBar(unicode(translate( -# 'SongsPlugin.OpenLyricsExport', 'Importing %s...')) % -# song.title) -# xml = openLyricsBuilder.song_to_xml(song, True) -# tree = etree.ElementTree(etree.fromstring(xml)) -# path = os.path.join(self.save_path, song.title) -# tree.write(path) -# return True From f2784fc4dd6874cba00112669018a4d3781c53fb Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 8 Jan 2011 21:59:46 +0100 Subject: [PATCH 33/43] removed whitespaces --- openlp/core/ui/__init__.py | 4 ++-- openlp/plugins/bibles/forms/bibleimportwizard.py | 2 +- openlp/plugins/songs/forms/authorsdialog.py | 2 +- openlp/plugins/songs/forms/songimportwizard.py | 2 +- openlp/plugins/songs/lib/xml.py | 16 ++++++++-------- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 26c59ed0f..ca2123c87 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -35,11 +35,11 @@ class HideMode(object): ``Blank`` This mode is used to hide all output, specifically by covering the display with a black screen. - + ``Theme`` This mode is used to hide all output, but covers the display with the current theme background, as opposed to black. - + ``Desktop`` This mode hides all output by minimising the display, leaving the user's desktop showing. diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index a85e430a1..3200bf974 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -234,7 +234,7 @@ class Ui_BibleImportWizard(object): QtGui.QSizePolicy.Minimum) self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole, self.openlp1Spacer) - self.selectStack.addWidget(self.openlp1Widget) + self.selectStack.addWidget(self.openlp1Widget) self.selectPageLayout.addLayout(self.selectStack) bibleImportWizard.addPage(self.selectPage) # License Page diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 28083ae05..6f1c7f2a4 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -54,7 +54,7 @@ class Ui_AuthorsDialog(object): self.displayEdit.setObjectName(u'displayEdit') self.displayLabel.setBuddy(self.displayEdit) self.authorLayout.addRow(self.displayLabel, self.displayEdit) - self.dialogLayout.addLayout(self.authorLayout) + self.dialogLayout.addLayout(self.authorLayout) self.buttonBox = QtGui.QDialogButtonBox(authorsDialog) self.buttonBox.setStandardButtons( QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel) diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py index 6eccff9b4..903300d0c 100644 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ b/openlp/plugins/songs/forms/songimportwizard.py @@ -39,7 +39,7 @@ class Ui_SongImportWizard(object): QtGui.QWizard.IndependentPages | QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnLastPage) - # Welcome Page + # Welcome Page self.welcomePage = QtGui.QWizardPage() self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, QtGui.QPixmap(u':/wizards/wizard_importsong.bmp')) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index a5c8ecd06..10d93b100 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -359,10 +359,10 @@ class OpenLyricsParser(object): OpenLP does not support the attribute *type* and *lang*. ** - This property is not supported. + This property is not supported. ** - The ** property is fully supported. But comments in lyrics + The ** property is fully supported. But comments in lyrics are not supported. ** @@ -372,23 +372,23 @@ class OpenLyricsParser(object): This property is not supported. ** - This property is not supported. + This property is not supported. ** - This property is not supported. + This property is not supported. ** The attribute *part* is not supported. ** - This property is not supported. + This property is not supported. ** As OpenLP does only support one songbook, we cannot consider more than one songbook. ** - This property is not supported. + This property is not supported. ** Topics, as they are called in OpenLP, are fully supported, whereby only @@ -399,9 +399,9 @@ class OpenLyricsParser(object): This property is not supported. ** - This property is not supported. + This property is not supported. - ** + ** The attribute *translit* and *lang* are not supported. ** From 6e8a371da7ea2531bb7901827e9ef504377b1c0f Mon Sep 17 00:00:00 2001 From: M2j Date: Sun, 9 Jan 2011 01:27:46 +0100 Subject: [PATCH 34/43] wrong parentship caused theme and servicemanager to disapear in a floating dock more intelligent resizing of item list in PluginForm and SongMaintenanceForm Fix in BS web bible parser --- openlp/core/ui/mainwindow.py | 6 +- openlp/core/ui/pluginform.py | 8 +- openlp/core/ui/servicemanager.py | 80 +++++++++---------- openlp/core/ui/themeform.py | 4 +- openlp/core/ui/thememanager.py | 12 +-- openlp/core/ui/themewizard.py | 30 ++++--- openlp/plugins/alerts/alertsplugin.py | 2 +- .../plugins/bibles/forms/bibleimportwizard.py | 32 ++++---- openlp/plugins/bibles/lib/http.py | 2 +- .../songs/forms/songmaintenancedialog.py | 19 +++-- 10 files changed, 101 insertions(+), 94 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 70b87966c..f2545766e 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -142,7 +142,8 @@ class Ui_MainWindow(object): build_icon(u':/system/system_servicemanager.png')) self.ServiceManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ServiceManagerContents = ServiceManager(MainWindow) + self.ServiceManagerContents = ServiceManager(MainWindow, + self.ServiceManagerDock) self.ServiceManagerDock.setWidget(self.ServiceManagerContents) MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.ServiceManagerDock) @@ -152,7 +153,8 @@ class Ui_MainWindow(object): build_icon(u':/system/system_thememanager.png')) self.ThemeManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ThemeManagerContents = ThemeManager(MainWindow) + self.ThemeManagerContents = ThemeManager(MainWindow, + self.ThemeManagerDock) self.ThemeManagerContents.setObjectName(u'ThemeManagerContents') self.ThemeManagerDock.setWidget(self.ThemeManagerContents) MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 26e6cf06c..112cd04dd 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -61,6 +61,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): self.programaticChange = True self._clearDetails() self.programaticChange = True + pluginListWidth = 0 for plugin in self.parent.pluginManager.plugins: item = QtGui.QListWidgetItem(self.pluginListWidget) # We do this just to make 100% sure the status is an integer as @@ -83,8 +84,11 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): if plugin.icon: item.setIcon(plugin.icon) self.pluginListWidget.addItem(item) - self.pluginListWidget.setFixedWidth( - self.pluginListWidget.sizeHint().width()) + pluginListWidth = max(pluginListWidth, self.fontMetrics().width( + unicode(translate('OpenLP.PluginForm', '%s (Inactive)')) % + name_string[u'singular'])) + self.pluginListWidget.setFixedWidth(pluginListWidth + + self.pluginListWidget.iconSize().width() + 48) def _clearDetails(self): self.statusComboBox.setCurrentIndex(-1) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e1aa126ae..3e272da47 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -43,33 +43,33 @@ class ServiceManagerList(QtGui.QTreeWidget): """ Set up key bindings and mouse behaviour for the service list """ - def __init__(self, parent=None, name=None): + def __init__(self, mainwindow, parent=None, name=None): QtGui.QTreeWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow def keyPressEvent(self, event): if isinstance(event, QtGui.QKeyEvent): #here accept the event and do something if event.key() == QtCore.Qt.Key_Enter: - self.parent.makeLive() + self.mainwindow.makeLive() event.accept() elif event.key() == QtCore.Qt.Key_Home: - self.parent.onServiceTop() + self.mainwindow.onServiceTop() event.accept() elif event.key() == QtCore.Qt.Key_End: - self.parent.onServiceEnd() + self.mainwindow.onServiceEnd() event.accept() elif event.key() == QtCore.Qt.Key_PageUp: - self.parent.onServiceUp() + self.mainwindow.onServiceUp() event.accept() elif event.key() == QtCore.Qt.Key_PageDown: - self.parent.onServiceDown() + self.mainwindow.onServiceDown() event.accept() elif event.key() == QtCore.Qt.Key_Up: - self.parent.onMoveSelectionUp() + self.mainwindow.onMoveSelectionUp() event.accept() elif event.key() == QtCore.Qt.Key_Down: - self.parent.onMoveSelectionDown() + self.mainwindow.onMoveSelectionDown() event.accept() event.ignore() else: @@ -98,12 +98,12 @@ class ServiceManager(QtGui.QWidget): the resources used into one OSZ file for use on any OpenLP v2 installation. Also handles the UI tasks of moving things up and down etc. """ - def __init__(self, parent): + def __init__(self, mainwindow, parent=None): """ Sets up the service manager, toolbars, list view, et al. """ QtGui.QWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow self.serviceItems = [] self.serviceName = u'' self.suffixes = [] @@ -112,8 +112,8 @@ class ServiceManager(QtGui.QWidget): # is a new service and has not been saved self._modified = False self._fileName = u'' - self.serviceNoteForm = ServiceNoteForm(self.parent) - self.serviceItemEditForm = ServiceItemEditForm(self.parent) + self.serviceNoteForm = ServiceNoteForm(self.mainwindow) + self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow) # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -247,7 +247,7 @@ class ServiceManager(QtGui.QWidget): QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate) # Last little bits of setting up self.service_theme = unicode(QtCore.QSettings().value( - self.parent.serviceSettingsSection + u'/service theme', + self.mainwindow.serviceSettingsSection + u'/service theme', QtCore.QVariant(u'')).toString()) self.servicePath = AppLocation.get_section_data_path(u'servicemanager') #build the drag and drop context menu @@ -294,7 +294,7 @@ class ServiceManager(QtGui.QWidget): """ self._modified = modified serviceFile = self.shortFileName() or u'Untitled Service' - self.parent.setServiceModified(modified, serviceFile) + self.mainwindow.setServiceModified(modified, serviceFile) def isModified(self): """ @@ -307,7 +307,7 @@ class ServiceManager(QtGui.QWidget): Setter for service file. """ self._fileName = unicode(fileName) - self.parent.setServiceModified(self.isModified, self.shortFileName()) + self.mainwindow.setServiceModified(self.isModified, self.shortFileName()) QtCore.QSettings(). \ setValue(u'service/last file',QtCore.QVariant(fileName)) @@ -341,7 +341,7 @@ class ServiceManager(QtGui.QWidget): Create a new service. """ if self.isModified(): - result = QtGui.QMessageBox.question(self.parent, + result = QtGui.QMessageBox.question(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Changes'), translate('OpenLP.ServiceManager', 'The current service has ' 'been modified, would you like to save it?'), @@ -356,7 +356,7 @@ class ServiceManager(QtGui.QWidget): def onLoadServiceClicked(self): if self.isModified(): - result = QtGui.QMessageBox.question(self.parent, + result = QtGui.QMessageBox.question(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Changes'), translate('OpenLP.ServiceManager', 'The current service has ' 'been modified, would you like to save it?'), @@ -366,14 +366,14 @@ class ServiceManager(QtGui.QWidget): return False elif result == QtGui.QMessageBox.Save: self.saveFile() - fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.parent, + fileName = unicode(QtGui.QFileDialog.getOpenFileName(self.mainwindow, translate('OpenLP.ServiceManager', 'Open File'), - SettingsManager.get_last_dir(self.parent.serviceSettingsSection), + SettingsManager.get_last_dir(self.mainwindow.serviceSettingsSection), translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) if not fileName: return False - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection, split_filename(fileName)[0]) self.loadFile(fileName) @@ -407,7 +407,7 @@ class ServiceManager(QtGui.QWidget): else: fileName = self.fileName() log.debug(u'ServiceManager.saveFile - %s' % fileName) - SettingsManager.set_last_dir(self.parent.serviceSettingsSection, + SettingsManager.set_last_dir(self.mainwindow.serviceSettingsSection, split_filename(fileName)[0]) service = [] serviceFileName = fileName.replace(u'.osz', u'.osd') @@ -447,7 +447,7 @@ class ServiceManager(QtGui.QWidget): except (IOError, OSError): # if not present do not worry pass - self.parent.addRecentFile(fileName) + self.mainwindow.addRecentFile(fileName) self.setModified(False) return True @@ -456,9 +456,9 @@ class ServiceManager(QtGui.QWidget): Get a file name and then call :function:`ServiceManager.saveFile` to save the file. """ - fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.parent, + fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow, translate('OpenLP.ServiceManager', 'Save Service'), - SettingsManager.get_last_dir(self.parent.serviceSettingsSection), + SettingsManager.get_last_dir(self.mainwindow.serviceSettingsSection), translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) if not fileName: @@ -508,7 +508,7 @@ class ServiceManager(QtGui.QWidget): self.newFile() for item in items: serviceItem = ServiceItem() - serviceItem.render_manager = self.parent.renderManager + serviceItem.render_manager = self.mainwindow.renderManager serviceItem.set_from_service(item, self.servicePath) self.validateItem(serviceItem) self.addServiceItem(serviceItem) @@ -535,7 +535,7 @@ class ServiceManager(QtGui.QWidget): if zip: zip.close() self.setFileName(fileName) - self.parent.addRecentFile(fileName) + self.mainwindow.addRecentFile(fileName) self.setModified(False) QtCore.QSettings(). \ setValue(u'service/last file',QtCore.QVariant(fileName)) @@ -886,9 +886,9 @@ class ServiceManager(QtGui.QWidget): """ log.debug(u'onThemeComboBoxSelected') self.service_theme = unicode(self.themeComboBox.currentText()) - self.parent.renderManager.set_service_theme(self.service_theme) + self.mainwindow.renderManager.set_service_theme(self.service_theme) QtCore.QSettings().setValue( - self.parent.serviceSettingsSection + u'/service theme', + self.mainwindow.serviceSettingsSection + u'/service theme', QtCore.QVariant(self.service_theme)) self.regenerateServiceItems() @@ -898,7 +898,7 @@ class ServiceManager(QtGui.QWidget): sure the theme combo box is in the correct state. """ log.debug(u'themeChange') - if self.parent.renderManager.theme_level == ThemeLevel.Global: + if self.mainwindow.renderManager.theme_level == ThemeLevel.Global: self.toolbar.actions[u'ThemeLabel'].setVisible(False) self.toolbar.actions[u'ThemeWidget'].setVisible(False) else: @@ -913,7 +913,7 @@ class ServiceManager(QtGui.QWidget): Receiver.send_message(u'cursor_busy') log.debug(u'regenerateServiceItems') # force reset of renderer as theme data has changed - self.parent.renderManager.themedata = None + self.mainwindow.renderManager.themedata = None if self.serviceItems: tempServiceItems = self.serviceItems self.serviceManagerList.clear() @@ -948,7 +948,7 @@ class ServiceManager(QtGui.QWidget): newItem.merge(item[u'service_item']) item[u'service_item'] = newItem self.repaintServiceList(itemcount + 1, 0) - self.parent.liveController.replaceServiceManagerItem(newItem) + self.mainwindow.liveController.replaceServiceManagerItem(newItem) self.setModified(True) def addServiceItem(self, item, rebuild=False, expand=None, replace=False): @@ -970,7 +970,7 @@ class ServiceManager(QtGui.QWidget): item.merge(self.serviceItems[sitem][u'service_item']) self.serviceItems[sitem][u'service_item'] = item self.repaintServiceList(sitem + 1, 0) - self.parent.liveController.replaceServiceManagerItem(item) + self.mainwindow.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd if self.dropPosition == 0: @@ -991,7 +991,7 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(self.dropPosition, 0) # if rebuilding list make sure live is fixed. if rebuild: - self.parent.liveController.replaceServiceManagerItem(item) + self.mainwindow.liveController.replaceServiceManagerItem(item) self.dropPosition = 0 self.setModified(True) @@ -1001,7 +1001,7 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.previewController.addServiceManagerItem( + self.mainwindow.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) else: QtGui.QMessageBox.critical(self, @@ -1025,18 +1025,18 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.liveController.addServiceManagerItem( + self.mainwindow.liveController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) if QtCore.QSettings().value( - self.parent.generalSettingsSection + u'/auto preview', + self.mainwindow.generalSettingsSection + u'/auto preview', QtCore.QVariant(False)).toBool(): item += 1 if self.serviceItems and item < len(self.serviceItems) and \ self.serviceItems[item][u'service_item'].is_capable( ItemCapabilities.AllowsPreview): - self.parent.previewController.addServiceManagerItem( + self.mainwindow.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], 0) - self.parent.liveController.PreviewListWidget.setFocus() + self.mainwindow.liveController.PreviewListWidget.setFocus() else: QtGui.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Missing Display Handler'), @@ -1156,7 +1156,7 @@ class ServiceManager(QtGui.QWidget): index = 0 self.service_theme = u'' self.themeComboBox.setCurrentIndex(index) - self.parent.renderManager.set_service_theme(self.service_theme) + self.mainwindow.renderManager.set_service_theme(self.service_theme) self.regenerateServiceItems() def onThemeChangeAction(self): diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index eaf54bdb9..43ca8828e 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -212,8 +212,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Updates the lines on a page on the wizard """ - self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', \ - '(%d lines per slide)' % int(lines)))) + self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', + '(%d lines per slide)')) % int(lines)) def resizeEvent(self, event=None): """ diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 0703402fd..9553a6028 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -45,13 +45,13 @@ class ThemeManager(QtGui.QWidget): """ Manages the orders of Theme. """ - def __init__(self, parent): + def __init__(self, mainwindow, parent=None): QtGui.QWidget.__init__(self, parent) - self.parent = parent + self.mainwindow = mainwindow self.settingsSection = u'themes' self.themeForm = ThemeForm(self) self.fileRenameForm = FileRenameForm(self) - self.serviceComboBox = self.parent.ServiceManagerContents.themeComboBox + self.serviceComboBox = self.mainwindow.ServiceManagerContents.themeComboBox # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -641,7 +641,7 @@ class ThemeManager(QtGui.QWidget): (QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if self.saveThemeName != u'': - for plugin in self.parent.pluginManager.plugins: + for plugin in self.mainwindow.pluginManager.plugins: if plugin.usesTheme(self.saveThemeName): plugin.renameTheme(self.saveThemeName, name) if unicode(self.serviceComboBox.currentText()) == name: @@ -727,7 +727,7 @@ class ThemeManager(QtGui.QWidget): Flag to tell message lines per page need to be generated. """ log.debug(u'generateImage \n%s ', themeData) - return self.parent.renderManager.generate_preview(themeData, forcePage) + return self.mainwindow.renderManager.generate_preview(themeData, forcePage) def getPreviewImage(self, theme): """ @@ -788,7 +788,7 @@ class ThemeManager(QtGui.QWidget): return False else: if testPlugin: - for plugin in self.parent.pluginManager.plugins: + for plugin in self.mainwindow.pluginManager.plugins: if plugin.usesTheme(theme): QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeManager', 'Error'), diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 691b5e568..e30570903 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -471,8 +471,6 @@ class Ui_ThemeWizard(object): self.mainColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.mainSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.mainSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) - self.mainLineCountLabel.setText( - translate('OpenLP.ThemeWizard', '(%d lines per slide)')) self.lineSpacingLabel.setText( translate('OpenLP.ThemeWizard', 'Line Spacing:')) self.lineSpacingSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) @@ -564,17 +562,17 @@ class Ui_ThemeWizard(object): self.themeNameLabel.setText( translate('OpenLP.ThemeWizard', 'Theme name:')) # Align all QFormLayouts towards each other. - width = max(self.backgroundLabel.minimumSizeHint().width(), - self.colorLabel.minimumSizeHint().width()) - width = max(width, self.gradientStartLabel.minimumSizeHint().width()) - width = max(width, self.gradientEndLabel.minimumSizeHint().width()) - width = max(width, self.gradientTypeLabel.minimumSizeHint().width()) - width = max(width, self.imageLabel.minimumSizeHint().width()) - self.backgroundTypeSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.colorSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.gradientSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.imageSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) + labelWidth = max(self.backgroundLabel.minimumSizeHint().width(), + self.colorLabel.minimumSizeHint().width(), + self.gradientStartLabel.minimumSizeHint().width(), + self.gradientEndLabel.minimumSizeHint().width(), + self.gradientTypeLabel.minimumSizeHint().width(), + self.imageLabel.minimumSizeHint().width()) + self.backgroundTypeSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.colorSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.gradientSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.imageSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 4a7e18cef..61be922d5 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -73,7 +73,7 @@ class AlertsPlugin(Plugin): self.toolsAlertItem.setStatusTip( translate('AlertsPlugin', 'Show an alert message.')) self.toolsAlertItem.setShortcut(u'F7') - self.serviceManager.parent.ToolsMenu.addAction(self.toolsAlertItem) + self.serviceManager.mainwindow.ToolsMenu.addAction(self.toolsAlertItem) QtCore.QObject.connect(self.toolsAlertItem, QtCore.SIGNAL(u'triggered()'), self.onAlertsTrigger) self.toolsAlertItem.setVisible(False) diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index a85e430a1..d22103fcb 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -373,19 +373,19 @@ class Ui_BibleImportWizard(object): 'you want to use this importer, you will need to install the ' '"python-sqlite" module.')) # Align all QFormLayouts towards each other. - width = max(self.formatLabel.minimumSizeHint().width(), - self.osisFileLabel.minimumSizeHint().width()) - width = max(width, self.csvBooksLabel.minimumSizeHint().width()) - width = max(width, self.csvVersesLabel.minimumSizeHint().width()) - width = max(width, self.openSongFileLabel.minimumSizeHint().width()) - width = max(width, self.openlp1FileLabel.minimumSizeHint().width()) - self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.osisSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.csvSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openSongSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openlp1Spacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) + labelWidth = max(self.formatLabel.minimumSizeHint().width(), + self.osisFileLabel.minimumSizeHint().width(), + self.csvBooksLabel.minimumSizeHint().width(), + self.csvVersesLabel.minimumSizeHint().width(), + self.openSongFileLabel.minimumSizeHint().width(), + self.openlp1FileLabel.minimumSizeHint().width()) + self.formatSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.osisSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.csvSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.openSongSpacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.openlp1Spacer.changeSize(labelWidth, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 6f26434de..64ee6da5a 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -306,7 +306,7 @@ class BSExtract(object): finally: if not content: return None - verse_number = re.compile(r'v(\d{2})(\d{3})(\d{3}) verse') + verse_number = re.compile(r'v(\d{1,2})(\d{3})(\d{3}) verse') verses = {} for verse in content: Receiver.send_message(u'openlp_process_events') diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 582b6ebe5..51fafcc7a 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -36,8 +36,6 @@ class Ui_SongMaintenanceDialog(object): self.dialogLayout = QtGui.QGridLayout(songMaintenanceDialog) self.dialogLayout.setObjectName(u'dialogLayout') self.typeListWidget = QtGui.QListWidget(songMaintenanceDialog) - # Caution: fixed widget width - self.typeListWidget.setFixedWidth(172) self.typeListWidget.setIconSize(QtCore.QSize(32, 32)) self.typeListWidget.setUniformItemSizes(True) self.typeListWidget.setObjectName(u'typeListWidget') @@ -147,12 +145,12 @@ class Ui_SongMaintenanceDialog(object): def retranslateUi(self, songMaintenanceDialog): songMaintenanceDialog.setWindowTitle( translate('SongsPlugin.SongMaintenanceForm', 'Song Maintenance')) - self.listItemAuthors.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Authors')) - self.listItemTopics.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Topics')) - self.listItemBooks.setText( - translate('SongsPlugin.SongMaintenanceForm', 'Song Books')) + authorsString = translate('SongsPlugin.SongMaintenanceForm', 'Authors') + topicsString = translate('SongsPlugin.SongMaintenanceForm', 'Topics') + booksString = translate('SongsPlugin.SongMaintenanceForm', 'Song Books') + self.listItemAuthors.setText(authorsString) + self.listItemTopics.setText(topicsString) + self.listItemBooks.setText(booksString) self.authorsAddButton.setText( translate('SongsPlugin.SongMaintenanceForm', '&Add')) self.authorsEditButton.setText( @@ -171,3 +169,8 @@ class Ui_SongMaintenanceDialog(object): translate('SongsPlugin.SongMaintenanceForm', '&Edit')) self.booksDeleteButton.setText( translate('SongsPlugin.SongMaintenanceForm', '&Delete')) + typeListWidth = max(self.fontMetrics().width(authorsString), + self.fontMetrics().width(topicsString), + self.fontMetrics().width(booksString)) + self.typeListWidget.setFixedWidth(typeListWidth + + self.typeListWidget.iconSize().width() + 32) From 23990c168a8c8b0378f7c5f8b75c555010a0072a Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 9 Jan 2011 08:17:17 +0000 Subject: [PATCH 35/43] Review Fixes --- openlp.pyw | 6 ++--- openlp/core/lib/__init__.py | 6 ++--- openlp/core/lib/displaytags.py | 32 ++++++-------------------- openlp/core/lib/spelltextedit.py | 6 ++--- openlp/core/ui/displaytagtab.py | 2 +- openlp/core/ui/thememanager.py | 22 +++++++++--------- openlp/plugins/images/lib/mediaitem.py | 6 ++--- 7 files changed, 31 insertions(+), 49 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index dbf4d1a27..017e12774 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -34,7 +34,7 @@ from subprocess import Popen, PIPE from PyQt4 import QtCore, QtGui -from openlp.core.lib import Receiver, checkDirectoryExists +from openlp.core.lib import Receiver, check_directory_exists from openlp.core.resources import qInitResources from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.exceptionform import ExceptionForm @@ -243,7 +243,7 @@ def main(): help='Set the Qt4 style (passed directly to Qt4).') # Set up logging log_path = AppLocation.get_directory(AppLocation.CacheDir) - checkDirectoryExists(log_path) + check_directory_exists(log_path) filename = os.path.join(log_path, u'openlp.log') logfile = logging.FileHandler(filename, u'w') logfile.setFormatter(logging.Formatter( @@ -280,4 +280,4 @@ if __name__ == u'__main__': """ Instantiate and run the application. """ - main() + main() \ No newline at end of file diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index dd1fb852b..6cd6d9d5c 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -306,14 +306,14 @@ def expand_tags(text): text = text.replace(tag[u'end tag'], tag[u'end html']) return text -def checkDirectoryExists(dir): +def check_directory_exists(dir): """ Check a theme directory exists and if not create it ``dir`` Theme directory to make sure exists """ - log.debug(u'checkDirectoryExists') + log.debug(u'check_directory_exists') if not os.path.exists(dir): os.mkdir(dir) @@ -337,4 +337,4 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from baselistwithdnd import BaseListWithDnD +from baselistwithdnd import BaseListWithDnD \ No newline at end of file diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py index 9e0e7b387..dd7276a7d 100644 --- a/openlp/core/lib/displaytags.py +++ b/openlp/core/lib/displaytags.py @@ -29,57 +29,39 @@ Provide Html Tag management and Display Tag access class from openlp.core.lib import base_html_expands -class HtmlTags(object): - """ - """ - def __init__(self): - self.html_expands = [] - self.reset_list() - - def reset_list(self): - """ - """ - self.html_expands = [] - for html in base_html_expands: - self.html_expands.append(html) - - def add_tag(self, html): - """ - """ - self.html_expands.append(html) - - class DisplayTags(object): """ Static Class to HTML Tags to be access around the code the list is managed by the Options Tab. """ - html_tags = HtmlTags() + html_expands = [] @staticmethod def get_html_tags(): """ Provide access to the html_expands list. """ - return DisplayTags.html_tags.html_expands + return DisplayTags.html_expands @staticmethod def reset_html_tags(): """ Resets the html_expands list. """ - return DisplayTags.html_tags.reset_list() + DisplayTags.html_expands = [] + for html in base_html_expands: + DisplayTags.html_expands.append(html) @staticmethod def add_html_tag(tag): """ Add a new tag to the list """ - return DisplayTags.html_tags.add_tag(tag) + DisplayTags.html_expands.append(tag) @staticmethod def remove_html_tag(id): """ Removes amd individual html_expands list. """ - return DisplayTags.html_tags.html_expands.pop(id) + DisplayTags.html_expands.pop(id) diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 4b8a0bb80..30811e08b 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -88,7 +88,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit): popupMenu.insertMenu(popupMenu.actions()[0], spell_menu) tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Formatting Tags')) - for html in DisplayTags.get_html_tags().html_expands: + for html in DisplayTags.get_html_tags(): action = SpellAction( html[u'desc'], tagMenu) action.correct.connect(self.htmlTag) tagMenu.addAction(action) @@ -110,7 +110,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit): """ Replaces the selected text with word. """ - for html in DisplayTags.get_html_tags().html_expands: + for html in DisplayTags.get_html_tags(): if tag == html[u'desc']: cursor = self.textCursor() if self.textCursor().hasSelection(): @@ -158,4 +158,4 @@ class SpellAction(QtGui.QAction): def __init__(self, *args): QtGui.QAction.__init__(self, *args) self.triggered.connect(lambda x: self.correct.emit( - unicode(self.text()))) \ No newline at end of file + unicode(self.text()))) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index b200f0765..b27141079 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -57,7 +57,7 @@ class DisplayTagTab(SettingsTab): user_expands = QtCore.QSettings().value(u'displayTags/html_tags', QtCore.QVariant(u'')).toString() # cPickle only accepts str not unicode strings - user_tags = cPickle.loads(str(user_expands)) + user_tags = cPickle.loads(str(unicode(user_expands).encode(u'utf8'))) # If we have some user ones added them as well for t in user_tags: DisplayTags.add_html_tag(t) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 28257ffda..99e5f8d5e 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -36,7 +36,7 @@ from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.theme import Theme from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ build_icon, Receiver, SettingsManager, translate, check_item_selected, \ - BackgroundType, BackgroundGradientType, checkDirectoryExists + BackgroundType, BackgroundGradientType, check_directory_exists from openlp.core.utils import AppLocation, get_filesystem_encoding log = logging.getLogger(__name__) @@ -130,9 +130,9 @@ class ThemeManager(QtGui.QWidget): # Variables self.themelist = [] self.path = AppLocation.get_section_data_path(self.settingsSection) - checkDirectoryExists(self.path) + check_directory_exists(self.path) self.thumbPath = os.path.join(self.path, u'thumbnails') - checkDirectoryExists(self.thumbPath) + check_directory_exists(self.thumbPath) self.themeForm.path = self.path self.oldBackgroundImage = None # Last little bits of setting up @@ -492,7 +492,7 @@ class ThemeManager(QtGui.QWidget): theme_dir = None if osfile.endswith(os.path.sep): theme_dir = os.path.join(dir, osfile) - checkDirectoryExists(theme_dir) + check_directory_exists(theme_dir) else: fullpath = os.path.join(dir, osfile) names = osfile.split(os.path.sep) @@ -502,7 +502,7 @@ class ThemeManager(QtGui.QWidget): themename = names[0] if theme_dir is None: theme_dir = os.path.join(dir, names[0]) - checkDirectoryExists(theme_dir) + check_directory_exists(theme_dir) if os.path.splitext(ucsfile)[1].lower() in [u'.xml']: xml_data = zip.read(file) try: @@ -522,7 +522,7 @@ class ThemeManager(QtGui.QWidget): self.generateAndSaveImage(dir, themename, theme) else: Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', \ + u'title': translate('OpenLP.ThemeManager', 'Validation Error'), u'message':translate('OpenLP.ThemeManager', 'File is not a valid theme.')}) @@ -530,7 +530,7 @@ class ThemeManager(QtGui.QWidget): filename) except (IOError, NameError): Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', \ + u'title': translate('OpenLP.ThemeManager', 'Validation Error'), u'message':translate('OpenLP.ThemeManager', 'File is not a valid theme.')}) @@ -567,7 +567,7 @@ class ThemeManager(QtGui.QWidget): theme_dir = os.path.join(self.path, themeName) if os.path.exists(theme_dir): Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', \ + u'title': translate('OpenLP.ThemeManager', 'Validation Error'), u'message':translate('OpenLP.ThemeManager', 'A theme with this name already exists.')}) @@ -583,7 +583,7 @@ class ThemeManager(QtGui.QWidget): theme_pretty_xml = theme.extract_formatted_xml() log.debug(u'saveTheme %s %s', name, theme_pretty_xml) theme_dir = os.path.join(self.path, name) - checkDirectoryExists(theme_dir) + check_directory_exists(theme_dir) theme_file = os.path.join(theme_dir, name + u'.xml') if imageTo and self.oldBackgroundImage and \ imageTo != self.oldBackgroundImage: @@ -701,7 +701,7 @@ class ThemeManager(QtGui.QWidget): for plugin in self.parent.pluginManager.plugins: if plugin.usesTheme(theme): Receiver.send_message(u'openlp_error_message', { - u'title': translate('OpenLP.ThemeManager', \ + u'title': translate('OpenLP.ThemeManager', 'Validation Error'), u'message': unicode(translate('OpenLP.ThemeManager', 'Theme %s is used in the %s plugin.')) % \ @@ -765,4 +765,4 @@ class ThemeManager(QtGui.QWidget): vAlignCorrection = 2 newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_vertical_align = vAlignCorrection - return newtheme.extract_xml() + return newtheme.extract_xml() \ No newline at end of file diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 79a97c541..063a80d02 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ ItemCapabilities, SettingsManager, translate, check_item_selected, \ - Receiver, checkDirectoryExists + Receiver, check_directory_exists from openlp.core.utils import AppLocation, get_images_filter log = logging.getLogger(__name__) @@ -88,7 +88,7 @@ class ImageMediaItem(MediaManagerItem): self.servicePath = os.path.join( AppLocation.get_section_data_path(self.settingsSection), u'thumbnails') - checkDirectoryExists(self.servicePath) + check_directory_exists(self.servicePath) self.loadList(SettingsManager.load_list( self.settingsSection, self.settingsSection)) @@ -216,4 +216,4 @@ class ImageMediaItem(MediaManagerItem): 'the image file "%s" no longer exists.')) % filename}) def onPreviewClick(self): - MediaManagerItem.onPreviewClick(self) + MediaManagerItem.onPreviewClick(self) \ No newline at end of file From ee652c4142f0cde4a15e985373488cebd6638340 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 9 Jan 2011 08:47:48 +0000 Subject: [PATCH 36/43] Fix typing error --- openlp/core/lib/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index b6485b480..5a3fa41ce 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -177,7 +177,7 @@ class Plugin(QtCore.QObject): self.settingsSection + u'/status', QtCore.QVariant(self.status)) if new_status == PluginStatus.Active: self.initialise() - elif new_status == PluginStatus.InActive: + elif new_status == PluginStatus.Inactive: self.finalise() def isActive(self): @@ -318,4 +318,4 @@ class Plugin(QtCore.QObject): """ Called to define all translatable texts of the plugin """ - pass \ No newline at end of file + pass From c4891f27ed56f9005571874698b90f90cceb9e1d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 9 Jan 2011 13:54:40 +0000 Subject: [PATCH 37/43] Fix merge errors --- openlp/core/lib/__init__.py | 4 ++-- openlp/core/ui/displaytagtab.py | 16 ++++++++-------- openlp/core/ui/maindisplay.py | 1 - openlp/core/ui/settingsform.py | 6 +++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 730fee232..7ad377817 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -316,7 +316,7 @@ def check_directory_exists(dir): """ log.debug(u'check_directory_exists') if not os.path.exists(dir): - os.mkdir(dir) + os.makedirs(dir) from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ BackgroundType, HorizontalType, VerticalType @@ -338,4 +338,4 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from baselistwithdnd import BaseListWithDnD \ No newline at end of file +from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index b27141079..1feb74b48 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -166,14 +166,14 @@ class DisplayTagTab(SettingsTab): self.defaultPushButton.setText( translate('OpenLP.DisplayTagTab', 'Default')) self.newPushButton.setText(translate('OpenLP.DisplayTagTab', 'New')) - self.tagTableWidget.horizontalHeaderItem(0). \ - setText(translate('OpenLP.DisplayTagTab', 'Description')) - self.tagTableWidget.horizontalHeaderItem(1). \ - setText(translate('OpenLP.DisplayTagTab', 'Tag id')) - self.tagTableWidget.horizontalHeaderItem(2). \ - setText(translate('OpenLP.DisplayTagTab', 'Start Html')) - self.tagTableWidget.horizontalHeaderItem(3). \ - setText(translate('OpenLP.DisplayTagTab', 'End Html')) + self.tagTableWidget.horizontalHeaderItem(0)\ + .setText(translate('OpenLP.DisplayTagTab', 'Description')) + self.tagTableWidget.horizontalHeaderItem(1)\ + .setText(translate('OpenLP.DisplayTagTab', 'Tag id')) + self.tagTableWidget.horizontalHeaderItem(2)\ + .setText(translate('OpenLP.DisplayTagTab', 'Start Html')) + self.tagTableWidget.horizontalHeaderItem(3)\ + .setText(translate('OpenLP.DisplayTagTab', 'End Html')) QtCore.QMetaObject.connectSlotsByName(self.displayTagEdit) self.tagTableWidget.setColumnWidth(0, 120) self.tagTableWidget.setColumnWidth(1, 40) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 0396deedc..adc2cb5fa 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -105,7 +105,6 @@ class MainDisplay(DisplayWidget): self.hideMode = None mainIcon = build_icon(u':/icon/openlp-logo-16x16.png') self.setWindowIcon(mainIcon) - self.setWindowTitle(u'OpenLP Display') self.retranslateUi() self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setWindowFlags(QtCore.Qt.FramelessWindowHint | diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 2696e6329..afea928b6 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -55,9 +55,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): # Advanced tab self.advancedTab = AdvancedTab() self.addTab(u'Advanced', self.advancedTab) - # Edit Tags tab - displayTagTab = DisplayTagTab() - self.addTab(u'Display Tags', displayTagTab) + # Edit Display Tags tab + self.displayTagTab = DisplayTagTab() + self.addTab(u'Display Tags', self.displayTagTab) def addTab(self, name, tab): """ From ce2ca01eacecd30f42b88ddd5bdaee31ae70ea92 Mon Sep 17 00:00:00 2001 From: M2j Date: Sun, 9 Jan 2011 16:37:45 +0100 Subject: [PATCH 38/43] fixed layout problem for long bible names (or long presentation controller names) unified the linebreak in setSizePolicy() calls --- openlp/core/ui/servicemanager.py | 6 ++++-- openlp/core/ui/themestab.py | 4 ++-- openlp/plugins/bibles/lib/biblestab.py | 8 ++++---- openlp/plugins/bibles/lib/mediaitem.py | 16 ++++++++++++++++ openlp/plugins/presentations/lib/mediaitem.py | 6 ++++-- openlp/plugins/remotes/lib/remotetab.py | 4 ++-- openlp/plugins/songs/forms/editsongdialog.py | 18 ++++++++++-------- 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index a9bf232d4..e0e9093d9 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -145,8 +145,10 @@ class ServiceManager(QtGui.QWidget): self.themeComboBox = QtGui.QComboBox(self.toolbar) self.themeComboBox.setToolTip(translate('OpenLP.ServiceManager', 'Select a theme for the service')) - self.themeComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.themeComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) + self.themeComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.themeComboBox.setObjectName(u'themeComboBox') self.toolbar.addToolbarWidget(u'ThemeWidget', self.themeComboBox) self.toolbar.setObjectName(u'toolbar') diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 229650739..a440a564e 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -46,8 +46,8 @@ class ThemesTab(SettingsTab): self.DefaultComboBox = QtGui.QComboBox(self.GlobalGroupBox) self.DefaultComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.DefaultComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.DefaultComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.DefaultComboBox.setObjectName(u'DefaultComboBox') self.GlobalGroupBoxLayout.addWidget(self.DefaultComboBox) self.DefaultListView = QtGui.QLabel(self.GlobalGroupBox) diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index 0a2effa5e..f6bd27324 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -76,8 +76,8 @@ class BiblesTab(SettingsTab): self.BibleThemeComboBox = QtGui.QComboBox(self.VerseDisplayGroupBox) self.BibleThemeComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.BibleThemeComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.BibleThemeComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.BibleThemeComboBox.addItem(u'') self.BibleThemeComboBox.setObjectName(u'BibleThemeComboBox') self.VerseDisplayLayout.addRow(self.BibleThemeLabel, @@ -88,8 +88,8 @@ class BiblesTab(SettingsTab): self.VerseDisplayLayout.addRow(self.ChangeNoteLabel) self.leftLayout.addWidget(self.VerseDisplayGroupBox) self.leftLayout.addStretch() - self.rightColumn.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Preferred) + self.rightColumn.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) self.rightLayout.addStretch() # Signals and slots QtCore.QObject.connect( diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index a669a51be..d1c092eec 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -86,6 +86,8 @@ class BibleMediaItem(MediaManagerItem): self.quickVersionLabel = QtGui.QLabel(self.quickTab) self.quickVersionLabel.setObjectName(u'quickVersionLabel') self.quickVersionComboBox = QtGui.QComboBox(self.quickTab) + self.quickVersionComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.quickVersionComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.quickVersionComboBox.setObjectName(u'quickVersionComboBox') @@ -95,6 +97,8 @@ class BibleMediaItem(MediaManagerItem): self.quickSecondLabel = QtGui.QLabel(self.quickTab) self.quickSecondLabel.setObjectName(u'quickSecondLabel') self.quickSecondComboBox = QtGui.QComboBox(self.quickTab) + self.quickSecondComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.quickSecondComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.quickSecondComboBox.setObjectName(u'quickSecondComboBox') @@ -103,6 +107,8 @@ class BibleMediaItem(MediaManagerItem): self.quickSearchTypeLabel = QtGui.QLabel(self.quickTab) self.quickSearchTypeLabel.setObjectName(u'quickSearchTypeLabel') self.quickSearchComboBox = QtGui.QComboBox(self.quickTab) + self.quickSearchComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.quickSearchComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.quickSearchComboBox.setObjectName(u'quickSearchComboBox') @@ -118,6 +124,8 @@ class BibleMediaItem(MediaManagerItem): self.quickClearLabel = QtGui.QLabel(self.quickTab) self.quickClearLabel.setObjectName(u'quickClearLabel') self.quickClearComboBox = QtGui.QComboBox(self.quickTab) + self.quickClearComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.quickClearComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.quickClearComboBox.setObjectName(u'quickClearComboBox') @@ -144,6 +152,8 @@ class BibleMediaItem(MediaManagerItem): self.advancedLayout.addWidget(self.advancedVersionLabel, 0, 0, QtCore.Qt.AlignRight) self.advancedVersionComboBox = QtGui.QComboBox(self.advancedTab) + self.advancedVersionComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.advancedVersionComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.advancedVersionComboBox.setObjectName(u'advancedVersionComboBox') @@ -154,6 +164,8 @@ class BibleMediaItem(MediaManagerItem): self.advancedLayout.addWidget(self.advancedSecondLabel, 1, 0, QtCore.Qt.AlignRight) self.advancedSecondComboBox = QtGui.QComboBox(self.advancedTab) + self.advancedSecondComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.advancedSecondComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.advancedSecondComboBox.setObjectName(u'advancedSecondComboBox') @@ -164,6 +176,8 @@ class BibleMediaItem(MediaManagerItem): self.advancedLayout.addWidget(self.advancedBookLabel, 2, 0, QtCore.Qt.AlignRight) self.advancedBookComboBox = QtGui.QComboBox(self.advancedTab) + self.advancedBookComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.advancedBookComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.advancedBookComboBox.setObjectName(u'advancedBookComboBox') @@ -201,6 +215,8 @@ class BibleMediaItem(MediaManagerItem): self.advancedLayout.addWidget(self.advancedClearLabel, 6, 0, QtCore.Qt.AlignRight) self.advancedClearComboBox = QtGui.QComboBox(self.quickTab) + self.advancedClearComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) self.advancedClearComboBox.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.advancedClearComboBox.setObjectName(u'advancedClearComboBox') diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 3c27801c8..1e65a3358 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -116,8 +116,10 @@ class PresentationMediaItem(MediaManagerItem): self.displayTypeLabel = QtGui.QLabel(self.presentationWidget) self.displayTypeLabel.setObjectName(u'displayTypeLabel') self.displayTypeComboBox = QtGui.QComboBox(self.presentationWidget) - self.displayTypeComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.displayTypeComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) + self.displayTypeComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.displayTypeComboBox.setObjectName(u'displayTypeComboBox') self.displayTypeLabel.setBuddy(self.displayTypeComboBox) self.displayLayout.addRow(self.displayTypeLabel, diff --git a/openlp/plugins/remotes/lib/remotetab.py b/openlp/plugins/remotes/lib/remotetab.py index e97d33762..d06e69164 100644 --- a/openlp/plugins/remotes/lib/remotetab.py +++ b/openlp/plugins/remotes/lib/remotetab.py @@ -46,8 +46,8 @@ class RemoteTab(SettingsTab): self.addressLabel = QtGui.QLabel(self.serverSettingsGroupBox) self.addressLabel.setObjectName(u'addressLabel') self.addressEdit = QtGui.QLineEdit(self.serverSettingsGroupBox) - self.addressEdit.setSizePolicy(QtGui.QSizePolicy.Preferred, - QtGui.QSizePolicy.Fixed) + self.addressEdit.setSizePolicy( + QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) self.addressEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp( u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'), self)) self.addressEdit.setObjectName(u'addressEdit') diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index c0ccd5d6a..675108af7 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -114,8 +114,8 @@ class Ui_EditSongDialog(object): self.authorsComboBox = QtGui.QComboBox(self.authorsGroupBox) self.authorsComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.authorsComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.authorsComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.authorsComboBox.setEditable(True) self.authorsComboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) self.authorsComboBox.setObjectName(u'authorsComboBox') @@ -155,8 +155,8 @@ class Ui_EditSongDialog(object): self.topicsComboBox = QtGui.QComboBox(self.topicsGroupBox) self.topicsComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.topicsComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.topicsComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.topicsComboBox.setEditable(True) self.topicsComboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) self.topicsComboBox.setObjectName(u'topicsComboBox') @@ -184,8 +184,10 @@ class Ui_EditSongDialog(object): self.songBookNameLabel = QtGui.QLabel(self.songBookGroupBox) self.songBookNameLabel.setObjectName(u'songBookNameLabel') self.songBookComboBox = QtGui.QComboBox(self.songBookGroupBox) - self.songBookComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.songBookComboBox.setSizeAdjustPolicy( + QtGui.QComboBox.AdjustToMinimumContentsLength) + self.songBookComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.songBookComboBox.setEditable(True) self.songBookComboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) self.songBookComboBox.setObjectName(u'songBookComboBox') @@ -216,8 +218,8 @@ class Ui_EditSongDialog(object): self.themeComboBox = QtGui.QComboBox(self.themeGroupBox) self.themeComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToMinimumContentsLength) - self.themeComboBox.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) + self.themeComboBox.setSizePolicy( + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) self.themeComboBox.setEditable(True) self.themeComboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) self.themeComboBox.setObjectName(u'themeComboBox') From ce1241aa0f9528cd06d0e1045e1f31f3e5b4b560 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 9 Jan 2011 17:52:31 +0100 Subject: [PATCH 39/43] merged classes together --- openlp/plugins/songs/forms/editsongform.py | 8 +- openlp/plugins/songs/lib/__init__.py | 3 +- openlp/plugins/songs/lib/mediaitem.py | 14 +- openlp/plugins/songs/lib/openlyricsimport.py | 6 +- openlp/plugins/songs/lib/songimport.py | 4 +- openlp/plugins/songs/lib/xml.py | 314 ++++++------------- openlp/plugins/songs/songsplugin.py | 4 +- 7 files changed, 109 insertions(+), 244 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 202cc43fe..86249f024 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib import SongXMLBuilder, SongXMLParser, VerseType +from openlp.plugins.songs.lib import SongXML, VerseType from openlp.plugins.songs.lib.db import Book, Song, Author, Topic from editsongdialog import Ui_EditSongDialog @@ -263,8 +263,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if isinstance(self.song.lyrics, buffer): self.song.lyrics = unicode(self.song.lyrics) if self.song.lyrics.startswith(u' - + @@ -71,32 +71,26 @@ from openlp.plugins.songs.lib.db import Author, Book, Song, Topic log = logging.getLogger(__name__) -class SongXMLBuilder(object): +class SongXML(object): """ - This class builds the XML used to describe songs. + This class builds and parses the XML used to describe songs. """ - log.info(u'SongXMLBuilder Loaded') + log.info(u'SongXML Loaded') - def __init__(self, song_language=None): + def __init__(self): """ - Set up the song builder. - - ``song_language`` - The language used in this song + Set up the default variables. """ - lang = u'en' - if song_language: - lang = song_language self.song_xml = objectify.fromstring(u'') - self.lyrics = etree.SubElement(self.song_xml, u'lyrics', language=lang) + self.lyrics = etree.SubElement(self.song_xml, u'lyrics') def add_verse_to_lyrics(self, type, number, content): """ - Add a verse to the ```` tag. + Add a verse to the ** tag. ``type`` - A string denoting the type of verse. Possible values are "Chorus", - "Verse", "Bridge", and "Custom". + A string denoting the type of verse. Possible values are "V", + "C", "B", "P", "I", "E" and "O". ``number`` An integer denoting the number of the item, for example: verse 1. @@ -109,13 +103,6 @@ class SongXMLBuilder(object): verse.text = etree.CDATA(content) self.lyrics.append(verse) - def dump_xml(self): - """ - Debugging aid to dump XML so that we can see what we have. - """ - return etree.tostring(self.song_xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=True) - def extract_xml(self): """ Extract our newly created XML song. @@ -123,16 +110,10 @@ class SongXMLBuilder(object): return etree.tostring(self.song_xml, encoding=u'UTF-8', xml_declaration=True) - -class SongXMLParser(object): - """ - A class to read in and parse a song's XML. - """ - log.info(u'SongXMLParser Loaded') - - def __init__(self, xml): + def get_verses(self, xml): """ - Set up our song XML parser. + Iterates through the verses in the XML and returns a list of verses + and their attributes. ``xml`` The XML of the song to be parsed. @@ -144,12 +125,6 @@ class SongXMLParser(object): self.song_xml = objectify.fromstring(xml) except etree.XMLSyntaxError: log.exception(u'Invalid xml %s', xml) - - def get_verses(self): - """ - Iterates through the verses in the XML and returns a list of verses - and their attributes. - """ xml_iter = self.song_xml.getiterator() verse_list = [] for element in xml_iter: @@ -166,191 +141,9 @@ class SongXMLParser(object): return etree.dump(self.song_xml) -#class LyricsXML(object): -# """ -# This class represents the XML in the ``lyrics`` field of a song. -# """ -# def __init__(self, song=None): -# if song: -# if song.lyrics.startswith(u'' % \ -# (verse[u'type'], verse[u'label'], verse[u'text']) -# lyrics_output = lyrics_output + \ -# u'%s' % \ -# (language[u'language'], verse_output) -# song_output = u'' + \ -# u'%s' % lyrics_output -# return song_output - - -class OpenLyricsBuilder(object): +class OpenLyrics(object): """ - This class represents the converter for song to OpenLyrics XML. - """ - def __init__(self, manager): - self.manager = manager - - def song_to_xml(self, song, pretty_print=False): - """ - Convert the song to OpenLyrics Format. - """ - song_xml_parser = SongXMLParser(song.lyrics) - verse_list = song_xml_parser.get_verses() - song_xml = objectify.fromstring( - u'') - properties = etree.SubElement(song_xml, u'properties') - titles = etree.SubElement(properties, u'titles') - self._add_text_to_element(u'title', titles, song.title) - if song.alternate_title: - self._add_text_to_element(u'title', titles, song.alternate_title) - if song.comments: - comments = etree.SubElement(properties, u'comments') - self._add_text_to_element(u'comment', comments, song.comments) - if song.copyright: - self._add_text_to_element(u'copyright', properties, song.copyright) - if song.verse_order: - self._add_text_to_element( - u'verseOrder', properties, song.verse_order) - if song.ccli_number: - self._add_text_to_element(u'ccliNo', properties, song.ccli_number) - if song.authors: - authors = etree.SubElement(properties, u'authors') - for author in song.authors: - self._add_text_to_element( - u'author', authors, author.display_name) - book = self.manager.get_object_filtered( - Book, Book.id == song.song_book_id) - if book is not None: - book = book.name - songbooks = etree.SubElement(properties, u'songbooks') - element = self._add_text_to_element( - u'songbook', songbooks, None, book) - element.set(u'entry', song.song_number) - if song.topics: - themes = etree.SubElement(properties, u'themes') - for topic in song.topics: - self._add_text_to_element(u'theme', themes, topic.name) - lyrics = etree.SubElement(song_xml, u'lyrics') - for verse in verse_list: - verse_tag = u'%s%s' % ( - verse[0][u'type'][0].lower(), verse[0][u'label']) - element = \ - self._add_text_to_element(u'verse', lyrics, None, verse_tag) - element = self._add_text_to_element(u'lines', element) - for line in unicode(verse[1]).split(u'\n'): - self._add_text_to_element(u'line', element, line) - return self._extract_xml(song_xml, pretty_print) - - def _add_text_to_element(self, tag, parent, text=None, label=None): - if label: - element = etree.Element(tag, name=unicode(label)) - else: - element = etree.Element(tag) - if text: - element.text = unicode(text) - parent.append(element) - return element - - def _extract_xml(self, xml, pretty_print): - """ - Extract our newly created XML song. - """ - return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=pretty_print) - - def _dump_xml(self, xml): - """ - Debugging aid to dump XML so that we can see what we have. - """ - return etree.tostring(xml, encoding=u'UTF-8', - xml_declaration=True, pretty_print=True) - - -class OpenLyricsParser(object): - """ - This class represents the converter for OpenLyrics XML to a song. + This class represents the converter for OpenLyrics XML to/from a song. As OpenLyrics has a rich set of different features, we cannot support them all. The following features are supported by the :class:`OpenLyricsParser`:: @@ -410,6 +203,57 @@ class OpenLyricsParser(object): def __init__(self, manager): self.manager = manager + def song_to_xml(self, song, pretty_print=False): + """ + Convert the song to OpenLyrics Format. + """ + sxml = SongXML() + verse_list = sxml.get_verses(song.lyrics) + song_xml = objectify.fromstring( + u'') + properties = etree.SubElement(song_xml, u'properties') + titles = etree.SubElement(properties, u'titles') + self._add_text_to_element(u'title', titles, song.title) + if song.alternate_title: + self._add_text_to_element(u'title', titles, song.alternate_title) + if song.comments: + comments = etree.SubElement(properties, u'comments') + self._add_text_to_element(u'comment', comments, song.comments) + if song.copyright: + self._add_text_to_element(u'copyright', properties, song.copyright) + if song.verse_order: + self._add_text_to_element( + u'verseOrder', properties, song.verse_order) + if song.ccli_number: + self._add_text_to_element(u'ccliNo', properties, song.ccli_number) + if song.authors: + authors = etree.SubElement(properties, u'authors') + for author in song.authors: + self._add_text_to_element( + u'author', authors, author.display_name) + book = self.manager.get_object_filtered( + Book, Book.id == song.song_book_id) + if book is not None: + book = book.name + songbooks = etree.SubElement(properties, u'songbooks') + element = self._add_text_to_element( + u'songbook', songbooks, None, book) + element.set(u'entry', song.song_number) + if song.topics: + themes = etree.SubElement(properties, u'themes') + for topic in song.topics: + self._add_text_to_element(u'theme', themes, topic.name) + lyrics = etree.SubElement(song_xml, u'lyrics') + for verse in verse_list: + verse_tag = u'%s%s' % ( + verse[0][u'type'][0].lower(), verse[0][u'label']) + element = \ + self._add_text_to_element(u'verse', lyrics, None, verse_tag) + element = self._add_text_to_element(u'lines', element) + for line in unicode(verse[1]).split(u'\n'): + self._add_text_to_element(u'line', element, line) + return self._extract_xml(song_xml, pretty_print) + def xml_to_song(self, xml): """ Create and save a song from OpenLyrics format xml to the database. Since @@ -441,6 +285,23 @@ class OpenLyricsParser(object): self.manager.save_object(song) return song.id + def _add_text_to_element(self, tag, parent, text=None, label=None): + if label: + element = etree.Element(tag, name=unicode(label)) + else: + element = etree.Element(tag) + if text: + element.text = unicode(text) + parent.append(element) + return element + + def _extract_xml(self, xml, pretty_print): + """ + Extract our newly created XML song. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True, pretty_print=pretty_print) + def _get(self, element, attribute): """ This returns the element's attribute as unicode string. @@ -562,7 +423,7 @@ class OpenLyricsParser(object): ``song`` The song object. """ - sxml = SongXMLBuilder() + sxml = SongXML() search_text = u'' temp_verse_order = [] for verse in lyrics.verse: @@ -682,3 +543,10 @@ class OpenLyricsParser(object): song.topics.append(topic) except AttributeError: pass + + def _dump_xml(self, xml): + """ + Debugging aid to dump XML so that we can see what we have. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True, pretty_print=True) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 545497acb..17e609fd4 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager -from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXMLParser +from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.importer import SongFormat @@ -153,7 +153,7 @@ class SongsPlugin(Plugin): song.search_title = self.whitespace.sub(u' ', song.title.lower() + \ u' ' + song.alternate_title.lower()) lyrics = u'' - verses = SongXMLParser(song.lyrics).get_verses() + verses = SongXML().get_verses(song.lyrics) for verse in verses: lyrics = lyrics + self.whitespace.sub(u' ', verse[1]) + u' ' song.search_lyrics = lyrics.lower() From 62794614f91682fd87b2db82963433ce2f09d425 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 9 Jan 2011 18:07:17 +0100 Subject: [PATCH 40/43] clean ups --- openlp/core/ui/__init__.py | 4 ++-- openlp/plugins/songs/lib/xml.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index ca2123c87..c509fe023 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -35,11 +35,11 @@ class HideMode(object): ``Blank`` This mode is used to hide all output, specifically by covering the display with a black screen. - + ``Theme`` This mode is used to hide all output, but covers the display with the current theme background, as opposed to black. - + ``Desktop`` This mode hides all output by minimising the display, leaving the user's desktop showing. diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 463e30d87..753383af3 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -269,7 +269,7 @@ class OpenLyrics(object): song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) properties = song_xml.properties From 39ff8e2bc45118d4a779bcc74029d2ec0c07ddd9 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 9 Jan 2011 17:17:42 +0000 Subject: [PATCH 41/43] Fix first time initialiation --- openlp/core/ui/displaytagtab.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagtab.py index 1feb74b48..3d6cd813d 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagtab.py @@ -57,10 +57,12 @@ class DisplayTagTab(SettingsTab): user_expands = QtCore.QSettings().value(u'displayTags/html_tags', QtCore.QVariant(u'')).toString() # cPickle only accepts str not unicode strings - user_tags = cPickle.loads(str(unicode(user_expands).encode(u'utf8'))) - # If we have some user ones added them as well - for t in user_tags: - DisplayTags.add_html_tag(t) + user_expands_string = str(unicode(user_expands).encode(u'utf8')) + if user_expands_string: + user_tags = cPickle.loads(user_expand_string) + # If we have some user ones added them as well + for t in user_tags: + DisplayTags.add_html_tag(t) self.selected = -1 def setupUi(self): From 29f3025d426182ddcdc3624193ad86f25dd58543 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 9 Jan 2011 18:51:06 +0000 Subject: [PATCH 42/43] Fix test --- openlp/core/ui/themeform.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index a6e925707..0155c6a4c 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -291,7 +291,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.updateThemeAllowed = True self.themeNameLabel.setVisible(not edit) self.themeNameEdit.setVisible(not edit) - self.edit = edit + self.edit_mode = edit if edit: self.setWindowTitle(unicode(translate('OpenLP.ThemeWizard', 'Edit Theme - %s')) % self.theme.theme_name) @@ -590,8 +590,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): os.path.split(unicode(self.theme.background_filename))[1] saveTo = os.path.join(self.path, self.theme.theme_name, filename) saveFrom = self.theme.background_filename - if not self.edit: - if not self.thememanager.checkIfThemeExists(self.theme.theme_name): + if not self.edit_mode and \ + not self.thememanager.checkIfThemeExists(self.theme.theme_name): return self.accepted = True self.thememanager.saveTheme(self.theme, saveFrom, saveTo) From b52d0aafd5da669a9ee5436663e18e0558a0bbd5 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 9 Jan 2011 20:18:08 +0100 Subject: [PATCH 43/43] re.compile code from reindex tool --- openlp/plugins/songs/lib/mediaitem.py | 7 +++---- openlp/plugins/songs/lib/xml.py | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 3f3755d14..73c8eaa10 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -351,8 +351,7 @@ class SongMediaItem(MediaManagerItem): service_item.theme = song.theme_name service_item.edit_id = item_id if song.lyrics.startswith(u'') properties = etree.SubElement(song_xml, u'properties') titles = etree.SubElement(properties, u'titles') - self._add_text_to_element(u'title', titles, song.title) + self._add_text_to_element(u'title', titles, song.title.strip()) if song.alternate_title: - self._add_text_to_element(u'title', titles, song.alternate_title) + self._add_text_to_element( + u'title', titles, song.alternate_title.strip()) if song.comments: comments = etree.SubElement(properties, u'comments') self._add_text_to_element(u'comment', comments, song.comments)