This time with changes sorry.

bzr-revno: 1200
This commit is contained in:
Tim Bentley 2011-01-09 19:13:38 +00:00
commit 32b93290a7
19 changed files with 933 additions and 297 deletions

View File

@ -34,7 +34,7 @@ from subprocess import Popen, PIPE
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver from openlp.core.lib import Receiver, check_directory_exists
from openlp.core.resources import qInitResources from openlp.core.resources import qInitResources
from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.mainwindow import MainWindow
from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui.exceptionform import ExceptionForm
@ -150,16 +150,16 @@ class OpenLP(QtGui.QApplication):
log.info(u'Openlp version %s' % app_version[u'version']) log.info(u'Openlp version %s' % app_version[u'version'])
return app_version return app_version
def notify(self, obj, evt): # def notify(self, obj, evt):
#TODO needed for presentation exceptions # #TODO needed for presentation exceptions
return QtGui.QApplication.notify(self, obj, evt) # return QtGui.QApplication.notify(self, obj, evt)
def run(self): def run(self):
""" """
Run the OpenLP application. Run the OpenLP application.
""" """
app_version = self._get_version() 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.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents) QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -216,7 +216,7 @@ class OpenLP(QtGui.QApplication):
def setNormalCursor(self): def setNormalCursor(self):
""" """
Sets the Normal Cursor forthe Application Sets the Normal Cursor for the Application
""" """
self.restoreOverrideCursor() self.restoreOverrideCursor()
@ -243,8 +243,7 @@ def main():
help='Set the Qt4 style (passed directly to Qt4).') help='Set the Qt4 style (passed directly to Qt4).')
# Set up logging # Set up logging
log_path = AppLocation.get_directory(AppLocation.CacheDir) log_path = AppLocation.get_directory(AppLocation.CacheDir)
if not os.path.exists(log_path): check_directory_exists(log_path)
os.makedirs(log_path)
filename = os.path.join(log_path, u'openlp.log') filename = os.path.join(log_path, u'openlp.log')
logfile = logging.FileHandler(filename, u'w') logfile = logging.FileHandler(filename, u'w')
logfile.setFormatter(logging.Formatter( logfile.setFormatter(logging.Formatter(
@ -281,4 +280,4 @@ if __name__ == u'__main__':
""" """
Instantiate and run the application. Instantiate and run the application.
""" """
main() main()

View File

@ -35,52 +35,51 @@ from PyQt4 import QtCore, QtGui
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# TODO make external and configurable in alpha 4 via a settings dialog base_html_expands = []
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'<span style="-webkit-text-fill-color:red">', u'start html': u'<span style="-webkit-text-fill-color:red">',
u'end tag': u'{/r}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/r}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Black', u'start tag': u'{b}', base_html_expands.append({u'desc': u'Black', u'start tag': u'{b}',
u'start html': u'<span style="-webkit-text-fill-color:black">', u'start html': u'<span style="-webkit-text-fill-color:black">',
u'end tag': u'{/b}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/b}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}', base_html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}',
u'start html': u'<span style="-webkit-text-fill-color:blue">', u'start html': u'<span style="-webkit-text-fill-color:blue">',
u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}', base_html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}',
u'start html': u'<span style="-webkit-text-fill-color:yellow">', u'start html': u'<span style="-webkit-text-fill-color:yellow">',
u'end tag': u'{/y}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/y}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Green', u'start tag': u'{g}', base_html_expands.append({u'desc': u'Green', u'start tag': u'{g}',
u'start html': u'<span style="-webkit-text-fill-color:green">', u'start html': u'<span style="-webkit-text-fill-color:green">',
u'end tag': u'{/g}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/g}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}', base_html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}',
u'start html': u'<span style="-webkit-text-fill-color:#CC33CC">', u'start html': u'<span style="-webkit-text-fill-color:#CC33CC">',
u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Orange', u'start tag': u'{o}', base_html_expands.append({u'desc': u'Orange', u'start tag': u'{o}',
u'start html': u'<span style="-webkit-text-fill-color:#CC0033">', u'start html': u'<span style="-webkit-text-fill-color:#CC0033">',
u'end tag': u'{/o}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/o}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}', base_html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}',
u'start html': u'<span style="-webkit-text-fill-color:#9900FF">', u'start html': u'<span style="-webkit-text-fill-color:#9900FF">',
u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'White', u'start tag': u'{w}', base_html_expands.append({u'desc': u'White', u'start tag': u'{w}',
u'start html': u'<span style="-webkit-text-fill-color:white">', u'start html': u'<span style="-webkit-text-fill-color:white">',
u'end tag': u'{/w}', u'end html': u'</span>', u'protected': False}) u'end tag': u'{/w}', u'end html': u'</span>', u'protected': True})
html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}', base_html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}',
u'start html': u'<sup>', u'end tag': u'{/su}', u'end html': u'</sup>', u'start html': u'<sup>', u'end tag': u'{/su}', u'end html': u'</sup>',
u'protected': True}) 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'<sub>', u'end tag': u'{/sb}', u'end html': u'</sub>', u'start html': u'<sub>', u'end tag': u'{/sb}', u'end html': u'</sub>',
u'protected': True}) 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'<p>', u'end tag': u'{/p}', u'end html': u'</p>', u'start html': u'<p>', u'end tag': u'{/p}', u'end html': u'</p>',
u'protected': True}) 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'<strong>', u'end tag': u'{/st}', u'end html': u'</strong>', u'start html': u'<strong>', u'end tag': u'{/st}', u'end html': u'</strong>',
u'protected': True}) 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'<em>', u'end tag': u'{/it}', u'end html': u'</em>', u'start html': u'<em>', u'end tag': u'{/it}', u'end html': u'</em>',
u'protected': True}) 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'<span style="text-decoration: underline;">', u'start html': u'<span style="text-decoration: underline;">',
u'end tag': u'{/u}', u'end html': u'</span>', u'protected': True}) u'end tag': u'{/u}', u'end html': u'</span>', u'protected': True})
@ -294,7 +293,7 @@ def clean_tags(text):
Remove Tags from text for display Remove Tags from text for display
""" """
text = text.replace(u'<br>', u'\n') text = text.replace(u'<br>', u'\n')
for tag in html_expands: for tag in DisplayTags.get_html_tags():
text = text.replace(tag[u'start tag'], u'') text = text.replace(tag[u'start tag'], u'')
text = text.replace(tag[u'end tag'], u'') text = text.replace(tag[u'end tag'], u'')
return text return text
@ -303,13 +302,25 @@ def expand_tags(text):
""" """
Expand tags HTML for display Expand tags HTML for display
""" """
for tag in 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'start tag'], tag[u'start html'])
text = text.replace(tag[u'end tag'], tag[u'end html']) text = text.replace(tag[u'end tag'], tag[u'end html'])
return text return text
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'check_directory_exists')
if not os.path.exists(dir):
os.makedirs(dir)
from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \
BackgroundType, HorizontalType, VerticalType BackgroundType, HorizontalType, VerticalType
from displaytags import DisplayTags
from spelltextedit import SpellTextEdit from spelltextedit import SpellTextEdit
from eventreceiver import Receiver from eventreceiver import Receiver
from imagemanager import ImageManager from imagemanager import ImageManager

View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-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 #
# --------------------------------------------------------------------------- #
# 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 DisplayTags(object):
"""
Static Class to HTML Tags to be access around the code the list is managed
by the Options Tab.
"""
html_expands = []
@staticmethod
def get_html_tags():
"""
Provide access to the html_expands list.
"""
return DisplayTags.html_expands
@staticmethod
def reset_html_tags():
"""
Resets the html_expands 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
"""
DisplayTags.html_expands.append(tag)
@staticmethod
def remove_html_tag(id):
"""
Removes amd individual html_expands list.
"""
DisplayTags.html_expands.pop(id)

View File

@ -175,6 +175,10 @@ class Plugin(QtCore.QObject):
self.status = new_status self.status = new_status
QtCore.QSettings().setValue( QtCore.QSettings().setValue(
self.settingsSection + u'/status', QtCore.QVariant(self.status)) 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): def isActive(self):
""" """
@ -314,4 +318,4 @@ class Plugin(QtCore.QObject):
""" """
Called to define all translatable texts of the plugin Called to define all translatable texts of the plugin
""" """
pass pass

View File

@ -114,6 +114,12 @@ class SettingsTab(QtGui.QWidget):
""" """
pass pass
def cancel(self):
"""
Reset any settings
"""
pass
def postSetUp(self, postUpdate=False): def postSetUp(self, postUpdate=False):
""" """
Changes which need to be made after setup of application Changes which need to be made after setup of application

View File

@ -36,7 +36,7 @@ except ImportError:
# http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check # http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import html_expands, translate from openlp.core.lib import translate, DisplayTags
class SpellTextEdit(QtGui.QPlainTextEdit): class SpellTextEdit(QtGui.QPlainTextEdit):
""" """
@ -88,7 +88,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
popupMenu.insertMenu(popupMenu.actions()[0], spell_menu) popupMenu.insertMenu(popupMenu.actions()[0], spell_menu)
tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
'Formatting Tags')) 'Formatting Tags'))
for html in html_expands: for html in DisplayTags.get_html_tags():
action = SpellAction( html[u'desc'], tagMenu) action = SpellAction( html[u'desc'], tagMenu)
action.correct.connect(self.htmlTag) action.correct.connect(self.htmlTag)
tagMenu.addAction(action) tagMenu.addAction(action)
@ -110,7 +110,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
""" """
Replaces the selected text with word. Replaces the selected text with word.
""" """
for html in html_expands: for html in DisplayTags.get_html_tags():
if tag == html[u'desc']: if tag == html[u'desc']:
cursor = self.textCursor() cursor = self.textCursor()
if self.textCursor().hasSelection(): if self.textCursor().hasSelection():
@ -158,4 +158,4 @@ class SpellAction(QtGui.QAction):
def __init__(self, *args): def __init__(self, *args):
QtGui.QAction.__init__(self, *args) QtGui.QAction.__init__(self, *args)
self.triggered.connect(lambda x: self.correct.emit( self.triggered.connect(lambda x: self.correct.emit(
unicode(self.text()))) unicode(self.text())))

View File

@ -598,4 +598,4 @@ class ThemeXML(object):
self.font_footer_shadow_size) self.font_footer_shadow_size)
self.add_display(self.display_horizontal_align, self.add_display(self.display_horizontal_align,
self.display_vertical_align, self.display_vertical_align,
self.display_slide_transition) self.display_slide_transition)

View File

@ -59,6 +59,7 @@ from splashscreen import SplashScreen
from generaltab import GeneralTab from generaltab import GeneralTab
from themestab import ThemesTab from themestab import ThemesTab
from advancedtab import AdvancedTab from advancedtab import AdvancedTab
from displaytagtab import DisplayTagTab
from aboutform import AboutForm from aboutform import AboutForm
from pluginform import PluginForm from pluginform import PluginForm
from settingsform import SettingsForm from settingsform import SettingsForm

View File

@ -0,0 +1,350 @@
# -*- 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-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 #
# --------------------------------------------------------------------------- #
# 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 resizeEvent(self, event=None):
pass
def preLoad(self):
"""
Initialise values before the Load takes place
"""
# Create initial copy from master
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_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):
'''
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, 650, 181))
self.editGroupBox.setObjectName(u'editGroupBox')
self.updatePushButton = QtGui.QPushButton(self.editGroupBox)
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(5, 20, 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(430, 188, 71, 26))
self.defaultPushButton.setObjectName(u'updatePushButton')
self.deletePushButton = QtGui.QPushButton(self.displayTagEdit)
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(600, 188, 71, 26))
self.newPushButton.setObjectName(u'newPushButton')
self.tagTableWidget = QtGui.QTableWidget(self.displayTagEdit)
self.tagTableWidget.setGeometry(QtCore.QRect(10, 10, 650, 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, 240)
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()):
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():
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()[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():
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
tag = {u'desc': u'New Item', u'start tag': u'{n}',
u'start html': u'<Html_here>', u'end tag': u'{/n}',
u'end html': u'</and here>', u'protected': False}
DisplayTags.add_html_tag(tag)
self._resetTable()
# Highlight new row
self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1)
def onDefaultPushed(self):
"""
Remove all Custom Tags and reset to base set only.
"""
DisplayTags.reset_html_tags()
self._resetTable()
def onDeletePushed(self):
"""
Delete selected custom tag.
"""
if self.selected != -1:
DisplayTags.remove_html_tag(self.selected)
self.selected = -1
self._resetTable()
def onUpdatePushed(self):
"""
Update Custom Tag details if not duplicate.
"""
html_expands = DisplayTags.get_html_tags()
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

View File

@ -32,7 +32,8 @@ from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.phonon import Phonon 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, \
translate build_icon, translate
from openlp.core.ui import HideMode from openlp.core.ui import HideMode
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -102,6 +103,8 @@ class MainDisplay(DisplayWidget):
self.isLive = live self.isLive = live
self.alertTab = None self.alertTab = None
self.hideMode = None self.hideMode = None
mainIcon = build_icon(u':/icon/openlp-logo-16x16.png')
self.setWindowIcon(mainIcon)
self.retranslateUi() self.retranslateUi()
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | self.setWindowFlags(QtCore.Qt.FramelessWindowHint |

View File

@ -126,10 +126,8 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
return return
if status == 0: if status == 0:
self.activePlugin.toggleStatus(PluginStatus.Active) self.activePlugin.toggleStatus(PluginStatus.Active)
self.activePlugin.initialise()
else: else:
self.activePlugin.toggleStatus(PluginStatus.Inactive) self.activePlugin.toggleStatus(PluginStatus.Inactive)
self.activePlugin.finalise()
status_text = unicode( status_text = unicode(
translate('OpenLP.PluginForm', '%s (Inactive)')) translate('OpenLP.PluginForm', '%s (Inactive)'))
if self.activePlugin.status == PluginStatus.Active: if self.activePlugin.status == PluginStatus.Active:

View File

@ -250,7 +250,7 @@ class ServiceManager(QtGui.QWidget):
self.parent.serviceSettingsSection + u'/service theme', self.parent.serviceSettingsSection + u'/service theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
self.servicePath = AppLocation.get_section_data_path(u'servicemanager') 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.dndMenu = QtGui.QMenu()
self.newAction = self.dndMenu.addAction( self.newAction = self.dndMenu.addAction(
translate('OpenLP.ServiceManager', '&Add New Item')) translate('OpenLP.ServiceManager', '&Add New Item'))

View File

@ -31,7 +31,7 @@ from openlp.core.lib import translate, build_icon
class Ui_SettingsDialog(object): class Ui_SettingsDialog(object):
def setupUi(self, settingsDialog): def setupUi(self, settingsDialog):
settingsDialog.setObjectName(u'settingsDialog') settingsDialog.setObjectName(u'settingsDialog')
settingsDialog.resize(700, 300) settingsDialog.resize(700, 500)
settingsDialog.setWindowIcon( settingsDialog.setWindowIcon(
build_icon(u':/system/system_settings.png')) build_icon(u':/system/system_settings.png'))
self.settingsLayout = QtGui.QVBoxLayout(settingsDialog) self.settingsLayout = QtGui.QVBoxLayout(settingsDialog)

View File

@ -31,7 +31,7 @@ import logging
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Receiver 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 from settingsdialog import Ui_SettingsDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -55,6 +55,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
# Advanced tab # Advanced tab
self.advancedTab = AdvancedTab() self.advancedTab = AdvancedTab()
self.addTab(u'Advanced', self.advancedTab) self.addTab(u'Advanced', self.advancedTab)
# Edit Display Tags tab
self.displayTagTab = DisplayTagTab()
self.addTab(u'Display Tags', self.displayTagTab)
def addTab(self, name, tab): 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 Add a tab to the form at a specific location
""" """
log.debug(u'Inserting %s tab' % tab.tabTitle) 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( self.settingsTabWidget.insertTab(
location + 14, tab, tab.tabTitleVisible) location + 15, tab, tab.tabTitleVisible)
def removeTab(self, tab): def removeTab(self, tab):
""" """
@ -93,6 +96,14 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
Receiver.send_message(u'config_updated') Receiver.send_message(u'config_updated')
return QtGui.QDialog.accept(self) 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): def postSetUp(self):
""" """
Run any post-setup code for the tabs on the form Run any post-setup code for the tabs on the form

View File

@ -291,9 +291,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.updateThemeAllowed = True self.updateThemeAllowed = True
self.themeNameLabel.setVisible(not edit) self.themeNameLabel.setVisible(not edit)
self.themeNameEdit.setVisible(not edit) self.themeNameEdit.setVisible(not edit)
self.edit_mode = edit
if edit: if edit:
self.setWindowTitle(unicode(translate('OpenLP.ThemeWizard', self.setWindowTitle(unicode(translate('OpenLP.ThemeWizard',
'Edit Theme %s')) % self.theme.theme_name) 'Edit Theme - %s')) % self.theme.theme_name)
self.next() self.next()
else: else:
self.setWindowTitle(translate('OpenLP.ThemeWizard', 'New Theme')) self.setWindowTitle(translate('OpenLP.ThemeWizard', 'New Theme'))
@ -581,7 +582,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
(QtGui.QMessageBox.Ok), (QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok) QtGui.QMessageBox.Ok)
return return
self.accepted = True
saveFrom = None saveFrom = None
saveTo = None saveTo = None
if self.theme.background_type == \ if self.theme.background_type == \
@ -590,8 +590,12 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
os.path.split(unicode(self.theme.background_filename))[1] os.path.split(unicode(self.theme.background_filename))[1]
saveTo = os.path.join(self.path, self.theme.theme_name, filename) saveTo = os.path.join(self.path, self.theme.theme_name, filename)
saveFrom = self.theme.background_filename saveFrom = self.theme.background_filename
if self.thememanager.saveTheme(self.theme, saveFrom, saveTo): if not self.edit_mode and \
return QtGui.QDialog.accept(self) 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): def _colorButton(self, field):
""" """

View File

@ -36,7 +36,7 @@ from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \
build_icon, Receiver, SettingsManager, translate, check_item_selected, \ build_icon, Receiver, SettingsManager, translate, check_item_selected, \
BackgroundType, BackgroundGradientType BackgroundType, BackgroundGradientType, check_directory_exists
from openlp.core.utils import AppLocation, get_filesystem_encoding from openlp.core.utils import AppLocation, get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -119,27 +119,38 @@ class ThemeManager(QtGui.QWidget):
self.exportAction = self.menu.addAction( self.exportAction = self.menu.addAction(
translate('OpenLP.ThemeManager', '&Export Theme')) translate('OpenLP.ThemeManager', '&Export Theme'))
self.exportAction.setIcon(build_icon(u':/general/general_export.png')) self.exportAction.setIcon(build_icon(u':/general/general_export.png'))
#Signals # Signals
QtCore.QObject.connect(self.themeListWidget, QtCore.QObject.connect(self.themeListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.changeGlobalFromScreen) self.changeGlobalFromScreen)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_global'), self.changeGlobalFromTab) 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.themelist = []
self.path = AppLocation.get_section_data_path(self.settingsSection) self.path = AppLocation.get_section_data_path(self.settingsSection)
self.checkThemesExists(self.path) check_directory_exists(self.path)
self.thumbPath = os.path.join(self.path, u'thumbnails') self.thumbPath = os.path.join(self.path, u'thumbnails')
self.checkThemesExists(self.thumbPath) check_directory_exists(self.thumbPath)
self.themeForm.path = self.path self.themeForm.path = self.path
self.oldBackgroundImage = None self.oldBackgroundImage = None
self.editingDefault = False
# Last little bits of setting up # 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.global_theme = unicode(QtCore.QSettings().value(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
QtCore.QVariant(u'')).toString()) QtCore.QVariant(u'')).toString())
def contextMenu(self, point): def contextMenu(self, point):
"""
Build the Right Click Context menu and set state depending on
the type of theme.
"""
item = self.themeListWidget.itemAt(point) item = self.themeListWidget.itemAt(point)
if item is None: if item is None:
return return
@ -220,7 +231,6 @@ class ThemeManager(QtGui.QWidget):
editing form for the user to make their customisations. editing form for the user to make their customisations.
""" """
theme = ThemeXML() theme = ThemeXML()
self.saveThemeName = u''
self.themeForm.theme = theme self.themeForm.theme = theme
self.themeForm.exec_() self.themeForm.exec_()
@ -236,12 +246,15 @@ class ThemeManager(QtGui.QWidget):
item = self.themeListWidget.currentItem() item = self.themeListWidget.currentItem()
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
self.fileRenameForm.fileNameEdit.setText(oldThemeName) self.fileRenameForm.fileNameEdit.setText(oldThemeName)
self.saveThemeName = oldThemeName
if self.fileRenameForm.exec_(): if self.fileRenameForm.exec_():
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
oldThemeData = self.getThemeData(oldThemeName) if self.checkIfThemeExists(newThemeName):
self.deleteTheme(oldThemeName) oldThemeData = self.getThemeData(oldThemeName)
self.cloneThemeData(oldThemeData, newThemeName) 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): def onCopyTheme(self):
""" """
@ -250,12 +263,12 @@ class ThemeManager(QtGui.QWidget):
item = self.themeListWidget.currentItem() item = self.themeListWidget.currentItem()
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
self.fileRenameForm.fileNameEdit.setText(oldThemeName) self.fileRenameForm.fileNameEdit.setText(oldThemeName)
self.saveThemeName = u''
if self.fileRenameForm.exec_(True): if self.fileRenameForm.exec_(True):
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
themeData = self.getThemeData(oldThemeName) if self.checkIfThemeExists(newThemeName):
self.cloneThemeData(themeData, newThemeName) themeData = self.getThemeData(oldThemeName)
self.loadThemes() self.cloneThemeData(themeData, newThemeName)
self.loadThemes()
def cloneThemeData(self, themeData, newThemeName): def cloneThemeData(self, themeData, newThemeName):
""" """
@ -281,14 +294,10 @@ class ThemeManager(QtGui.QWidget):
'You must select a theme to edit.')): 'You must select a theme to edit.')):
item = self.themeListWidget.currentItem() item = self.themeListWidget.currentItem()
themeName = unicode(item.text()) themeName = unicode(item.text())
if themeName != unicode(item.data(QtCore.Qt.UserRole).toString()):
self.editingDefault = True
theme = self.getThemeData( theme = self.getThemeData(
unicode(item.data(QtCore.Qt.UserRole).toString())) unicode(item.data(QtCore.Qt.UserRole).toString()))
if theme.background_type == u'image': if theme.background_type == u'image':
self.oldBackgroundImage = theme.background_filename self.oldBackgroundImage = theme.background_filename
self.saveThemeName = unicode(
item.data(QtCore.Qt.UserRole).toString())
self.themeForm.theme = theme self.themeForm.theme = theme
self.themeForm.exec_(True) self.themeForm.exec_(True)
@ -449,20 +458,9 @@ class ThemeManager(QtGui.QWidget):
unicode(themeName) + u'.xml') unicode(themeName) + u'.xml')
xml = get_text_file_string(xmlFile) xml = get_text_file_string(xmlFile)
if not xml: if not xml:
return self.baseTheme() return self._baseTheme()
else: else:
return self.createThemeFromXml(xml, self.path) return self._createThemeFromXml(xml, self.path)
def checkThemesExists(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): def unzipTheme(self, filename, dir):
""" """
@ -494,8 +492,7 @@ class ThemeManager(QtGui.QWidget):
theme_dir = None theme_dir = None
if osfile.endswith(os.path.sep): if osfile.endswith(os.path.sep):
theme_dir = os.path.join(dir, osfile) theme_dir = os.path.join(dir, osfile)
if not os.path.exists(theme_dir): check_directory_exists(theme_dir)
os.mkdir(os.path.join(dir, osfile))
else: else:
fullpath = os.path.join(dir, osfile) fullpath = os.path.join(dir, osfile)
names = osfile.split(os.path.sep) names = osfile.split(os.path.sep)
@ -505,8 +502,7 @@ class ThemeManager(QtGui.QWidget):
themename = names[0] themename = names[0]
if theme_dir is None: if theme_dir is None:
theme_dir = os.path.join(dir, names[0]) theme_dir = os.path.join(dir, names[0])
if not os.path.exists(theme_dir): check_directory_exists(theme_dir)
os.mkdir(os.path.join(dir, names[0]))
if os.path.splitext(ucsfile)[1].lower() in [u'.xml']: if os.path.splitext(ucsfile)[1].lower() in [u'.xml']:
xml_data = zip.read(file) xml_data = zip.read(file)
try: try:
@ -522,19 +518,22 @@ class ThemeManager(QtGui.QWidget):
outfile = open(fullpath, u'wb') outfile = open(fullpath, u'wb')
outfile.write(zip.read(file)) outfile.write(zip.read(file))
if filexml: if filexml:
theme = self.createThemeFromXml(filexml, self.path) theme = self._createThemeFromXml(filexml, self.path)
self.generateAndSaveImage(dir, themename, theme) self.generateAndSaveImage(dir, themename, theme)
else: else:
QtGui.QMessageBox.critical(self, Receiver.send_message(u'openlp_error_message', {
translate('OpenLP.ThemeManager', 'Error'), u'title': translate('OpenLP.ThemeManager',
translate('OpenLP.ThemeManager', 'Validation Error'),
'File is not a valid theme.')) u'message':translate('OpenLP.ThemeManager',
'File is not a valid theme.')})
log.exception(u'Theme file does not contain XML data %s' % log.exception(u'Theme file does not contain XML data %s' %
filename) filename)
except (IOError, NameError): except (IOError, NameError):
QtGui.QMessageBox.critical(self, Receiver.send_message(u'openlp_error_message', {
translate('OpenLP.ThemeManager', 'Error'), u'title': translate('OpenLP.ThemeManager',
translate('OpenLP.ThemeManager', 'File is not a valid theme.')) 'Validation Error'),
u'message':translate('OpenLP.ThemeManager',
'File is not a valid theme.')})
log.exception(u'Importing theme from zip failed %s' % filename) log.exception(u'Importing theme from zip failed %s' % filename)
finally: finally:
if zip: if zip:
@ -556,9 +555,161 @@ class ThemeManager(QtGui.QWidget):
if tree.find(u'BackgroundType') is None: if tree.find(u'BackgroundType') is None:
return xml_data return xml_data
else: 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):
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
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)
check_directory_exists(theme_dir)
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, select_text, confirm_title, confirm_text,
testPlugin=True):
"""
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, select_text):
item = self.themeListWidget.currentItem()
theme = unicode(item.text())
# confirm deletion
answer = QtGui.QMessageBox.question(self, confirm_title,
confirm_text % theme, QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | 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()):
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:
if plugin.usesTheme(theme):
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
return True
def _migrateVersion122(self, xml_data):
""" """
Convert the xml data from version 1 format to the current format. Convert the xml data from version 1 format to the current format.
@ -614,192 +765,4 @@ class ThemeManager(QtGui.QWidget):
vAlignCorrection = 2 vAlignCorrection = 2
newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_horizontal_align = theme.HorizontalAlign
newtheme.display_vertical_align = vAlignCorrection newtheme.display_vertical_align = vAlignCorrection
return newtheme.extract_xml() return newtheme.extract_xml()
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 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:
# 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()
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
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, select_text, confirm_title, confirm_text,
testPlugin=True):
"""
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, select_text):
item = self.themeListWidget.currentItem()
theme = unicode(item.text())
# confirm deletion
answer = QtGui.QMessageBox.question(self, confirm_title,
confirm_text % theme, QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | 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()):
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

View File

@ -30,7 +30,8 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
ItemCapabilities, SettingsManager, translate, check_item_selected, Receiver ItemCapabilities, SettingsManager, translate, check_item_selected, \
Receiver, check_directory_exists
from openlp.core.utils import AppLocation, get_images_filter from openlp.core.utils import AppLocation, get_images_filter
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -87,8 +88,7 @@ class ImageMediaItem(MediaManagerItem):
self.servicePath = os.path.join( self.servicePath = os.path.join(
AppLocation.get_section_data_path(self.settingsSection), AppLocation.get_section_data_path(self.settingsSection),
u'thumbnails') u'thumbnails')
if not os.path.exists(self.servicePath): check_directory_exists(self.servicePath)
os.mkdir(self.servicePath)
self.loadList(SettingsManager.load_list( self.loadList(SettingsManager.load_list(
self.settingsSection, self.settingsSection)) self.settingsSection, self.settingsSection))
@ -216,4 +216,4 @@ class ImageMediaItem(MediaManagerItem):
'the image file "%s" no longer exists.')) % filename}) 'the image file "%s" no longer exists.')) % filename})
def onPreviewClick(self): def onPreviewClick(self):
MediaManagerItem.onPreviewClick(self) MediaManagerItem.onPreviewClick(self)

View File

@ -153,7 +153,11 @@ class SongMediaItem(MediaManagerItem):
(3, u':/songs/song_search_lyrics.png', (3, u':/songs/song_search_lyrics.png',
translate('SongsPlugin.MediaItem', 'Lyrics')), translate('SongsPlugin.MediaItem', 'Lyrics')),
(4, u':/songs/song_search_author.png', (4, u':/songs/song_search_author.png',
translate('SongsPlugin.MediaItem', 'Authors'))]) translate('SongsPlugin.MediaItem', 'Authors')),
(5, u':/slides/slide_theme.png',
translate('SongsPlugin.MediaItem', 'Themes'))
])
self.configUpdated() self.configUpdated()
def onSearchTextButtonClick(self): def onSearchTextButtonClick(self):
@ -187,6 +191,12 @@ class SongMediaItem(MediaManagerItem):
Author.display_name.like(u'%' + search_keywords + u'%'), Author.display_name.like(u'%' + search_keywords + u'%'),
Author.display_name.asc()) Author.display_name.asc())
self.displayResultsAuthor(search_results) self.displayResultsAuthor(search_results)
elif search_type == 5:
log.debug(u'Theme Search')
search_results = self.parent.manager.get_all_objects(Song,
Song.theme_name == search_keywords,
Song.search_lyrics.asc())
self.displayResultsSong(search_results)
def onSongListLoad(self): def onSongListLoad(self):
""" """

View File

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>displayTagEdit</class>
<widget class="QWidget" name="displayTagEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>717</width>
<height>554</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QGroupBox" name="editGroupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>320</y>
<width>691</width>
<height>181</height>
</rect>
</property>
<property name="title">
<string>Edit Selection</string>
</property>
<widget class="QPushButton" name="updatePushButton">
<property name="geometry">
<rect>
<x>600</x>
<y>140</y>
<width>73</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Update</string>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>50</y>
<width>571</width>
<height>114</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="descriptionLabel">
<property name="text">
<string>Description</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="descriptionLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="tagLabel">
<property name="text">
<string>Tag</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="tagLineEdit">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="maxLength">
<number>5</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="startTagLabel">
<property name="text">
<string>Start tag</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="startTagLineEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="endTagLabel">
<property name="text">
<string>End tag</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="endTagLineEdit"/>
</item>
</layout>
</widget>
</widget>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>540</x>
<y>510</y>
<width>162</width>
<height>26</height>
</rect>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QPushButton" name="deletePushButton">
<property name="geometry">
<rect>
<x>530</x>
<y>280</y>
<width>71</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
<widget class="QPushButton" name="addPushButton">
<property name="geometry">
<rect>
<x>610</x>
<y>280</y>
<width>71</width>
<height>26</height>
</rect>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
<widget class="QTableWidget" name="tagTableWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>691</width>
<height>271</height>
</rect>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>Description</string>
</property>
</column>
<column>
<property name="text">
<string>Key</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Start Tag</string>
</property>
</column>
<column>
<property name="text">
<string>End Tag</string>
</property>
</column>
</widget>
</widget>
<resources/>
<connections/>
</ui>