diff --git a/documentation/manual/source/index.rst b/documentation/manual/source/index.rst index ac29c4360..5786af1ae 100644 --- a/documentation/manual/source/index.rst +++ b/documentation/manual/source/index.rst @@ -14,6 +14,8 @@ Contents: introduction glossary dualmonitors + mediamanager + songs Indices and tables ================== diff --git a/documentation/manual/source/mediamanager.rst b/documentation/manual/source/mediamanager.rst new file mode 100644 index 000000000..2cf1d2c57 --- /dev/null +++ b/documentation/manual/source/mediamanager.rst @@ -0,0 +1,26 @@ +============= +Media Manager +============= + +Once you get your system set up for OpenLP you will be ready to add content to +your setup. This will all happen through the **Media Manager**. The +`Media Manager` contains all the bibles, songs, presentations, media, and +everything else that you will project through OpenLP. + +Enabling the Plugins +-------------------- + +You may need to enable the plugins that came with OpenLP. As you can see below +this is what the `Media Manager` looks like with all the plugins enabled. + +.. image:: pics/mediamanager.png + +To enable the plugins navigate to :menuselection:`Settings --> Plugins` or +press `F7`. You will then want to click on the plugin to the left that you want +to enable and select **active** from the drop down box to the right. + +.. image:: pics/plugins.png + + +Now you should be ready to add content to OpenLP check out the section of this +guide on the individual plugins. diff --git a/documentation/manual/source/pics/finishedimport.png b/documentation/manual/source/pics/finishedimport.png new file mode 100644 index 000000000..d49876ec9 Binary files /dev/null and b/documentation/manual/source/pics/finishedimport.png differ diff --git a/documentation/manual/source/pics/plugins.png b/documentation/manual/source/pics/plugins.png new file mode 100644 index 000000000..b6810242b Binary files /dev/null and b/documentation/manual/source/pics/plugins.png differ diff --git a/documentation/manual/source/pics/selectsongs.png b/documentation/manual/source/pics/selectsongs.png new file mode 100644 index 000000000..20df3ba2a Binary files /dev/null and b/documentation/manual/source/pics/selectsongs.png differ diff --git a/documentation/manual/source/pics/songimporter.png b/documentation/manual/source/pics/songimporter.png new file mode 100644 index 000000000..96c39ea38 Binary files /dev/null and b/documentation/manual/source/pics/songimporter.png differ diff --git a/documentation/manual/source/pics/songimporterchoices.png b/documentation/manual/source/pics/songimporterchoices.png new file mode 100644 index 000000000..5c458838e Binary files /dev/null and b/documentation/manual/source/pics/songimporterchoices.png differ diff --git a/documentation/manual/source/pics/songselectlyrics.png b/documentation/manual/source/pics/songselectlyrics.png new file mode 100644 index 000000000..2e3d92f0d Binary files /dev/null and b/documentation/manual/source/pics/songselectlyrics.png differ diff --git a/documentation/manual/source/pics/songselectsongsearch.png b/documentation/manual/source/pics/songselectsongsearch.png new file mode 100644 index 000000000..de0ea12ca Binary files /dev/null and b/documentation/manual/source/pics/songselectsongsearch.png differ diff --git a/documentation/manual/source/pics/songusage.png b/documentation/manual/source/pics/songusage.png new file mode 100644 index 000000000..10f29f2a9 Binary files /dev/null and b/documentation/manual/source/pics/songusage.png differ diff --git a/documentation/manual/source/pics/songusagedelete.png b/documentation/manual/source/pics/songusagedelete.png new file mode 100644 index 000000000..fec1b5e5d Binary files /dev/null and b/documentation/manual/source/pics/songusagedelete.png differ diff --git a/documentation/manual/source/pics/songusagereport.png b/documentation/manual/source/pics/songusagereport.png new file mode 100644 index 000000000..c0d9df3dd Binary files /dev/null and b/documentation/manual/source/pics/songusagereport.png differ diff --git a/documentation/manual/source/pics/vistadisplaysettings.png b/documentation/manual/source/pics/vistadisplaysettings.png old mode 100755 new mode 100644 diff --git a/documentation/manual/source/pics/vistapersonalize.png b/documentation/manual/source/pics/vistapersonalize.png old mode 100755 new mode 100644 diff --git a/documentation/manual/source/pics/winsevendisplay.png b/documentation/manual/source/pics/winsevendisplay.png old mode 100755 new mode 100644 diff --git a/documentation/manual/source/pics/winsevenresolution.png b/documentation/manual/source/pics/winsevenresolution.png old mode 100755 new mode 100644 diff --git a/documentation/manual/source/pics/xpdisplaysettings.png b/documentation/manual/source/pics/xpdisplaysettings.png index eb7a8921c..e1ec66c6f 100644 Binary files a/documentation/manual/source/pics/xpdisplaysettings.png and b/documentation/manual/source/pics/xpdisplaysettings.png differ diff --git a/documentation/manual/source/songs.rst b/documentation/manual/source/songs.rst new file mode 100644 index 000000000..678a6206c --- /dev/null +++ b/documentation/manual/source/songs.rst @@ -0,0 +1,100 @@ +===== +Songs +===== + +Managing your songs in OpenLP is a relatively simple process. There are also +converters provided to get data from other formats into OpenLP. + +Song Importer +============= + +If you are using an earlier version of OpenLP or come from another software +package, you may be able to convert your existing database to work in OpenLP +2.0. To access the Song Importer :menuselection:`File --> Import --> Song`. +You will then see the Song Importer window, then click :guilabel:`Next`. + +.. image:: pics/songimporter.png + +After choosing :guilabel:`Next` you can then select from the various types of +software that OpenLP will convert songs from. + +.. image:: pics/songimporterchoices.png + +Then click on the file folder icon to choose the file of the song database you +want to import. See the following sections for information on the different +formats that OpenLP will import. + +Importing from OpenLP Version 1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Converting from OpenLP Version 1 is a pretty simple process. You will first +need to locate your version 1 database file. + +Windows XP:: + + C:\Documents and Settings\All Users\Application Data\openlp.org\Data\songs.olp + +Windows Vista / Windows 7:: + + C:\ProgramData\openlp.org\Data\songs.olp + +After clicking :guilabel:`Next` your conversion should be complete. + +.. image:: pics/finishedimport.png + +Then press :guilabel:`Finish` and you should now be ready to use your OpenLP +version one songs. + +Importing from OpenSong +^^^^^^^^^^^^^^^^^^^^^^^ + +Converting from OpenSong you will need to locate your songs database. In the +later versions of OpenSong you are asked to define the location of this. The +songs will be located in a folder named :guilabel:`Songs`. This folder should +contain files with all your songs in them without a file extension. (file.xxx). +When you have located this folder you will then need to select the songs from +the folder. + +.. image:: pics/selectsongs.png + +On most operating systems to select all the songs, first select the first song +in the lest then press shift and select the last song in the list. After this +press :guilabel:`Next` and you should see that your import has been successful. + +.. image:: pics/finishedimport.png + +Press :guilabel:`Finish` and you will now be ready to use your songs imported +from OpenSong. + +Importing from CCLI Song Select +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To import from CCLI Song Select you must be a CCLI Subscriber and also a +subscriber of the Song Select service. For info on that go to: +http://www.ccli.com + +The first step for importing from CCLI Song Select is to log into your account. +Then search for your desired song. For this example we will be adding the song +"Amazing Grace". + +.. image:: pics/songselectsongsearch.png + +For the song you are searching for select `lyrics` This should take you to a +page displaying the lyrics and copyright info for your song. + +.. image:: pics/songselectlyrics.png + +Next, hover over the :guilabel:`Lyrics` menu from the upper right corner. Then +choose either the .txt or .usr file. You will then be asked to chose a download +location if your browser does not automatically select that for you. Select +this file from the OpenLP import window and then click :guilabel:`Next` You can +also select multiple songs for import at once on most operating systems by +selecting the first item in the list then holding shift select the last item in +the list. When finished you should see that your import has completed. + +.. image:: pics/finishedimport.png + +Press :guilabel:`Finish` and you will now be ready to use your songs imported +from CCLI SongSelect. + + diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index a90a4c194..956b6c787 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -306,8 +306,8 @@ def expand_tags(text): text = text.replace(tag[u'end tag'], tag[u'end html']) return text -from theme import ThemeLevel, ThemeXML, BackgroundGradientType, BackgroundType, \ - HorizontalType, VerticalType +from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ + BackgroundType, HorizontalType, VerticalType from spelltextedit import SpellTextEdit from eventreceiver import Receiver from imagemanager import ImageManager diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 0dc138abc..8afa02111 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -294,4 +294,5 @@ class Manager(object): """ if self.is_dirty: engine = create_engine(self.db_url) - engine.execute("vacuum") + if self.db_url.startswith(u'sqlite'): + engine.execute("vacuum") diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index b2f46e655..9bbaa65d1 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -371,7 +371,8 @@ def build_background_css(item, width, height): theme = item.themedata background = u'background-color: black' if theme: - if theme.background_type == BackgroundType.to_string(BackgroundType.Solid): + if theme.background_type == \ + BackgroundType.to_string(BackgroundType.Solid): background = u'background-color: %s' % theme.background_color else: if theme.background_direction == BackgroundGradientType.to_string \ @@ -381,21 +382,24 @@ def build_background_css(item, width, height): u'-webkit-gradient(linear, left top, left bottom, ' \ 'from(%s), to(%s))' % (theme.background_start_color, theme.background_end_color) - elif theme.background_direction == BackgroundGradientType.to_string \ - (BackgroundGradientType.LeftTop): + elif theme.background_direction == \ + BackgroundGradientType.to_string( \ + BackgroundGradientType.LeftTop): background = \ u'background: ' \ u'-webkit-gradient(linear, left top, right bottom, ' \ 'from(%s), to(%s))' % (theme.background_start_color, theme.background_end_color) - elif theme.background_direction == BackgroundGradientType.to_string \ + elif theme.background_direction == \ + BackgroundGradientType.to_string \ (BackgroundGradientType.LeftBottom): background = \ u'background: ' \ u'-webkit-gradient(linear, left bottom, right top, ' \ 'from(%s), to(%s))' % (theme.background_start_color, theme.background_end_color) - elif theme.background_direction == BackgroundGradientType.to_string \ + elif theme.background_direction == \ + BackgroundGradientType.to_string \ (BackgroundGradientType.Vertical): background = \ u'background: -webkit-gradient(linear, left top, ' \ diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 0e0660bda..14de141fc 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -46,13 +46,13 @@ class ImageThread(QtCore.QThread): """ def __init__(self, manager): QtCore.QThread.__init__(self, None) - self.image_mamager = manager + self.imageManager = manager def run(self): """ Run the thread. """ - self.image_mamager.process() + self.imageManager.process() class Image(object): @@ -113,6 +113,14 @@ class ImageManager(QtCore.QObject): time.sleep(0.1) return self._cache[name].image_bytes + def del_image(self, name): + """ + Delete the Image from the Cache + """ + log.debug(u'del_image %s' % name) + if name in self._cache: + del self._cache[name] + def add_image(self, name, path): """ Add image to cache if it is not already there @@ -125,6 +133,8 @@ class ImageManager(QtCore.QObject): image.image = resize_image(path, self.width, self.height) self._cache[name] = image + else: + log.debug(u'Image in cache %s:%s' % (name, path)) self._cache_dirty = True # only one thread please if not self._thread_running: diff --git a/openlp/core/lib/mailto/LICENSE b/openlp/core/lib/mailto/LICENSE new file mode 100644 index 000000000..d8ab2d8d2 --- /dev/null +++ b/openlp/core/lib/mailto/LICENSE @@ -0,0 +1,38 @@ +PSF LICENSE AGREEMENT FOR PYTHON 2.7.1 + + 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), + and the Individual or Organization ("Licensee") accessing and otherwise + using Python 2.7.1 software in source or binary form and its associated + documentation. + 2. Subject to the terms and conditions of this License Agreement, PSF hereby + grants Licensee a nonexclusive, royalty-free, world-wide license to + reproduce, analyze, test, perform and/or display publicly, prepare + derivative works, distribute, and otherwise use Python 2.7.1 alone or in any + derivative version, provided, however, that PSF's License Agreement and + PSF's notice of copyright, i.e., "Copyright (c) 2001-2010 Python Software + Foundation; All Rights Reserved" are retained in Python 2.7.1 alone or in + any derivative version prepared by Licensee. + 3. In the event Licensee prepares a derivative work that is based on or + incorporates Python 2.7.1 or any part thereof, and wants to make the + derivative work available to others as provided herein, then Licensee hereby + agrees to include in any such work a brief summary of the changes made to + Python 2.7.1. + 4. PSF is making Python 2.7.1 available to Licensee on an "AS IS" basis. PSF + MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF + EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION + OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT + THE USE OF PYTHON 2.7.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.1 FOR + ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF + MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.1, OR ANY DERIVATIVE + THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + 6. This License Agreement will automatically terminate upon a material breach + of its terms and conditions. + 7. Nothing in this License Agreement shall be deemed to create any relationship + of agency, partnership, or joint venture between PSF and Licensee. This + License Agreement does not grant permission to use PSF trademarks or trade + name in a trademark sense to endorse or promote products or services of + Licensee, or any third party. + 8. By copying, installing or otherwise using Python 2.7.1, Licensee agrees to + be bound by the terms and conditions of this License Agreement. + diff --git a/openlp/core/lib/mailto/__init__.py b/openlp/core/lib/mailto/__init__.py new file mode 100644 index 000000000..9cfc319a8 --- /dev/null +++ b/openlp/core/lib/mailto/__init__.py @@ -0,0 +1,321 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# Utilities for opening files or URLs in the registered default application # +# and for sending e-mail using the user's preferred composer. # +# --------------------------------------------------------------------------- # +# Copyright (c) 2007 Antonio Valentino # +# All rights reserved. # +# --------------------------------------------------------------------------- # +# This program offered under the PSF License as published by the Python # +# Software Foundation. # +# # +# The license text can be found at http://docs.python.org/license.html # +# # +# This code is taken from: http://code.activestate.com/recipes/511443 # +# Modified for use in OpenLP # +############################################################################### + +__version__ = u'1.1' +__all__ = [u'open', u'mailto'] + +import os +import sys +import webbrowser +import subprocess + +from email.Utils import encode_rfc2231 + +_controllers = {} +_open = None + + +class BaseController(object): + """ + Base class for open program controllers. + """ + + def __init__(self, name): + self.name = name + + def open(self, filename): + raise NotImplementedError + + +class Controller(BaseController): + """ + Controller for a generic open program. + """ + + def __init__(self, *args): + super(Controller, self).__init__(os.path.basename(args[0])) + self.args = list(args) + + def _invoke(self, cmdline): + if sys.platform[:3] == u'win': + closefds = False + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + else: + closefds = True + startupinfo = None + + if (os.environ.get(u'DISPLAY') or sys.platform[:3] == u'win' or \ + sys.platform == u'darwin'): + inout = file(os.devnull, u'r+') + else: + # for TTY programs, we need stdin/out + inout = None + + # if possible, put the child precess in separate process group, + # so keyboard interrupts don't affect child precess as well as + # Python + setsid = getattr(os, u'setsid', None) + if not setsid: + setsid = getattr(os, u'setpgrp', None) + + pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout, + stderr=inout, close_fds=closefds, preexec_fn=setsid, + startupinfo=startupinfo) + + # It is assumed that this kind of tools (gnome-open, kfmclient, + # exo-open, xdg-open and open for OSX) immediately exit after lauching + # the specific application + returncode = pipe.wait() + if hasattr(self, u'fixreturncode'): + returncode = self.fixreturncode(returncode) + return not returncode + + def open(self, filename): + if isinstance(filename, basestring): + cmdline = self.args + [filename] + else: + # assume it is a sequence + cmdline = self.args + filename + try: + return self._invoke(cmdline) + except OSError: + return False + + +# Platform support for Windows +if sys.platform[:3] == u'win': + + class Start(BaseController): + """ + Controller for the win32 start progam through os.startfile. + """ + + def open(self, filename): + try: + os.startfile(filename) + except WindowsError: + # [Error 22] No application is associated with the specified + # file for this operation: '' + return False + else: + return True + + _controllers[u'windows-default'] = Start(u'start') + _open = _controllers[u'windows-default'].open + + +# Platform support for MacOS +elif sys.platform == u'darwin': + _controllers[u'open']= Controller(u'open') + _open = _controllers[u'open'].open + + +# Platform support for Unix +else: + + import commands + + # @WARNING: use the private API of the webbrowser module + from webbrowser import _iscommand + + class KfmClient(Controller): + """ + Controller for the KDE kfmclient program. + """ + + def __init__(self, kfmclient=u'kfmclient'): + super(KfmClient, self).__init__(kfmclient, u'exec') + self.kde_version = self.detect_kde_version() + + def detect_kde_version(self): + kde_version = None + try: + info = commands.getoutput(u'kfmclient --version') + + for line in info.splitlines(): + if line.startswith(u'KDE'): + kde_version = line.split(u':')[-1].strip() + break + except (OSError, RuntimeError): + pass + + return kde_version + + def fixreturncode(self, returncode): + if returncode is not None and self.kde_version > u'3.5.4': + return returncode + else: + return os.EX_OK + + def detect_desktop_environment(): + """ + Checks for known desktop environments + + Return the desktop environments name, lowercase (kde, gnome, xfce) + or "generic" + """ + + desktop_environment = u'generic' + + if os.environ.get(u'KDE_FULL_SESSION') == u'true': + desktop_environment = u'kde' + elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'): + desktop_environment = u'gnome' + else: + try: + info = commands.getoutput(u'xprop -root _DT_SAVE_MODE') + if u' = "xfce4"' in info: + desktop_environment = u'xfce' + except (OSError, RuntimeError): + pass + + return desktop_environment + + + def register_X_controllers(): + if _iscommand(u'kfmclient'): + _controllers[u'kde-open'] = KfmClient() + + for command in (u'gnome-open', u'exo-open', u'xdg-open'): + if _iscommand(command): + _controllers[command] = Controller(command) + + + def get(): + controllers_map = { + u'gnome': u'gnome-open', + u'kde': u'kde-open', + u'xfce': u'exo-open', + } + + desktop_environment = detect_desktop_environment() + + try: + controller_name = controllers_map[desktop_environment] + return _controllers[controller_name].open + + except KeyError: + if _controllers.has_key(u'xdg-open'): + return _controllers[u'xdg-open'].open + else: + return webbrowser.open + + if os.environ.get(u'DISPLAY'): + register_X_controllers() + _open = get() + + +def open(filename): + """ + Open a file or an URL in the registered default application. + """ + + return _open(filename) + + +def _fix_addersses(**kwargs): + for headername in (u'address', u'to', u'cc', u'bcc'): + try: + headervalue = kwargs[headername] + if not headervalue: + del kwargs[headername] + continue + elif not isinstance(headervalue, basestring): + # assume it is a sequence + headervalue = u','.join(headervalue) + except KeyError: + pass + except TypeError: + raise TypeError(u'string or sequence expected for "%s", %s ' + u'found' % (headername, type(headervalue).__name__)) + else: + translation_map = {u'%': u'%25', u'&': u'%26', u'?': u'%3F'} + for char, replacement in translation_map.items(): + headervalue = headervalue.replace(char, replacement) + kwargs[headername] = headervalue + + return kwargs + + +def mailto_format(**kwargs): + """ + Compile mailto string from call parameters + """ + # @TODO: implement utf8 option + + kwargs = _fix_addersses(**kwargs) + parts = [] + for headername in (u'to', u'cc', u'bcc', u'subject', u'body', u'attach'): + if kwargs.has_key(headername): + headervalue = kwargs[headername] + if not headervalue: + continue + if headername in (u'address', u'to', u'cc', u'bcc'): + parts.append(u'%s=%s' % (headername, headervalue)) + else: + headervalue = encode_rfc2231(headervalue) # @TODO: check + parts.append(u'%s=%s' % (headername, headervalue)) + + mailto_string = u'mailto:%s' % kwargs.get(u'address', '') + if parts: + mailto_string = u'%s?%s' % (mailto_string, u'&'.join(parts)) + + return mailto_string + + +def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None, + attach=None): + """ + Send an e-mail using the user's preferred composer. + + Open the user's preferred e-mail composer in order to send a mail to + address(es) that must follow the syntax of RFC822. Multiple addresses + may be provided (for address, cc and bcc parameters) as separate + arguments. + + All parameters provided are used to prefill corresponding fields in + the user's e-mail composer. The user will have the opportunity to + change any of this information before actually sending the e-mail. + + ``address`` + specify the destination recipient + + ``cc`` + specify a recipient to be copied on the e-mail + + ``bcc`` + specify a recipient to be blindly copied on the e-mail + + ``subject`` + specify a subject for the e-mail + + ``body`` + specify a body for the e-mail. Since the user will be able to make + changes before actually sending the e-mail, this can be used to provide + the user with a template for the e-mail text may contain linebreaks + + ``attach`` + specify an attachment for the e-mail. file must point to an existing + file + """ + + mailto_string = mailto_format(**locals()) + return open(mailto_string) + diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 3eae97238..acf24ae22 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -320,15 +320,9 @@ class MediaManagerItem(QtGui.QWidget): translate('OpenLP.MediaManagerItem', '&Add to selected Service Item'), self.onAddEditClick)) - if QtCore.QSettings().value(u'advanced/double click live', - QtCore.QVariant(False)).toBool(): - QtCore.QObject.connect(self.listView, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), - self.onLiveClick) - else: - QtCore.QObject.connect(self.listView, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), - self.onPreviewClick) + QtCore.QObject.connect(self.listView, + QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), + self.onClickPressed) def initialise(self): """ @@ -426,10 +420,20 @@ class MediaManagerItem(QtGui.QWidget): raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to ' u'be defined by the plugin') - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, serviceItem, item=None, xmlVersion=False): raise NotImplementedError(u'MediaManagerItem.generateSlideData needs ' u'to be defined by the plugin') + def onClickPressed(self): + """ + Allows the list click action to be determined dynamically + """ + if QtCore.QSettings().value(u'advanced/double click live', + QtCore.QVariant(False)).toBool(): + self.onLiveClick() + else: + self.onPreviewClick() + def onPreviewClick(self): """ Preview an item by building a service item then adding that service @@ -442,10 +446,10 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items to preview.')) else: log.debug(self.plugin.name + u' Preview requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = True - self.parent.previewController.addServiceItem(service_item) + serviceItem = self.buildServiceItem() + if serviceItem: + serviceItem.from_plugin = True + self.parent.previewController.addServiceItem(serviceItem) def onLiveClick(self): """ @@ -459,10 +463,10 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items to send live.')) else: log.debug(self.plugin.name + u' Live requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = True - self.parent.liveController.addServiceItem(service_item) + serviceItem = self.buildServiceItem() + if serviceItem: + serviceItem.from_plugin = True + self.parent.liveController.addServiceItem(serviceItem) def onAddClick(self): """ @@ -474,22 +478,22 @@ class MediaManagerItem(QtGui.QWidget): translate('OpenLP.MediaManagerItem', 'You must select one or more items.')) else: - # Is it posssible to process multiple list items to generate multiple - # service items? + # Is it posssible to process multiple list items to generate + # multiple service items? if self.singleServiceItem or self.remoteTriggered: log.debug(self.plugin.name + u' Add requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = False - self.parent.serviceManager.addServiceItem(service_item, + serviceItem = self.buildServiceItem(None, True) + if serviceItem: + serviceItem.from_plugin = False + self.parent.serviceManager.addServiceItem(serviceItem, replace=self.remoteTriggered) else: items = self.listView.selectedIndexes() for item in items: - service_item = self.buildServiceItem(item) - if service_item: - service_item.from_plugin = False - self.parent.serviceManager.addServiceItem(service_item) + serviceItem = self.buildServiceItem(item, True) + if serviceItem: + serviceItem.from_plugin = False + self.parent.serviceManager.addServiceItem(serviceItem) def onAddEditClick(self): """ @@ -502,16 +506,16 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items')) else: log.debug(self.plugin.name + u' Add requested') - service_item = self.parent.serviceManager.getServiceItem() - if not service_item: - QtGui.QMessageBox.information(self, + serviceItem = self.parent.serviceManager.getServiceItem() + if not serviceItem: + QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'No Service Item Selected'), translate('OpenLP.MediaManagerItem', 'You must select an existing service item to add to.')) - elif self.title.lower() == service_item.name.lower(): - self.generateSlideData(service_item) - self.parent.serviceManager.addServiceItem(service_item, + elif self.title.lower() == serviceItem.name.lower(): + self.generateSlideData(serviceItem) + self.parent.serviceManager.addServiceItem(serviceItem, replace=True) else: # Turn off the remote edit update message indicator @@ -521,17 +525,17 @@ class MediaManagerItem(QtGui.QWidget): unicode(translate('OpenLP.MediaManagerItem', 'You must select a %s service item.')) % self.title) - def buildServiceItem(self, item=None): + def buildServiceItem(self, item=None, xmlVersion=False): """ Common method for generating a service item """ - service_item = ServiceItem(self.parent) + serviceItem = ServiceItem(self.parent) if self.serviceItemIconName: - service_item.add_icon(self.serviceItemIconName) + serviceItem.add_icon(self.serviceItemIconName) else: - service_item.add_icon(self.parent.icon_path) - if self.generateSlideData(service_item, item): - return service_item + serviceItem.add_icon(self.parent.icon_path) + if self.generateSlideData(serviceItem, item, xmlVersion): + return serviceItem else: return None diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 37ac3d74a..f73b58735 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -108,7 +108,7 @@ class Plugin(QtCore.QObject): """ log.info(u'loaded') - def __init__(self, name, version=None, plugin_helpers=None): + def __init__(self, name, version=None, pluginHelpers=None): """ This is the constructor for the plugin object. This provides an easy way for descendent plugins to populate common data. This method *must* @@ -124,7 +124,7 @@ class Plugin(QtCore.QObject): ``version`` Defaults to *None*. The version of the plugin. - ``plugin_helpers`` + ``pluginHelpers`` Defaults to *None*. A list of helper objects. """ QtCore.QObject.__init__(self) @@ -139,14 +139,14 @@ class Plugin(QtCore.QObject): self.status = PluginStatus.Inactive # Set up logging self.log = logging.getLogger(self.name) - self.previewController = plugin_helpers[u'preview'] - self.liveController = plugin_helpers[u'live'] - self.renderManager = plugin_helpers[u'render'] - self.serviceManager = plugin_helpers[u'service'] - self.settingsForm = plugin_helpers[u'settings form'] - self.mediadock = plugin_helpers[u'toolbox'] - self.pluginManager = plugin_helpers[u'pluginmanager'] - self.formparent = plugin_helpers[u'formparent'] + self.previewController = pluginHelpers[u'preview'] + self.liveController = pluginHelpers[u'live'] + self.renderManager = pluginHelpers[u'render'] + self.serviceManager = pluginHelpers[u'service'] + self.settingsForm = pluginHelpers[u'settings form'] + self.mediadock = pluginHelpers[u'toolbox'] + self.pluginManager = pluginHelpers[u'pluginmanager'] + self.formparent = pluginHelpers[u'formparent'] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_add_service_item' % self.name), self.processAddServiceEvent) diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index 81cde12a0..fc7ba38b8 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -213,6 +213,8 @@ class RenderManager(object): # make big page for theme edit dialog to get line count if self.force_page: verse = verse + verse + verse + else: + self.image_manager.del_image(self.theme_data.theme_name) footer = [] footer.append(u'Arky Arky (Unknown)' ) footer.append(u'Public Domain') diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 0cbc34de5..9b4a035a5 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -44,6 +44,7 @@ class ServiceItemType(object): Image = 2 Command = 3 + class ItemCapabilities(object): """ Provides an enumeration of a serviceitem's capabilities @@ -101,6 +102,7 @@ class ServiceItem(object): self.search_string = u'' self.data_string = u'' self.edit_id = None + self.xml_version = None self._new_item() def _new_item(self): @@ -252,7 +254,8 @@ class ServiceItem(object): u'from_plugin': self.from_plugin, u'capabilities': self.capabilities, u'search': self.search_string, - u'data': self.data_string + u'data': self.data_string, + u'xml_version': self.xml_version } service_data = [] if self.service_item_type == ServiceItemType.Text: @@ -294,6 +297,8 @@ class ServiceItem(object): if u'search' in header: self.search_string = header[u'search'] self.data_string = header[u'data'] + if u'xml_version' in header: + self.xml_version = header[u'xml_version'] if self.service_item_type == ServiceItemType.Text: for slide in serviceitem[u'serviceitem'][u'data']: self._raw_frames.append(slide) diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index 8de42e7a0..048751006 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -87,8 +87,12 @@ class SettingsTab(QtGui.QWidget): """ pass - def postSetUp(self): + def postSetUp(self, postUpdate=False): """ Changes which need to be made after setup of application + + ``postUpdate`` + Indicates if called before or after updates. + """ pass diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 603197c07..76271b6a7 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -33,12 +33,15 @@ except ImportError: enchant_available = False # based on code from -# 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 openlp.core.lib import html_expands, translate class SpellTextEdit(QtGui.QPlainTextEdit): + """ + Spell checking widget based on QPlanTextEdit. + """ def __init__(self, *args): QtGui.QPlainTextEdit.__init__(self, *args) # Default dictionary based on the current locale. @@ -60,7 +63,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit): QtGui.QPlainTextEdit.mousePressEvent(self, event) def contextMenuEvent(self, event): - popup_menu = self.createStandardContextMenu() + popupMenu = self.createStandardContextMenu() # Select the word under the cursor. cursor = self.textCursor() # only select text if not already selected @@ -81,17 +84,17 @@ class SpellTextEdit(QtGui.QPlainTextEdit): # Only add the spelling suggests to the menu if there are # suggestions. if len(spell_menu.actions()) != 0: - popup_menu.insertSeparator(popup_menu.actions()[0]) - popup_menu.insertMenu(popup_menu.actions()[0], spell_menu) - tag_menu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', + popupMenu.insertSeparator(popupMenu.actions()[0]) + popupMenu.insertMenu(popupMenu.actions()[0], spell_menu) + tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Formatting Tags')) for html in html_expands: - action = SpellAction( html[u'desc'], tag_menu) + action = SpellAction( html[u'desc'], tagMenu) action.correct.connect(self.htmlTag) - tag_menu.addAction(action) - popup_menu.insertSeparator(popup_menu.actions()[0]) - popup_menu.insertMenu(popup_menu.actions()[0], tag_menu) - popup_menu.exec_(event.globalPos()) + tagMenu.addAction(action) + popupMenu.insertSeparator(popupMenu.actions()[0]) + popupMenu.insertMenu(popupMenu.actions()[0], tagMenu) + popupMenu.exec_(event.globalPos()) def correctWord(self, word): """ diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index f211048e3..130eb817d 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -31,7 +31,6 @@ import re import logging from xml.dom.minidom import Document -from xml.etree.ElementTree import ElementTree, XML from lxml import etree, objectify from openlp.core.lib import str_to_bool @@ -56,7 +55,7 @@ BLANK_THEME_XML = \ Arial #FFFFFF - 30 + 40 False False 0 @@ -261,8 +260,9 @@ class ThemeXML(object): def add_font(self, name, color, size, override, fonttype=u'main', bold=u'False', italics=u'False', line_adjustment=0, - xpos=0, ypos=0, width=0, height=0 , outline=u'False', outline_color=u'#ffffff', - outline_pixel=2, shadow=u'False', shadow_color=u'#ffffff', shadow_pixel=5): + xpos=0, ypos=0, width=0, height=0 , outline=u'False', + outline_color=u'#ffffff', outline_pixel=2, shadow=u'False', + shadow_color=u'#ffffff', shadow_pixel=5): """ Add a Font. @@ -317,7 +317,6 @@ class ThemeXML(object): ``shadow_size`` How big the Shadow is - """ background = self.theme_xml.createElement(u'font') background.setAttribute(u'type', fonttype) @@ -325,7 +324,7 @@ class ThemeXML(object): # Create Font name element self.child_element(background, u'name', name) # Create Font color element - self.child_element(background, u'color', color) + self.child_element(background, u'color', unicode(color)) # Create Proportion name element self.child_element(background, u'size', unicode(size)) # Create weight name element @@ -441,7 +440,7 @@ class ThemeXML(object): if line: xml = xml[line + 2:] try: - theme_xml = objectify.fromstring(xml) + theme_xml = objectify.fromstring(xml) except etree.XMLSyntaxError: log.exception(u'Invalid xml %s', xml) return @@ -457,7 +456,8 @@ class ThemeXML(object): if element.getparent().tag == u'display': if element.tag.startswith(u'shadow') or \ element.tag.startswith(u'outline'): - self._create_attr(u'font_main', element.tag, element.text) + self._create_attr(u'font_main', element.tag, + element.text) master = element.getparent().tag if element.getparent().tag == u'background': master = element.getparent().tag @@ -471,7 +471,8 @@ class ThemeXML(object): for attr in element.attrib: base_element = attr # correction for the shadow and outline tags - if element.tag == u'shadow' or element.tag == u'outline': + if element.tag == u'shadow' or \ + element.tag == u'outline': if not attr.startswith(element.tag): base_element = element.tag + u'_' + attr self._create_attr(master, base_element, @@ -540,8 +541,8 @@ class ThemeXML(object): """ Change Camel Case string to python string """ - s1 = re.sub(u'(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub(u'([a-z0-9])([A-Z])', r'\1_\2', s1).lower() + sub_name = re.sub(u'(.)([A-Z][a-z]+)', r'\1_\2', name) + return re.sub(u'([a-z0-9])([A-Z])', r'\1_\2', sub_name).lower() def _build_xml_from_attrs(self): """ diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index dc126d863..df3add595 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -82,7 +82,8 @@ class AdvancedTab(SettingsTab): self.doubleClickLiveCheckBox.setObjectName(u'doubleClickLiveCheckBox') self.uiLayout.addWidget(self.doubleClickLiveCheckBox) # self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox) -# self.expandServiceItemCheckBox.setObjectName(u'expandServiceItemCheckBox') +# self.expandServiceItemCheckBox.setObjectName( +# u'expandServiceItemCheckBox') # self.uiLayout.addWidget(self.expandServiceItemCheckBox) self.leftLayout.addWidget(self.uiGroupBox) self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox) @@ -146,7 +147,7 @@ class AdvancedTab(SettingsTab): self.mediaPluginCheckBox.setText(translate('OpenLP.AdvancedTab', 'Remember active media manager tab on startup')) self.doubleClickLiveCheckBox.setText(translate('OpenLP.AdvancedTab', - 'Double-click to send items straight to live (requires restart)')) + 'Double-click to send items straight to live')) self.expandServiceItemCheckBox.setText(translate('OpenLP.AdvancedTab', 'Expand new service items on creation')) # self.sharedDirGroupBox.setTitle( diff --git a/openlp/core/ui/amendthemedialog.py b/openlp/core/ui/amendthemedialog.py deleted file mode 100644 index b77c9cfff..000000000 --- a/openlp/core/ui/amendthemedialog.py +++ /dev/null @@ -1,799 +0,0 @@ -# -*- 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 # -############################################################################### - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import build_icon, translate - -class Ui_AmendThemeDialog(object): - def setupUi(self, amendThemeDialog): - amendThemeDialog.setObjectName(u'amendThemeDialog') - amendThemeDialog.setWindowModality(QtCore.Qt.ApplicationModal) - amendThemeDialog.resize(586, 651) - icon = build_icon(u':/icon/openlp-logo-16x16.png') - amendThemeDialog.setWindowIcon(icon) - amendThemeDialog.setModal(True) - self.amendThemeLayout = QtGui.QVBoxLayout(amendThemeDialog) - self.amendThemeLayout.setSpacing(8) - self.amendThemeLayout.setMargin(8) - self.amendThemeLayout.setObjectName(u'amendThemeLayout') - self.themeNameWidget = QtGui.QWidget(amendThemeDialog) - self.themeNameWidget.setObjectName(u'themeNameWidget') - self.themeNameLayout = QtGui.QHBoxLayout(self.themeNameWidget) - self.themeNameLayout.setSpacing(8) - self.themeNameLayout.setMargin(0) - self.themeNameLayout.setObjectName(u'themeNameLayout') - self.themeNameLabel = QtGui.QLabel(self.themeNameWidget) - self.themeNameLabel.setObjectName(u'themeNameLabel') - self.themeNameLayout.addWidget(self.themeNameLabel) - self.themeNameEdit = QtGui.QLineEdit(self.themeNameWidget) - self.themeNameEdit.setObjectName(u'themeNameEdit') - self.themeNameLabel.setBuddy(self.themeNameEdit) - self.themeNameLayout.addWidget(self.themeNameEdit) - self.amendThemeLayout.addWidget(self.themeNameWidget) - self.contentWidget = QtGui.QWidget(amendThemeDialog) - self.contentWidget.setObjectName(u'contentWidget') - self.contentLayout = QtGui.QHBoxLayout(self.contentWidget) - self.contentLayout.setSpacing(8) - self.contentLayout.setMargin(0) - self.contentLayout.setObjectName(u'contentLayout') - self.themeTabWidget = QtGui.QTabWidget(self.contentWidget) - self.themeTabWidget.setObjectName(u'themeTabWidget') - self.backgroundTab = QtGui.QWidget() - self.backgroundTab.setObjectName(u'backgroundTab') - self.backgroundLayout = QtGui.QFormLayout(self.backgroundTab) - self.backgroundLayout.setMargin(8) - self.backgroundLayout.setSpacing(8) - self.backgroundLayout.setObjectName(u'backgroundLayout') - self.backgroundTypeLabel = QtGui.QLabel(self.backgroundTab) - self.backgroundTypeLabel.setObjectName(u'backgroundTypeLabel') - self.backgroundLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.backgroundTypeLabel) - self.backgroundTypeComboBox = QtGui.QComboBox(self.backgroundTab) - self.backgroundTypeComboBox.setObjectName(u'backgroundTypeComboBox') - self.backgroundTypeComboBox.addItem(QtCore.QString()) - self.backgroundTypeComboBox.addItem(QtCore.QString()) - self.backgroundTypeComboBox.addItem(QtCore.QString()) - self.backgroundLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.backgroundTypeComboBox) - self.color1Label = QtGui.QLabel(self.backgroundTab) - self.color1Label.setObjectName(u'color1Label') - self.backgroundLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.color1Label) - self.color1PushButton = QtGui.QPushButton(self.backgroundTab) - self.color1PushButton.setObjectName(u'color1PushButton') - self.backgroundLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.color1PushButton) - self.color2Label = QtGui.QLabel(self.backgroundTab) - self.color2Label.setObjectName(u'color2Label') - self.backgroundLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.color2Label) - self.color2PushButton = QtGui.QPushButton(self.backgroundTab) - self.color2PushButton.setObjectName(u'color2PushButton') - self.backgroundLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.color2PushButton) - self.imageLabel = QtGui.QLabel(self.backgroundTab) - self.imageLabel.setObjectName(u'imageLabel') - self.backgroundLayout.setWidget(4, QtGui.QFormLayout.LabelRole, - self.imageLabel) - self.gradientLabel = QtGui.QLabel(self.backgroundTab) - self.gradientLabel.setObjectName(u'gradientLabel') - self.backgroundLayout.setWidget(6, QtGui.QFormLayout.LabelRole, - self.gradientLabel) - self.gradientComboBox = QtGui.QComboBox(self.backgroundTab) - self.gradientComboBox.setObjectName(u'gradientComboBox') - self.gradientComboBox.addItem(QtCore.QString()) - self.gradientComboBox.addItem(QtCore.QString()) - self.gradientComboBox.addItem(QtCore.QString()) - self.backgroundLayout.setWidget(6, QtGui.QFormLayout.FieldRole, - self.gradientComboBox) - self.imageFilenameWidget = QtGui.QWidget(self.backgroundTab) - self.imageFilenameWidget.setObjectName(u'imageFilenameWidget') - self.horizontalLayout2 = QtGui.QHBoxLayout(self.imageFilenameWidget) - self.horizontalLayout2.setSpacing(0) - self.horizontalLayout2.setMargin(0) - self.horizontalLayout2.setObjectName(u'horizontalLayout2') - self.imageLineEdit = QtGui.QLineEdit(self.imageFilenameWidget) - self.imageLineEdit.setObjectName(u'imageLineEdit') - self.horizontalLayout2.addWidget(self.imageLineEdit) - self.imageToolButton = QtGui.QToolButton(self.imageFilenameWidget) - self.imageToolButton.setIcon(build_icon(u':/general/general_open.png')) - self.imageToolButton.setObjectName(u'imageToolButton') - self.imageToolButton.setAutoRaise(True) - self.horizontalLayout2.addWidget(self.imageToolButton) - self.backgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole, - self.imageFilenameWidget) - self.themeTabWidget.addTab(self.backgroundTab, u'') - self.fontMainTab = QtGui.QWidget() - self.fontMainTab.setObjectName(u'fontMainTab') - self.fontMainLayout = QtGui.QHBoxLayout(self.fontMainTab) - self.fontMainLayout.setSpacing(8) - self.fontMainLayout.setMargin(8) - self.fontMainLayout.setObjectName(u'fontMainLayout') - self.mainLeftWidget = QtGui.QWidget(self.fontMainTab) - self.mainLeftWidget.setObjectName(u'mainLeftWidget') - self.mainLeftLayout = QtGui.QVBoxLayout(self.mainLeftWidget) - self.mainLeftLayout.setSpacing(8) - self.mainLeftLayout.setMargin(0) - self.mainLeftLayout.setObjectName(u'mainLeftLayout') - self.fontMainGroupBox = QtGui.QGroupBox(self.mainLeftWidget) - self.fontMainGroupBox.setObjectName(u'fontMainGroupBox') - self.mainFontLayout = QtGui.QFormLayout(self.fontMainGroupBox) - self.mainFontLayout.setFormAlignment(QtCore.Qt.AlignLeading | - QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.mainFontLayout.setMargin(8) - self.mainFontLayout.setSpacing(8) - self.mainFontLayout.setObjectName(u'mainFontLayout') - self.fontMainlabel = QtGui.QLabel(self.fontMainGroupBox) - self.fontMainlabel.setObjectName(u'fontMainlabel') - self.mainFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.fontMainlabel) - self.fontMainComboBox = QtGui.QFontComboBox(self.fontMainGroupBox) - self.fontMainComboBox.setObjectName(u'fontMainComboBox') - self.mainFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.fontMainComboBox) - self.fontMainColorLabel = QtGui.QLabel(self.fontMainGroupBox) - self.fontMainColorLabel.setObjectName(u'fontMainColorLabel') - self.mainFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.fontMainColorLabel) - self.fontMainColorPushButton = QtGui.QPushButton(self.fontMainGroupBox) - self.fontMainColorPushButton.setObjectName(u'fontMainColorPushButton') - self.mainFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.fontMainColorPushButton) - self.fontMainSize = QtGui.QLabel(self.fontMainGroupBox) - self.fontMainSize.setObjectName(u'fontMainSize') - self.mainFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.fontMainSize) - self.fontMainSizeSpinBox = QtGui.QSpinBox(self.fontMainGroupBox) - defaultSizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - defaultSizePolicy.setHeightForWidth( - self.fontMainSizeSpinBox.sizePolicy().hasHeightForWidth()) - self.fontMainSizeSpinBox.setSizePolicy(defaultSizePolicy) - self.fontMainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) - self.fontMainSizeSpinBox.setProperty(u'value', QtCore.QVariant(16)) - self.fontMainSizeSpinBox.setMaximum(999) - self.fontMainSizeSpinBox.setObjectName(u'fontMainSizeSpinBox') - self.mainFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.fontMainSizeSpinBox) - self.fontMainWeightComboBox = QtGui.QComboBox(self.fontMainGroupBox) - self.fontMainWeightComboBox.setObjectName(u'fontMainWeightComboBox') - self.fontMainWeightComboBox.addItem(QtCore.QString()) - self.fontMainWeightComboBox.addItem(QtCore.QString()) - self.fontMainWeightComboBox.addItem(QtCore.QString()) - self.fontMainWeightComboBox.addItem(QtCore.QString()) - self.mainFontLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.fontMainWeightComboBox) - self.fontMainWeightLabel = QtGui.QLabel(self.fontMainGroupBox) - self.fontMainWeightLabel.setObjectName(u'fontMainWeightLabel') - self.mainFontLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.fontMainWeightLabel) - self.mainLeftLayout.addWidget(self.fontMainGroupBox) - self.fontMainWrapLineAdjustmentLabel = QtGui.QLabel( - self.fontMainGroupBox) - self.fontMainWrapLineAdjustmentLabel.setObjectName( - u'fontMainWrapLineAdjustmentLabel') - self.mainFontLayout.setWidget(4, QtGui.QFormLayout.LabelRole, - self.fontMainWrapLineAdjustmentLabel) - self.fontMainLineAdjustmentSpinBox = QtGui.QSpinBox( - self.fontMainGroupBox) - self.fontMainLineAdjustmentSpinBox.setObjectName( - u'fontMainLineAdjustmentSpinBox') - self.fontMainLineAdjustmentSpinBox.setMinimum(-99) - self.mainFontLayout.setWidget(4, QtGui.QFormLayout.FieldRole, - self.fontMainLineAdjustmentSpinBox) - self.fontMainLinesPageLabel = QtGui.QLabel(self.fontMainGroupBox) - self.fontMainLinesPageLabel.setObjectName(u'fontMainLinesPageLabel') - self.mainFontLayout.addRow(self.fontMainLinesPageLabel) - spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.mainLeftLayout.addItem(spacerItem1) - self.fontMainLayout.addWidget(self.mainLeftWidget) - self.mainRightWidget = QtGui.QWidget(self.fontMainTab) - self.mainRightWidget.setObjectName(u'mainRightWidget') - self.mainRightLayout = QtGui.QVBoxLayout(self.mainRightWidget) - self.mainRightLayout.setSpacing(8) - self.mainRightLayout.setMargin(0) - self.mainRightLayout.setObjectName(u'mainRightLayout') - self.mainLocationGroupBox = QtGui.QGroupBox(self.mainRightWidget) - self.mainLocationGroupBox.setObjectName(u'mainLocationGroupBox') - self.mainLocationLayout = QtGui.QFormLayout(self.mainLocationGroupBox) - self.mainLocationLayout.setMargin(8) - self.mainLocationLayout.setSpacing(8) - self.mainLocationLayout.setObjectName(u'mainLocationLayout') - self.defaultLocationLabel = QtGui.QLabel(self.mainLocationGroupBox) - self.defaultLocationLabel.setObjectName(u'defaultLocationLabel') - self.mainLocationLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.defaultLocationLabel) - self.fontMainDefaultCheckBox = QtGui.QCheckBox( - self.mainLocationGroupBox) - self.fontMainDefaultCheckBox.setTristate(False) - self.fontMainDefaultCheckBox.setObjectName(u'fontMainDefaultCheckBox') - self.mainLocationLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.fontMainDefaultCheckBox) - self.fontMainXLabel = QtGui.QLabel(self.mainLocationGroupBox) - self.fontMainXLabel.setObjectName(u'fontMainXLabel') - self.mainLocationLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.fontMainXLabel) - self.fontMainYLabel = QtGui.QLabel(self.mainLocationGroupBox) - self.fontMainYLabel.setObjectName(u'fontMainYLabel') - self.mainLocationLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.fontMainYLabel) - self.fontMainWidthLabel = QtGui.QLabel(self.mainLocationGroupBox) - self.fontMainWidthLabel.setObjectName(u'fontMainWidthLabel') - self.mainLocationLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.fontMainWidthLabel) - self.fontMainHeightLabel = QtGui.QLabel(self.mainLocationGroupBox) - self.fontMainHeightLabel.setObjectName(u'fontMainHeightLabel') - self.mainLocationLayout.setWidget(4, QtGui.QFormLayout.LabelRole, - self.fontMainHeightLabel) - self.fontMainXSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontMainXSpinBox.sizePolicy().hasHeightForWidth()) - self.fontMainXSpinBox.setSizePolicy(defaultSizePolicy) - self.fontMainXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontMainXSpinBox.setProperty(u'value', QtCore.QVariant(0)) - self.fontMainXSpinBox.setMaximum(9999) - self.fontMainXSpinBox.setObjectName(u'fontMainXSpinBox') - self.mainLocationLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.fontMainXSpinBox) - self.fontMainYSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontMainYSpinBox.sizePolicy().hasHeightForWidth()) - self.fontMainYSpinBox.setSizePolicy(defaultSizePolicy) - self.fontMainYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontMainYSpinBox.setMaximum(9999) - self.fontMainYSpinBox.setObjectName(u'fontMainYSpinBox') - self.mainLocationLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.fontMainYSpinBox) - self.fontMainWidthSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontMainWidthSpinBox.sizePolicy().hasHeightForWidth()) - self.fontMainWidthSpinBox.setSizePolicy(defaultSizePolicy) - self.fontMainWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontMainWidthSpinBox.setMaximum(9999) - self.fontMainWidthSpinBox.setObjectName(u'fontMainWidthSpinBox') - self.mainLocationLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.fontMainWidthSpinBox) - self.fontMainHeightSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontMainHeightSpinBox.sizePolicy().hasHeightForWidth()) - self.fontMainHeightSpinBox.setSizePolicy(defaultSizePolicy) - self.fontMainHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontMainHeightSpinBox.setMaximum(9999) - self.fontMainHeightSpinBox.setObjectName(u'fontMainHeightSpinBox') - self.mainLocationLayout.setWidget(4, QtGui.QFormLayout.FieldRole, - self.fontMainHeightSpinBox) - self.mainRightLayout.addWidget(self.mainLocationGroupBox) - spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.mainRightLayout.addItem(spacerItem2) - self.fontMainLayout.addWidget(self.mainRightWidget) - self.themeTabWidget.addTab(self.fontMainTab, u'') - self.fontFooterTab = QtGui.QWidget() - self.fontFooterTab.setObjectName(u'fontFooterTab') - self.fontFooterLayout = QtGui.QHBoxLayout(self.fontFooterTab) - self.fontFooterLayout.setSpacing(8) - self.fontFooterLayout.setMargin(8) - self.fontFooterLayout.setObjectName(u'fontFooterLayout') - self.footerLeftWidget = QtGui.QWidget(self.fontFooterTab) - self.footerLeftWidget.setObjectName(u'footerLeftWidget') - self.footerLeftLayout = QtGui.QVBoxLayout(self.footerLeftWidget) - self.footerLeftLayout.setSpacing(8) - self.footerLeftLayout.setMargin(0) - self.footerLeftLayout.setObjectName(u'footerLeftLayout') - self.footerFontGroupBox = QtGui.QGroupBox(self.footerLeftWidget) - self.footerFontGroupBox.setObjectName(u'footerFontGroupBox') - self.footerFontLayout = QtGui.QFormLayout(self.footerFontGroupBox) - self.footerFontLayout.setFieldGrowthPolicy( - QtGui.QFormLayout.ExpandingFieldsGrow) - self.footerFontLayout.setFormAlignment(QtCore.Qt.AlignLeading | - QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.footerFontLayout.setMargin(8) - self.footerFontLayout.setSpacing(8) - self.footerFontLayout.setObjectName(u'footerFontLayout') - self.fontFooterLabel = QtGui.QLabel(self.footerFontGroupBox) - self.fontFooterLabel.setObjectName(u'fontFooterLabel') - self.footerFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.fontFooterLabel) - self.fontFooterComboBox = QtGui.QFontComboBox(self.footerFontGroupBox) - self.fontFooterComboBox.setObjectName(u'fontFooterComboBox') - self.footerFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.fontFooterComboBox) - self.fontFooterColorLabel = QtGui.QLabel(self.footerFontGroupBox) - self.fontFooterColorLabel.setObjectName(u'fontFooterColorLabel') - self.footerFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.fontFooterColorLabel) - self.fontFooterColorPushButton = QtGui.QPushButton( - self.footerFontGroupBox) - self.fontFooterColorPushButton.setObjectName( - u'fontFooterColorPushButton') - self.footerFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.fontFooterColorPushButton) - self.fontFooterSizeLabel = QtGui.QLabel(self.footerFontGroupBox) - self.fontFooterSizeLabel.setObjectName(u'fontFooterSizeLabel') - self.footerFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.fontFooterSizeLabel) - self.fontFooterSizeSpinBox = QtGui.QSpinBox(self.footerFontGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontFooterSizeSpinBox.sizePolicy().hasHeightForWidth()) - self.fontFooterSizeSpinBox.setSizePolicy(defaultSizePolicy) - self.fontFooterSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) - self.fontFooterSizeSpinBox.setProperty(u'value', QtCore.QVariant(10)) - self.fontFooterSizeSpinBox.setMaximum(999) - self.fontFooterSizeSpinBox.setObjectName(u'fontFooterSizeSpinBox') - self.footerFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.fontFooterSizeSpinBox) - self.fontFooterWeightComboBox = QtGui.QComboBox(self.footerFontGroupBox) - self.fontFooterWeightComboBox.setObjectName(u'fontFooterWeightComboBox') - self.fontFooterWeightComboBox.addItem(QtCore.QString()) - self.fontFooterWeightComboBox.addItem(QtCore.QString()) - self.fontFooterWeightComboBox.addItem(QtCore.QString()) - self.fontFooterWeightComboBox.addItem(QtCore.QString()) - self.footerFontLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.fontFooterWeightComboBox) - self.fontFooterWeightLabel = QtGui.QLabel(self.footerFontGroupBox) - self.fontFooterWeightLabel.setObjectName(u'fontFooterWeightLabel') - self.footerFontLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.fontFooterWeightLabel) - self.footerLeftLayout.addWidget(self.footerFontGroupBox) - spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.footerLeftLayout.addItem(spacerItem3) - self.fontFooterLayout.addWidget(self.footerLeftWidget) - self.footerRightWidget = QtGui.QWidget(self.fontFooterTab) - self.footerRightWidget.setObjectName(u'footerRightWidget') - self.footerRightLayout = QtGui.QVBoxLayout(self.footerRightWidget) - self.footerRightLayout.setSpacing(8) - self.footerRightLayout.setMargin(0) - self.footerRightLayout.setObjectName(u'footerRightLayout') - self.locationFooterGroupBox = QtGui.QGroupBox(self.footerRightWidget) - self.locationFooterGroupBox.setObjectName(u'locationFooterGroupBox') - self.locationFooterLayout = QtGui.QFormLayout( - self.locationFooterGroupBox) - self.locationFooterLayout.setFieldGrowthPolicy( - QtGui.QFormLayout.ExpandingFieldsGrow) - self.locationFooterLayout.setFormAlignment(QtCore.Qt.AlignLeading | - QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.locationFooterLayout.setMargin(8) - self.locationFooterLayout.setSpacing(8) - self.locationFooterLayout.setObjectName(u'locationFooterLayout') - self.fontFooterDefaultLabel = QtGui.QLabel(self.locationFooterGroupBox) - self.fontFooterDefaultLabel.setObjectName(u'fontFooterDefaultLabel') - self.locationFooterLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.fontFooterDefaultLabel) - self.fontFooterDefaultCheckBox = QtGui.QCheckBox( - self.locationFooterGroupBox) - self.fontFooterDefaultCheckBox.setTristate(False) - self.fontFooterDefaultCheckBox.setObjectName( - u'fontFooterDefaultCheckBox') - self.locationFooterLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.fontFooterDefaultCheckBox) - self.fontFooterXLabel = QtGui.QLabel(self.locationFooterGroupBox) - self.fontFooterXLabel.setObjectName(u'fontFooterXLabel') - self.locationFooterLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.fontFooterXLabel) - self.fontFooterYLabel = QtGui.QLabel(self.locationFooterGroupBox) - self.fontFooterYLabel.setObjectName(u'fontFooterYLabel') - self.locationFooterLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.fontFooterYLabel) - self.fontFooterWidthLabel = QtGui.QLabel(self.locationFooterGroupBox) - self.fontFooterWidthLabel.setObjectName(u'fontFooterWidthLabel') - self.locationFooterLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.fontFooterWidthLabel) - self.fontFooterHeightLabel = QtGui.QLabel(self.locationFooterGroupBox) - self.fontFooterHeightLabel.setObjectName(u'fontFooterHeightLabel') - self.locationFooterLayout.setWidget(4, QtGui.QFormLayout.LabelRole, - self.fontFooterHeightLabel) - self.fontFooterXSpinBox = QtGui.QSpinBox(self.locationFooterGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontFooterXSpinBox.sizePolicy().hasHeightForWidth()) - self.fontFooterXSpinBox.setSizePolicy(defaultSizePolicy) - self.fontFooterXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontFooterXSpinBox.setProperty(u'value', QtCore.QVariant(0)) - self.fontFooterXSpinBox.setMaximum(9999) - self.fontFooterXSpinBox.setObjectName(u'fontFooterXSpinBox') - self.locationFooterLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.fontFooterXSpinBox) - self.fontFooterYSpinBox = QtGui.QSpinBox(self.locationFooterGroupBox) - defaultSizePolicy.setHeightForWidth( - self.fontFooterXSpinBox.sizePolicy().hasHeightForWidth()) - self.fontFooterYSpinBox.setSizePolicy(defaultSizePolicy) - self.fontFooterYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontFooterYSpinBox.setProperty(u'value', QtCore.QVariant(0)) - self.fontFooterYSpinBox.setMaximum(9999) - self.fontFooterYSpinBox.setObjectName(u'fontFooterYSpinBox') - self.locationFooterLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.fontFooterYSpinBox) - self.fontFooterWidthSpinBox = QtGui.QSpinBox( - self.locationFooterGroupBox) - self.fontFooterWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontFooterWidthSpinBox.setMaximum(9999) - self.fontFooterWidthSpinBox.setObjectName(u'fontFooterWidthSpinBox') - self.locationFooterLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.fontFooterWidthSpinBox) - self.fontFooterHeightSpinBox = QtGui.QSpinBox( - self.locationFooterGroupBox) - self.fontFooterHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0)) - self.fontFooterHeightSpinBox.setMaximum(9999) - self.fontFooterHeightSpinBox.setObjectName(u'fontFooterHeightSpinBox') - self.locationFooterLayout.setWidget(4, QtGui.QFormLayout.FieldRole, - self.fontFooterHeightSpinBox) - self.footerRightLayout.addWidget(self.locationFooterGroupBox) - spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.footerRightLayout.addItem(spacerItem4) - self.fontFooterLayout.addWidget(self.footerRightWidget) - self.themeTabWidget.addTab(self.fontFooterTab, u'') - self.otherOptionsTab = QtGui.QWidget() - self.otherOptionsTab.setObjectName(u'otherOptionsTab') - self.otherOptionsLayout = QtGui.QHBoxLayout(self.otherOptionsTab) - self.otherOptionsLayout.setSpacing(8) - self.otherOptionsLayout.setMargin(8) - self.otherOptionsLayout.setObjectName(u'otherOptionsLayout') - self.optionsLeftWidget = QtGui.QWidget(self.otherOptionsTab) - self.optionsLeftWidget.setObjectName(u'optionsLeftWidget') - self.optionsLeftLayout = QtGui.QVBoxLayout(self.optionsLeftWidget) - self.optionsLeftLayout.setSpacing(8) - self.optionsLeftLayout.setMargin(0) - self.optionsLeftLayout.setObjectName(u'optionsLeftLayout') - self.outlineGroupBox = QtGui.QGroupBox(self.optionsLeftWidget) - self.outlineGroupBox.setObjectName(u'outlineGroupBox') - self.verticalLayout = QtGui.QVBoxLayout(self.outlineGroupBox) - self.verticalLayout.setSpacing(8) - self.verticalLayout.setMargin(8) - self.verticalLayout.setObjectName(u'verticalLayout') - self.outlineWidget = QtGui.QWidget(self.outlineGroupBox) - self.outlineWidget.setObjectName(u'outlineWidget') - self.outlineLayout = QtGui.QFormLayout(self.outlineWidget) - self.outlineLayout.setMargin(0) - self.outlineLayout.setSpacing(8) - self.outlineLayout.setObjectName(u'outlineLayout') - self.outlineCheckBox = QtGui.QCheckBox(self.outlineWidget) - self.outlineCheckBox.setObjectName(u'outlineCheckBox') - self.outlineLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.outlineCheckBox) - self.outlineSpinBox = QtGui.QSpinBox(self.outlineWidget) - self.outlineSpinBox.setObjectName(u'outlineSpinBox') - self.outlineSpinBox.setMaximum(10) - self.outlineLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.outlineSpinBox) - self.outlineSpinBoxLabel = QtGui.QLabel(self.outlineWidget) - self.outlineSpinBoxLabel.setObjectName(u'outlineSpinBoxLabel') - self.outlineLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.outlineSpinBoxLabel) - self.outlineColorLabel = QtGui.QLabel(self.outlineWidget) - self.outlineColorLabel.setObjectName(u'outlineColorLabel') - self.outlineLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.outlineColorLabel) - self.outlineColorPushButton = QtGui.QPushButton(self.outlineWidget) - self.outlineColorPushButton.setObjectName(u'outlineColorPushButton') - self.outlineLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.outlineColorPushButton) - self.outlineEnabledLabel = QtGui.QLabel(self.outlineWidget) - self.outlineEnabledLabel.setObjectName(u'outlineEnabledLabel') - self.outlineLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.outlineEnabledLabel) - self.verticalLayout.addWidget(self.outlineWidget) - self.optionsLeftLayout.addWidget(self.outlineGroupBox) - self.shadowGroupBox = QtGui.QGroupBox(self.optionsLeftWidget) - self.shadowGroupBox.setObjectName(u'shadowGroupBox') - self.verticalLayout = QtGui.QVBoxLayout(self.shadowGroupBox) - self.verticalLayout.setSpacing(8) - self.verticalLayout.setMargin(8) - self.verticalLayout.setObjectName(u'verticalLayout') - self.shadowWidget = QtGui.QWidget(self.shadowGroupBox) - self.shadowWidget.setObjectName(u'shadowWidget') - self.shadowLayout = QtGui.QFormLayout(self.shadowWidget) - self.shadowLayout.setMargin(0) - self.shadowLayout.setSpacing(8) - self.shadowLayout.setObjectName(u'shadowLayout') - self.shadowCheckBox = QtGui.QCheckBox(self.shadowWidget) - self.shadowCheckBox.setObjectName(u'shadowCheckBox') - self.shadowLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.shadowCheckBox) - self.shadowSpinBox = QtGui.QSpinBox(self.outlineWidget) - self.shadowSpinBox.setObjectName(u'shadowSpinBox') - self.shadowSpinBox.setMaximum(10) - self.shadowLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.shadowSpinBox) - self.shadowSpinBoxLabel = QtGui.QLabel(self.outlineWidget) - self.shadowSpinBoxLabel.setObjectName(u'shadowSpinBoxLabel') - self.shadowLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.shadowSpinBoxLabel) - self.shadowColorLabel = QtGui.QLabel(self.shadowWidget) - self.shadowColorLabel.setObjectName(u'shadowColorLabel') - self.shadowLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.shadowColorLabel) - self.shadowColorPushButton = QtGui.QPushButton(self.shadowWidget) - self.shadowColorPushButton.setObjectName(u'shadowColorPushButton') - self.shadowLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.shadowColorPushButton) - self.shadowEnabledLabel = QtGui.QLabel(self.shadowWidget) - self.shadowEnabledLabel.setObjectName(u'shadowEnabledLabel') - self.shadowLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.shadowEnabledLabel) - self.verticalLayout.addWidget(self.shadowWidget) - self.optionsLeftLayout.addWidget(self.shadowGroupBox) - spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.optionsLeftLayout.addItem(spacerItem5) - self.otherOptionsLayout.addWidget(self.optionsLeftWidget) - self.optionsRightWidget = QtGui.QWidget(self.otherOptionsTab) - self.optionsRightWidget.setObjectName(u'optionsRightWidget') - self.optionsRightLayout = QtGui.QVBoxLayout(self.optionsRightWidget) - self.optionsRightLayout.setSpacing(8) - self.optionsRightLayout.setMargin(0) - self.optionsRightLayout.setObjectName(u'optionsRightLayout') - self.alignmentGroupBox = QtGui.QGroupBox(self.optionsRightWidget) - self.alignmentGroupBox.setObjectName(u'alignmentGroupBox') - self.gridLayout4 = QtGui.QGridLayout(self.alignmentGroupBox) - self.gridLayout4.setObjectName(u'gridLayout4') - self.horizontalLabel = QtGui.QLabel(self.alignmentGroupBox) - self.horizontalLabel.setObjectName(u'horizontalLabel') - self.gridLayout4.addWidget(self.horizontalLabel, 0, 0, 1, 1) - self.horizontalComboBox = QtGui.QComboBox(self.alignmentGroupBox) - self.horizontalComboBox.setObjectName(u'horizontalComboBox') - self.horizontalComboBox.addItem(QtCore.QString()) - self.horizontalComboBox.addItem(QtCore.QString()) - self.horizontalComboBox.addItem(QtCore.QString()) - self.gridLayout4.addWidget(self.horizontalComboBox, 0, 1, 1, 1) - self.verticalLabel = QtGui.QLabel(self.alignmentGroupBox) - self.verticalLabel.setObjectName(u'verticalLabel') - self.gridLayout4.addWidget(self.verticalLabel, 1, 0, 1, 1) - self.verticalComboBox = QtGui.QComboBox(self.alignmentGroupBox) - self.verticalComboBox.setObjectName(u'verticalComboBox') - self.verticalComboBox.addItem(QtCore.QString()) - self.verticalComboBox.addItem(QtCore.QString()) - self.verticalComboBox.addItem(QtCore.QString()) - self.gridLayout4.addWidget(self.verticalComboBox, 1, 1, 1, 1) - self.optionsRightLayout.addWidget(self.alignmentGroupBox) - self.transitionGroupBox = QtGui.QGroupBox(self.optionsRightWidget) - self.transitionGroupBox.setObjectName(u'transitionGroupBox') - self.gridLayout5 = QtGui.QGridLayout(self.transitionGroupBox) - self.gridLayout5.setObjectName(u'gridLayout5') - self.slideTransitionCheckBoxLabel = QtGui.QLabel( - self.transitionGroupBox) - self.slideTransitionCheckBoxLabel.setObjectName( - u'slideTransitionCheckBoxLabel') - self.gridLayout5.addWidget( - self.slideTransitionCheckBoxLabel, 0, 0, 1, 1) - self.slideTransitionCheckBox = QtGui.QCheckBox(self.alignmentGroupBox) - self.slideTransitionCheckBox.setTristate(False) - self.gridLayout5.addWidget(self.slideTransitionCheckBox, 0, 1, 1, 1) - self.optionsRightLayout.addWidget(self.transitionGroupBox) - spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.optionsRightLayout.addItem(spacerItem6) - self.otherOptionsLayout.addWidget(self.optionsRightWidget) - self.themeTabWidget.addTab(self.otherOptionsTab, u'') - self.contentLayout.addWidget(self.themeTabWidget) - self.amendThemeLayout.addWidget(self.contentWidget) - self.previewGroupBox = QtGui.QGroupBox(amendThemeDialog) - self.previewGroupBox.setObjectName(u'previewGroupBox') - self.themePreviewLayout = QtGui.QHBoxLayout(self.previewGroupBox) - self.themePreviewLayout.setSpacing(8) - self.themePreviewLayout.setMargin(8) - self.themePreviewLayout.setObjectName(u'themePreviewLayout') - spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - self.themePreviewLayout.addItem(spacerItem7) - self.themePreview = QtGui.QLabel(self.previewGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.themePreview.sizePolicy().hasHeightForWidth()) - self.themePreview.setSizePolicy(sizePolicy) - self.themePreview.setMaximumSize(QtCore.QSize(300, 225)) - self.themePreview.setFrameShape(QtGui.QFrame.WinPanel) - self.themePreview.setFrameShadow(QtGui.QFrame.Sunken) - self.themePreview.setLineWidth(1) - self.themePreview.setScaledContents(True) - self.themePreview.setObjectName(u'themePreview') - self.themePreviewLayout.addWidget(self.themePreview) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - self.themePreviewLayout.addItem(spacerItem8) - self.amendThemeLayout.addWidget(self.previewGroupBox) - self.themeButtonBox = QtGui.QDialogButtonBox(amendThemeDialog) - self.themeButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | - QtGui.QDialogButtonBox.Ok) - self.themeButtonBox.setObjectName(u'themeButtonBox') - self.amendThemeLayout.addWidget(self.themeButtonBox) - - self.retranslateUi(amendThemeDialog) - self.themeTabWidget.setCurrentIndex(0) - QtCore.QObject.connect(self.themeButtonBox, - QtCore.SIGNAL(u'accepted()'), amendThemeDialog.accept) - QtCore.QObject.connect(self.themeButtonBox, - QtCore.SIGNAL(u'rejected()'), amendThemeDialog.reject) - QtCore.QMetaObject.connectSlotsByName(amendThemeDialog) - - def retranslateUi(self, amendThemeDialog): - amendThemeDialog.setWindowTitle( - translate('OpenLP.AmendThemeForm', 'Theme Maintenance')) - self.themeNameLabel.setText( - translate('OpenLP.AmendThemeForm', 'Theme &name:')) - self.backgroundTypeLabel.setText( - translate('OpenLP.AmendThemeForm', 'Type:')) - self.backgroundTypeComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Solid Color')) - self.backgroundTypeComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Gradient')) - self.backgroundTypeComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Image')) - self.color1Label.setText(u':') - self.color2Label.setText(u':') - self.imageLabel.setText( - translate('OpenLP.AmendThemeForm', 'Image:')) - self.gradientLabel.setText( - translate('OpenLP.AmendThemeForm', 'Gradient:')) - self.gradientComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Horizontal')) - self.gradientComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Vertical')) - self.gradientComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Circular')) - self.themeTabWidget.setTabText( - self.themeTabWidget.indexOf(self.backgroundTab), - translate('OpenLP.AmendThemeForm', '&Background')) - self.fontMainGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Main Font')) - self.fontMainlabel.setText( - translate('OpenLP.AmendThemeForm', 'Font:')) - self.fontMainColorLabel.setText( - translate('OpenLP.AmendThemeForm', 'Color:')) - self.fontMainSize.setText( - translate('OpenLP.AmendThemeForm', 'Size:')) - self.fontMainSizeSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'pt')) - self.fontMainWrapLineAdjustmentLabel.setText( - translate('OpenLP.AmendThemeForm', 'Adjust line spacing:')) - self.fontMainWeightComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Normal')) - self.fontMainWeightComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Bold')) - self.fontMainWeightComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Italics')) - self.fontMainWeightComboBox.setItemText(3, - translate('OpenLP.AmendThemeForm', 'Bold/Italics')) - self.fontMainWeightLabel.setText( - translate('OpenLP.AmendThemeForm', 'Style:')) - self.mainLocationGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Display Location')) - self.defaultLocationLabel.setText( - translate('OpenLP.AmendThemeForm', 'Use default location')) - self.fontMainXLabel.setText( - translate('OpenLP.AmendThemeForm', 'X position:')) - self.fontMainYLabel.setText( - translate('OpenLP.AmendThemeForm', 'Y position:')) - self.fontMainWidthLabel.setText( - translate('OpenLP.AmendThemeForm', 'Width:')) - self.fontMainHeightLabel.setText( - translate('OpenLP.AmendThemeForm', 'Height:')) - self.fontMainXSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontMainYSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontMainWidthSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontMainHeightSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.themeTabWidget.setTabText( - self.themeTabWidget.indexOf(self.fontMainTab), - translate('OpenLP.AmendThemeForm', '&Main Font')) - self.footerFontGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Footer Font')) - self.fontFooterLabel.setText( - translate('OpenLP.AmendThemeForm', 'Font:')) - self.fontFooterColorLabel.setText( - translate('OpenLP.AmendThemeForm', 'Color:')) - self.fontFooterSizeLabel.setText( - translate('OpenLP.AmendThemeForm', 'Size:')) - self.fontFooterSizeSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'pt')) - self.fontFooterWeightComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Normal')) - self.fontFooterWeightComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Bold')) - self.fontFooterWeightComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Italics')) - self.fontFooterWeightComboBox.setItemText(3, - translate('OpenLP.AmendThemeForm', 'Bold/Italics')) - self.fontFooterWeightLabel.setText( - translate('OpenLP.AmendThemeForm', 'Style:')) - self.locationFooterGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Display Location')) - self.fontFooterDefaultLabel.setText( - translate('OpenLP.AmendThemeForm', 'Use default location')) - self.fontFooterXLabel.setText( - translate('OpenLP.AmendThemeForm', 'X position:')) - self.fontFooterYLabel.setText( - translate('OpenLP.AmendThemeForm', 'Y position:')) - self.fontFooterWidthLabel.setText( - translate('OpenLP.AmendThemeForm', 'Width:')) - self.fontFooterHeightLabel.setText( - translate('OpenLP.AmendThemeForm', 'Height:')) - self.fontFooterXSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontFooterYSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontFooterWidthSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.fontFooterHeightSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.themeTabWidget.setTabText( - self.themeTabWidget.indexOf(self.fontFooterTab), - translate('OpenLP.AmendThemeForm', '&Footer Font')) - self.outlineGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Outline')) - self.outlineSpinBoxLabel.setText( - translate('OpenLP.AmendThemeForm', 'Outline size:')) - self.outlineSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.outlineColorLabel.setText( - translate('OpenLP.AmendThemeForm', 'Outline color:')) - self.outlineEnabledLabel.setText( - translate('OpenLP.AmendThemeForm', 'Show outline:')) - self.shadowGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Shadow')) - self.shadowSpinBoxLabel.setText( - translate('OpenLP.AmendThemeForm', 'Shadow size:')) - self.shadowSpinBox.setSuffix( - translate('OpenLP.AmendThemeForm', 'px')) - self.shadowColorLabel.setText( - translate('OpenLP.AmendThemeForm', 'Shadow color:')) - self.shadowEnabledLabel.setText( - translate('OpenLP.AmendThemeForm', 'Show shadow:')) - self.alignmentGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Alignment')) - self.horizontalLabel.setText( - translate('OpenLP.AmendThemeForm', 'Horizontal align:')) - self.horizontalComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Left')) - self.horizontalComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Right')) - self.horizontalComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Center')) - self.verticalLabel.setText( - translate('OpenLP.AmendThemeForm', 'Vertical align:')) - self.verticalComboBox.setItemText(0, - translate('OpenLP.AmendThemeForm', 'Top')) - self.verticalComboBox.setItemText(1, - translate('OpenLP.AmendThemeForm', 'Middle')) - self.verticalComboBox.setItemText(2, - translate('OpenLP.AmendThemeForm', 'Bottom')) - self.transitionGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Slide Transition')) - self.slideTransitionCheckBoxLabel.setText( - translate('OpenLP.AmendThemeForm', 'Transition active')) - self.themeTabWidget.setTabText( - self.themeTabWidget.indexOf(self.otherOptionsTab), - translate('OpenLP.AmendThemeForm', '&Other Options')) - self.previewGroupBox.setTitle( - translate('OpenLP.AmendThemeForm', 'Preview')) diff --git a/openlp/core/ui/amendthemeform.py b/openlp/core/ui/amendthemeform.py deleted file mode 100644 index 1a7871f22..000000000 --- a/openlp/core/ui/amendthemeform.py +++ /dev/null @@ -1,722 +0,0 @@ -# -*- 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 # -############################################################################### - -import logging -import os -import os.path - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import ThemeXML, translate -from openlp.core.utils import get_images_filter -from amendthemedialog import Ui_AmendThemeDialog - -log = logging.getLogger(u'AmendThemeForm') - -class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): - """ - The :class:`AmendThemeForm` class provides the user interface to set up - new and edit existing themes. - """ - def __init__(self, parent): - """ - Initialise the theme editor user interface - """ - QtGui.QDialog.__init__(self, parent) - self.thememanager = parent - self.path = None - self.theme = ThemeXML() - self.setupUi(self) - # Buttons - QtCore.QObject.connect(self.color1PushButton, - QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked) - QtCore.QObject.connect(self.color2PushButton, - QtCore.SIGNAL(u'pressed()'), self.onColor2PushButtonClicked) - QtCore.QObject.connect(self.fontMainColorPushButton, - QtCore.SIGNAL(u'pressed()'), self.onFontMainColorPushButtonClicked) - QtCore.QObject.connect(self.fontFooterColorPushButton, - QtCore.SIGNAL(u'pressed()'), - self.onFontFooterColorPushButtonClicked) - QtCore.QObject.connect(self.outlineColorPushButton, - QtCore.SIGNAL(u'pressed()'), self.onOutlineColorPushButtonClicked) - QtCore.QObject.connect(self.shadowColorPushButton, - QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked) - QtCore.QObject.connect(self.imageToolButton, - QtCore.SIGNAL(u'clicked()'), self.onImageToolButtonClicked) - # Combo boxes - QtCore.QObject.connect(self.backgroundTypeComboBox, - QtCore.SIGNAL(u'activated(int)'), - self.onBackgroundTypeComboBoxSelected) - QtCore.QObject.connect(self.gradientComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onGradientComboBoxSelected) - QtCore.QObject.connect(self.fontMainComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onFontMainComboBoxSelected) - QtCore.QObject.connect(self.fontMainWeightComboBox, - QtCore.SIGNAL(u'activated(int)'), - self.onFontMainWeightComboBoxSelected) - QtCore.QObject.connect(self.fontFooterComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onFontFooterComboBoxSelected) - QtCore.QObject.connect(self.fontFooterWeightComboBox, - QtCore.SIGNAL(u'activated(int)'), - self.onFontFooterWeightComboBoxSelected) - QtCore.QObject.connect(self.horizontalComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected) - QtCore.QObject.connect(self.verticalComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected) - # Spin boxes - QtCore.QObject.connect(self.fontMainSizeSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainSizeSpinBoxChanged) - QtCore.QObject.connect(self.fontMainLineAdjustmentSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainLineAdjustmentSpinBoxChanged) - QtCore.QObject.connect(self.shadowSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onShadowSpinBoxChanged) - QtCore.QObject.connect(self.outlineSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onOutlineSpinBoxChanged) - - QtCore.QObject.connect(self.fontFooterSizeSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterSizeSpinBoxChanged) - QtCore.QObject.connect(self.fontMainXSpinBox, - QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged) - QtCore.QObject.connect(self.fontMainYSpinBox, - QtCore.SIGNAL(u'editingFinished()'), self.onFontMainYSpinBoxChanged) - QtCore.QObject.connect(self.fontMainWidthSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainWidthSpinBoxChanged) - QtCore.QObject.connect(self.fontMainHeightSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainHeightSpinBoxChanged) - QtCore.QObject.connect(self.fontMainLineAdjustmentSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainLineAdjustmentSpinBoxChanged) - QtCore.QObject.connect(self.fontFooterXSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterXSpinBoxChanged) - QtCore.QObject.connect(self.fontFooterYSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterYSpinBoxChanged) - QtCore.QObject.connect(self.fontFooterWidthSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterWidthSpinBoxChanged) - QtCore.QObject.connect(self.fontFooterHeightSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterHeightSpinBoxChanged) - - # CheckBoxes - QtCore.QObject.connect(self.fontMainDefaultCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onFontMainDefaultCheckBoxChanged) - QtCore.QObject.connect(self.fontFooterDefaultCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onFontFooterDefaultCheckBoxChanged) - QtCore.QObject.connect(self.outlineCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged) - QtCore.QObject.connect(self.shadowCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged) - QtCore.QObject.connect(self.slideTransitionCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onSlideTransitionCheckBoxChanged) - - def accept(self): - new_theme = ThemeXML() - theme_name = unicode(self.themeNameEdit.text()) - new_theme.new_document(theme_name) - save_from = None - save_to = None - if self.theme.background_type == u'solid': - new_theme.add_background_solid( - unicode(self.theme.background_color)) - elif self.theme.background_type == u'gradient': - new_theme.add_background_gradient( - unicode(self.theme.background_start_color), - unicode(self.theme.background_end_color), - self.theme.background_direction) - else: - filename = \ - os.path.split(unicode(self.theme.background_filename))[1] - new_theme.add_background_image(filename) - save_to = os.path.join(self.path, theme_name, filename) - save_from = self.theme.background_filename - new_theme.add_font(unicode(self.theme.font_main_name), - unicode(self.theme.font_main_color), - unicode(self.theme.font_main_proportion), - unicode(self.theme.font_main_override), u'main', - unicode(self.theme.font_main_weight), - unicode(self.theme.font_main_italics), - unicode(self.theme.font_main_line_adjustment), - unicode(self.theme.font_main_x), - unicode(self.theme.font_main_y), - unicode(self.theme.font_main_width), - unicode(self.theme.font_main_height)) - new_theme.add_font(unicode(self.theme.font_footer_name), - unicode(self.theme.font_footer_color), - unicode(self.theme.font_footer_proportion), - unicode(self.theme.font_footer_override), u'footer', - unicode(self.theme.font_footer_weight), - unicode(self.theme.font_footer_italics), - 0, # line adjustment - unicode(self.theme.font_footer_x), - unicode(self.theme.font_footer_y), - unicode(self.theme.font_footer_width), - unicode(self.theme.font_footer_height)) - new_theme.add_display(unicode(self.theme.display_shadow), - unicode(self.theme.display_shadow_color), - unicode(self.theme.display_outline), - unicode(self.theme.display_outline_color), - unicode(self.theme.display_horizontal_align), - unicode(self.theme.display_vertical_align), - unicode(self.theme.display_wrap_style), - unicode(self.theme.display_slide_transition), - unicode(self.theme.display_shadow_size), - unicode(self.theme.display_outline_size)) - theme = new_theme.extract_xml() - pretty_theme = new_theme.extract_formatted_xml() - if self.thememanager.saveTheme(theme_name, theme, pretty_theme, - save_from, save_to) is not False: - return QtGui.QDialog.accept(self) - - def loadTheme(self, theme): - log.debug(u'LoadTheme %s', theme) - self.theme = theme - # Stop the initial screen setup generating 1 preview per field! - self.allowPreview = False - self.paintUi(self.theme) - self.allowPreview = True - self.previewTheme() - - def onImageToolButtonClicked(self): - images_filter = get_images_filter() - images_filter = '%s;;%s (*.*) (*)' % (images_filter, - translate('OpenLP.AmendThemeForm', 'All Files')) - filename = QtGui.QFileDialog.getOpenFileName(self, - translate('OpenLP.AmendThemeForm', 'Select Image'), u'', - images_filter) - if filename: - self.imageLineEdit.setText(filename) - self.theme.background_filename = filename - self.previewTheme() - # - # Main Font Tab - # - def onFontMainComboBoxSelected(self): - self.theme.font_main_name = self.fontMainComboBox.currentFont().family() - self.previewTheme() - - def onFontMainWeightComboBoxSelected(self, value): - if value == 0: - self.theme.font_main_weight = u'Normal' - self.theme.font_main_italics = False - elif value == 1: - self.theme.font_main_weight = u'Bold' - self.theme.font_main_italics = False - elif value == 2: - self.theme.font_main_weight = u'Normal' - self.theme.font_main_italics = True - else: - self.theme.font_main_weight = u'Bold' - self.theme.font_main_italics = True - self.previewTheme() - - def onFontMainColorPushButtonClicked(self): - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.font_main_color), self) - if new_color.isValid(): - self.theme.font_main_color = new_color.name() - self.fontMainColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(self.theme.font_main_color)) - self.previewTheme() - - def onFontMainSizeSpinBoxChanged(self): - if self.theme.font_main_proportion != self.fontMainSizeSpinBox.value(): - self.theme.font_main_proportion = self.fontMainSizeSpinBox.value() - self.previewTheme() - - def onFontMainDefaultCheckBoxChanged(self, value): - if value == 2: # checked - self.theme.font_main_override = False - else: - self.theme.font_main_override = True - - if not self.theme.font_main_x and not self.theme.font_main_y and \ - not self.theme.font_main_width and not self.theme.font_main_height: - self.theme.font_main_x = u'10' - self.theme.font_main_y = u'10' - self.theme.font_main_width = u'1024' - self.theme.font_main_height = u'730' - self.fontMainXSpinBox.setValue(self.theme.font_main_x) - self.fontMainYSpinBox.setValue(self.theme.font_main_y) - self.fontMainWidthSpinBox.setValue(self.theme.font_main_width) - self.fontMainHeightSpinBox.setValue(self.theme.font_main_height) - self.fontMainLineAdjustmentSpinBox.setValue( - self.theme.font_main_line_adjustment) - self.stateChanging(self.theme) - self.previewTheme() - - def onFontMainXSpinBoxChanged(self): - if self.theme.font_main_x != self.fontMainXSpinBox.value(): - self.theme.font_main_x = self.fontMainXSpinBox.value() - self.previewTheme() - - def onFontMainYSpinBoxChanged(self): - if self.theme.font_main_y != self.fontMainYSpinBox.value(): - self.theme.font_main_y = self.fontMainYSpinBox.value() - self.previewTheme() - - def onFontMainWidthSpinBoxChanged(self): - if self.theme.font_main_width != self.fontMainWidthSpinBox.value(): - self.theme.font_main_width = self.fontMainWidthSpinBox.value() - self.previewTheme() - - def onFontMainLineAdjustmentSpinBoxChanged(self): - if self.theme.font_main_line_adjustment != \ - self.fontMainLineAdjustmentSpinBox.value(): - self.theme.font_main_line_adjustment = \ - self.fontMainLineAdjustmentSpinBox.value() - self.previewTheme() - - def onFontMainHeightSpinBoxChanged(self): - if self.theme.font_main_height != self.fontMainHeightSpinBox.value(): - self.theme.font_main_height = self.fontMainHeightSpinBox.value() - self.previewTheme() - # - # Footer Font Tab - # - def onFontFooterComboBoxSelected(self): - self.theme.font_footer_name = \ - self.fontFooterComboBox.currentFont().family() - self.previewTheme() - - def onFontFooterWeightComboBoxSelected(self, value): - if value == 0: - self.theme.font_footer_weight = u'Normal' - self.theme.font_footer_italics = False - elif value == 1: - self.theme.font_footer_weight = u'Bold' - self.theme.font_footer_italics = False - elif value == 2: - self.theme.font_footer_weight = u'Normal' - self.theme.font_footer_italics = True - else: - self.theme.font_footer_weight = u'Bold' - self.theme.font_footer_italics = True - self.previewTheme() - - def onFontFooterColorPushButtonClicked(self): - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.font_footer_color), self) - if new_color.isValid(): - self.theme.font_footer_color = new_color.name() - self.fontFooterColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(self.theme.font_footer_color)) - self.previewTheme() - - def onFontFooterSizeSpinBoxChanged(self): - if self.theme.font_footer_proportion != \ - self.fontFooterSizeSpinBox.value(): - self.theme.font_footer_proportion = \ - self.fontFooterSizeSpinBox.value() - self.previewTheme() - - def onFontFooterDefaultCheckBoxChanged(self, value): - if value == 2: # checked - self.theme.font_footer_override = False - else: - self.theme.font_footer_override = True - if not self.theme.font_footer_x and not self.theme.font_footer_y and \ - not self.theme.font_footer_width and \ - not self.theme.font_footer_height: - self.theme.font_footer_x = u'10' - self.theme.font_footer_y = u'730' - self.theme.font_footer_width = u'1024' - self.theme.font_footer_height = u'38' - self.fontFooterXSpinBox.setValue(self.theme.font_footer_x) - self.fontFooterYSpinBox.setValue(self.theme.font_footer_y) - self.fontFooterWidthSpinBox.setValue(self.theme.font_footer_width) - self.fontFooterHeightSpinBox.setValue( - self.theme.font_footer_height) - self.stateChanging(self.theme) - self.previewTheme() - - def onFontFooterXSpinBoxChanged(self): - if self.theme.font_footer_x != self.fontFooterXSpinBox.value(): - self.theme.font_footer_x = self.fontFooterXSpinBox.value() - self.previewTheme() - - def onFontFooterYSpinBoxChanged(self): - if self.theme.font_footer_y != self.fontFooterYSpinBox.value(): - self.theme.font_footer_y = self.fontFooterYSpinBox.value() - self.previewTheme() - - def onFontFooterWidthSpinBoxChanged(self): - if self.theme.font_footer_width != self.fontFooterWidthSpinBox.value(): - self.theme.font_footer_width = self.fontFooterWidthSpinBox.value() - self.previewTheme() - - def onFontFooterHeightSpinBoxChanged(self): - if self.theme.font_footer_height != \ - self.fontFooterHeightSpinBox.value(): - self.theme.font_footer_height = \ - self.fontFooterHeightSpinBox.value() - self.previewTheme() - # - # Background Tab - # - def onGradientComboBoxSelected(self, currentIndex): - self.setBackground(self.backgroundTypeComboBox.currentIndex(), - currentIndex) - - def onBackgroundTypeComboBoxSelected(self, currentIndex): - self.setBackground(currentIndex, self.gradientComboBox.currentIndex()) - - def setBackground(self, background, gradient): - if background == 0: # Solid - self.theme.background_type = u'solid' - if self.theme.background_color is None: - self.theme.background_color = u'#000000' - self.imageLineEdit.setText(u'') - elif background == 1: # Gradient - self.theme.background_type = u'gradient' - if gradient == 0: # Horizontal - self.theme.background_direction = u'horizontal' - elif gradient == 1: # vertical - self.theme.background_direction = u'vertical' - else: - self.theme.background_direction = u'circular' - if self.theme.background_start_color is None: - self.theme.background_start_color = u'#000000' - if self.theme.background_end_color is None: - self.theme.background_end_color = u'#ff0000' - self.imageLineEdit.setText(u'') - else: - self.theme.background_type = u'image' - self.stateChanging(self.theme) - self.previewTheme() - - def onColor1PushButtonClicked(self): - if self.theme.background_type == u'solid': - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.background_color), self) - if new_color.isValid(): - self.theme.background_color = new_color.name() - self.color1PushButton.setStyleSheet(u'background-color: %s' % - unicode(self.theme.background_color)) - else: - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.background_start_color), self) - if new_color.isValid(): - self.theme.background_start_color = new_color.name() - self.color1PushButton.setStyleSheet(u'background-color: %s' % - unicode(self.theme.background_start_color)) - self.previewTheme() - - def onColor2PushButtonClicked(self): - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.background_end_color), self) - if new_color.isValid(): - self.theme.background_end_color = new_color.name() - self.color2PushButton.setStyleSheet(u'background-color: %s' % - unicode(self.theme.background_end_color)) - self.previewTheme() - # - # Other Tab - # - def onOutlineCheckBoxChanged(self, value): - if value == 2: # checked - self.theme.display_outline = True - else: - self.theme.display_outline = False - self.stateChanging(self.theme) - self.previewTheme() - - def onOutlineSpinBoxChanged(self): - if self.theme.display_outline_size != self.outlineSpinBox.value(): - self.theme.display_outline_size = self.outlineSpinBox.value() - self.previewTheme() - - def onShadowSpinBoxChanged(self): - if self.theme.display_shadow_size != self.shadowSpinBox.value(): - self.theme.display_shadow_size = self.shadowSpinBox.value() - self.previewTheme() - - def onOutlineColorPushButtonClicked(self): - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.display_outline_color), self) - if new_color.isValid(): - self.theme.display_outline_color = new_color.name() - self.outlineColorPushButton.setStyleSheet(u'background-color: %s' % - unicode(self.theme.display_outline_color)) - self.previewTheme() - - def onShadowCheckBoxChanged(self, value): - if value == 2: # checked - self.theme.display_shadow = True - else: - self.theme.display_shadow = False - self.stateChanging(self.theme) - self.previewTheme() - - def onSlideTransitionCheckBoxChanged(self, value): - if value == 2: # checked - self.theme.display_slide_transition = True - else: - self.theme.display_slide_transition = False - self.stateChanging(self.theme) - self.previewTheme() - - def onShadowColorPushButtonClicked(self): - new_color = QtGui.QColorDialog.getColor( - QtGui.QColor(self.theme.display_shadow_color), self) - if new_color.isValid(): - self.theme.display_shadow_color = new_color.name() - self.shadowColorPushButton.setStyleSheet(u'background-color: %s' % - unicode(self.theme.display_shadow_color)) - self.previewTheme() - - def onHorizontalComboBoxSelected(self, currentIndex): - self.theme.display_horizontal_align = currentIndex - self.stateChanging(self.theme) - self.previewTheme() - - def onVerticalComboBoxSelected(self, currentIndex): - self.theme.display_vertical_align = currentIndex - self.stateChanging(self.theme) - self.previewTheme() - # - # Local Methods - # - def paintUi(self, theme): - self.stateChanging(theme) - self.themeNameEdit.setText(self.theme.theme_name) - # Background Tab - self.imageLineEdit.setText(u'') - if theme.background_type == u'solid': - self.backgroundTypeComboBox.setCurrentIndex(0) - elif theme.background_type == u'gradient': - self.backgroundTypeComboBox.setCurrentIndex(1) - else: - self.backgroundTypeComboBox.setCurrentIndex(2) - self.imageLineEdit.setText(self.theme.background_filename) - if self.theme.background_direction == u'horizontal': - self.gradientComboBox.setCurrentIndex(0) - elif self.theme.background_direction == u'vertical': - self.gradientComboBox.setCurrentIndex(1) - else: - self.gradientComboBox.setCurrentIndex(2) - # Font Main Tab - self.mainFontComboBox.setCurrentFont( - QtGui.QFont(self.theme.font_main_name)) - self.fontMainSizeSpinBox.setValue(self.theme.font_main_proportion) - if not self.theme.font_main_italics and \ - self.theme.font_main_weight == u'Normal': - self.fontMainWeightComboBox.setCurrentIndex(0) - elif not self.theme.font_main_italics and \ - self.theme.font_main_weight == u'Bold': - self.fontMainWeightComboBox.setCurrentIndex(1) - elif self.theme.font_main_italics and \ - self.theme.font_main_weight == u'Normal': - self.fontMainWeightComboBox.setCurrentIndex(2) - else: - self.fontMainWeightComboBox.setCurrentIndex(3) - self.fontMainXSpinBox.setValue(self.theme.font_main_x) - self.fontMainYSpinBox.setValue(self.theme.font_main_y) - self.fontMainWidthSpinBox.setValue(self.theme.font_main_width) - self.fontMainHeightSpinBox.setValue(self.theme.font_main_height) - # Font Footer Tab - self.fontFooterComboBox.setCurrentFont( - QtGui.QFont(self.theme.font_footer_name)) - self.fontFooterSizeSpinBox.setValue( - self.theme.font_footer_proportion) - if not self.theme.font_footer_italics and \ - self.theme.font_footer_weight == u'Normal': - self.fontFooterWeightComboBox.setCurrentIndex(0) - elif not self.theme.font_footer_italics and \ - self.theme.font_footer_weight == u'Bold': - self.fontFooterWeightComboBox.setCurrentIndex(1) - elif self.theme.font_footer_italics and \ - self.theme.font_footer_weight == u'Normal': - self.fontFooterWeightComboBox.setCurrentIndex(2) - else: - self.fontFooterWeightComboBox.setCurrentIndex(3) - self.fontFooterXSpinBox.setValue(self.theme.font_footer_x) - self.fontFooterYSpinBox.setValue(self.theme.font_footer_y) - self.fontFooterWidthSpinBox.setValue(self.theme.font_footer_width) - self.fontFooterHeightSpinBox.setValue(self.theme.font_footer_height) - self.fontMainColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(theme.font_main_color)) - self.fontFooterColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(theme.font_footer_color)) - if not self.theme.font_main_override: - self.fontMainDefaultCheckBox.setChecked(True) - else: - self.fontMainDefaultCheckBox.setChecked(False) - if not self.theme.font_footer_override: - self.fontFooterDefaultCheckBox.setChecked(True) - else: - self.fontFooterDefaultCheckBox.setChecked(False) - self.outlineColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(theme.display_outline_color)) - self.shadowColorPushButton.setStyleSheet( - u'background-color: %s' % unicode(theme.display_shadow_color)) - if self.theme.display_outline: - self.outlineCheckBox.setChecked(True) - self.outlineColorPushButton.setEnabled(True) - else: - self.outlineCheckBox.setChecked(False) - self.outlineColorPushButton.setEnabled(False) - self.outlineSpinBox.setValue(int(self.theme.display_outline_size)) - if self.theme.display_shadow: - self.shadowCheckBox.setChecked(True) - self.shadowColorPushButton.setEnabled(True) - else: - self.shadowCheckBox.setChecked(False) - self.shadowColorPushButton.setEnabled(False) - self.shadowSpinBox.setValue(int(self.theme.display_shadow_size)) - if self.theme.display_slide_transition: - self.slideTransitionCheckBox.setCheckState(QtCore.Qt.Checked) - else: - self.slideTransitionCheckBox.setCheckState(QtCore.Qt.Unchecked) - self.horizontalComboBox.setCurrentIndex( - self.theme.display_horizontal_align) - self.verticalComboBox.setCurrentIndex(self.theme.display_vertical_align) - - def stateChanging(self, theme): - self.backgroundTypeComboBox.setVisible(True) - self.backgroundTypeLabel.setVisible(True) - if theme.background_type == u'solid': - self.color1PushButton.setStyleSheet( - u'background-color: %s' % unicode(theme.background_color)) - self.color1Label.setText( - translate('OpenLP.AmendThemeForm', 'Color:')) - self.color1Label.setVisible(True) - self.color1PushButton.setVisible(True) - self.color2Label.setVisible(False) - self.color2PushButton.setVisible(False) - self.imageLabel.setVisible(False) - self.imageLineEdit.setVisible(False) - self.imageFilenameWidget.setVisible(False) - self.gradientLabel.setVisible(False) - self.gradientComboBox.setVisible(False) - elif theme.background_type == u'gradient': - self.color1PushButton.setStyleSheet(u'background-color: %s' \ - % unicode(theme.background_start_color)) - self.color2PushButton.setStyleSheet(u'background-color: %s' \ - % unicode(theme.background_end_color)) - self.color1Label.setText( - translate('OpenLP.AmendThemeForm', 'First color:')) - self.color2Label.setText( - translate('OpenLP.AmendThemeForm', 'Second color:')) - self.color1Label.setVisible(True) - self.color1PushButton.setVisible(True) - self.color2Label.setVisible(True) - self.color2PushButton.setVisible(True) - self.imageLabel.setVisible(False) - self.imageLineEdit.setVisible(False) - self.imageFilenameWidget.setVisible(False) - self.gradientLabel.setVisible(True) - self.gradientComboBox.setVisible(True) - else: # must be image - self.color1Label.setVisible(False) - self.color1PushButton.setVisible(False) - self.color2Label.setVisible(False) - self.color2PushButton.setVisible(False) - self.imageLabel.setVisible(True) - self.imageLineEdit.setVisible(True) - self.imageFilenameWidget.setVisible(True) - self.gradientLabel.setVisible(False) - self.gradientComboBox.setVisible(False) - if not theme.font_main_override: - self.fontMainXSpinBox.setEnabled(False) - self.fontMainYSpinBox.setEnabled(False) - self.fontMainWidthSpinBox.setEnabled(False) - self.fontMainHeightSpinBox.setEnabled(False) - else: - self.fontMainXSpinBox.setEnabled(True) - self.fontMainYSpinBox.setEnabled(True) - self.fontMainWidthSpinBox.setEnabled(True) - self.fontMainHeightSpinBox.setEnabled(True) - - if not theme.font_footer_override: - self.fontFooterXSpinBox.setEnabled(False) - self.fontFooterYSpinBox.setEnabled(False) - self.fontFooterWidthSpinBox.setEnabled(False) - self.fontFooterHeightSpinBox.setEnabled(False) - else: - self.fontFooterXSpinBox.setEnabled(True) - self.fontFooterYSpinBox.setEnabled(True) - self.fontFooterWidthSpinBox.setEnabled(True) - self.fontFooterHeightSpinBox.setEnabled(True) - - if self.theme.display_outline: - self.outlineColorPushButton.setEnabled(True) - else: - self.outlineColorPushButton.setEnabled(False) - - if self.theme.display_shadow: - self.shadowColorPushButton.setEnabled(True) - else: - self.shadowColorPushButton.setEnabled(False) - - def previewTheme(self): - if self.allowPreview: - #calculate main number of rows - metrics = self._getThemeMetrics() - line_height = metrics.height() \ - + int(self.theme.font_main_line_adjustment) - if self.theme.display_shadow: - line_height += int(self.theme.display_shadow_size) - if self.theme.display_outline: - # pixels top/bottom - line_height += 2 * int(self.theme.display_outline_size) - page_length = \ - ((self.fontMainHeightSpinBox.value()) / line_height ) - log.debug(u'Page Length area height %s, metrics %s, lines %s' % - (self.fontMainHeightSpinBox.value(), metrics.height(), - page_length)) - page_length_text = unicode( - translate('OpenLP.AmendThemeForm', 'Slide height is %s rows.')) - self.fontMainLinesPageLabel.setText(page_length_text % page_length) - frame = self.thememanager.generateImage(self.theme) - self.themePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) - - def _getThemeMetrics(self): - main_weight = 50 - if self.theme.font_main_weight == u'Bold': - main_weight = 75 - mainFont = QtGui.QFont(self.theme.font_main_name, - self.theme.font_main_proportion, # size - main_weight, # weight - self.theme.font_main_italics)# italic - mainFont.setPixelSize(self.theme.font_main_proportion) - metrics = QtGui.QFontMetrics(mainFont) - # Validate that the screen width is big enough to display the text - if self.theme.font_main_width < metrics.maxWidth() * 2 + 64: - self.theme.font_main_width = metrics.maxWidth() * 2 + 64 - self.fontMainWidthSpinBox.setValue(self.theme.font_main_width) - return metrics diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py index 49e2c8151..03bbde764 100644 --- a/openlp/core/ui/exceptiondialog.py +++ b/openlp/core/ui/exceptiondialog.py @@ -26,7 +26,7 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, build_icon class Ui_ExceptionDialog(object): def setupUi(self, exceptionDialog): @@ -63,12 +63,27 @@ class Ui_ExceptionDialog(object): self.exceptionButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Close) self.exceptionButtonBox.setObjectName(u'exceptionButtonBox') self.exceptionLayout.addWidget(self.exceptionButtonBox) + self.sendReportButton = QtGui.QPushButton(exceptionDialog) + self.sendReportButton.setIcon(build_icon( + u':/general/general_email.png')) + self.sendReportButton.setObjectName(u'sendReportButton') + self.exceptionButtonBox.addButton(self.sendReportButton, + QtGui.QDialogButtonBox.ActionRole) + self.saveReportButton = QtGui.QPushButton(exceptionDialog) + self.saveReportButton.setIcon(build_icon(u':/general/general_save.png')) + self.saveReportButton.setObjectName(u'saveReportButton') + self.exceptionButtonBox.addButton(self.saveReportButton, + QtGui.QDialogButtonBox.ActionRole) self.retranslateUi(exceptionDialog) QtCore.QObject.connect(self.exceptionButtonBox, QtCore.SIGNAL(u'accepted()'), exceptionDialog.accept) QtCore.QObject.connect(self.exceptionButtonBox, QtCore.SIGNAL(u'rejected()'), exceptionDialog.reject) + QtCore.QObject.connect(self.sendReportButton, + QtCore.SIGNAL(u'pressed()'), self.onSendReportButtonPressed) + QtCore.QObject.connect(self.saveReportButton, + QtCore.SIGNAL(u'pressed()'), self.onSaveReportButtonPressed) QtCore.QMetaObject.connectSlotsByName(exceptionDialog) def retranslateUi(self, exceptionDialog): @@ -80,3 +95,7 @@ class Ui_ExceptionDialog(object): 'developers, so please e-mail it to bugs@openlp.org, along with a ' 'detailed description of what you were doing when the problem ' 'occurred.')) + self.sendReportButton.setText(translate('OpenLP.ExceptionDialog', + 'Send E-Mail')) + self.saveReportButton.setText(translate('OpenLP.ExceptionDialog', + 'Save to File')) diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index b40c9e063..cc66f21d7 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -24,7 +24,38 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtGui +import re +import os +import platform + +import sqlalchemy +import BeautifulSoup +from lxml import etree +from PyQt4 import Qt, QtCore, QtGui + +try: + from PyQt4.phonon import Phonon + phonon_version = Phonon.phononVersion() +except ImportError: + phonon_version = u'-' +try: + import chardet + chardet_version = chardet.__version__ +except ImportError: + chardet_version = u'-' +try: + import enchant + enchant_version = enchant.__version__ +except ImportError: + enchant_version = u'-' +try: + import sqlite + sqlite_version = sqlite.version +except ImportError: + sqlite_version = u'-' + +from openlp.core.lib import translate, SettingsManager +from openlp.core.lib.mailto import mailto from exceptiondialog import Ui_ExceptionDialog @@ -35,3 +66,78 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): def __init__(self, parent): QtGui.QDialog.__init__(self, parent) self.setupUi(self) + self.settingsSection = u'crashreport' + + def _createReport(self): + openlp_version = self.parent().applicationVersion[u'full'] + traceback = unicode(self.exceptionTextEdit.toPlainText()) + system = unicode(translate('OpenLP.ExceptionForm', + 'Platform: %s\n')) % platform.platform() + libraries = u'Python: %s\n' % platform.python_version() + \ + u'Qt4: %s\n' % Qt.qVersion() + \ + u'Phonon: %s\n' % phonon_version + \ + u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \ + u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \ + u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \ + u'lxml: %s\n' % etree.__version__ + \ + u'Chardet: %s\n' % chardet_version + \ + u'PyEnchant: %s\n' % enchant_version + \ + u'PySQLite: %s\n' % sqlite_version + if platform.system() == u'Linux': + if os.environ.get(u'KDE_FULL_SESSION') == u'true': + system = system + u'Desktop: KDE SC\n' + elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'): + system = system + u'Desktop: GNOME\n' + return (openlp_version, traceback, system, libraries) + + def onSaveReportButtonPressed(self): + """ + Saving exception log and system informations to a file. + """ + report = unicode(translate('OpenLP.ExceptionForm', + '**OpenLP Bug Report**\n' + 'Version: %s\n\n' + '--- Exception Traceback ---\n%s\n' + '--- System information ---\n%s\n' + '--- Library Versions ---\n%s\n')) + filename = QtGui.QFileDialog.getSaveFileName(self, + translate('OpenLP.ExceptionForm', 'Save Crash Report'), + SettingsManager.get_last_dir(self.settingsSection), + translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)')) + if filename: + filename = unicode(QtCore.QDir.toNativeSeparators(filename)) + SettingsManager.set_last_dir(self.settingsSection, os.path.dirname( + filename)) + report = report % self._createReport() + try: + file = open(filename, u'w') + try: + file.write(report) + except UnicodeError: + file.close() + file = open(filename, u'wb') + file.write(report.encode(u'utf-8')) + file.close() + except IOError: + log.exception(u'Failed to write crash report') + + def onSendReportButtonPressed(self): + """ + Opening systems default email client and inserting exception log and + system informations. + """ + body = unicode(translate('OpenLP.ExceptionForm', + '*OpenLP Bug Report*\n' + 'Version: %s\n\n' + '--- Please enter the report below this line. ---\n\n\n' + '--- Exception Traceback ---\n%s\n' + '--- System information ---\n%s\n' + '--- Library Versions ---\n%s\n')) + content = self._createReport() + for line in content[1].split(u'\n'): + if re.search(r'[/\\]openlp[/\\]', line): + source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line) + if u':' in line: + exception = line.split(u'\n')[-1].split(u':')[0] + subject = u'Bug report: %s in %s' % (exception, source) + mailto(address=u'bugs@openlp.org', subject=subject, body=body % content) diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py index 02eefe7ed..600027940 100644 --- a/openlp/core/ui/filerenamedialog.py +++ b/openlp/core/ui/filerenamedialog.py @@ -30,24 +30,24 @@ from openlp.core.lib import translate class Ui_FileRenameDialog(object): def setupUi(self, FileRenameDialog): - FileRenameDialog.setObjectName("FileRenameDialog") + FileRenameDialog.setObjectName(u'FileRenameDialog') FileRenameDialog.resize(400, 87) self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog) self.buttonBox.setGeometry(QtCore.QRect(210, 50, 171, 25)) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") + self.buttonBox.setObjectName(u'buttonBox') self.widget = QtGui.QWidget(FileRenameDialog) self.widget.setGeometry(QtCore.QRect(10, 10, 381, 35)) - self.widget.setObjectName("widget") + self.widget.setObjectName(u'widget') self.horizontalLayout = QtGui.QHBoxLayout(self.widget) - self.horizontalLayout.setObjectName("horizontalLayout") - self.FileRenameLabel = QtGui.QLabel(self.widget) - self.FileRenameLabel.setObjectName("FileRenameLabel") - self.horizontalLayout.addWidget(self.FileRenameLabel) - self.FileNameEdit = QtGui.QLineEdit(self.widget) - self.FileNameEdit.setObjectName("FileNameEdit") - self.horizontalLayout.addWidget(self.FileNameEdit) + self.horizontalLayout.setObjectName(u'horizontalLayout') + self.fileRenameLabel = QtGui.QLabel(self.widget) + self.fileRenameLabel.setObjectName(u'fileRenameLabel') + self.horizontalLayout.addWidget(self.fileRenameLabel) + self.fileNameEdit = QtGui.QLineEdit(self.widget) + self.fileNameEdit.setObjectName(u'fileNameEdit') + self.horizontalLayout.addWidget(self.fileNameEdit) self.retranslateUi(FileRenameDialog) QtCore.QMetaObject.connectSlotsByName(FileRenameDialog) @@ -55,6 +55,5 @@ class Ui_FileRenameDialog(object): def retranslateUi(self, FileRenameDialog): FileRenameDialog.setWindowTitle(translate('OpenLP.FileRenameForm', 'File Rename')) - self.FileRenameLabel.setText(translate('OpenLP.FileRenameForm', + self.fileRenameLabel.setText(translate('OpenLP.FileRenameForm', 'New File Name:')) - diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index d8481e801..b8894fe9a 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -23,11 +23,34 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate +log = logging.getLogger(__name__) + +class ValidEdit(QtGui.QLineEdit): + """ + Only allow numeric characters to be edited + """ + def __init__(self, parent): + """ + Set up Override and Validator + """ + QtGui.QLineEdit.__init__(self, parent) + self.setValidator(QtGui.QIntValidator(0, 9999, self)) + + def validText(self): + """ + Only return Integers. Space is 0 + """ + if self.text().isEmpty(): + return QtCore.QString(u'0') + else: + return self.text() + class GeneralTab(SettingsTab): """ GeneralTab is the general settings tab in the settings dialog. @@ -240,7 +263,7 @@ class GeneralTab(SettingsTab): self.customXLabel.setAlignment(QtCore.Qt.AlignCenter) self.customXLabel.setObjectName(u'customXLabel') self.customXLayout.addWidget(self.customXLabel) - self.customXValueEdit = QtGui.QLineEdit(self.displayGroupBox) + self.customXValueEdit = ValidEdit(self.displayGroupBox) self.customXValueEdit.setObjectName(u'customXValueEdit') self.customXLayout.addWidget(self.customXValueEdit) self.customLayout.addLayout(self.customXLayout) @@ -252,7 +275,7 @@ class GeneralTab(SettingsTab): self.customYLabel.setAlignment(QtCore.Qt.AlignCenter) self.customYLabel.setObjectName(u'customYLabel') self.customYLayout.addWidget(self.customYLabel) - self.customYValueEdit = QtGui.QLineEdit(self.displayGroupBox) + self.customYValueEdit = ValidEdit(self.displayGroupBox) self.customYValueEdit.setObjectName(u'customYValueEdit') self.customYLayout.addWidget(self.customYValueEdit) self.customLayout.addLayout(self.customYLayout) @@ -265,7 +288,7 @@ class GeneralTab(SettingsTab): self.customWidthLabel.setAlignment(QtCore.Qt.AlignCenter) self.customWidthLabel.setObjectName(u'customWidthLabel') self.customWidthLayout.addWidget(self.customWidthLabel) - self.customWidthValueEdit = QtGui.QLineEdit(self.displayGroupBox) + self.customWidthValueEdit = ValidEdit(self.displayGroupBox) self.customWidthValueEdit.setObjectName(u'customWidthValueEdit') self.customWidthLayout.addWidget(self.customWidthValueEdit) self.customLayout.addLayout(self.customWidthLayout) @@ -277,7 +300,7 @@ class GeneralTab(SettingsTab): self.customHeightLabel.setAlignment(QtCore.Qt.AlignCenter) self.customHeightLabel.setObjectName(u'customHeightLabel') self.customHeightLayout.addWidget(self.customHeightLabel) - self.customHeightValueEdit = QtGui.QLineEdit(self.displayGroupBox) + self.customHeightValueEdit = ValidEdit(self.displayGroupBox) self.customHeightValueEdit.setObjectName(u'customHeightValueEdit') self.customHeightLayout.addWidget(self.customHeightValueEdit) self.customLayout.addLayout(self.customHeightLayout) @@ -465,10 +488,10 @@ class GeneralTab(SettingsTab): # Reset screens after initial definition if self.overrideChanged: self.screens.override[u'size'] = QtCore.QRect( - int(self.customXValueEdit.text()), - int(self.customYValueEdit.text()), - int(self.customWidthValueEdit.text()), - int(self.customHeightValueEdit.text())) + int(self.customXValueEdit.validText()), + int(self.customYValueEdit.validText()), + int(self.customWidthValueEdit.validText()), + int(self.customHeightValueEdit.validText())) if self.overrideCheckBox.isChecked(): self.screens.set_override_display() else: diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 5a53a84fe..69eb9305d 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -23,7 +23,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +""" import logging import os @@ -100,7 +101,7 @@ class MainDisplay(DisplayWidget): self.screens = screens self.isLive = live self.alertTab = None - self.hide_mode = None + self.hideMode = None self.setWindowTitle(u'OpenLP Display') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setWindowFlags(QtCore.Qt.FramelessWindowHint | @@ -229,7 +230,7 @@ class MainDisplay(DisplayWidget): """ API for replacement backgrounds so Images are added directly to cache """ - image = self.imageManager.add_image(name, path) + self.imageManager.add_image(name, path) self.image(name) def image(self, name): @@ -381,8 +382,8 @@ class MainDisplay(DisplayWidget): if self.isLive: self.setVisible(True) # if was hidden keep it hidden - if self.hide_mode and self.isLive: - self.hideDisplay(self.hide_mode) + if self.hideMode and self.isLive: + self.hideDisplay(self.hideMode) preview = QtGui.QImage(self.screen[u'size'].width(), self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) @@ -412,8 +413,8 @@ class MainDisplay(DisplayWidget): if serviceItem.foot_text and serviceItem.foot_text: self.footer(serviceItem.foot_text) # if was hidden keep it hidden - if self.hide_mode and self.isLive: - self.hideDisplay(self.hide_mode) + if self.hideMode and self.isLive: + self.hideDisplay(self.hideMode) def footer(self, text): """ @@ -444,7 +445,7 @@ class MainDisplay(DisplayWidget): self.setVisible(True) if self.phononActive: self.webView.setVisible(True) - self.hide_mode = mode + self.hideMode = mode def showDisplay(self): """ @@ -459,9 +460,9 @@ class MainDisplay(DisplayWidget): if self.phononActive: self.webView.setVisible(False) self.videoPlay() + self.hideMode = None # Trigger actions when display is active again Receiver.send_message(u'maindisplay_active') - self.hide_mode = None class AudioPlayer(QtCore.QObject): """ diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index a513cc99e..a319e005f 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -97,16 +97,16 @@ class Ui_MainWindow(object): self.ControlSplitter.setObjectName(u'ControlSplitter') self.MainContentLayout.addWidget(self.ControlSplitter) # Create slide controllers - self.PreviewController = SlideController(self, self.settingsmanager, + self.previewController = SlideController(self, self.settingsmanager, self.screens) - self.LiveController = SlideController(self, self.settingsmanager, + self.liveController = SlideController(self, self.settingsmanager, self.screens, True) previewVisible = QtCore.QSettings().value( u'user interface/preview panel', QtCore.QVariant(True)).toBool() - self.PreviewController.Panel.setVisible(previewVisible) + self.previewController.Panel.setVisible(previewVisible) liveVisible = QtCore.QSettings().value(u'user interface/live panel', QtCore.QVariant(True)).toBool() - self.LiveController.Panel.setVisible(liveVisible) + self.liveController.Panel.setVisible(liveVisible) # Create menu self.MenuBar = QtGui.QMenuBar(MainWindow) self.MenuBar.setGeometry(QtCore.QRect(0, 0, 1087, 27)) @@ -362,8 +362,8 @@ class Ui_MainWindow(object): """ Splitter between the Preview and Live Controllers. """ - self.LiveController.widthChanged() - self.PreviewController.widthChanged() + self.liveController.widthChanged() + self.previewController.widthChanged() def retranslateUi(self, MainWindow): """ @@ -548,8 +548,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.recentFiles = QtCore.QStringList() # Set up the path with plugins pluginpath = AppLocation.get_directory(AppLocation.PluginsDir) - self.plugin_manager = PluginManager(pluginpath) - self.plugin_helpers = {} + self.pluginManager = PluginManager(pluginpath) + self.pluginHelpers = {} # Set up the interface self.setupUi(self) # Load settings after setupUi so default UI sizes are overwritten @@ -627,39 +627,39 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # warning cyclic dependency # RenderManager needs to call ThemeManager and # ThemeManager needs to call RenderManager - self.RenderManager = RenderManager( + self.renderManager = RenderManager( self.ThemeManagerContents, self.screens) # Define the media Dock Manager self.mediaDockManager = MediaDockManager(self.MediaToolBox) log.info(u'Load Plugins') # make the controllers available to the plugins - self.plugin_helpers[u'preview'] = self.PreviewController - self.plugin_helpers[u'live'] = self.LiveController - self.plugin_helpers[u'render'] = self.RenderManager - self.plugin_helpers[u'service'] = self.ServiceManagerContents - self.plugin_helpers[u'settings form'] = self.settingsForm - self.plugin_helpers[u'toolbox'] = self.mediaDockManager - self.plugin_helpers[u'pluginmanager'] = self.plugin_manager - self.plugin_helpers[u'formparent'] = self - self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers) + self.pluginHelpers[u'preview'] = self.previewController + self.pluginHelpers[u'live'] = self.liveController + self.pluginHelpers[u'render'] = self.renderManager + self.pluginHelpers[u'service'] = self.ServiceManagerContents + self.pluginHelpers[u'settings form'] = self.settingsForm + self.pluginHelpers[u'toolbox'] = self.mediaDockManager + self.pluginHelpers[u'pluginmanager'] = self.pluginManager + self.pluginHelpers[u'formparent'] = self + self.pluginManager.find_plugins(pluginpath, self.pluginHelpers) # hook methods have to happen after find_plugins. Find plugins needs # the controllers hence the hooks have moved from setupUI() to here # Find and insert settings tabs log.info(u'hook settings') - self.plugin_manager.hook_settings_tabs(self.settingsForm) + self.pluginManager.hook_settings_tabs(self.settingsForm) # Find and insert media manager items log.info(u'hook media') - self.plugin_manager.hook_media_manager(self.mediaDockManager) + self.pluginManager.hook_media_manager(self.mediaDockManager) # Call the hook method to pull in import menus. log.info(u'hook menus') - self.plugin_manager.hook_import_menu(self.FileImportMenu) + self.pluginManager.hook_import_menu(self.FileImportMenu) # Call the hook method to pull in export menus. - self.plugin_manager.hook_export_menu(self.FileExportMenu) + self.pluginManager.hook_export_menu(self.FileExportMenu) # Call the hook method to pull in tools menus. - self.plugin_manager.hook_tools_menu(self.ToolsMenu) + self.pluginManager.hook_tools_menu(self.ToolsMenu) # Call the initialise method to setup plugins. log.info(u'initialise plugins') - self.plugin_manager.initialise_plugins() + self.pluginManager.initialise_plugins() # Once all components are initialised load the Themes log.info(u'Load Themes') self.ThemeManagerContents.loadThemes() @@ -695,10 +695,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): Show the main form, as well as the display form """ QtGui.QWidget.show(self) - self.LiveController.display.setup() - self.PreviewController.display.setup() - if self.LiveController.display.isVisible(): - self.LiveController.display.setFocus() + self.liveController.display.setup() + self.previewController.display.setup() + if self.liveController.display.isVisible(): + self.liveController.display.setFocus() self.activateWindow() if QtCore.QSettings().value( self.generalSettingsSection + u'/auto open', @@ -723,7 +723,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): settings = QtCore.QSettings() if settings.value(u'%s/screen blank' % self.generalSettingsSection, QtCore.QVariant(False)).toBool(): - self.LiveController.mainDisplaySetBackground() + self.liveController.mainDisplaySetBackground() if settings.value(u'blank warning', QtCore.QVariant(False)).toBool(): QtGui.QMessageBox.question(self, @@ -809,7 +809,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): their locations """ log.debug(u'screenChanged') - self.RenderManager.update_display() + self.renderManager.update_display() self.setFocus() self.activateWindow() @@ -852,11 +852,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.QVariant(self.MediaToolBox.currentIndex())) # Call the cleanup method to shutdown plugins. log.info(u'cleanup plugins') - self.plugin_manager.finalise_plugins() + self.pluginManager.finalise_plugins() # Save settings self.saveSettings() # Close down the display - self.LiveController.display.close() + self.liveController.display.close() def serviceChanged(self, reset=False, serviceName=None): """ @@ -910,7 +910,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): True - Visible False - Hidden """ - self.PreviewController.Panel.setVisible(visible) + self.previewController.Panel.setVisible(visible) QtCore.QSettings().setValue(u'user interface/preview panel', QtCore.QVariant(visible)) self.ViewPreviewPanel.setChecked(visible) @@ -925,7 +925,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): True - Visible False - Hidden """ - self.LiveController.Panel.setVisible(visible) + self.liveController.Panel.setVisible(visible) QtCore.QSettings().setValue(u'user interface/live panel', QtCore.QVariant(visible)) self.ViewLivePanel.setChecked(visible) diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index a857caee7..3d3a814a0 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -61,7 +61,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): self.programaticChange = True self._clearDetails() self.programaticChange = True - for plugin in self.parent.plugin_manager.plugins: + 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 # sometimes when it's loaded from the config, it isn't cast to int. @@ -110,7 +110,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): plugin_name_plural = \ self.pluginListWidget.currentItem().text().split(u' ')[0] self.activePlugin = None - for plugin in self.parent.plugin_manager.plugins: + for plugin in self.parent.pluginManager.plugins: name_string = plugin.getString(StringContent.Name) if name_string[u'plural'] == plugin_name_plural: self.activePlugin = plugin diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py index f385754f5..e57474315 100644 --- a/openlp/core/ui/serviceitemeditform.py +++ b/openlp/core/ui/serviceitemeditform.py @@ -64,8 +64,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog): self.item._raw_frames = [] if self.item.is_image(): for item in self.itemList: - self.item.add_from_image(item[u'path'], item[u'title'], - item[u'image']) + self.item.add_from_image(item[u'path'], item[u'title']) self.item.render() return self.item diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index f294cedd4..32e46dffb 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -759,7 +759,7 @@ class ServiceManager(QtGui.QWidget): self.onNewService() for item in items: serviceitem = ServiceItem() - serviceitem.render_manager = self.parent.RenderManager + serviceitem.render_manager = self.parent.renderManager serviceitem.set_from_service(item, self.servicePath) self.validateItem(serviceitem) self.addServiceItem(serviceitem) @@ -789,6 +789,8 @@ class ServiceManager(QtGui.QWidget): self.serviceName = name[len(name) - 1] self.parent.addRecentFile(filename) self.parent.serviceChanged(True, self.serviceName) + # Refresh Plugin lists + Receiver.send_message(u'plugin_list_refresh') def validateItem(self, serviceItem): """ @@ -818,7 +820,7 @@ 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.parent.renderManager.set_service_theme(self.service_theme) QtCore.QSettings().setValue( self.parent.serviceSettingsSection + u'/service theme', QtCore.QVariant(self.service_theme)) @@ -830,7 +832,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.parent.renderManager.theme_level == ThemeLevel.Global: self.toolbar.actions[u'ThemeLabel'].setVisible(False) self.toolbar.actions[u'ThemeWidget'].setVisible(False) else: @@ -844,7 +846,7 @@ class ServiceManager(QtGui.QWidget): """ log.debug(u'regenerateServiceItems') # force reset of renderer as theme data has changed - self.parent.RenderManager.themedata = None + self.parent.renderManager.themedata = None if self.serviceItems: tempServiceItems = self.serviceItems self.serviceManagerList.clear() @@ -878,7 +880,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.parent.liveController.replaceServiceManagerItem(newItem) self.parent.serviceChanged(False, self.serviceName) def addServiceItem(self, item, rebuild=False, expand=None, replace=False): @@ -900,7 +902,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.parent.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd if self.droppos == 0: @@ -921,7 +923,7 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(self.droppos, 0) # if rebuilding list make sure live is fixed. if rebuild: - self.parent.LiveController.replaceServiceManagerItem(item) + self.parent.liveController.replaceServiceManagerItem(item) self.droppos = 0 self.parent.serviceChanged(False, self.serviceName) @@ -931,7 +933,7 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.PreviewController.addServiceManagerItem( + self.parent.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) else: QtGui.QMessageBox.critical(self, @@ -955,7 +957,7 @@ class ServiceManager(QtGui.QWidget): """ item, count = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: - self.parent.LiveController.addServiceManagerItem( + self.parent.liveController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) if QtCore.QSettings().value( self.parent.generalSettingsSection + u'/auto preview', @@ -964,9 +966,9 @@ class ServiceManager(QtGui.QWidget): if self.serviceItems and item < len(self.serviceItems) and \ self.serviceItems[item][u'service_item'].is_capable( ItemCapabilities.AllowsPreview): - self.parent.PreviewController.addServiceManagerItem( + self.parent.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], 0) - self.parent.LiveController.PreviewListWidget.setFocus() + self.parent.liveController.PreviewListWidget.setFocus() else: QtGui.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Missing Display Handler'), @@ -1028,6 +1030,9 @@ class ServiceManager(QtGui.QWidget): # ServiceManager started the drag and drop if plugin == u'ServiceManager': startpos, startCount = self.findServiceItem() + # If no items selected + if startpos == -1: + return if item is None: endpos = len(self.serviceItems) else: @@ -1083,7 +1088,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.parent.renderManager.set_service_theme(self.service_theme) self.regenerateServiceItems() def onThemeChangeAction(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 0afb0efaa..4f75a3ce0 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -331,10 +331,8 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(self.PreviewListWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) if not self.isLive: - if QtCore.QSettings().value(u'advanced/double click live', - QtCore.QVariant(False)).toBool(): - QtCore.QObject.connect(self.PreviewListWidget, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLive) + QtCore.QObject.connect(self.PreviewListWidget, + QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick) if isLive: QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), @@ -391,6 +389,8 @@ class SlideController(QtGui.QWidget): if self.isLive: QtCore.QObject.connect(self.volumeSlider, QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview) def screenSizeChanged(self): """ @@ -400,7 +400,7 @@ class SlideController(QtGui.QWidget): 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 + self.display.imageManager = self.parent.renderManager.image_manager self.display.alertTab = self.alertTab self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) @@ -416,7 +416,7 @@ class SlideController(QtGui.QWidget): """ log.debug(u'widthChanged live = %s' % self.isLive) width = self.parent.ControlSplitter.sizes()[self.split] - height = width * self.parent.RenderManager.screen_ratio + height = width * self.parent.renderManager.screen_ratio self.PreviewListWidget.setColumnWidth(0, width) # Sort out image heights (Songs, bibles excluded) if self.serviceItem and not self.serviceItem.is_text(): @@ -466,7 +466,7 @@ class SlideController(QtGui.QWidget): self.Toolbar.actions[u'Stop Loop'].setVisible(False) if item.is_text(): if QtCore.QSettings().value( - self.parent.songsSettingsSection + u'/show songbar', + self.parent.songsSettingsSection + u'/display songbar', QtCore.QVariant(True)).toBool() and len(self.slideList) > 0: self.Toolbar.makeWidgetsVisible([u'Song Menu']) if item.is_capable(ItemCapabilities.AllowsLoop) and \ @@ -560,7 +560,7 @@ class SlideController(QtGui.QWidget): [serviceItem, self.isLive, blanked, slideno]) self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] - # Set pointing cursor when we have somthing to point at + # Set pointing cursor when we have something to point at self.PreviewListWidget.setCursor(QtCore.Qt.PointingHandCursor) self.serviceItem = serviceItem self.PreviewListWidget.clear() @@ -595,14 +595,14 @@ class SlideController(QtGui.QWidget): label.setScaledContents(True) if self.serviceItem.is_command(): image = resize_image(frame[u'image'], - self.parent.RenderManager.width, - self.parent.RenderManager.height) + self.parent.renderManager.width, + self.parent.renderManager.height) else: - image = self.parent.RenderManager.image_manager. \ + image = self.parent.renderManager.image_manager. \ get_image(frame[u'title']) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.PreviewListWidget.setCellWidget(framenumber, 0, label) - slideHeight = width * self.parent.RenderManager.screen_ratio + slideHeight = width * self.parent.renderManager.screen_ratio row += 1 text.append(unicode(row)) self.PreviewListWidget.setItem(framenumber, 0, item) @@ -823,16 +823,15 @@ class SlideController(QtGui.QWidget): row) def updatePreview(self): + log.debug(u'updatePreview %s ' %self.screens.current[u'primary']) if not self.screens.current[u'primary']: # Grab now, but try again in a couple of seconds if slide change # is slow QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) QtCore.QTimer.singleShot(2.5, self.grabMainDisplay) else: - label = self.PreviewListWidget.cellWidget( - self.PreviewListWidget.currentRow(), 1) - if label: - self.SlidePreview.setPixmap(label.pixmap()) + self.SlidePreview.setPixmap( + QtGui.QPixmap.fromImage(self.display.preview())) def grabMainDisplay(self): winid = QtGui.QApplication.desktop().winId() @@ -944,13 +943,21 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(), u'P:%s' % self.serviceItem.edit_id) + def onGoLiveClick(self): + """ + triggered by clicking the Preview slide items + """ + if QtCore.QSettings().value(u'advanced/double click live', + QtCore.QVariant(False)).toBool(): + self.onGoLive() + def onGoLive(self): """ If preview copy slide item to live """ row = self.PreviewListWidget.currentRow() if row > -1 and row < self.PreviewListWidget.rowCount(): - self.parent.LiveController.addServiceManagerItem( + self.parent.liveController.addServiceManagerItem( self.serviceItem, row) def onMediaStart(self, item): diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index cc52abafc..7ed58e943 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -55,30 +55,34 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.setupUi(self) self.registerFields() self.accepted = False + self.updateThemeAllowed = True QtCore.QObject.connect(self.backgroundTypeComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onBackgroundComboBox) QtCore.QObject.connect(self.gradientComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onGradientComboBox) - QtCore.QObject.connect(self.color1PushButton, + QtCore.QObject.connect(self.colorButton, QtCore.SIGNAL(u'pressed()'), - self.onColor1PushButtonClicked) - QtCore.QObject.connect(self.color2PushButton, + self.onColorButtonClicked) + QtCore.QObject.connect(self.gradientStartButton, QtCore.SIGNAL(u'pressed()'), - self.onColor2PushButtonClicked) + self.onGradientStartButtonClicked) + QtCore.QObject.connect(self.gradientEndButton, + QtCore.SIGNAL(u'pressed()'), + self.onGradientEndButtonClicked) QtCore.QObject.connect(self.imageBrowseButton, QtCore.SIGNAL(u'pressed()'), - self.onImageBrowseButtonClicked) + self.onImageBrowseButtonClicked) QtCore.QObject.connect(self.mainColorPushButton, QtCore.SIGNAL(u'pressed()'), - self.onMainColourPushButtonClicked) + self.onMainColourPushButtonClicked) QtCore.QObject.connect(self.outlineColorPushButton, QtCore.SIGNAL(u'pressed()'), - self.onOutlineColourPushButtonClicked) + self.onOutlineColourPushButtonClicked) QtCore.QObject.connect(self.shadowColorPushButton, QtCore.SIGNAL(u'pressed()'), - self.onShadowColourPushButtonClicked) + self.onShadowColourPushButtonClicked) QtCore.QObject.connect(self.outlineCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckCheckBoxChanged) @@ -157,15 +161,15 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.backgroundPage.registerField( u'background_type', self.backgroundTypeComboBox) self.backgroundPage.registerField( - u'color_1', self.color1PushButton) + u'color', self.colorButton) self.backgroundPage.registerField( - u'color_2', self.color2PushButton) + u'grandient_start', self.gradientStartButton) + self.backgroundPage.registerField( + u'grandient_end', self.gradientEndButton) self.backgroundPage.registerField( u'background_image', self.imageLineEdit) self.backgroundPage.registerField( u'gradient', self.gradientComboBox) - self.mainAreaPage.registerField( - u'mainFontComboBox', self.mainFontComboBox) self.mainAreaPage.registerField( u'mainColorPushButton', self.mainColorPushButton) self.mainAreaPage.registerField( @@ -281,11 +285,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.footerHeightSpinBox.setEnabled(self.theme.font_footer_override) self.footerWidthSpinBox.setEnabled(self.theme.font_footer_override) - def exec_(self): + def exec_(self, edit=False): """ Run the wizard. """ + log.debug(u'Editing theme %s' % self.theme.theme_name) + self.updateThemeAllowed = False self.setDefaults() + self.updateThemeAllowed = True + if edit: + self.next() return QtGui.QWizard.exec_(self) def initializePage(self, id): @@ -311,54 +320,19 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ if self.theme.background_type == \ BackgroundType.to_string(BackgroundType.Solid): - self.setField(u'background_type', QtCore.QVariant(0)) - self.color1PushButton.setVisible(True) - self.color1Label.setVisible(True) - self.color1PushButton.setStyleSheet(u'background-color: %s' % + self.colorButton.setStyleSheet(u'background-color: %s' % self.theme.background_color) - self.color1Label.setText( - translate('OpenLP.ThemeForm', 'Color:')) - self.color2PushButton.setVisible(False) - self.color2Label.setVisible(False) - self.gradientLabel.setVisible(False) - self.gradientComboBox.setVisible(False) - self.imageLabel.setVisible(False) - self.imageLineEdit.setVisible(False) - self.imageBrowseButton.setVisible(False) - self.imageLineEdit.setText(u'') + self.setField(u'background_type', QtCore.QVariant(0)) elif self.theme.background_type == \ BackgroundType.to_string(BackgroundType.Gradient): - self.setField(u'background_type', QtCore.QVariant(1)) - self.color1PushButton.setVisible(True) - self.color1Label.setVisible(True) - self.color1PushButton.setStyleSheet(u'background-color: %s' % + self.gradientStartButton.setStyleSheet(u'background-color: %s' % self.theme.background_start_color) - self.color1Label.setText( - translate('OpenLP.ThemeForm', 'First color:')) - self.color2PushButton.setVisible(True) - self.color2Label.setVisible(True) - self.color2PushButton.setStyleSheet(u'background-color: %s' % + self.gradientEndButton.setStyleSheet(u'background-color: %s' % self.theme.background_end_color) - self.color2Label.setText( - translate('OpenLP.ThemeForm', 'Second color:')) - self.gradientLabel.setVisible(True) - self.gradientComboBox.setVisible(True) - self.imageLabel.setVisible(False) - self.imageLineEdit.setVisible(False) - self.imageBrowseButton.setVisible(False) - self.imageLineEdit.setText(u'') + self.setField(u'background_type', QtCore.QVariant(1)) else: - self.setField(u'background_type', QtCore.QVariant(2)) - self.color1PushButton.setVisible(False) - self.color1Label.setVisible(False) - self.color2PushButton.setVisible(False) - self.color2Label.setVisible(False) - self.gradientLabel.setVisible(False) - self.gradientComboBox.setVisible(False) - self.imageLineEdit.setVisible(True) - self.imageLabel.setVisible(True) - self.imageBrowseButton.setVisible(True) self.imageLineEdit.setText(self.theme.background_filename) + self.setField(u'background_type', QtCore.QVariant(2)) if self.theme.background_direction == \ BackgroundGradientType.to_string(BackgroundGradientType.Horizontal): self.setField(u'gradient', QtCore.QVariant(0)) @@ -471,7 +445,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): def setPreviewTabValues(self): self.setField(u'name', QtCore.QVariant(self.theme.theme_name)) - if len(self.theme.theme_name) > 1: + if len(self.theme.theme_name) > 0: self.themeNameEdit.setEnabled(False) else: self.themeNameEdit.setEnabled(True) @@ -491,20 +465,23 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): BackgroundGradientType.to_string(index) self.setBackgroundTabValues() - def onColor1PushButtonClicked(self): + def onColorButtonClicked(self): """ Background / Gradient 1 Color button pushed. """ - if self.theme.background_type == \ - BackgroundType.to_string(BackgroundType.Solid): - self.theme.background_color = \ - self._colorButton(self.theme.background_color) - else: - self.theme.background_start_color = \ - self._colorButton(self.theme.background_start_color) + self.theme.background_color = \ + self._colorButton(self.theme.background_color) self.setBackgroundTabValues() - def onColor2PushButtonClicked(self): + def onGradientStartButtonClicked(self): + """ + Gradient 2 Color button pushed. + """ + self.theme.background_start_color = \ + self._colorButton(self.theme.background_start_color) + self.setBackgroundTabValues() + + def onGradientEndButtonClicked(self): """ Gradient 2 Color button pushed. """ @@ -526,12 +503,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.theme.background_filename = unicode(filename) self.setBackgroundTabValues() - def onMainFontComboBox(self): - """ - Main Font Combo box changed - """ - self.theme.font_main_name = self.mainFontComboBox.currentFont().family() - def onMainColourPushButtonClicked(self): self.theme.font_main_color = \ self._colorButton(self.theme.font_main_color) @@ -557,6 +528,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): Update the theme object from the UI for fields not already updated when the are changed. """ + if not self.updateThemeAllowed: + return log.debug(u'updateTheme') # main page self.theme.font_main_name = \ @@ -606,7 +579,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): # Hack to stop it for now. if self.accepted: return - self.accepted = True # Save the theme name self.theme.theme_name = \ unicode(self.field(u'name').toString()) @@ -628,6 +600,7 @@ 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 == \ @@ -646,5 +619,5 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): new_color = QtGui.QColorDialog.getColor( QtGui.QColor(field), self) if new_color.isValid(): - field = new_color.name() + field = new_color.name() return field diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 65913a9f6..0b0d8281d 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -225,10 +225,10 @@ class ThemeManager(QtGui.QWidget): """ item = self.themeListWidget.currentItem() 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_(): - newThemeName = unicode(self.fileRenameForm.FileNameEdit.text()) + newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) oldThemeData = self.getThemeData(oldThemeName) self.deleteTheme(oldThemeName) self.cloneThemeData(oldThemeData, newThemeName) @@ -239,10 +239,10 @@ class ThemeManager(QtGui.QWidget): """ item = self.themeListWidget.currentItem() 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_(): - newThemeName = unicode(self.fileRenameForm.FileNameEdit.text()) + newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) themeData = self.getThemeData(oldThemeName) self.cloneThemeData(themeData, newThemeName) self.loadThemes() @@ -280,7 +280,7 @@ class ThemeManager(QtGui.QWidget): self.saveThemeName = unicode( item.data(QtCore.Qt.UserRole).toString()) self.themeForm.theme = theme - self.themeForm.exec_() + self.themeForm.exec_(True) def onDeleteTheme(self): """ @@ -310,7 +310,7 @@ class ThemeManager(QtGui.QWidget): translate('OpenLP.ThemeManager', 'You are unable to delete the default theme.')) else: - for plugin in self.parent.plugin_manager.plugins: + for plugin in self.parent.pluginManager.plugins: if plugin.usesTheme(theme): QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeManager', 'Error'), @@ -627,7 +627,8 @@ class ThemeManager(QtGui.QWidget): newtheme.font_main_shadow_color = unicode(theme.ShadowColor.name()) if theme.Outline == 1: newtheme.font_main_outline = True - newtheme.font_main_outline_color = unicode(theme.OutlineColor.name()) + newtheme.font_main_outline_color = \ + unicode(theme.OutlineColor.name()) vAlignCorrection = 0 if theme.VerticalAlign == 2: vAlignCorrection = 1 @@ -662,7 +663,7 @@ class ThemeManager(QtGui.QWidget): (QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if self.saveThemeName != u'': - for plugin in self.parent.plugin_manager.plugins: + for plugin in self.parent.pluginManager.plugins: if plugin.usesTheme(self.saveThemeName): plugin.renameTheme(self.saveThemeName, name) if unicode(self.serviceComboBox.currentText()) == name: @@ -749,7 +750,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.parent.renderManager.generate_preview(themeData, forcePage) def getPreviewImage(self, theme): """ diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 853865bb5..294d521dc 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -153,7 +153,7 @@ class ThemesTab(SettingsTab): settings.setValue(u'global theme', QtCore.QVariant(self.global_theme)) settings.endGroup() - self.parent.RenderManager.set_global_theme( + self.parent.renderManager.set_global_theme( self.global_theme, self.theme_level) Receiver.send_message(u'theme_update_global', self.global_theme) @@ -171,7 +171,7 @@ class ThemesTab(SettingsTab): def onDefaultComboBoxChanged(self, value): self.global_theme = unicode(self.DefaultComboBox.currentText()) - self.parent.RenderManager.set_global_theme( + self.parent.renderManager.set_global_theme( self.global_theme, self.theme_level) image = self.parent.ThemeManagerContents.getPreviewImage( self.global_theme) @@ -183,9 +183,14 @@ class ThemesTab(SettingsTab): def updateThemeList(self, theme_list): """ - Called from ThemeManager when the Themes have changed + Called from ThemeManager when the Themes have changed. + + ``theme_list`` + The list of available themes:: + + [u'Bible Theme', u'Song Theme'] """ - #reload as may have been triggered by the ThemeManager + # Reload as may have been triggered by the ThemeManager. self.global_theme = unicode(QtCore.QSettings().value( self.settingsSection + u'/global theme', QtCore.QVariant(u'')).toString()) @@ -198,7 +203,7 @@ class ThemesTab(SettingsTab): id = 0 # Not Found self.global_theme = u'' self.DefaultComboBox.setCurrentIndex(id) - self.parent.RenderManager.set_global_theme( + self.parent.renderManager.set_global_theme( self.global_theme, self.theme_level) if self.global_theme is not u'': image = self.parent.ThemeManagerContents.getPreviewImage( diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index b3af9df98..234c9de5e 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -30,135 +30,216 @@ from openlp.core.lib import translate, build_icon class Ui_ThemeWizard(object): def setupUi(self, ThemeWizard): - ThemeWizard.setObjectName(u'ThemeWizard') + ThemeWizard.setObjectName(u'OpenLP.ThemeWizard') ThemeWizard.resize(550, 386) ThemeWizard.setModal(True) ThemeWizard.setWizardStyle(QtGui.QWizard.ModernStyle) - ThemeWizard.setOptions(QtGui.QWizard.IndependentPages|QtGui.QWizard.NoBackButtonOnStartPage) + ThemeWizard.setOptions( + QtGui.QWizard.IndependentPages | + QtGui.QWizard.NoBackButtonOnStartPage) self.welcomePage = QtGui.QWizardPage() self.welcomePage.setTitle(u'') self.welcomePage.setSubTitle(u'') self.welcomePage.setObjectName(u'welcomePage') + self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, + QtGui.QPixmap(u':/wizards/wizard_createtheme.bmp')) self.welcomeLayout = QtGui.QHBoxLayout(self.welcomePage) self.welcomeLayout.setSpacing(8) self.welcomeLayout.setMargin(0) self.welcomeLayout.setObjectName(u'welcomeLayout') - self.importBibleImage = QtGui.QLabel(self.welcomePage) - self.importBibleImage.setMinimumSize(QtCore.QSize(163, 0)) - self.importBibleImage.setMaximumSize(QtCore.QSize(163, 16777215)) - self.importBibleImage.setLineWidth(0) - self.importBibleImage.setText(u'') - self.importBibleImage.setPixmap(QtGui.QPixmap(u':/wizards/wizard_importbible.bmp')) - self.importBibleImage.setIndent(0) - self.importBibleImage.setObjectName(u'importBibleImage') - self.welcomeLayout.addWidget(self.importBibleImage) self.welcomePageLayout = QtGui.QVBoxLayout() self.welcomePageLayout.setSpacing(8) self.welcomePageLayout.setObjectName(u'welcomePageLayout') self.titleLabel = QtGui.QLabel(self.welcomePage) self.titleLabel.setObjectName(u'titleLabel') self.welcomePageLayout.addWidget(self.titleLabel) - spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) - self.welcomePageLayout.addItem(spacerItem) + self.welcomeTopSpacer = QtGui.QSpacerItem(20, 40, + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + self.welcomePageLayout.addItem(self.welcomeTopSpacer) self.informationLabel = QtGui.QLabel(self.welcomePage) self.informationLabel.setWordWrap(True) self.informationLabel.setMargin(10) self.informationLabel.setObjectName(u'informationLabel') self.welcomePageLayout.addWidget(self.informationLabel) - spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.welcomePageLayout.addItem(spacerItem1) + self.welcomeBottomSpacer = QtGui.QSpacerItem(20, 40, + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.welcomePageLayout.addItem(self.welcomeBottomSpacer) self.welcomeLayout.addLayout(self.welcomePageLayout) ThemeWizard.addPage(self.welcomePage) self.backgroundPage = QtGui.QWizardPage() self.backgroundPage.setObjectName(u'backgroundPage') - self.backgroundLayout = QtGui.QFormLayout(self.backgroundPage) - self.backgroundLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow) - self.backgroundLayout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.backgroundLayout.setMargin(20) + self.backgroundLayout = QtGui.QVBoxLayout(self.backgroundPage) self.backgroundLayout.setSpacing(8) + self.backgroundLayout.setMargin(20) self.backgroundLayout.setObjectName(u'backgroundLayout') + self.backgroundTypeLayout = QtGui.QHBoxLayout() + self.backgroundTypeLayout.setSpacing(8) + self.backgroundTypeLayout.setObjectName(u'backgroundTypeLayout') self.backgroundTypeLabel = QtGui.QLabel(self.backgroundPage) self.backgroundTypeLabel.setObjectName(u'backgroundTypeLabel') - self.backgroundLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.backgroundTypeLabel) + self.backgroundTypeLayout.addWidget(self.backgroundTypeLabel) self.backgroundTypeComboBox = QtGui.QComboBox(self.backgroundPage) self.backgroundTypeComboBox.setObjectName(u'backgroundTypeComboBox') self.backgroundTypeComboBox.addItem(u'') self.backgroundTypeComboBox.addItem(u'') self.backgroundTypeComboBox.addItem(u'') - self.backgroundLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backgroundTypeComboBox) - self.color1Label = QtGui.QLabel(self.backgroundPage) - self.color1Label.setObjectName(u'color1Label') - self.backgroundLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.color1Label) - self.color1PushButton = QtGui.QPushButton(self.backgroundPage) - self.color1PushButton.setText(u'') - self.color1PushButton.setObjectName(u'color1PushButton') - self.backgroundLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.color1PushButton) - self.color2Label = QtGui.QLabel(self.backgroundPage) - self.color2Label.setObjectName(u'color2Label') - self.backgroundLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.color2Label) - self.color2PushButton = QtGui.QPushButton(self.backgroundPage) - self.color2PushButton.setText(u'') - self.color2PushButton.setObjectName(u'color2PushButton') - self.backgroundLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.color2PushButton) - self.imageLabel = QtGui.QLabel(self.backgroundPage) - self.imageLabel.setObjectName(u'imageLabel') - self.backgroundLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.imageLabel) - self.imageLayout = QtGui.QHBoxLayout() - self.imageLayout.setSpacing(8) - self.imageLayout.setObjectName(u'imageLayout') - self.imageLineEdit = QtGui.QLineEdit(self.backgroundPage) - self.imageLineEdit.setObjectName(u'imageLineEdit') - self.imageLayout.addWidget(self.imageLineEdit) - self.imageBrowseButton = QtGui.QToolButton(self.backgroundPage) - self.imageBrowseButton.setText(u'') - self.imageBrowseButton.setIcon(build_icon(u':/general/general_open.png')) - self.imageBrowseButton.setObjectName(u'imageBrowseButton') - self.imageLayout.addWidget(self.imageBrowseButton) - self.backgroundLayout.setLayout(3, QtGui.QFormLayout.FieldRole, self.imageLayout) - self.gradientLabel = QtGui.QLabel(self.backgroundPage) - self.gradientLabel.setObjectName(u'gradientLabel') - self.backgroundLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.gradientLabel) - self.gradientComboBox = QtGui.QComboBox(self.backgroundPage) + self.backgroundTypeLayout.addWidget(self.backgroundTypeComboBox) + self.backgroundTypeSpacer = QtGui.QSpacerItem(40, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.backgroundTypeLayout.addItem(self.backgroundTypeSpacer) + self.backgroundLayout.addLayout(self.backgroundTypeLayout) + self.backgroundStackedWidget = QtGui.QStackedWidget( + self.backgroundPage) + self.backgroundStackedWidget.setObjectName(u'backgroundStackedWidget') + self.colorPage = QtGui.QWidget() + self.colorPage.setObjectName(u'colorPage') + self.colorLayout = QtGui.QFormLayout(self.colorPage) + self.colorLayout.setMargin(0) + self.colorLayout.setSpacing(8) + self.colorLayout.setObjectName(u'colorLayout') + self.colorLabel = QtGui.QLabel(self.colorPage) + self.colorLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.colorLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.colorLabel.setObjectName(u'colorLabel') + self.colorLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.colorLabel) + self.colorButton = QtGui.QPushButton(self.colorPage) + self.colorButton.setText(u'') + self.colorButton.setObjectName(u'colorButton') + self.colorLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.colorButton) + self.backgroundStackedWidget.addWidget(self.colorPage) + self.gradientPage = QtGui.QWidget() + self.gradientPage.setObjectName(u'gradientPage') + self.gradientLayout = QtGui.QFormLayout(self.gradientPage) + self.gradientLayout.setMargin(0) + self.gradientLayout.setSpacing(8) + self.gradientLayout.setObjectName(u'gradientLayout') + self.gradientStartLabel = QtGui.QLabel(self.gradientPage) + self.gradientStartLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.gradientStartLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.gradientStartLabel.setObjectName(u'gradientStartLabel') + self.gradientLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.gradientStartLabel) + self.gradientStartButton = QtGui.QPushButton(self.gradientPage) + self.gradientStartButton.setText(u'') + self.gradientStartButton.setObjectName(u'gradientStartButton') + self.gradientLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.gradientStartButton) + self.gradientEndLabel = QtGui.QLabel(self.gradientPage) + self.gradientEndLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.gradientEndLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.gradientEndLabel.setObjectName(u'gradientEndLabel') + self.gradientLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.gradientEndLabel) + self.gradientEndButton = QtGui.QPushButton(self.gradientPage) + self.gradientEndButton.setText(u'') + self.gradientEndButton.setObjectName(u'gradientEndButton') + self.gradientLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.gradientEndButton) + self.gradientTypeLabel = QtGui.QLabel(self.gradientPage) + self.gradientTypeLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.gradientTypeLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.gradientTypeLabel.setObjectName(u'gradientTypeLabel') + self.gradientLayout.setWidget(2, + QtGui.QFormLayout.LabelRole, self.gradientTypeLabel) + self.gradientComboBox = QtGui.QComboBox(self.gradientPage) self.gradientComboBox.setObjectName(u'gradientComboBox') self.gradientComboBox.addItem(u'') self.gradientComboBox.addItem(u'') self.gradientComboBox.addItem(u'') self.gradientComboBox.addItem(u'') self.gradientComboBox.addItem(u'') - self.backgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.gradientComboBox) + self.gradientLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.gradientComboBox) + self.backgroundStackedWidget.addWidget(self.gradientPage) + self.imagePage = QtGui.QWidget() + self.imagePage.setObjectName(u'imagePage') + self.imageLayout = QtGui.QFormLayout(self.imagePage) + self.imageLayout.setMargin(0) + self.imageLayout.setSpacing(8) + self.imageLayout.setObjectName(u'imageLayout') + self.imageLabel = QtGui.QLabel(self.imagePage) + self.imageLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.imageLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + self.imageLabel.setObjectName(u'imageLabel') + self.imageLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.imageLabel) + self.imageFileLayout = QtGui.QHBoxLayout() + self.imageFileLayout.setSpacing(8) + self.imageFileLayout.setObjectName(u'imageFileLayout') + self.imageLineEdit = QtGui.QLineEdit(self.imagePage) + self.imageLineEdit.setObjectName(u'imageLineEdit') + self.imageFileLayout.addWidget(self.imageLineEdit) + self.imageBrowseButton = QtGui.QToolButton(self.imagePage) + self.imageBrowseButton.setText(u'') + self.imageBrowseButton.setIcon( + build_icon(u':/general/general_open.png')) + self.imageBrowseButton.setObjectName(u'imageBrowseButton') + self.imageFileLayout.addWidget(self.imageBrowseButton) + self.imageLayout.setLayout(0, + QtGui.QFormLayout.FieldRole, self.imageFileLayout) + self.backgroundStackedWidget.addWidget(self.imagePage) + self.backgroundLayout.addWidget(self.backgroundStackedWidget) ThemeWizard.addPage(self.backgroundPage) self.mainAreaPage = QtGui.QWizardPage() self.mainAreaPage.setObjectName(u'mainAreaPage') - self.formLayout = QtGui.QFormLayout(self.mainAreaPage) - self.formLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) - self.formLayout.setContentsMargins(-1, 20, 20, 20) - self.formLayout.setSpacing(8) - self.formLayout.setObjectName(u'formLayout') + self.mainAreaLayout = QtGui.QFormLayout(self.mainAreaPage) + self.mainAreaLayout.setFormAlignment(QtCore.Qt.AlignLeading | + QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) + self.mainAreaLayout.setMargin(20) + self.mainAreaLayout.setSpacing(8) + self.mainAreaLayout.setObjectName(u'mainAreaLayout') self.mainFontLabel = QtGui.QLabel(self.mainAreaPage) + self.mainFontLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.mainFontLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.mainFontLabel.setObjectName(u'mainFontLabel') - self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.mainFontLabel) + self.mainAreaLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.mainFontLabel) self.mainFontComboBox = QtGui.QFontComboBox(self.mainAreaPage) self.mainFontComboBox.setObjectName(u'mainFontComboBox') - self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainFontComboBox) + self.mainAreaLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.mainFontComboBox) self.mainColorLabel = QtGui.QLabel(self.mainAreaPage) self.mainColorLabel.setObjectName(u'mainColorLabel') - self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.mainColorLabel) + self.mainAreaLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.mainColorLabel) + self.fontPropertiesLayout = QtGui.QHBoxLayout() + self.fontPropertiesLayout.setSpacing(24) + self.fontPropertiesLayout.setObjectName(u'fontPropertiesLayout') self.mainColorPushButton = QtGui.QPushButton(self.mainAreaPage) self.mainColorPushButton.setText(u'') self.mainColorPushButton.setObjectName(u'mainColorPushButton') - self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.mainColorPushButton) + self.fontPropertiesLayout.addWidget(self.mainColorPushButton) + self.boldCheckBox = QtGui.QCheckBox(self.mainAreaPage) + self.boldCheckBox.setObjectName(u'boldCheckBox') + self.fontPropertiesLayout.addWidget(self.boldCheckBox) + self.italicsCheckBox = QtGui.QCheckBox(self.mainAreaPage) + self.italicsCheckBox.setObjectName(u'italicsCheckBox') + self.fontPropertiesLayout.addWidget(self.italicsCheckBox) + self.mainAreaLayout.setLayout(1, + QtGui.QFormLayout.FieldRole, self.fontPropertiesLayout) self.mainSizeLabel = QtGui.QLabel(self.mainAreaPage) self.mainSizeLabel.setObjectName(u'mainSizeLabel') - self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.mainSizeLabel) + self.mainAreaLayout.setWidget(2, + QtGui.QFormLayout.LabelRole, self.mainSizeLabel) self.mainSizeLayout = QtGui.QHBoxLayout() self.mainSizeLayout.setSpacing(8) self.mainSizeLayout.setMargin(0) self.mainSizeLayout.setObjectName(u'mainSizeLayout') self.mainSizeSpinBox = QtGui.QSpinBox(self.mainAreaPage) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.mainSizeSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.mainSizeSpinBox.sizePolicy().hasHeightForWidth()) self.mainSizeSpinBox.setSizePolicy(sizePolicy) self.mainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) self.mainSizeSpinBox.setMaximum(999) @@ -168,18 +249,22 @@ class Ui_ThemeWizard(object): self.mainLineCountLabel = QtGui.QLabel(self.mainAreaPage) self.mainLineCountLabel.setObjectName(u'mainLineCountLabel') self.mainSizeLayout.addWidget(self.mainLineCountLabel) - self.formLayout.setLayout(2, QtGui.QFormLayout.FieldRole, self.mainSizeLayout) + self.mainAreaLayout.setLayout(2, + QtGui.QFormLayout.FieldRole, self.mainSizeLayout) self.lineSpacingLabel = QtGui.QLabel(self.mainAreaPage) self.lineSpacingLabel.setObjectName(u'lineSpacingLabel') - self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.lineSpacingLabel) + self.mainAreaLayout.setWidget(3, + QtGui.QFormLayout.LabelRole, self.lineSpacingLabel) self.lineSpacingSpinBox = QtGui.QSpinBox(self.mainAreaPage) self.lineSpacingSpinBox.setMinimum(-50) self.lineSpacingSpinBox.setMaximum(50) self.lineSpacingSpinBox.setObjectName(u'lineSpacingSpinBox') - self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.lineSpacingSpinBox) + self.mainAreaLayout.setWidget(3, + QtGui.QFormLayout.FieldRole, self.lineSpacingSpinBox) self.outlineCheckBox = QtGui.QCheckBox(self.mainAreaPage) self.outlineCheckBox.setObjectName(u'outlineCheckBox') - self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.outlineCheckBox) + self.mainAreaLayout.setWidget(4, + QtGui.QFormLayout.LabelRole, self.outlineCheckBox) self.outlineLayout = QtGui.QHBoxLayout() self.outlineLayout.setObjectName(u'outlineLayout') self.outlineColorPushButton = QtGui.QPushButton(self.mainAreaPage) @@ -193,10 +278,12 @@ class Ui_ThemeWizard(object): self.outlineSizeSpinBox = QtGui.QSpinBox(self.mainAreaPage) self.outlineSizeSpinBox.setObjectName(u'outlineSizeSpinBox') self.outlineLayout.addWidget(self.outlineSizeSpinBox) - self.formLayout.setLayout(4, QtGui.QFormLayout.FieldRole, self.outlineLayout) + self.mainAreaLayout.setLayout(4, + QtGui.QFormLayout.FieldRole, self.outlineLayout) self.shadowCheckBox = QtGui.QCheckBox(self.mainAreaPage) self.shadowCheckBox.setObjectName(u'shadowCheckBox') - self.formLayout.setWidget(5, QtGui.QFormLayout.LabelRole, self.shadowCheckBox) + self.mainAreaLayout.setWidget(5, + QtGui.QFormLayout.LabelRole, self.shadowCheckBox) self.shadowLayout = QtGui.QHBoxLayout() self.shadowLayout.setObjectName(u'shadowLayout') self.shadowColorPushButton = QtGui.QPushButton(self.mainAreaPage) @@ -210,83 +297,99 @@ class Ui_ThemeWizard(object): self.shadowSizeSpinBox = QtGui.QSpinBox(self.mainAreaPage) self.shadowSizeSpinBox.setObjectName(u'shadowSizeSpinBox') self.shadowLayout.addWidget(self.shadowSizeSpinBox) - self.formLayout.setLayout(5, QtGui.QFormLayout.FieldRole, self.shadowLayout) - self.boldCheckBox = QtGui.QCheckBox(self.mainAreaPage) - self.boldCheckBox.setObjectName(u'boldCheckBox') - self.formLayout.setWidget(6, QtGui.QFormLayout.FieldRole, self.boldCheckBox) - self.italicsCheckBox = QtGui.QCheckBox(self.mainAreaPage) - self.italicsCheckBox.setObjectName(u'italicsCheckBox') - self.formLayout.setWidget(7, QtGui.QFormLayout.FieldRole, self.italicsCheckBox) + self.mainAreaLayout.setLayout(5, + QtGui.QFormLayout.FieldRole, self.shadowLayout) ThemeWizard.addPage(self.mainAreaPage) self.footerAreaPage = QtGui.QWizardPage() self.footerAreaPage.setObjectName(u'footerAreaPage') self.footerLayout = QtGui.QFormLayout(self.footerAreaPage) - self.footerLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow) - self.footerLayout.setContentsMargins(50, 20, 20, 20) + self.footerLayout.setFieldGrowthPolicy( + QtGui.QFormLayout.ExpandingFieldsGrow) + self.footerLayout.setMargin(20) self.footerLayout.setSpacing(8) self.footerLayout.setObjectName(u'footerLayout') self.footerFontLabel = QtGui.QLabel(self.footerAreaPage) + self.footerFontLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.footerFontLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.footerFontLabel.setObjectName(u'footerFontLabel') - self.footerLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.footerFontLabel) + self.footerLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.footerFontLabel) self.footerFontComboBox = QtGui.QFontComboBox(self.footerAreaPage) self.footerFontComboBox.setObjectName(u'footerFontComboBox') - self.footerLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.footerFontComboBox) + self.footerLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.footerFontComboBox) self.footerColorLabel = QtGui.QLabel(self.footerAreaPage) self.footerColorLabel.setObjectName(u'footerColorLabel') - self.footerLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.footerColorLabel) + self.footerLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.footerColorLabel) self.footerColorPushButton = QtGui.QPushButton(self.footerAreaPage) self.footerColorPushButton.setText(u'') self.footerColorPushButton.setObjectName(u'footerColorPushButton') - self.footerLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.footerColorPushButton) + self.footerLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.footerColorPushButton) self.footerSizeLabel = QtGui.QLabel(self.footerAreaPage) self.footerSizeLabel.setObjectName(u'footerSizeLabel') - self.footerLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.footerSizeLabel) + self.footerLayout.setWidget(2, + QtGui.QFormLayout.LabelRole, self.footerSizeLabel) self.footerSizeSpinBox = QtGui.QSpinBox(self.footerAreaPage) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.footerSizeSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.footerSizeSpinBox.sizePolicy().hasHeightForWidth()) self.footerSizeSpinBox.setSizePolicy(sizePolicy) self.footerSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) self.footerSizeSpinBox.setMaximum(999) self.footerSizeSpinBox.setProperty(u'value', 10) self.footerSizeSpinBox.setObjectName(u'footerSizeSpinBox') - self.footerLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.footerSizeSpinBox) + self.footerLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.footerSizeSpinBox) ThemeWizard.addPage(self.footerAreaPage) self.alignmentPage = QtGui.QWizardPage() self.alignmentPage.setObjectName(u'alignmentPage') - self.formLayout_2 = QtGui.QFormLayout(self.alignmentPage) - self.formLayout_2.setMargin(20) - self.formLayout_2.setObjectName(u'formLayout_2') + self.alignmentLayout = QtGui.QFormLayout(self.alignmentPage) + self.alignmentLayout.setMargin(20) + self.alignmentLayout.setSpacing(8) + self.alignmentLayout.setObjectName(u'alignmentLayout') self.horizontalLabel = QtGui.QLabel(self.alignmentPage) + self.horizontalLabel.setMinimumSize(QtCore.QSize(103, 0)) + self.horizontalLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.horizontalLabel.setObjectName(u'horizontalLabel') - self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.horizontalLabel) + self.alignmentLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.horizontalLabel) self.horizontalComboBox = QtGui.QComboBox(self.alignmentPage) self.horizontalComboBox.setEditable(False) self.horizontalComboBox.setObjectName(u'horizontalComboBox') self.horizontalComboBox.addItem(u'') self.horizontalComboBox.addItem(u'') self.horizontalComboBox.addItem(u'') - self.formLayout_2.setWidget(0, QtGui.QFormLayout.FieldRole, self.horizontalComboBox) + self.alignmentLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.horizontalComboBox) self.verticalLabel = QtGui.QLabel(self.alignmentPage) self.verticalLabel.setObjectName(u'verticalLabel') - self.formLayout_2.setWidget(1, QtGui.QFormLayout.LabelRole, self.verticalLabel) + self.alignmentLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.verticalLabel) self.verticalComboBox = QtGui.QComboBox(self.alignmentPage) self.verticalComboBox.setObjectName(u'verticalComboBox') self.verticalComboBox.addItem(u'') self.verticalComboBox.addItem(u'') self.verticalComboBox.addItem(u'') - self.formLayout_2.setWidget(1, QtGui.QFormLayout.FieldRole, self.verticalComboBox) + self.alignmentLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.verticalComboBox) self.transitionsCheckBox = QtGui.QCheckBox(self.alignmentPage) self.transitionsCheckBox.setObjectName(u'transitionsCheckBox') - self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.transitionsCheckBox) + self.alignmentLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.transitionsCheckBox) ThemeWizard.addPage(self.alignmentPage) self.areaPositionPage = QtGui.QWizardPage() self.areaPositionPage.setObjectName(u'areaPositionPage') - self.gridLayout_2 = QtGui.QGridLayout(self.areaPositionPage) - self.gridLayout_2.setMargin(20) - self.gridLayout_2.setSpacing(8) - self.gridLayout_2.setObjectName(u'gridLayout_2') + self.areaPositionLayout = QtGui.QGridLayout(self.areaPositionPage) + self.areaPositionLayout.setMargin(20) + self.areaPositionLayout.setSpacing(8) + self.areaPositionLayout.setObjectName(u'areaPositionLayout') self.mainPositionGroupBox = QtGui.QGroupBox(self.areaPositionPage) self.mainPositionGroupBox.setMinimumSize(QtCore.QSize(248, 0)) self.mainPositionGroupBox.setObjectName(u'mainPositionGroupBox') @@ -294,254 +397,361 @@ class Ui_ThemeWizard(object): self.mainPositionLayout.setMargin(8) self.mainPositionLayout.setSpacing(8) self.mainPositionLayout.setObjectName(u'mainPositionLayout') - self.mainDefaultPositionCheckBox = QtGui.QCheckBox(self.mainPositionGroupBox) + self.mainDefaultPositionCheckBox = QtGui.QCheckBox( + self.mainPositionGroupBox) self.mainDefaultPositionCheckBox.setChecked(True) self.mainDefaultPositionCheckBox.setTristate(False) - self.mainDefaultPositionCheckBox.setObjectName(u'mainDefaultPositionCheckBox') - self.mainPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainDefaultPositionCheckBox) + self.mainDefaultPositionCheckBox.setObjectName( + u'mainDefaultPositionCheckBox') + self.mainPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.mainDefaultPositionCheckBox) self.nainXLabel = QtGui.QLabel(self.mainPositionGroupBox) self.nainXLabel.setObjectName(u'nainXLabel') - self.mainPositionLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.nainXLabel) + self.mainPositionLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.nainXLabel) self.mainXSpinBox = QtGui.QSpinBox(self.mainPositionGroupBox) self.mainXSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.mainXSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.mainXSpinBox.sizePolicy().hasHeightForWidth()) self.mainXSpinBox.setSizePolicy(sizePolicy) self.mainXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.mainXSpinBox.setMaximum(9999) self.mainXSpinBox.setProperty(u'value', 0) self.mainXSpinBox.setObjectName(u'mainXSpinBox') - self.mainPositionLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.mainXSpinBox) + self.mainPositionLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.mainXSpinBox) self.mainYSpinBox = QtGui.QSpinBox(self.mainPositionGroupBox) self.mainYSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.mainYSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.mainYSpinBox.sizePolicy().hasHeightForWidth()) self.mainYSpinBox.setSizePolicy(sizePolicy) self.mainYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.mainYSpinBox.setMaximum(9999) self.mainYSpinBox.setObjectName(u'mainYSpinBox') - self.mainPositionLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.mainYSpinBox) + self.mainPositionLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.mainYSpinBox) self.mainYLabel = QtGui.QLabel(self.mainPositionGroupBox) self.mainYLabel.setObjectName(u'mainYLabel') - self.mainPositionLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.mainYLabel) + self.mainPositionLayout.setWidget(2, + QtGui.QFormLayout.LabelRole, self.mainYLabel) self.mainWidthSpinBox = QtGui.QSpinBox(self.mainPositionGroupBox) self.mainWidthSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.mainWidthSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.mainWidthSpinBox.sizePolicy().hasHeightForWidth()) self.mainWidthSpinBox.setSizePolicy(sizePolicy) self.mainWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.mainWidthSpinBox.setMaximum(9999) self.mainWidthSpinBox.setObjectName(u'mainWidthSpinBox') - self.mainPositionLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.mainWidthSpinBox) + self.mainPositionLayout.setWidget(3, + QtGui.QFormLayout.FieldRole, self.mainWidthSpinBox) self.mainWidthLabel = QtGui.QLabel(self.mainPositionGroupBox) self.mainWidthLabel.setObjectName(u'mainWidthLabel') - self.mainPositionLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.mainWidthLabel) + self.mainPositionLayout.setWidget(3, + QtGui.QFormLayout.LabelRole, self.mainWidthLabel) self.mainHeightSpinBox = QtGui.QSpinBox(self.mainPositionGroupBox) self.mainHeightSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.mainHeightSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.mainHeightSpinBox.sizePolicy().hasHeightForWidth()) self.mainHeightSpinBox.setSizePolicy(sizePolicy) self.mainHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.mainHeightSpinBox.setMaximum(9999) self.mainHeightSpinBox.setObjectName(u'mainHeightSpinBox') - self.mainPositionLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.mainHeightSpinBox) + self.mainPositionLayout.setWidget(4, + QtGui.QFormLayout.FieldRole, self.mainHeightSpinBox) self.mainHeightLabel = QtGui.QLabel(self.mainPositionGroupBox) self.mainHeightLabel.setObjectName(u'mainHeightLabel') - self.mainPositionLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.mainHeightLabel) - self.gridLayout_2.addWidget(self.mainPositionGroupBox, 1, 0, 1, 1) + self.mainPositionLayout.setWidget(4, + QtGui.QFormLayout.LabelRole, self.mainHeightLabel) + self.areaPositionLayout.addWidget( + self.mainPositionGroupBox, 1, 0, 1, 1) self.footerPositionGroupBox = QtGui.QGroupBox(self.areaPositionPage) self.footerPositionGroupBox.setMinimumSize(QtCore.QSize(248, 0)) self.footerPositionGroupBox.setObjectName(u'footerPositionGroupBox') - self.footerPositionLayout = QtGui.QFormLayout(self.footerPositionGroupBox) + self.footerPositionLayout = QtGui.QFormLayout( + self.footerPositionGroupBox) self.footerPositionLayout.setMargin(8) self.footerPositionLayout.setSpacing(8) self.footerPositionLayout.setObjectName(u'footerPositionLayout') self.footerXLabel = QtGui.QLabel(self.footerPositionGroupBox) self.footerXLabel.setObjectName(u'footerXLabel') - self.footerPositionLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.footerXLabel) + self.footerPositionLayout.setWidget(1, + QtGui.QFormLayout.LabelRole, self.footerXLabel) self.footerXSpinBox = QtGui.QSpinBox(self.footerPositionGroupBox) self.footerXSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.footerXSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.footerXSpinBox.sizePolicy().hasHeightForWidth()) self.footerXSpinBox.setSizePolicy(sizePolicy) self.footerXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.footerXSpinBox.setMaximum(9999) self.footerXSpinBox.setProperty(u'value', 0) self.footerXSpinBox.setObjectName(u'footerXSpinBox') - self.footerPositionLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.footerXSpinBox) + self.footerPositionLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.footerXSpinBox) self.footerYLabel = QtGui.QLabel(self.footerPositionGroupBox) self.footerYLabel.setObjectName(u'footerYLabel') - self.footerPositionLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.footerYLabel) + self.footerPositionLayout.setWidget(2, + QtGui.QFormLayout.LabelRole, self.footerYLabel) self.footerYSpinBox = QtGui.QSpinBox(self.footerPositionGroupBox) self.footerYSpinBox.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.footerYSpinBox.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.footerYSpinBox.sizePolicy().hasHeightForWidth()) self.footerYSpinBox.setSizePolicy(sizePolicy) self.footerYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.footerYSpinBox.setMaximum(9999) self.footerYSpinBox.setProperty(u'value', 0) self.footerYSpinBox.setObjectName(u'footerYSpinBox') - self.footerPositionLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.footerYSpinBox) + self.footerPositionLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.footerYSpinBox) self.footerWidthLabel = QtGui.QLabel(self.footerPositionGroupBox) self.footerWidthLabel.setObjectName(u'footerWidthLabel') - self.footerPositionLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.footerWidthLabel) + self.footerPositionLayout.setWidget(3, + QtGui.QFormLayout.LabelRole, self.footerWidthLabel) self.footerWidthSpinBox = QtGui.QSpinBox(self.footerPositionGroupBox) self.footerWidthSpinBox.setEnabled(False) self.footerWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.footerWidthSpinBox.setMaximum(9999) self.footerWidthSpinBox.setObjectName(u'footerWidthSpinBox') - self.footerPositionLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.footerWidthSpinBox) + self.footerPositionLayout.setWidget(3, + QtGui.QFormLayout.FieldRole, self.footerWidthSpinBox) self.footerHeightLabel = QtGui.QLabel(self.footerPositionGroupBox) self.footerHeightLabel.setObjectName(u'footerHeightLabel') - self.footerPositionLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.footerHeightLabel) + self.footerPositionLayout.setWidget(4, + QtGui.QFormLayout.LabelRole, self.footerHeightLabel) self.footerHeightSpinBox = QtGui.QSpinBox(self.footerPositionGroupBox) self.footerHeightSpinBox.setEnabled(False) self.footerHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.footerHeightSpinBox.setMaximum(9999) self.footerHeightSpinBox.setObjectName(u'footerHeightSpinBox') - self.footerPositionLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.footerHeightSpinBox) - self.footerDefaultPositionCheckBox = QtGui.QCheckBox(self.footerPositionGroupBox) + self.footerPositionLayout.setWidget(4, + QtGui.QFormLayout.FieldRole, self.footerHeightSpinBox) + self.footerDefaultPositionCheckBox = QtGui.QCheckBox( + self.footerPositionGroupBox) self.footerDefaultPositionCheckBox.setChecked(True) - self.footerDefaultPositionCheckBox.setObjectName(u'footerDefaultPositionCheckBox') - self.footerPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.footerDefaultPositionCheckBox) - self.gridLayout_2.addWidget(self.footerPositionGroupBox, 1, 1, 1, 1) + self.footerDefaultPositionCheckBox.setObjectName( + u'footerDefaultPositionCheckBox') + self.footerPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.footerDefaultPositionCheckBox) + self.areaPositionLayout.addWidget(self.footerPositionGroupBox, 1, 1, 1, 1) ThemeWizard.addPage(self.areaPositionPage) self.previewPage = QtGui.QWizardPage() self.previewPage.setObjectName(u'previewPage') + self.previewLayout = QtGui.QVBoxLayout(self.previewPage) + self.previewLayout.setSpacing(8) + self.previewLayout.setMargin(20) + self.previewLayout.setObjectName(u'previewLayout') + self.themeNameLayout = QtGui.QHBoxLayout() + self.themeNameLayout.setSpacing(8) + self.themeNameLayout.setObjectName(u'themeNameLayout') self.themeNameLabel = QtGui.QLabel(self.previewPage) - self.themeNameLabel.setGeometry(QtCore.QRect(20, 10, 82, 16)) + self.themeNameLabel.setMinimumSize(QtCore.QSize(103, 0)) self.themeNameLabel.setTextFormat(QtCore.Qt.PlainText) + self.themeNameLabel.setAlignment(QtCore.Qt.AlignRight | + QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.themeNameLabel.setObjectName(u'themeNameLabel') - self.previewLabel = QtGui.QLabel(self.previewPage) - self.previewLabel.setGeometry(QtCore.QRect(250, 60, 48, 16)) - self.previewLabel.setAlignment(QtCore.Qt.AlignCenter) - self.previewLabel.setObjectName(u'previewLabel') + self.themeNameLayout.addWidget(self.themeNameLabel) self.themeNameEdit = QtGui.QLineEdit(self.previewPage) - self.themeNameEdit.setGeometry(QtCore.QRect(117, 4, 351, 23)) self.themeNameEdit.setObjectName(u'themeNameEdit') - self.groupBox = QtGui.QGroupBox(self.previewPage) - self.groupBox.setGeometry(QtCore.QRect(40, 80, 464, 214)) - self.groupBox.setTitle(u'') - self.groupBox.setObjectName(u'groupBox') - self.horizontalLayout = QtGui.QHBoxLayout(self.groupBox) - self.horizontalLayout.setObjectName(u'horizontalLayout') - spacerItem2 = QtGui.QSpacerItem(58, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem2) - self.previewBoxLabel = QtGui.QLabel(self.groupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.themeNameLayout.addWidget(self.themeNameEdit) + self.previewLayout.addLayout(self.themeNameLayout) + self.previewPaneLayout = QtGui.QHBoxLayout() + self.previewPaneLayout.setSpacing(0) + self.previewPaneLayout.setObjectName(u'previewPaneLayout') + self.previewLeftSpacer = QtGui.QSpacerItem(58, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.previewPaneLayout.addItem(self.previewLeftSpacer) + self.previewBoxLabel = QtGui.QLabel(self.previewPage) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.previewBoxLabel.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.previewBoxLabel.sizePolicy().hasHeightForWidth()) self.previewBoxLabel.setSizePolicy(sizePolicy) - self.previewBoxLabel.setMinimumSize(QtCore.QSize(300, 200)) + self.previewBoxLabel.setMinimumSize(QtCore.QSize(100, 150)) self.previewBoxLabel.setFrameShape(QtGui.QFrame.WinPanel) self.previewBoxLabel.setFrameShadow(QtGui.QFrame.Sunken) self.previewBoxLabel.setLineWidth(1) self.previewBoxLabel.setText(u'') self.previewBoxLabel.setScaledContents(True) self.previewBoxLabel.setObjectName(u'previewBoxLabel') - self.horizontalLayout.addWidget(self.previewBoxLabel) - spacerItem3 = QtGui.QSpacerItem(78, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem3) + self.previewPaneLayout.addWidget(self.previewBoxLabel) + self.previewRightSpacer = QtGui.QSpacerItem(78, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.previewPaneLayout.addItem(self.previewRightSpacer) + self.previewLayout.addLayout(self.previewPaneLayout) ThemeWizard.addPage(self.previewPage) self.themeNameLabel.setBuddy(self.themeNameEdit) self.retranslateUi(ThemeWizard) - QtCore.QObject.connect(ThemeWizard, QtCore.SIGNAL(u'accepted()'), ThemeWizard.accept) + self.backgroundStackedWidget.setCurrentIndex(0) + QtCore.QObject.connect( + ThemeWizard, + QtCore.SIGNAL(u'accepted()'), + ThemeWizard.accept) + QtCore.QObject.connect( + self.backgroundTypeComboBox, + QtCore.SIGNAL(u'currentIndexChanged(int)'), + self.backgroundStackedWidget.setCurrentIndex) QtCore.QMetaObject.connectSlotsByName(ThemeWizard) def retranslateUi(self, ThemeWizard): - ThemeWizard.setWindowTitle(translate('OpenLP.ThemeForm', 'Theme Wizard')) - self.titleLabel.setText(translate('OpenLP.ThemeForm', '\n' -'\n' -'

Welcome to the Theme Wizard

')) - self.informationLabel.setText(translate('OpenLP.ThemeForm', 'This wizard will help you to maintain Themes . Click the next button below to start the process by setting up your background.')) - self.backgroundPage.setTitle(translate('OpenLP.ThemeForm', 'Set Up Background')) - self.backgroundPage.setSubTitle(translate('OpenLP.ThemeForm', 'Set up your theme\'s background according to the parameters below.')) - self.backgroundTypeLabel.setText(translate('OpenLP.ThemeForm', 'Background type:')) - self.backgroundTypeComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Solid Color')) - self.backgroundTypeComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Gradient')) - self.backgroundTypeComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Image')) - self.color1Label.setText(translate('OpenLP.ThemeForm', '')) - self.color2Label.setText(translate('OpenLP.ThemeForm', '')) - self.imageLabel.setText(translate('OpenLP.ThemeForm', 'Image:')) - self.gradientLabel.setText(translate('OpenLP.ThemeForm', 'Gradient:')) - self.gradientComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Horizontal')) - self.gradientComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Vertical')) - self.gradientComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Circular')) - self.gradientComboBox.setItemText(3, translate('OpenLP.ThemeForm', 'Top Left - Bottom Right')) - self.gradientComboBox.setItemText(4, translate('OpenLP.ThemeForm', 'Bottom Left - Top Right')) - self.mainAreaPage.setTitle(translate('OpenLP.ThemeForm', 'Main Area Font Details')) - self.mainAreaPage.setSubTitle(translate('OpenLP.ThemeForm', 'Define the font and display characteristics for the Display text')) - self.mainFontLabel.setText(translate('OpenLP.ThemeForm', 'Font:')) - self.mainColorLabel.setText(translate('OpenLP.ThemeForm', 'Color:')) - self.mainSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:')) - self.mainSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt')) - self.mainLineCountLabel.setText(translate('OpenLP.ThemeForm', '(%d lines per slide)')) - self.lineSpacingLabel.setText(translate('OpenLP.ThemeForm', 'Line Spacing:')) - self.lineSpacingSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt')) - self.outlineCheckBox.setText(translate('OpenLP.ThemeForm', '&Outline:')) - self.outlineSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:')) - self.outlineSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt')) - self.shadowCheckBox.setText(translate('OpenLP.ThemeForm', '&Shadow:')) - self.shadowSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:')) - self.shadowSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt')) - self.boldCheckBox.setText(translate('OpenLP.ThemeForm', 'Bold Display')) - self.italicsCheckBox.setText(translate('OpenLP.ThemeForm', 'Italic Display')) - self.footerAreaPage.setTitle(translate('OpenLP.ThemeForm', 'Footer Area Font Details')) - self.footerAreaPage.setSubTitle(translate('OpenLP.ThemeForm', 'Define the font and display characteristics for the Footer text')) - self.footerFontLabel.setText(translate('OpenLP.ThemeForm', 'Font:')) - self.footerColorLabel.setText(translate('OpenLP.ThemeForm', 'Color:')) - self.footerSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:')) - self.footerSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt')) - self.alignmentPage.setTitle(translate('OpenLP.ThemeForm', 'Text Formatting Details')) - self.alignmentPage.setSubTitle(translate('OpenLP.ThemeForm', 'Allows additional display formatting information to be defined')) - self.horizontalLabel.setText(translate('OpenLP.ThemeForm', 'Horizontal Align:')) - self.horizontalComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Left')) - self.horizontalComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Right')) - self.horizontalComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Center')) - self.verticalLabel.setText(translate('OpenLP.ThemeForm', 'Vertcal Align:')) - self.verticalComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Top')) - self.verticalComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Middle')) - self.verticalComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Bottom')) - self.transitionsCheckBox.setText(translate('OpenLP.ThemeForm', 'Transitions')) - self.areaPositionPage.setTitle(translate('OpenLP.ThemeForm', 'Output Area Locations')) - self.areaPositionPage.setSubTitle(translate('OpenLP.ThemeForm', 'Allows you to change and move the Main and Footer areas.')) - self.mainPositionGroupBox.setTitle(translate('OpenLP.ThemeForm', '&Main Area')) - self.mainDefaultPositionCheckBox.setText(translate('OpenLP.ThemeForm', '&Use default location')) - self.nainXLabel.setText(translate('OpenLP.ThemeForm', 'X position:')) - self.mainXSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.mainYSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.mainYLabel.setText(translate('OpenLP.ThemeForm', 'Y position:')) - self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.mainWidthLabel.setText(translate('OpenLP.ThemeForm', 'Width:')) - self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.mainHeightLabel.setText(translate('OpenLP.ThemeForm', 'Height:')) - self.footerPositionGroupBox.setTitle(translate('OpenLP.ThemeForm', 'Footer Area')) - self.footerXLabel.setText(translate('OpenLP.ThemeForm', 'X position:')) - self.footerXSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.footerYLabel.setText(translate('OpenLP.ThemeForm', 'Y position:')) - self.footerYSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.footerWidthLabel.setText(translate('OpenLP.ThemeForm', 'Width:')) - self.footerWidthSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.footerHeightLabel.setText(translate('OpenLP.ThemeForm', 'Height:')) - self.footerHeightSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px')) - self.footerDefaultPositionCheckBox.setText(translate('OpenLP.ThemeForm', 'Use default location')) - self.previewPage.setTitle(translate('OpenLP.ThemeForm', 'Save and Preview')) - self.previewPage.setSubTitle(translate('OpenLP.ThemeForm', 'View the theme and save it replacing the current one or change the name to create a new theme')) - self.themeNameLabel.setText(translate('OpenLP.ThemeForm', 'Theme name:')) - self.previewLabel.setText(translate('OpenLP.ThemeForm', 'Preview')) + ThemeWizard.setWindowTitle( + translate('OpenLP.ThemeWizard', 'Theme Wizard')) + self.titleLabel.setText( + u'%s' % \ + translate('OpenLP.ThemeWizard', 'Welcome to the Theme Wizard')) + self.informationLabel.setText( + translate('OpenLP.ThemeWizard', 'This wizard will help you to ' + 'create and edit your themes . Click the next button below to ' + 'start the process by setting up your background.')) + self.backgroundPage.setTitle( + translate('OpenLP.ThemeWizard', 'Set Up Background')) + self.backgroundPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'Set up your theme\'s background ' + 'according to the parameters below.')) + self.backgroundTypeLabel.setText( + translate('OpenLP.ThemeWizard', 'Background type:')) + self.backgroundTypeComboBox.setItemText(0, + translate('OpenLP.ThemeWizard', 'Solid Color')) + self.backgroundTypeComboBox.setItemText(1, + translate('OpenLP.ThemeWizard', 'Gradient')) + self.backgroundTypeComboBox.setItemText(2, + translate('OpenLP.ThemeWizard', 'Image')) + self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) + self.gradientStartLabel.setText( + translate(u'OpenLP.ThemeWizard', 'Starting color:')) + self.gradientEndLabel.setText( + translate(u'OpenLP.ThemeWizard', 'Ending color:')) + self.gradientTypeLabel.setText( + translate('OpenLP.ThemeWizard', 'Gradient:')) + self.gradientComboBox.setItemText(0, + translate('OpenLP.ThemeWizard', 'Horizontal')) + self.gradientComboBox.setItemText(1, + translate('OpenLP.ThemeWizard', 'Vertical')) + self.gradientComboBox.setItemText(2, + translate('OpenLP.ThemeWizard', 'Circular')) + self.gradientComboBox.setItemText(3, + translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right')) + self.gradientComboBox.setItemText(4, + translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) + self.imageLabel.setText(translate('OpenLP.ThemeWizard', 'Image:')) + self.mainAreaPage.setTitle( + translate('OpenLP.ThemeWizard', 'Main Area Font Details')) + self.mainAreaPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'Define the font and display ' + 'characteristics for the Display text')) + self.mainFontLabel.setText( + translate('OpenLP.ThemeWizard', 'Font:')) + 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')) + self.outlineCheckBox.setText( + translate('OpenLP.ThemeWizard', '&Outline:')) + self.outlineSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) + self.outlineSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.shadowCheckBox.setText(translate('OpenLP.ThemeWizard', '&Shadow:')) + self.shadowSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) + self.shadowSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.boldCheckBox.setText( + translate('OpenLP.ThemeWizard', 'Bold')) + self.italicsCheckBox.setText( + translate('OpenLP.ThemeWizard', 'Italic')) + self.footerAreaPage.setTitle( + translate('OpenLP.ThemeWizard', 'Footer Area Font Details')) + self.footerAreaPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'Define the font and display ' + 'characteristics for the Footer text')) + self.footerFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:')) + self.footerColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) + self.footerSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) + self.footerSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.alignmentPage.setTitle( + translate('OpenLP.ThemeWizard', 'Text Formatting Details')) + self.alignmentPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'Allows additional display ' + 'formatting information to be defined')) + self.horizontalLabel.setText( + translate('OpenLP.ThemeWizard', 'Horizontal Align:')) + self.horizontalComboBox.setItemText(0, + translate('OpenLP.ThemeWizard', 'Left')) + self.horizontalComboBox.setItemText(1, + translate('OpenLP.ThemeWizard', 'Right')) + self.horizontalComboBox.setItemText(2, + translate('OpenLP.ThemeWizard', 'Center')) + self.verticalLabel.setText( + translate('OpenLP.ThemeWizard', 'Vertical Align:')) + self.verticalComboBox.setItemText(0, + translate('OpenLP.ThemeWizard', 'Top')) + self.verticalComboBox.setItemText(1, + translate('OpenLP.ThemeWizard', 'Middle')) + self.verticalComboBox.setItemText(2, + translate('OpenLP.ThemeWizard', 'Bottom')) + self.transitionsCheckBox.setText( + translate('OpenLP.ThemeWizard', 'Transitions')) + self.areaPositionPage.setTitle( + translate('OpenLP.ThemeWizard', 'Output Area Locations')) + self.areaPositionPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'Allows you to change and move the ' + 'main and footer areas.')) + self.mainPositionGroupBox.setTitle( + translate('OpenLP.ThemeWizard', '&Main Area')) + self.mainDefaultPositionCheckBox.setText( + translate('OpenLP.ThemeWizard', '&Use default location')) + self.nainXLabel.setText(translate('OpenLP.ThemeWizard', 'X position:')) + self.mainXSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.mainYSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.mainYLabel.setText(translate('OpenLP.ThemeWizard', 'Y position:')) + self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.mainWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:')) + self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.mainHeightLabel.setText(translate('OpenLP.ThemeWizard', 'Height:')) + self.footerPositionGroupBox.setTitle( + translate('OpenLP.ThemeWizard', 'Footer Area')) + self.footerXLabel.setText(translate('OpenLP.ThemeWizard', 'X position:')) + self.footerXSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.footerYLabel.setText(translate('OpenLP.ThemeWizard', 'Y position:')) + self.footerYSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.footerWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:')) + self.footerWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.footerHeightLabel.setText( + translate('OpenLP.ThemeWizard', 'Height:')) + self.footerHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) + self.footerDefaultPositionCheckBox.setText( + translate('OpenLP.ThemeWizard', 'Use default location')) + self.previewPage.setTitle( + translate('OpenLP.ThemeWizard', 'Save and Preview')) + self.previewPage.setSubTitle( + translate('OpenLP.ThemeWizard', 'View the theme and save it ' + 'replacing the current one or change the name to create a ' + 'new theme')) + self.themeNameLabel.setText( + translate('OpenLP.ThemeWizard', 'Theme name:')) diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index 5b4c324dc..24cc4317b 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -128,7 +128,7 @@ class Ui_AlertDialog(object): self.AlertEntryLabel.setText( translate('AlertsPlugin.AlertForm', 'Alert &text:')) self.AlertParameter.setText( - translate('AlertsPlugin.AlertForm', '&Parameter(s):')) + translate('AlertsPlugin.AlertForm', '&Parameter:')) self.NewButton.setText( translate('AlertsPlugin.AlertForm', '&New')) self.SaveButton.setText( diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 377a43f6c..ff5072560 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -62,6 +62,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSingleClick) def loadList(self): + """ + Loads the list with alerts. + """ self.AlertListWidget.clear() alerts = self.manager.get_all_objects(AlertItem, order_by_ref=AlertItem.text) @@ -81,12 +84,16 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.close() def onDeleteClick(self): + """ + Deletes the selected item. + """ item = self.AlertListWidget.currentItem() if item: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] self.manager.delete_object(AlertItem, item_id) row = self.AlertListWidget.row(item) self.AlertListWidget.takeItem(row) + self.item_id = None self.AlertTextEdit.setText(u'') self.SaveButton.setEnabled(False) self.DeleteButton.setEnabled(False) @@ -96,8 +103,8 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): QtGui.QMessageBox.information(self, translate('AlertsPlugin.AlertForm', 'New Alert'), translate('AlertsPlugin.AlertForm', 'You haven\'t specified ' - 'any text for your alert. Please type in some text before ' - 'clicking New.')) + 'any text for your alert. Please type in some text before ' + 'clicking New.')) else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) @@ -107,7 +114,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): def onSaveClick(self): """ - Save an alert + Save the alert, we are editing. """ if self.item_id: alert = self.manager.get_object(AlertItem, self.item_id) @@ -115,14 +122,14 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.manager.save_object(alert) self.item_id = None self.loadList() - else: - self.onNewClick() def onTextChanged(self): """ Enable save button when data has been changed by editing the form """ - self.SaveButton.setEnabled(True) + # Only enable the button, if we are editing an item. + if self.item_id: + self.SaveButton.setEnabled(True) def onDoubleClick(self): """ @@ -131,8 +138,8 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): items = self.AlertListWidget.selectedIndexes() for item in items: bitem = self.AlertListWidget.item(item.row()) - self.triggerAlert(bitem.text()) - self.AlertTextEdit.setText(bitem.text()) + self.triggerAlert(unicode(bitem.text())) + self.AlertTextEdit.setText(unicode(bitem.text())) self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0] self.SaveButton.setEnabled(False) self.DeleteButton.setEnabled(True) @@ -145,13 +152,45 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): items = self.AlertListWidget.selectedIndexes() for item in items: bitem = self.AlertListWidget.item(item.row()) - self.AlertTextEdit.setText(bitem.text()) + self.AlertTextEdit.setText(unicode(bitem.text())) self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0] + # If the alert does not contain '<>' we clear the ParameterEdit field. + if unicode(self.AlertTextEdit.text()).find(u'<>') == -1: + self.ParameterEdit.setText(u'') self.SaveButton.setEnabled(False) self.DeleteButton.setEnabled(True) def triggerAlert(self, text): + """ + Prepares the alert text for displaying. + + ``text`` + The alert text (unicode). + """ if text: + # We found '<>' in the alert text, but the ParameterEdit field is + # empty. + if text.find(u'<>') != -1 and not self.ParameterEdit.text() and \ + QtGui.QMessageBox.question(self, translate( + 'AlertPlugin.AlertForm', 'No Parameter found'), + translate('AlertPlugin.AlertForm', 'You have not entered a ' + 'parameter to be replaced.\nDo you want to continue ' + 'anyway?'), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | + QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: + self.ParameterEdit.setFocus() + return False + # The ParameterEdit field is not empty, but we have not found '<>' + # in the alert text. + elif text.find(u'<>') == -1 and self.ParameterEdit.text() and \ + QtGui.QMessageBox.question(self, translate( + 'AlertPlugin.AlertForm', 'No Placeholder found'), + translate('AlertPlugin.AlertForm', 'The alert text does not' + ' contain \'<>\'.\nDo want to continue anyway?'), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | + QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: + self.ParameterEdit.setFocus() + return False text = text.replace(u'<>', unicode(self.ParameterEdit.text())) self.parent.alertsmanager.displayAlert(text) return True diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index a418c6fec..0f2eb4ec7 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -86,7 +86,7 @@ class AlertsManager(QtCore.QObject): text = self.alertList.pop(0) alertTab = self.parent.alertsTab self.parent.liveController.display.alert(text) - # check to see if we have a timer running + # Check to see if we have a timer running. if self.timer_id == 0: self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) @@ -94,9 +94,9 @@ class AlertsManager(QtCore.QObject): """ Time has finished so if our time then request the next Alert if there is one and reset the timer. + ``event`` the QT event that has been triggered. - """ log.debug(u'timer event') if event.timerId() == self.timer_id: diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 2e11c30ad..53e659064 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -43,10 +43,12 @@ class WebDownload(object): Unknown = -1 Crosswalk = 0 BibleGateway = 1 + Bibleserver = 2 Names = { 0: u'Crosswalk', - 1: u'BibleGateway' + 1: u'BibleGateway', + 2: u'Bibleserver' } @classmethod @@ -77,6 +79,12 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QWizard.__init__(self, parent) self.setupUi(self) self.registerFields() + if not BibleFormat.get_availability(BibleFormat.OpenLP1): + self.openlp1Page.setVisible(False) + self.openlp1LocationLabel.setVisible(False) + self.openlp1LocationEdit.setVisible(False) + self.openlp1FileButton.setVisible(False) + self.openlp1DisabledLabel.setVisible(True) self.finishButton = self.button(QtGui.QWizard.FinishButton) self.cancelButton = self.button(QtGui.QWizard.CancelButton) self.manager = manager @@ -84,24 +92,24 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.manager.set_process_dialog(self) self.web_bible_list = {} self.loadWebBibles() - QtCore.QObject.connect(self.LocationComboBox, + QtCore.QObject.connect(self.locationComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onLocationComboBoxChanged) - QtCore.QObject.connect(self.OsisFileButton, + QtCore.QObject.connect(self.osisFileButton, QtCore.SIGNAL(u'clicked()'), self.onOsisFileButtonClicked) - QtCore.QObject.connect(self.BooksFileButton, + QtCore.QObject.connect(self.booksFileButton, QtCore.SIGNAL(u'clicked()'), self.onBooksFileButtonClicked) - QtCore.QObject.connect(self.CsvVersesFileButton, + QtCore.QObject.connect(self.csvVersesFileButton, QtCore.SIGNAL(u'clicked()'), self.onCsvVersesFileButtonClicked) - QtCore.QObject.connect(self.OpenSongBrowseButton, + QtCore.QObject.connect(self.openSongBrowseButton, QtCore.SIGNAL(u'clicked()'), self.onOpenSongBrowseButtonClicked) - QtCore.QObject.connect(self.cancelButton, - QtCore.SIGNAL(u'clicked(bool)'), - self.onCancelButtonClicked) + QtCore.QObject.connect(self.openlp1FileButton, + QtCore.SIGNAL(u'clicked()'), + self.onOpenlp1FileButtonClicked) QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged) @@ -113,6 +121,15 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.setDefaults() return QtGui.QWizard.exec_(self) + def reject(self): + """ + Stop the import on cancel button, close button or ESC key. + """ + log.debug('Import canceled by user.') + if self.currentId() == 3: + Receiver.send_message(u'bibles_stop_import') + self.done(QtGui.QDialog.Rejected) + def validateCurrentPage(self): """ Validate the current page before moving on to the next page. @@ -123,7 +140,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): elif self.currentId() == 1: # Select page if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: - if self.field(u'osis_location').toString() == u'': + if not self.field(u'osis_location').toString(): QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Invalid Bible Location'), @@ -133,34 +150,44 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.OSISLocationEdit.setFocus() return False elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV: - if self.field(u'csv_booksfile').toString() == u'': + if not self.field(u'csv_booksfile').toString(): QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Invalid Books File'), translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file with books of ' 'the Bible to use in the import.')) - self.BooksLocationEdit.setFocus() + self.booksLocationEdit.setFocus() return False - elif self.field(u'csv_versefile').toString() == u'': + elif not self.field(u'csv_versefile').toString(): QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Invalid Verse File'), translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file of Bible ' 'verses to import.')) - self.CsvVerseLocationEdit.setFocus() + self.csvVerseLocationEdit.setFocus() return False elif self.field(u'source_format').toInt()[0] == \ BibleFormat.OpenSong: - if self.field(u'opensong_file').toString() == u'': + if not self.field(u'opensong_file').toString(): QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Invalid OpenSong Bible'), translate('BiblesPlugin.ImportWizardForm', 'You need to specify an OpenSong Bible ' 'file to import.')) - self.OpenSongFileEdit.setFocus() + self.openSongFileEdit.setFocus() + return False + elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1: + if not self.field(u'openlp1_location').toString(): + QtGui.QMessageBox.critical(self, + translate('BiblesPlugin.ImportWizardForm', + 'Invalid Bible Location'), + translate('BiblesPlugin.ImportWizardForm', + 'You need to specify a file to import your ' + 'Bible from.')) + self.openlp1LocationEdit.setFocus() return False return True elif self.currentId() == 2: @@ -168,22 +195,22 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): license_version = unicode(self.field(u'license_version').toString()) license_copyright = \ unicode(self.field(u'license_copyright').toString()) - if license_version == u'': + if not license_version: QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Empty Version Name'), translate('BiblesPlugin.ImportWizardForm', 'You need to specify a version name for your Bible.')) - self.VersionNameEdit.setFocus() + self.versionNameEdit.setFocus() return False - elif license_copyright == u'': + elif not license_copyright: QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Empty Copyright'), translate('BiblesPlugin.ImportWizardForm', 'You need to set a copyright for your Bible. ' 'Bibles in the Public Domain need to be marked as such.')) - self.CopyrightEdit.setFocus() + self.copyrightEdit.setFocus() return False elif self.manager.exists(license_version): QtGui.QMessageBox.critical(self, @@ -191,7 +218,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): translate('BiblesPlugin.ImportWizardForm', 'This Bible already exists. Please import ' 'a different Bible or first delete the existing one.')) - self.VersionNameEdit.setFocus() + self.versionNameEdit.setFocus() return False return True if self.currentId() == 3: @@ -206,10 +233,11 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): ``index`` The index of the combo box. """ - self.BibleComboBox.clear() - for bible in self.web_bible_list[index].keys(): - self.BibleComboBox.addItem(unicode( - translate('BiblesPlugin.ImportWizardForm', bible))) + self.bibleComboBox.clear() + bibles = self.web_bible_list[index].keys() + bibles.sort() + for bible in bibles: + self.bibleComboBox.addItem(bible) def onOsisFileButtonClicked(self): """ @@ -225,14 +253,14 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): """ self.getFileName( translate('BiblesPlugin.ImportWizardForm', 'Open Books CSV File'), - self.BooksLocationEdit) + self.booksLocationEdit) def onCsvVersesFileButtonClicked(self): """ Show the file open dialog for the verses CSV file. """ self.getFileName(translate('BiblesPlugin.ImportWizardForm', - 'Open Verses CSV File'), self.CsvVerseLocationEdit) + 'Open Verses CSV File'), self.csvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): """ @@ -240,15 +268,15 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): """ self.getFileName( translate('BiblesPlugin.ImportWizardForm', 'Open OpenSong Bible'), - self.OpenSongFileEdit) + self.openSongFileEdit) - def onCancelButtonClicked(self, checked): + def onOpenlp1FileButtonClicked(self): """ - Stop the import on pressing the cancel button. + Show the file open dialog for the openlp.org 1.x file. """ - log.debug('Cancel button pressed!') - if self.currentId() == 3: - Receiver.send_message(u'bibles_stop_import') + self.getFileName( + translate('BiblesPlugin.ImportWizardForm', + 'Open openlp.org 1.x Bible'), self.openlp1LocationEdit) def onCurrentIdChanged(self, pageId): if pageId == 3: @@ -257,32 +285,25 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.postImport() def registerFields(self): - self.SelectPage.registerField( - u'source_format', self.FormatComboBox) - self.SelectPage.registerField( - u'osis_location', self.OSISLocationEdit) - self.SelectPage.registerField( - u'csv_booksfile', self.BooksLocationEdit) - self.SelectPage.registerField( - u'csv_versefile', self.CsvVerseLocationEdit) - self.SelectPage.registerField( - u'opensong_file', self.OpenSongFileEdit) - self.SelectPage.registerField( - u'web_location', self.LocationComboBox) - self.SelectPage.registerField( - u'web_biblename', self.BibleComboBox) - self.SelectPage.registerField( - u'proxy_server', self.AddressEdit) - self.SelectPage.registerField( - u'proxy_username', self.UsernameEdit) - self.SelectPage.registerField( - u'proxy_password', self.PasswordEdit) - self.LicenseDetailsPage.registerField( - u'license_version', self.VersionNameEdit) - self.LicenseDetailsPage.registerField( - u'license_copyright', self.CopyrightEdit) - self.LicenseDetailsPage.registerField( - u'license_permissions', self.PermissionsEdit) + self.selectPage.registerField(u'source_format', self.formatComboBox) + self.selectPage.registerField(u'osis_location', self.OSISLocationEdit) + self.selectPage.registerField(u'csv_booksfile', self.booksLocationEdit) + self.selectPage.registerField( + u'csv_versefile', self.csvVerseLocationEdit) + self.selectPage.registerField(u'opensong_file', self.openSongFileEdit) + self.selectPage.registerField(u'web_location', self.locationComboBox) + self.selectPage.registerField(u'web_biblename', self.bibleComboBox) + self.selectPage.registerField(u'proxy_server', self.addressEdit) + self.selectPage.registerField(u'proxy_username', self.usernameEdit) + self.selectPage.registerField(u'proxy_password', self.passwordEdit) + self.selectPage.registerField( + u'openlp1_location', self.openlp1LocationEdit) + self.licenseDetailsPage.registerField( + u'license_version', self.versionNameEdit) + self.licenseDetailsPage.registerField( + u'license_copyright', self.copyrightEdit) + self.licenseDetailsPage.registerField( + u'license_permissions', self.permissionsEdit) def setDefaults(self): settings = QtCore.QSettings() @@ -297,19 +318,20 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): self.setField(u'opensong_file', QtCore.QVariant('')) self.setField(u'web_location', QtCore.QVariant(WebDownload.Crosswalk)) self.setField(u'web_biblename', - QtCore.QVariant(self.BibleComboBox.currentIndex())) + QtCore.QVariant(self.bibleComboBox.currentIndex())) self.setField(u'proxy_server', settings.value(u'proxy address', QtCore.QVariant(u''))) self.setField(u'proxy_username', settings.value(u'proxy username', QtCore.QVariant(u''))) self.setField(u'proxy_password', settings.value(u'proxy password', QtCore.QVariant(u''))) + self.setField(u'openlp1_location', QtCore.QVariant('')) self.setField(u'license_version', - QtCore.QVariant(self.VersionNameEdit.text())) + QtCore.QVariant(self.versionNameEdit.text())) self.setField(u'license_copyright', - QtCore.QVariant(self.CopyrightEdit.text())) + QtCore.QVariant(self.copyrightEdit.text())) self.setField(u'license_permissions', - QtCore.QVariant(self.PermissionsEdit.text())) + QtCore.QVariant(self.permissionsEdit.text())) self.onLocationComboBoxChanged(WebDownload.Crosswalk) settings.endGroup() @@ -317,31 +339,27 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): """ Load the list of Crosswalk and BibleGateway bibles. """ - #Load and store Crosswalk Bibles + # Load Crosswalk Bibles. filepath = AppLocation.get_directory(AppLocation.PluginsDir) filepath = os.path.join(filepath, u'bibles', u'resources') books_file = None try: self.web_bible_list[WebDownload.Crosswalk] = {} books_file = open( - os.path.join(filepath, u'crosswalkbooks.csv'), 'r') + os.path.join(filepath, u'crosswalkbooks.csv'), 'rb') dialect = csv.Sniffer().sniff(books_file.read(1024)) books_file.seek(0) books_reader = csv.reader(books_file, dialect) for line in books_reader: - ver = line[0] - name = line[1] - if not isinstance(ver, unicode): - ver = unicode(ver, u'utf8') - if not isinstance(name, unicode): - name = unicode(name, u'utf8') + ver = unicode(line[0], u'utf-8') + name = unicode(line[1], u'utf-8') self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip() except IOError: log.exception(u'Crosswalk resources missing') finally: if books_file: books_file.close() - #Load and store BibleGateway Bibles + # Load BibleGateway Bibles. books_file = None try: self.web_bible_list[WebDownload.BibleGateway] = {} @@ -363,6 +381,26 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): finally: if books_file: books_file.close() + # Load and Bibleserver Bibles. + filepath = AppLocation.get_directory(AppLocation.PluginsDir) + filepath = os.path.join(filepath, u'bibles', u'resources') + books_file = None + try: + self.web_bible_list[WebDownload.Bibleserver] = {} + books_file = open( + os.path.join(filepath, u'bibleserver.csv'), 'rb') + dialect = csv.Sniffer().sniff(books_file.read(1024)) + books_file.seek(0) + books_reader = csv.reader(books_file, dialect) + for line in books_reader: + ver = unicode(line[0], u'utf-8') + name = unicode(line[1], u'utf-8') + self.web_bible_list[WebDownload.Bibleserver][ver] = name.strip() + except IOError, UnicodeError: + log.exception(u'Bibleserver resources missing') + finally: + if books_file: + books_file.close() def getFileName(self, title, editbox): filename = QtGui.QFileDialog.getOpenFileName(self, title, @@ -374,20 +412,32 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): def incrementProgressBar(self, status_text): log.debug(u'IncrementBar %s', status_text) - self.ImportProgressLabel.setText(status_text) - self.ImportProgressBar.setValue(self.ImportProgressBar.value() + 1) + self.importProgressLabel.setText(status_text) + self.importProgressBar.setValue(self.importProgressBar.value() + 1) Receiver.send_message(u'openlp_process_events') def preImport(self): + """ + Prepare the UI for the import. + """ + bible_type = self.field(u'source_format').toInt()[0] self.finishButton.setVisible(False) - self.ImportProgressBar.setMinimum(0) - self.ImportProgressBar.setMaximum(1188) - self.ImportProgressBar.setValue(0) - self.ImportProgressLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Starting import...')) + self.importProgressBar.setMinimum(0) + self.importProgressBar.setMaximum(1188) + self.importProgressBar.setValue(0) + if bible_type == BibleFormat.WebDownload: + self.importProgressLabel.setText(translate( + 'BiblesPlugin.ImportWizardForm', + 'Starting Registering bible...')) + else: + self.importProgressLabel.setText(translate( + 'BiblesPlugin.ImportWizardForm', 'Starting import...')) Receiver.send_message(u'openlp_process_events') def performImport(self): + """ + Perform the actual import. + """ bible_type = self.field(u'source_format').toInt()[0] license_version = unicode(self.field(u'license_version').toString()) license_copyright = unicode(self.field(u'license_copyright').toString()) @@ -395,35 +445,38 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): unicode(self.field(u'license_permissions').toString()) importer = None if bible_type == BibleFormat.OSIS: - # Import an OSIS bible + # Import an OSIS bible. importer = self.manager.import_bible(BibleFormat.OSIS, name=license_version, filename=unicode(self.field(u'osis_location').toString()) ) elif bible_type == BibleFormat.CSV: - # Import a CSV bible + # Import a CSV bible. importer = self.manager.import_bible(BibleFormat.CSV, name=license_version, booksfile=unicode(self.field(u'csv_booksfile').toString()), versefile=unicode(self.field(u'csv_versefile').toString()) ) elif bible_type == BibleFormat.OpenSong: - # Import an OpenSong bible + # Import an OpenSong bible. importer = self.manager.import_bible(BibleFormat.OpenSong, name=license_version, filename=unicode(self.field(u'opensong_file').toString()) ) elif bible_type == BibleFormat.WebDownload: - # Import a bible from the web - self.ImportProgressBar.setMaximum(1) + # Import a bible from the web. + self.importProgressBar.setMaximum(1) download_location = self.field(u'web_location').toInt()[0] - bible_version = unicode(self.BibleComboBox.currentText()) + bible_version = unicode(self.bibleComboBox.currentText()) if download_location == WebDownload.Crosswalk: bible = \ self.web_bible_list[WebDownload.Crosswalk][bible_version] elif download_location == WebDownload.BibleGateway: bible = \ self.web_bible_list[WebDownload.BibleGateway][bible_version] + elif download_location == WebDownload.Bibleserver: + bible = \ + self.web_bible_list[WebDownload.Bibleserver][bible_version] importer = self.manager.import_bible( BibleFormat.WebDownload, name=license_version, @@ -434,20 +487,31 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): unicode(self.field(u'proxy_username').toString()), proxy_password=unicode(self.field(u'proxy_password').toString()) ) + elif bible_type == BibleFormat.OpenLP1: + # Import an openlp.org 1.x bible. + importer = self.manager.import_bible(BibleFormat.OpenLP1, + name=license_version, + filename=unicode(self.field(u'openlp1_location').toString()) + ) if importer.do_import(): self.manager.save_meta_data(license_version, license_version, license_copyright, license_permissions) self.manager.reload_bibles() - self.ImportProgressLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Finished import.')) + if bible_type == BibleFormat.WebDownload: + self.importProgressLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Registered ' + 'bible. Please note, that verses will be downloaded on\n' + 'demand and thus an internet connection is required.')) + else: + self.importProgressLabel.setText(translate( + 'BiblesPlugin.ImportWizardForm', 'Finished import.')) else: - self.ImportProgressLabel.setText( - translate('BiblesPlugin.ImportWizardForm', - 'Your Bible import failed.')) + self.importProgressLabel.setText(translate( + 'BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) delete_database(self.bibleplugin.settingsSection, importer.file) def postImport(self): - self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) + self.importProgressBar.setValue(self.importProgressBar.maximum()) self.finishButton.setVisible(True) self.cancelButton.setVisible(False) Receiver.send_message(u'openlp_process_events') diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index 304e9fb0f..a0b2b99b9 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -29,356 +29,404 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate class Ui_BibleImportWizard(object): - def setupUi(self, BibleImportWizard): - BibleImportWizard.setObjectName(u'BibleImportWizard') - BibleImportWizard.resize(550, 386) - BibleImportWizard.setModal(True) - BibleImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle) - BibleImportWizard.setOptions( + def setupUi(self, bibleImportWizard): + bibleImportWizard.setObjectName(u'bibleImportWizard') + bibleImportWizard.resize(550, 386) + bibleImportWizard.setModal(True) + bibleImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle) + bibleImportWizard.setOptions( QtGui.QWizard.IndependentPages | QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnLastPage) - self.WelcomePage = QtGui.QWizardPage() - self.WelcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, + # Welcome page + self.welcomePage = QtGui.QWizardPage() + self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, QtGui.QPixmap(u':/wizards/wizard_importbible.bmp')) - self.WelcomePage.setObjectName(u'WelcomePage') - self.WelcomeLayout = QtGui.QVBoxLayout(self.WelcomePage) - self.WelcomeLayout.setSpacing(8) - self.WelcomeLayout.setMargin(0) - self.WelcomeLayout.setObjectName(u'WelcomeLayout') - self.TitleLabel = QtGui.QLabel(self.WelcomePage) - self.TitleLabel.setObjectName(u'TitleLabel') - self.WelcomeLayout.addWidget(self.TitleLabel) + self.welcomePage.setObjectName(u'WelcomePage') + self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage) + self.welcomeLayout.setSpacing(8) + self.welcomeLayout.setMargin(0) + self.welcomeLayout.setObjectName(u'WelcomeLayout') + self.titleLabel = QtGui.QLabel(self.welcomePage) + self.titleLabel.setObjectName(u'TitleLabel') + self.welcomeLayout.addWidget(self.titleLabel) spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) - self.WelcomeLayout.addItem(spacerItem) - self.InformationLabel = QtGui.QLabel(self.WelcomePage) - self.InformationLabel.setWordWrap(True) - self.InformationLabel.setMargin(10) - self.InformationLabel.setObjectName(u'InformationLabel') - self.WelcomeLayout.addWidget(self.InformationLabel) + self.welcomeLayout.addItem(spacerItem) + self.informationLabel = QtGui.QLabel(self.welcomePage) + self.informationLabel.setWordWrap(True) + self.informationLabel.setMargin(10) + self.informationLabel.setObjectName(u'InformationLabel') + self.welcomeLayout.addWidget(self.informationLabel) spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.WelcomeLayout.addItem(spacerItem1) - BibleImportWizard.addPage(self.WelcomePage) - self.SelectPage = QtGui.QWizardPage() - self.SelectPage.setObjectName(u'SelectPage') - self.selectPageLayout = QtGui.QVBoxLayout(self.SelectPage) + self.welcomeLayout.addItem(spacerItem1) + bibleImportWizard.addPage(self.welcomePage) + # Select page + self.selectPage = QtGui.QWizardPage() + self.selectPage.setObjectName(u'SelectPage') + self.selectPageLayout = QtGui.QVBoxLayout(self.selectPage) self.selectPageLayout.setSpacing(8) self.selectPageLayout.setMargin(20) self.selectPageLayout.setObjectName(u'selectPageLayout') - self.FormatSelectLayout = QtGui.QHBoxLayout() - self.FormatSelectLayout.setSpacing(8) - self.FormatSelectLayout.setObjectName(u'FormatSelectLayout') - self.FormatLabel = QtGui.QLabel(self.SelectPage) - self.FormatLabel.setObjectName(u'FormatLabel') - self.FormatSelectLayout.addWidget(self.FormatLabel) - self.FormatComboBox = QtGui.QComboBox(self.SelectPage) - self.FormatComboBox.setObjectName(u'FormatComboBox') - self.FormatComboBox.addItem(u'') - self.FormatComboBox.addItem(u'') - self.FormatComboBox.addItem(u'') - self.FormatComboBox.addItem(u'') - self.FormatSelectLayout.addWidget(self.FormatComboBox) + self.formatSelectLayout = QtGui.QHBoxLayout() + self.formatSelectLayout.setSpacing(8) + self.formatSelectLayout.setObjectName(u'FormatSelectLayout') + self.formatLabel = QtGui.QLabel(self.selectPage) + self.formatLabel.setObjectName(u'FormatLabel') + self.formatSelectLayout.addWidget(self.formatLabel) + self.formatComboBox = QtGui.QComboBox(self.selectPage) + self.formatComboBox.setObjectName(u'FormatComboBox') + self.formatComboBox.addItem(u'') + self.formatComboBox.addItem(u'') + self.formatComboBox.addItem(u'') + self.formatComboBox.addItem(u'') + self.formatComboBox.addItem(u'') + self.formatSelectLayout.addWidget(self.formatComboBox) spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.FormatSelectLayout.addItem(spacerItem2) - self.selectPageLayout.addLayout(self.FormatSelectLayout) - self.FormatWidget = QtGui.QStackedWidget(self.SelectPage) - self.FormatWidget.setObjectName(u'FormatWidget') - self.OsisPage = QtGui.QWidget() - self.OsisPage.setObjectName(u'OsisPage') - self.OsisLayout = QtGui.QFormLayout(self.OsisPage) - self.OsisLayout.setFieldGrowthPolicy( - QtGui.QFormLayout.ExpandingFieldsGrow) - self.OsisLayout.setMargin(0) - self.OsisLayout.setSpacing(8) - self.OsisLayout.setObjectName(u'OsisLayout') - self.OsisLocationLabel = QtGui.QLabel(self.OsisPage) - self.OsisLocationLabel.setObjectName(u'OsisLocationLabel') - self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.OsisLocationLabel) - self.OsisLocationLayout = QtGui.QHBoxLayout() - self.OsisLocationLayout.setSpacing(8) - self.OsisLocationLayout.setObjectName(u'OsisLocationLayout') - self.OSISLocationEdit = QtGui.QLineEdit(self.OsisPage) - self.OSISLocationEdit.setObjectName(u'OSISLocationEdit') - self.OsisLocationLayout.addWidget(self.OSISLocationEdit) - self.OsisFileButton = QtGui.QToolButton(self.OsisPage) - self.OsisFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) + self.formatSelectLayout.addItem(spacerItem2) + self.selectPageLayout.addLayout(self.formatSelectLayout) + self.formatWidget = QtGui.QStackedWidget(self.selectPage) + self.formatWidget.setObjectName(u'FormatWidget') generalIcon = build_icon(u':/general/general_open.png') - self.OsisFileButton.setIcon(generalIcon) - self.OsisFileButton.setObjectName(u'OsisFileButton') - self.OsisLocationLayout.addWidget(self.OsisFileButton) - self.OsisLayout.setLayout(1, QtGui.QFormLayout.FieldRole, - self.OsisLocationLayout) - self.FormatWidget.addWidget(self.OsisPage) - self.CsvPage = QtGui.QWidget() - self.CsvPage.setObjectName(u'CsvPage') - self.CsvSourceLayout = QtGui.QFormLayout(self.CsvPage) - self.CsvSourceLayout.setFieldGrowthPolicy( + self.osisPage = QtGui.QWidget() + self.osisPage.setObjectName(u'OsisPage') + self.osisLayout = QtGui.QFormLayout(self.osisPage) + self.osisLayout.setFieldGrowthPolicy( QtGui.QFormLayout.ExpandingFieldsGrow) - self.CsvSourceLayout.setLabelAlignment(QtCore.Qt.AlignBottom | + self.osisLayout.setMargin(0) + self.osisLayout.setSpacing(8) + self.osisLayout.setObjectName(u'OsisLayout') + self.osisLocationLabel = QtGui.QLabel(self.osisPage) + self.osisLocationLabel.setObjectName(u'OsisLocationLabel') + self.osisLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.osisLocationLabel) + self.osisLocationLayout = QtGui.QHBoxLayout() + self.osisLocationLayout.setSpacing(8) + self.osisLocationLayout.setObjectName(u'OsisLocationLayout') + self.OSISLocationEdit = QtGui.QLineEdit(self.osisPage) + self.OSISLocationEdit.setObjectName(u'OSISLocationEdit') + self.osisLocationLayout.addWidget(self.OSISLocationEdit) + self.osisFileButton = QtGui.QToolButton(self.osisPage) + self.osisFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) + self.osisFileButton.setIcon(generalIcon) + self.osisFileButton.setObjectName(u'OsisFileButton') + self.osisLocationLayout.addWidget(self.osisFileButton) + self.osisLayout.setLayout(1, QtGui.QFormLayout.FieldRole, + self.osisLocationLayout) + self.formatWidget.addWidget(self.osisPage) + self.csvPage = QtGui.QWidget() + self.csvPage.setObjectName(u'CsvPage') + self.csvSourceLayout = QtGui.QFormLayout(self.csvPage) + self.csvSourceLayout.setFieldGrowthPolicy( + QtGui.QFormLayout.ExpandingFieldsGrow) + self.csvSourceLayout.setLabelAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing) - self.CsvSourceLayout.setFormAlignment(QtCore.Qt.AlignLeading | + self.csvSourceLayout.setFormAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) - self.CsvSourceLayout.setMargin(0) - self.CsvSourceLayout.setSpacing(8) - self.CsvSourceLayout.setObjectName(u'CsvSourceLayout') - self.BooksLocationLabel = QtGui.QLabel(self.CsvPage) - self.BooksLocationLabel.setObjectName(u'BooksLocationLabel') - self.CsvSourceLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.BooksLocationLabel) - self.CsvBooksLayout = QtGui.QHBoxLayout() - self.CsvBooksLayout.setSpacing(8) - self.CsvBooksLayout.setObjectName(u'CsvBooksLayout') - self.BooksLocationEdit = QtGui.QLineEdit(self.CsvPage) - self.BooksLocationEdit.setObjectName(u'BooksLocationEdit') - self.CsvBooksLayout.addWidget(self.BooksLocationEdit) - self.BooksFileButton = QtGui.QToolButton(self.CsvPage) - self.BooksFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) - self.BooksFileButton.setIcon(generalIcon) - self.BooksFileButton.setObjectName(u'BooksFileButton') - self.CsvBooksLayout.addWidget(self.BooksFileButton) - self.CsvSourceLayout.setLayout(0, QtGui.QFormLayout.FieldRole, - self.CsvBooksLayout) - self.VerseLocationLabel = QtGui.QLabel(self.CsvPage) - self.VerseLocationLabel.setObjectName(u'VerseLocationLabel') - self.CsvSourceLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.VerseLocationLabel) - self.CsvVerseLayout = QtGui.QHBoxLayout() - self.CsvVerseLayout.setSpacing(8) - self.CsvVerseLayout.setObjectName(u'CsvVerseLayout') - self.CsvVerseLocationEdit = QtGui.QLineEdit(self.CsvPage) - self.CsvVerseLocationEdit.setObjectName(u'CsvVerseLocationEdit') - self.CsvVerseLayout.addWidget(self.CsvVerseLocationEdit) - self.CsvVersesFileButton = QtGui.QToolButton(self.CsvPage) - self.CsvVersesFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) - self.CsvVersesFileButton.setIcon(generalIcon) - self.CsvVersesFileButton.setObjectName(u'CsvVersesFileButton') - self.CsvVerseLayout.addWidget(self.CsvVersesFileButton) - self.CsvSourceLayout.setLayout(1, QtGui.QFormLayout.FieldRole, - self.CsvVerseLayout) - self.FormatWidget.addWidget(self.CsvPage) - self.OpenSongPage = QtGui.QWidget() - self.OpenSongPage.setObjectName(u'OpenSongPage') - self.OpenSongLayout = QtGui.QFormLayout(self.OpenSongPage) - self.OpenSongLayout.setMargin(0) - self.OpenSongLayout.setSpacing(8) - self.OpenSongLayout.setObjectName(u'OpenSongLayout') - self.OpenSongFileLabel = QtGui.QLabel(self.OpenSongPage) - self.OpenSongFileLabel.setObjectName(u'OpenSongFileLabel') - self.OpenSongLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.OpenSongFileLabel) - self.OpenSongFileLayout = QtGui.QHBoxLayout() - self.OpenSongFileLayout.setSpacing(8) - self.OpenSongFileLayout.setObjectName(u'OpenSongFileLayout') - self.OpenSongFileEdit = QtGui.QLineEdit(self.OpenSongPage) - self.OpenSongFileEdit.setObjectName(u'OpenSongFileEdit') - self.OpenSongFileLayout.addWidget(self.OpenSongFileEdit) - self.OpenSongBrowseButton = QtGui.QToolButton(self.OpenSongPage) - self.OpenSongBrowseButton.setIcon(generalIcon) - self.OpenSongBrowseButton.setObjectName(u'OpenSongBrowseButton') - self.OpenSongFileLayout.addWidget(self.OpenSongBrowseButton) - self.OpenSongLayout.setLayout(0, QtGui.QFormLayout.FieldRole, - self.OpenSongFileLayout) - self.FormatWidget.addWidget(self.OpenSongPage) - self.WebDownloadPage = QtGui.QWidget() - self.WebDownloadPage.setObjectName(u'WebDownloadPage') - self.WebDownloadLayout = QtGui.QVBoxLayout(self.WebDownloadPage) - self.WebDownloadLayout.setSpacing(8) - self.WebDownloadLayout.setMargin(0) - self.WebDownloadLayout.setObjectName(u'WebDownloadLayout') - self.WebDownloadTabWidget = QtGui.QTabWidget(self.WebDownloadPage) - self.WebDownloadTabWidget.setObjectName(u'WebDownloadTabWidget') - self.DownloadOptionsTab = QtGui.QWidget() - self.DownloadOptionsTab.setObjectName(u'DownloadOptionsTab') - self.DownloadOptionsLayout = QtGui.QFormLayout(self.DownloadOptionsTab) - self.DownloadOptionsLayout.setMargin(8) - self.DownloadOptionsLayout.setSpacing(8) - self.DownloadOptionsLayout.setObjectName(u'DownloadOptionsLayout') - self.LocationLabel = QtGui.QLabel(self.DownloadOptionsTab) - self.LocationLabel.setObjectName(u'LocationLabel') - self.DownloadOptionsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.LocationLabel) - self.LocationComboBox = QtGui.QComboBox(self.DownloadOptionsTab) - self.LocationComboBox.setObjectName(u'LocationComboBox') - self.LocationComboBox.addItem(u'') - self.LocationComboBox.addItem(u'') - self.DownloadOptionsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.LocationComboBox) - self.BibleLabel = QtGui.QLabel(self.DownloadOptionsTab) - self.BibleLabel.setObjectName(u'BibleLabel') - self.DownloadOptionsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.BibleLabel) - self.BibleComboBox = QtGui.QComboBox(self.DownloadOptionsTab) - self.BibleComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) - self.BibleComboBox.setObjectName(u'BibleComboBox') - self.BibleComboBox.addItem(u'') - self.BibleComboBox.addItem(u'') - self.BibleComboBox.addItem(u'') - self.DownloadOptionsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.BibleComboBox) - self.WebDownloadTabWidget.addTab(self.DownloadOptionsTab, u'') - self.ProxyServerTab = QtGui.QWidget() - self.ProxyServerTab.setObjectName(u'ProxyServerTab') - self.ProxyServerLayout = QtGui.QFormLayout(self.ProxyServerTab) - self.ProxyServerLayout.setObjectName(u'ProxyServerLayout') - self.AddressLabel = QtGui.QLabel(self.ProxyServerTab) - self.AddressLabel.setObjectName(u'AddressLabel') - self.ProxyServerLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.AddressLabel) - self.AddressEdit = QtGui.QLineEdit(self.ProxyServerTab) - self.AddressEdit.setObjectName(u'AddressEdit') - self.ProxyServerLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.AddressEdit) - self.UsernameLabel = QtGui.QLabel(self.ProxyServerTab) - self.UsernameLabel.setObjectName(u'UsernameLabel') - self.ProxyServerLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.UsernameLabel) - self.UsernameEdit = QtGui.QLineEdit(self.ProxyServerTab) - self.UsernameEdit.setObjectName(u'UsernameEdit') - self.ProxyServerLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.UsernameEdit) - self.PasswordLabel = QtGui.QLabel(self.ProxyServerTab) - self.PasswordLabel.setObjectName(u'PasswordLabel') - self.ProxyServerLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.PasswordLabel) - self.PasswordEdit = QtGui.QLineEdit(self.ProxyServerTab) - self.PasswordEdit.setObjectName(u'PasswordEdit') - self.ProxyServerLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.PasswordEdit) - self.WebDownloadTabWidget.addTab(self.ProxyServerTab, u'') - self.WebDownloadLayout.addWidget(self.WebDownloadTabWidget) - self.FormatWidget.addWidget(self.WebDownloadPage) - self.selectPageLayout.addWidget(self.FormatWidget) - BibleImportWizard.addPage(self.SelectPage) - self.LicenseDetailsPage = QtGui.QWizardPage() - self.LicenseDetailsPage.setObjectName(u'LicenseDetailsPage') - self.LicenseDetailsLayout = QtGui.QFormLayout(self.LicenseDetailsPage) - self.LicenseDetailsLayout.setMargin(20) - self.LicenseDetailsLayout.setSpacing(8) - self.LicenseDetailsLayout.setObjectName(u'LicenseDetailsLayout') - self.VersionNameLabel = QtGui.QLabel(self.LicenseDetailsPage) - self.VersionNameLabel.setObjectName(u'VersionNameLabel') - self.LicenseDetailsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.VersionNameLabel) - self.VersionNameEdit = QtGui.QLineEdit(self.LicenseDetailsPage) - self.VersionNameEdit.setObjectName(u'VersionNameEdit') - self.LicenseDetailsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.VersionNameEdit) - self.CopyrightLabel = QtGui.QLabel(self.LicenseDetailsPage) - self.CopyrightLabel.setObjectName(u'CopyrightLabel') - self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, - self.CopyrightLabel) - self.CopyrightEdit = QtGui.QLineEdit(self.LicenseDetailsPage) - self.CopyrightEdit.setObjectName(u'CopyrightEdit') - self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.CopyrightEdit) - self.PermissionsLabel = QtGui.QLabel(self.LicenseDetailsPage) - self.PermissionsLabel.setObjectName(u'PermissionsLabel') - self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.PermissionsLabel) - self.PermissionsEdit = QtGui.QLineEdit(self.LicenseDetailsPage) - self.PermissionsEdit.setObjectName(u'PermissionsEdit') - self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.PermissionsEdit) - BibleImportWizard.addPage(self.LicenseDetailsPage) - self.ImportPage = QtGui.QWizardPage() - self.ImportPage.setObjectName(u'ImportPage') - self.ImportLayout = QtGui.QVBoxLayout(self.ImportPage) - self.ImportLayout.setSpacing(8) - self.ImportLayout.setMargin(50) - self.ImportLayout.setObjectName(u'ImportLayout') - self.ImportProgressLabel = QtGui.QLabel(self.ImportPage) - self.ImportProgressLabel.setObjectName(u'ImportProgressLabel') - self.ImportLayout.addWidget(self.ImportProgressLabel) - self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage) - self.ImportProgressBar.setValue(0) - self.ImportProgressBar.setObjectName(u'ImportProgressBar') - self.ImportLayout.addWidget(self.ImportProgressBar) - BibleImportWizard.addPage(self.ImportPage) + self.csvSourceLayout.setMargin(0) + self.csvSourceLayout.setSpacing(8) + self.csvSourceLayout.setObjectName(u'CsvSourceLayout') + self.booksLocationLabel = QtGui.QLabel(self.csvPage) + self.booksLocationLabel.setObjectName(u'BooksLocationLabel') + self.csvSourceLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.booksLocationLabel) + self.csvBooksLayout = QtGui.QHBoxLayout() + self.csvBooksLayout.setSpacing(8) + self.csvBooksLayout.setObjectName(u'CsvBooksLayout') + self.booksLocationEdit = QtGui.QLineEdit(self.csvPage) + self.booksLocationEdit.setObjectName(u'BooksLocationEdit') + self.csvBooksLayout.addWidget(self.booksLocationEdit) + self.booksFileButton = QtGui.QToolButton(self.csvPage) + self.booksFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) + self.booksFileButton.setIcon(generalIcon) + self.booksFileButton.setObjectName(u'BooksFileButton') + self.csvBooksLayout.addWidget(self.booksFileButton) + self.csvSourceLayout.setLayout(0, QtGui.QFormLayout.FieldRole, + self.csvBooksLayout) + self.verseLocationLabel = QtGui.QLabel(self.csvPage) + self.verseLocationLabel.setObjectName(u'VerseLocationLabel') + self.csvSourceLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.verseLocationLabel) + self.csvVerseLayout = QtGui.QHBoxLayout() + self.csvVerseLayout.setSpacing(8) + self.csvVerseLayout.setObjectName(u'CsvVerseLayout') + self.csvVerseLocationEdit = QtGui.QLineEdit(self.csvPage) + self.csvVerseLocationEdit.setObjectName(u'CsvVerseLocationEdit') + self.csvVerseLayout.addWidget(self.csvVerseLocationEdit) + self.csvVersesFileButton = QtGui.QToolButton(self.csvPage) + self.csvVersesFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) + self.csvVersesFileButton.setIcon(generalIcon) + self.csvVersesFileButton.setObjectName(u'CsvVersesFileButton') + self.csvVerseLayout.addWidget(self.csvVersesFileButton) + self.csvSourceLayout.setLayout(1, QtGui.QFormLayout.FieldRole, + self.csvVerseLayout) + self.formatWidget.addWidget(self.csvPage) + self.openSongPage = QtGui.QWidget() + self.openSongPage.setObjectName(u'OpenSongPage') + self.openSongLayout = QtGui.QFormLayout(self.openSongPage) + self.openSongLayout.setMargin(0) + self.openSongLayout.setSpacing(8) + self.openSongLayout.setObjectName(u'OpenSongLayout') + self.openSongFileLabel = QtGui.QLabel(self.openSongPage) + self.openSongFileLabel.setObjectName(u'OpenSongFileLabel') + self.openSongLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.openSongFileLabel) + self.openSongFileLayout = QtGui.QHBoxLayout() + self.openSongFileLayout.setSpacing(8) + self.openSongFileLayout.setObjectName(u'OpenSongFileLayout') + self.openSongFileEdit = QtGui.QLineEdit(self.openSongPage) + self.openSongFileEdit.setObjectName(u'OpenSongFileEdit') + self.openSongFileLayout.addWidget(self.openSongFileEdit) + self.openSongBrowseButton = QtGui.QToolButton(self.openSongPage) + self.openSongBrowseButton.setIcon(generalIcon) + self.openSongBrowseButton.setObjectName(u'OpenSongBrowseButton') + self.openSongFileLayout.addWidget(self.openSongBrowseButton) + self.openSongLayout.setLayout(0, QtGui.QFormLayout.FieldRole, + self.openSongFileLayout) + self.formatWidget.addWidget(self.openSongPage) + self.webDownloadPage = QtGui.QWidget() + self.webDownloadPage.setObjectName(u'WebDownloadPage') + self.webDownloadLayout = QtGui.QVBoxLayout(self.webDownloadPage) + self.webDownloadLayout.setSpacing(8) + self.webDownloadLayout.setMargin(0) + self.webDownloadLayout.setObjectName(u'WebDownloadLayout') + self.webDownloadTabWidget = QtGui.QTabWidget(self.webDownloadPage) + self.webDownloadTabWidget.setObjectName(u'WebDownloadTabWidget') + self.downloadOptionsTab = QtGui.QWidget() + self.downloadOptionsTab.setObjectName(u'DownloadOptionsTab') + self.downloadOptionsLayout = QtGui.QFormLayout(self.downloadOptionsTab) + self.downloadOptionsLayout.setMargin(8) + self.downloadOptionsLayout.setSpacing(8) + self.downloadOptionsLayout.setObjectName(u'DownloadOptionsLayout') + self.locationLabel = QtGui.QLabel(self.downloadOptionsTab) + self.locationLabel.setObjectName(u'LocationLabel') + self.downloadOptionsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.locationLabel) + self.locationComboBox = QtGui.QComboBox(self.downloadOptionsTab) + self.locationComboBox.setObjectName(u'LocationComboBox') + self.locationComboBox.addItem(u'') + self.locationComboBox.addItem(u'') + self.locationComboBox.addItem(u'') + self.downloadOptionsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.locationComboBox) + self.bibleLabel = QtGui.QLabel(self.downloadOptionsTab) + self.bibleLabel.setObjectName(u'BibleLabel') + self.downloadOptionsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.bibleLabel) + self.bibleComboBox = QtGui.QComboBox(self.downloadOptionsTab) + self.bibleComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) + self.bibleComboBox.setObjectName(u'BibleComboBox') + self.bibleComboBox.addItem(u'') + self.bibleComboBox.addItem(u'') + self.bibleComboBox.addItem(u'') + self.downloadOptionsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.bibleComboBox) + self.webDownloadTabWidget.addTab(self.downloadOptionsTab, u'') + self.proxyServerTab = QtGui.QWidget() + self.proxyServerTab.setObjectName(u'ProxyServerTab') + self.proxyServerLayout = QtGui.QFormLayout(self.proxyServerTab) + self.proxyServerLayout.setObjectName(u'ProxyServerLayout') + self.addressLabel = QtGui.QLabel(self.proxyServerTab) + self.addressLabel.setObjectName(u'AddressLabel') + self.proxyServerLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.addressLabel) + self.addressEdit = QtGui.QLineEdit(self.proxyServerTab) + self.addressEdit.setObjectName(u'AddressEdit') + self.proxyServerLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.addressEdit) + self.usernameLabel = QtGui.QLabel(self.proxyServerTab) + self.usernameLabel.setObjectName(u'UsernameLabel') + self.proxyServerLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.usernameLabel) + self.usernameEdit = QtGui.QLineEdit(self.proxyServerTab) + self.usernameEdit.setObjectName(u'UsernameEdit') + self.proxyServerLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.usernameEdit) + self.passwordLabel = QtGui.QLabel(self.proxyServerTab) + self.passwordLabel.setObjectName(u'PasswordLabel') + self.proxyServerLayout.setWidget(2, QtGui.QFormLayout.LabelRole, + self.passwordLabel) + self.passwordEdit = QtGui.QLineEdit(self.proxyServerTab) + self.passwordEdit.setObjectName(u'PasswordEdit') + self.proxyServerLayout.setWidget(2, QtGui.QFormLayout.FieldRole, + self.passwordEdit) + self.webDownloadTabWidget.addTab(self.proxyServerTab, u'') + self.webDownloadLayout.addWidget(self.webDownloadTabWidget) + self.formatWidget.addWidget(self.webDownloadPage) + self.openlp1Page = QtGui.QWidget() + self.openlp1Page.setObjectName(u'Openlp1Page') + self.openlp1Layout = QtGui.QFormLayout(self.openlp1Page) + self.openlp1Layout.setFieldGrowthPolicy( + QtGui.QFormLayout.ExpandingFieldsGrow) + self.openlp1Layout.setMargin(0) + self.openlp1Layout.setSpacing(8) + self.openlp1Layout.setObjectName(u'Openlp1Layout') + self.openlp1LocationLabel = QtGui.QLabel(self.openlp1Page) + self.openlp1LocationLabel.setObjectName(u'Openlp1LocationLabel') + self.openlp1Layout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.openlp1LocationLabel) + self.openlp1LocationLayout = QtGui.QHBoxLayout() + self.openlp1LocationLayout.setSpacing(8) + self.openlp1LocationLayout.setObjectName(u'Openlp1LocationLayout') + self.openlp1LocationEdit = QtGui.QLineEdit(self.openlp1Page) + self.openlp1LocationEdit.setObjectName(u'Openlp1LocationEdit') + self.openlp1LocationLayout.addWidget(self.openlp1LocationEdit) + self.openlp1FileButton = QtGui.QToolButton(self.openlp1Page) + self.openlp1FileButton.setMaximumSize(QtCore.QSize(32, 16777215)) + self.openlp1FileButton.setIcon(generalIcon) + self.openlp1FileButton.setObjectName(u'Openlp1FileButton') + self.openlp1LocationLayout.addWidget(self.openlp1FileButton) + self.openlp1Layout.setLayout(1, QtGui.QFormLayout.FieldRole, + self.openlp1LocationLayout) + self.openlp1DisabledLabel = QtGui.QLabel(self.openlp1Page) + self.openlp1DisabledLabel.setObjectName(u'openlp1DisabledLabel') + self.openlp1DisabledLabel.setVisible(False) + self.openlp1DisabledLabel.setWordWrap(True) + self.openlp1Layout.addWidget(self.openlp1DisabledLabel) + self.formatWidget.addWidget(self.openlp1Page) + self.selectPageLayout.addWidget(self.formatWidget) + bibleImportWizard.addPage(self.selectPage) + # License page + self.licenseDetailsPage = QtGui.QWizardPage() + self.licenseDetailsPage.setObjectName(u'LicenseDetailsPage') + self.licenseDetailsLayout = QtGui.QFormLayout(self.licenseDetailsPage) + self.licenseDetailsLayout.setMargin(20) + self.licenseDetailsLayout.setSpacing(8) + self.licenseDetailsLayout.setObjectName(u'LicenseDetailsLayout') + self.versionNameLabel = QtGui.QLabel(self.licenseDetailsPage) + self.versionNameLabel.setObjectName(u'VersionNameLabel') + self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.LabelRole, + self.versionNameLabel) + self.versionNameEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.versionNameEdit.setObjectName(u'VersionNameEdit') + self.licenseDetailsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, + self.versionNameEdit) + self.copyrightLabel = QtGui.QLabel(self.licenseDetailsPage) + self.copyrightLabel.setObjectName(u'CopyrightLabel') + self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.LabelRole, + self.copyrightLabel) + self.copyrightEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.copyrightEdit.setObjectName(u'CopyrightEdit') + self.licenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, + self.copyrightEdit) + self.permissionsLabel = QtGui.QLabel(self.licenseDetailsPage) + self.permissionsLabel.setObjectName(u'PermissionsLabel') + self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, + self.permissionsLabel) + self.permissionsEdit = QtGui.QLineEdit(self.licenseDetailsPage) + self.permissionsEdit.setObjectName(u'PermissionsEdit') + self.licenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, + self.permissionsEdit) + bibleImportWizard.addPage(self.licenseDetailsPage) + # Progress page + self.importPage = QtGui.QWizardPage() + self.importPage.setObjectName(u'ImportPage') + self.importLayout = QtGui.QVBoxLayout(self.importPage) + self.importLayout.setSpacing(8) + self.importLayout.setMargin(50) + self.importLayout.setObjectName(u'ImportLayout') + self.importProgressLabel = QtGui.QLabel(self.importPage) + self.importProgressLabel.setObjectName(u'ImportProgressLabel') + self.importLayout.addWidget(self.importProgressLabel) + self.importProgressBar = QtGui.QProgressBar(self.importPage) + self.importProgressBar.setValue(0) + self.importProgressBar.setObjectName(u'ImportProgressBar') + self.importLayout.addWidget(self.importProgressBar) + bibleImportWizard.addPage(self.importPage) - self.retranslateUi(BibleImportWizard) - self.FormatWidget.setCurrentIndex(0) - self.WebDownloadTabWidget.setCurrentIndex(0) - QtCore.QObject.connect(self.FormatComboBox, + self.retranslateUi(bibleImportWizard) + self.formatWidget.setCurrentIndex(0) + self.webDownloadTabWidget.setCurrentIndex(0) + QtCore.QObject.connect(self.formatComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), - self.FormatWidget.setCurrentIndex) - QtCore.QMetaObject.connectSlotsByName(BibleImportWizard) + self.formatWidget.setCurrentIndex) + QtCore.QMetaObject.connectSlotsByName(bibleImportWizard) - def retranslateUi(self, BibleImportWizard): - BibleImportWizard.setWindowTitle( + def retranslateUi(self, bibleImportWizard): + bibleImportWizard.setWindowTitle( translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard')) - self.TitleLabel.setText( + self.titleLabel.setText( u'%s' % \ translate('BiblesPlugin.ImportWizardForm', - 'Welcome to the Bible Import Wizard')) - self.InformationLabel.setText( + 'Welcome to the Bible Import Wizard')) + self.informationLabel.setText( translate('BiblesPlugin.ImportWizardForm', - 'This wizard will help you to import Bibles from a ' - 'variety of formats. Click the next button below to start the ' - 'process by selecting a format to import from.')) - self.SelectPage.setTitle(translate('BiblesPlugin.ImportWizardForm', + 'This wizard will help you to import Bibles from a ' + 'variety of formats. Click the next button below to start the ' + 'process by selecting a format to import from.')) + self.selectPage.setTitle(translate('BiblesPlugin.ImportWizardForm', 'Select Import Source')) - self.SelectPage.setSubTitle( + self.selectPage.setSubTitle( translate('BiblesPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.FormatLabel.setText( + 'Select the import format, and where to import from.')) + self.formatLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Format:')) - self.FormatComboBox.setItemText(0, + self.formatComboBox.setItemText(0, translate('BiblesPlugin.ImportWizardForm', 'OSIS')) - self.FormatComboBox.setItemText(1, + self.formatComboBox.setItemText(1, translate('BiblesPlugin.ImportWizardForm', 'CSV')) - self.FormatComboBox.setItemText(2, + self.formatComboBox.setItemText(2, translate('BiblesPlugin.ImportWizardForm', 'OpenSong')) - self.FormatComboBox.setItemText(3, + self.formatComboBox.setItemText(3, translate('BiblesPlugin.ImportWizardForm', 'Web Download')) - self.OsisLocationLabel.setText( + self.formatComboBox.setItemText(4, + translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x')) + self.openlp1LocationLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'File location:')) - self.BooksLocationLabel.setText( + self.osisLocationLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'File location:')) + self.booksLocationLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Books location:')) - self.VerseLocationLabel.setText( + self.verseLocationLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Verse location:')) - self.OpenSongFileLabel.setText( + self.openSongFileLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Bible filename:')) - self.LocationLabel.setText( + self.locationLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Location:')) - self.LocationComboBox.setItemText(0, + self.locationComboBox.setItemText(0, translate('BiblesPlugin.ImportWizardForm', 'Crosswalk')) - self.LocationComboBox.setItemText(1, + self.locationComboBox.setItemText(1, translate('BiblesPlugin.ImportWizardForm', 'BibleGateway')) - self.BibleLabel.setText( + self.locationComboBox.setItemText(2, + translate('BiblesPlugin.ImportWizardForm', 'Bibleserver')) + self.bibleLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Bible:')) - self.WebDownloadTabWidget.setTabText( - self.WebDownloadTabWidget.indexOf(self.DownloadOptionsTab), + self.webDownloadTabWidget.setTabText( + self.webDownloadTabWidget.indexOf(self.downloadOptionsTab), translate('BiblesPlugin.ImportWizardForm', 'Download Options')) - self.AddressLabel.setText( + self.addressLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Server:')) - self.UsernameLabel.setText( + self.usernameLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Username:')) - self.PasswordLabel.setText( + self.passwordLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Password:')) - self.WebDownloadTabWidget.setTabText( - self.WebDownloadTabWidget.indexOf(self.ProxyServerTab), + self.webDownloadTabWidget.setTabText( + self.webDownloadTabWidget.indexOf(self.proxyServerTab), translate('BiblesPlugin.ImportWizardForm', - 'Proxy Server (Optional)')) - self.LicenseDetailsPage.setTitle( + 'Proxy Server (Optional)')) + self.licenseDetailsPage.setTitle( translate('BiblesPlugin.ImportWizardForm', 'License Details')) - self.LicenseDetailsPage.setSubTitle( + self.licenseDetailsPage.setSubTitle( translate('BiblesPlugin.ImportWizardForm', - 'Set up the Bible\'s license details.')) - self.VersionNameLabel.setText( + 'Set up the Bible\'s license details.')) + self.versionNameLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Version name:')) - self.CopyrightLabel.setText( + self.copyrightLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) - self.PermissionsLabel.setText( + self.permissionsLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Permissions:')) - self.ImportPage.setTitle( + self.importPage.setTitle( translate('BiblesPlugin.ImportWizardForm', 'Importing')) - self.ImportPage.setSubTitle( + self.importPage.setSubTitle( translate('BiblesPlugin.ImportWizardForm', - 'Please wait while your Bible is imported.')) - self.ImportProgressLabel.setText( + 'Please wait while your Bible is imported.')) + self.importProgressLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Ready.')) - self.ImportProgressBar.setFormat(u'%p%') + self.importProgressBar.setFormat(u'%p%') + self.openlp1DisabledLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'The openlp.org 1.x ' + '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.')) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index a6fc03045..7975bfed7 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -32,134 +32,164 @@ import re log = logging.getLogger(__name__) -BIBLE_REFERENCE = re.compile( - r'^([\w ]+?) *([0-9]+)' # Initial book and chapter - r'(?: *[:|v|V] *([0-9]+))?' # Verse for first chapter - r'(?: *- *([0-9]+|end$))?' # Range for verses or chapters - r'(?:(?:,([0-9]+))?' # Second chapter - r' *[,|:|v|V] *([0-9]+|end$)' # More range for verses or chapters - r'(?: *- *([0-9]+|end$))?)?$', # End of second verse range - re.UNICODE) +def get_reference_match(match_type): + local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end' + ).split(u';;') # English + # local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde' + # ).split(u';;') # German + separators = { + u'sep_v_display': local_separator[0], u'sep_v': local_separator[1], + u'sep_r_display': local_separator[2], u'sep_r': local_separator[3], + u'sep_l_display': local_separator[4], u'sep_l': local_separator[5], + u'sep_e': local_separator[6]} -def check_end(match_group): - """ - Check if a regular expression match group contains the text u'end' or - should be converted to an int. - - ``match_group`` - The match group to check. - """ - if match_group == u'end': - return -1 + # verse range match: (:)?(-((:)?|end)?)? + range_string = str(r'(?:(?P[0-9]+)%(sep_v)s)?(?P' + r'[0-9]+)(?P%(sep_r)s(?:(?:(?P[0-9]+)%(sep_v)s)?' + r'(?P[0-9]+)|%(sep_e)s)?)?') % separators + if match_type == u'range': + return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE) + elif match_type == u'range_separator': + return re.compile(separators[u'sep_l']) + elif match_type == u'full': + # full reference match: ((,|(?=$)))+ + return re.compile(str(r'^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:' + range_string + r'(?:%(sep_l)s|(?=\s*$)))+)\s*$') + % separators, re.UNICODE) else: - return int(match_group) + return separators[match_type] def parse_reference(reference): """ - This is the über-awesome function that takes a person's typed in string - and converts it to a reference list, a list of references to be queried - from the Bible database files. + This is the next generation über-awesome function that takes a person's + typed in string and converts it to a reference list, a list of references to + be queried from the Bible database files. - The ``BIBLE_REFERENCE`` constant regular expression produces the following - match groups: + This is a user manual like description, how the references are working. - 0. (match string) - This is a special group consisting of the whole string that matched. - 1. ``[\w ]+`` - The book the reference is from. - 2. ``[0-9]+`` - The first (or only) chapter in the reference. - 3. ``None`` or ``[0-9]+`` - ``None``, or the only verse, or the first verse in a verse range or, - the start verse in a chapter range. - 4. ``None`` or ``[0-9]+`` or ``end`` - ``None``, or the end verse of the first verse range, or the end chapter - of a chapter range. - 5. ``None`` or ``[0-9]+`` - ``None``, or the second chapter in multiple (non-ranged) chapters. - 6. ``None`` or ``[0-9]+`` or ``end`` - ``None``, the start of the second verse range. or the end of a chapter - range. - 7. ``None`` or ``[0-9]+`` or ``end`` - ``None``, or the end of the second verse range. + - Each reference starts with the book name. A chapter name is manditory. + ``John 3`` refers to Gospel of John chapter 3 + - A reference range can be given after a range separator. + ``John 3-5`` refers to John chapters 3 to 5 + - Single verses can be addressed after a verse separator + ``John 3:16`` refers to John chapter 3 verse 16 + ``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3 + - After a verse reference all further single values are treat as verse in + the last selected chapter. + ``John 3:16-18`` refers to John chapter 3 verses 16 to 18 + - After a list separator it is possible to refer to additional verses. They + are build analog to the first ones. This way it is possible to define each + number of verse references. It is not possible to refer to verses in + additional books. + ``John 3:16,18`` refers to John chapter 3 verses 16 and 18 + ``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20 + ``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and + chapter 3 verse 1 + - If there is a range separator without further verse declaration the last + refered chapter is addressed until the end. + + ``range_string`` is a regular expression which matches for verse range + declarations: + + 1. ``(?:(?P[0-9]+)%(sep_v)s)?' + It starts with a optional chapter reference ``from_chapter`` followed by + a verse separator. + 2. ``(?P[0-9]+)`` + The verse reference ``from_verse`` is manditory + 3. ``(?P%(sep_r)s(?:`` ... ``|%(sep_e)s)?)?`` + A ``range_to`` declaration is optional. It starts with a range separator + and contains optional a chapter and verse declaration or a end + separator. + 4. ``(?:(?P[0-9]+)%(sep_v)s)?`` + The ``to_chapter`` reference with separator is equivalent to group 1. + 5. ``(?P[0-9]+)`` + The ``to_verse`` reference is equivalent to group 2. + + The full reference is matched against get_reference_match(u'full'). This + regular expression looks like this: + + 1. ``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$`` + The second group contains all ``ranges``. This can be multiple + declarations of a range_string separated by a list separator. The reference list is a list of tuples, with each tuple structured like this:: - (book, chapter, start_verse, end_verse) + (book, chapter, from_verse, to_verse) ``reference`` The bible reference to parse. Returns None or a reference list. """ - reference = reference.strip() log.debug('parse_reference("%s")', reference) - unified_ref_list = [] - match = BIBLE_REFERENCE.match(reference) + match = get_reference_match(u'full').match(reference) if match: log.debug(u'Matched reference %s' % reference) - book = match.group(1) - chapter = int(match.group(2)) - if match.group(7): - # Two verse ranges - vr1_start = int(match.group(3)) - vr1_end = int(match.group(4)) - unified_ref_list.append((book, chapter, vr1_start, vr1_end)) - vr2_start = int(match.group(6)) - vr2_end = check_end(match.group(7)) - if match.group(5): - # One verse range per chapter - chapter2 = int(match.group(5)) - unified_ref_list.append((book, chapter2, vr2_start, vr2_end)) + book = match.group(u'book') + ranges = match.group(u'ranges') + range_list = get_reference_match(u'range_separator').split(ranges) + ref_list = [] + chapter = None + for this_range in range_list: + range_match = get_reference_match(u'range').match(this_range) + from_chapter = range_match.group(u'from_chapter') + from_verse = range_match.group(u'from_verse') + has_range = range_match.group(u'range_to') + to_chapter = range_match.group(u'to_chapter') + to_verse = range_match.group(u'to_verse') + if from_chapter: + from_chapter = int(from_chapter) + if from_verse: + from_verse = int(from_verse) + if to_chapter: + to_chapter = int(to_chapter) + if to_verse: + to_verse = int(to_verse) + # Fill chapter fields with reasonable values. + if from_chapter: + chapter = from_chapter + elif chapter: + from_chapter = chapter else: - unified_ref_list.append((book, chapter, vr2_start, vr2_end)) - elif match.group(6): - # Chapter range with verses - if match.group(3): - vr1_start = int(match.group(3)) - else: - vr1_start = 1 - if match.group(2) == match.group(4): - vr1_end = int(match.group(6)) - unified_ref_list.append((book, chapter, vr1_start, vr1_end)) - else: - vr1_end = -1 - unified_ref_list.append((book, chapter, vr1_start, vr1_end)) - vr2_end = check_end(match.group(6)) - if int(match.group(4)) > chapter: - for i in range(chapter + 1, int(match.group(4)) + 1): - if i == int(match.group(4)): - unified_ref_list.append((book, i, 1, vr2_end)) - else: - unified_ref_list.append((book, i, 1, -1)) - elif match.group(4): - # Chapter range or chapter and verse range - if match.group(3): - vr1_start = int(match.group(3)) - vr1_end = check_end(match.group(4)) - if vr1_end == -1 or vr1_end > vr1_start: - unified_ref_list.append((book, chapter, vr1_start, vr1_end)) + from_chapter = from_verse + from_verse = None + if to_chapter: + if to_chapter < from_chapter: + continue else: - log.debug(u'Ambiguous reference: %s' % reference) - return None - elif match.group(4) != u'end': - for i in range(chapter, int(match.group(4)) + 1): - unified_ref_list.append((book, i, 1, -1)) + chapter = to_chapter + elif to_verse: + if chapter: + to_chapter = chapter + else: + to_chapter = to_verse + to_verse = None + # Append references to the list + if has_range: + if not from_verse: + from_verse = 1 + if not to_verse: + to_verse = -1 + if to_chapter > from_chapter: + ref_list.append((book, from_chapter, from_verse, -1)) + for i in range(from_chapter + 1, to_chapter - 1): + ref_list.append((book, i, 1, -1)) + ref_list.append((book, to_chapter, 1, to_verse)) + elif to_verse >= from_verse or to_verse == -1: + ref_list.append((book, from_chapter, from_verse, to_verse)) + elif from_verse: + ref_list.append((book, from_chapter, from_verse, from_verse)) else: - log.debug(u'Unsupported reference: %s' % reference) - return None - elif match.group(3): - # Single chapter and verse - verse = int(match.group(3)) - unified_ref_list.append((book, chapter, verse, verse)) - else: - # Single chapter - unified_ref_list.append((book, chapter, -1, -1)) + ref_list.append((book, from_chapter, 1, -1)) + return ref_list else: log.debug(u'Invalid reference: %s' % reference) return None - return unified_ref_list class SearchResults(object): diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index b7d1b9bde..a52c31fb7 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -110,9 +110,9 @@ class BiblesTab(SettingsTab): self.BibleThemeComboBox.setObjectName(u'BibleThemeComboBox') self.BibleThemeComboBox.addItem(QtCore.QString()) self.BibleThemeLayout.addWidget(self.BibleThemeComboBox) - self.BibleDualCheckBox = QtGui.QCheckBox(self.VerseDisplayGroupBox) - self.BibleDualCheckBox.setObjectName(u'BibleDualCheckBox') - self.VerseDisplayLayout.addWidget(self.BibleDualCheckBox, 3, 0, 1, 1) + self.BibleSecondCheckBox = QtGui.QCheckBox(self.VerseDisplayGroupBox) + self.BibleSecondCheckBox.setObjectName(u'BibleSecondCheckBox') + self.VerseDisplayLayout.addWidget(self.BibleSecondCheckBox, 3, 0, 1, 1) self.VerseDisplayLayout.addWidget(self.BibleThemeWidget, 4, 0, 1, 1) self.ChangeNoteLabel = QtGui.QLabel(self.VerseDisplayGroupBox) self.ChangeNoteLabel.setObjectName(u'ChangeNoteLabel') @@ -143,8 +143,8 @@ class BiblesTab(SettingsTab): self.LayoutStyleComboBox, QtCore.SIGNAL(u'activated(int)'), self.onLayoutStyleComboBoxChanged) QtCore.QObject.connect( - self.BibleDualCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), - self.onBibleDualCheckBox) + self.BibleSecondCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), + self.onBibleSecondCheckBox) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) @@ -176,8 +176,8 @@ class BiblesTab(SettingsTab): translate('BiblesPlugin.BiblesTab', '[ And ]')) self.ChangeNoteLabel.setText(translate('BiblesPlugin.BiblesTab', 'Note:\nChanges do not affect verses already in the service.')) - self.BibleDualCheckBox.setText( - translate('BiblesPlugin.BiblesTab', 'Display dual Bible verses')) + self.BibleSecondCheckBox.setText( + translate('BiblesPlugin.BiblesTab', 'Display second Bible verses')) def onBibleThemeComboBoxChanged(self): self.bible_theme = self.BibleThemeComboBox.currentText() @@ -190,15 +190,15 @@ class BiblesTab(SettingsTab): def onNewChaptersCheckBoxChanged(self, check_state): self.show_new_chapters = False - # we have a set value convert to True/False + # We have a set value convert to True/False. if check_state == QtCore.Qt.Checked: self.show_new_chapters = True - def onBibleDualCheckBox(self, check_state): - self.dual_bibles = False - # we have a set value convert to True/False + def onBibleSecondCheckBox(self, check_state): + self.second_bibles = False + # We have a set value convert to True/False. if check_state == QtCore.Qt.Checked: - self.dual_bibles = True + self.second_bibles = True def load(self): settings = QtCore.QSettings() @@ -211,12 +211,12 @@ class BiblesTab(SettingsTab): u'verse layout style', QtCore.QVariant(0)).toInt()[0] self.bible_theme = unicode( settings.value(u'bible theme', QtCore.QVariant(u'')).toString()) - self.dual_bibles = settings.value( - u'dual bibles', QtCore.QVariant(True)).toBool() + self.second_bibles = settings.value( + u'second bibles', QtCore.QVariant(True)).toBool() self.NewChaptersCheckBox.setChecked(self.show_new_chapters) self.DisplayStyleComboBox.setCurrentIndex(self.display_style) self.LayoutStyleComboBox.setCurrentIndex(self.layout_style) - self.BibleDualCheckBox.setChecked(self.dual_bibles) + self.BibleSecondCheckBox.setChecked(self.second_bibles) settings.endGroup() def save(self): @@ -228,13 +228,18 @@ class BiblesTab(SettingsTab): QtCore.QVariant(self.display_style)) settings.setValue(u'verse layout style', QtCore.QVariant(self.layout_style)) - settings.setValue(u'dual bibles', QtCore.QVariant(self.dual_bibles)) + settings.setValue(u'second bibles', QtCore.QVariant(self.second_bibles)) settings.setValue(u'bible theme', QtCore.QVariant(self.bible_theme)) settings.endGroup() def updateThemeList(self, theme_list): """ - Called from ThemeManager when the Themes have changed + Called from ThemeManager when the Themes have changed. + + ``theme_list`` + The list of available themes:: + + [u'Bible Theme', u'Song Theme'] """ self.BibleThemeComboBox.clear() self.BibleThemeComboBox.addItem(u'') @@ -243,7 +248,7 @@ class BiblesTab(SettingsTab): index = self.BibleThemeComboBox.findText( unicode(self.bible_theme), QtCore.Qt.MatchExactly) if index == -1: - # Not Found + # Not Found. index = 0 self.bible_theme = u'' self.BibleThemeComboBox.setCurrentIndex(index) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index cc981059c..d02ff2a70 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -30,7 +30,7 @@ import csv from PyQt4 import QtCore -from openlp.core.lib import Receiver +from openlp.core.lib import Receiver, translate from db import BibleDB log = logging.getLogger(__name__) @@ -46,21 +46,19 @@ class CSVBible(BibleDB): This class assumes the files contain all the information and a clean bible is being loaded. """ - BibleDB.__init__(self, parent, **kwargs) log.info(self.__class__.__name__) - if u'booksfile' not in kwargs: - raise KeyError(u'You have to supply a file to import books from.') + BibleDB.__init__(self, parent, **kwargs) self.booksfile = kwargs[u'booksfile'] - if u'versefile' not in kwargs: - raise KeyError(u'You have to supply a file to import verses from.') self.versesfile = kwargs[u'versefile'] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) def do_import(self): - #Populate the Tables success = True books_file = None + book_ptr = None + verse_file = None + # Populate the Tables try: books_file = open(self.booksfile, 'r') dialect = csv.Sniffer().sniff(books_file.read(1024)) @@ -82,9 +80,7 @@ class CSVBible(BibleDB): books_file.close() if not success: return False - verse_file = None try: - book_ptr = None verse_file = open(self.versesfile, 'r') dialect = csv.Sniffer().sniff(verse_file.read(1024)) verse_file.seek(0) @@ -96,11 +92,12 @@ class CSVBible(BibleDB): if book_ptr != line[0]: book = self.get_book(line[0]) book_ptr = book.name - self.wizard.incrementProgressBar( - u'Importing %s %s' % (book.name, line[1])) + self.wizard.incrementProgressBar(u'%s %s %s...' % ( + translate('BiblesPlugin.CSVImport', 'Importing'), + book.name, line[1])) self.session.commit() self.create_verse(book.id, line[1], line[2], - unicode(line[3], details['encoding'])) + unicode(line[3], details['encoding'])) Receiver.send_message(u'openlp_process_events') self.session.commit() except IOError: @@ -110,7 +107,6 @@ class CSVBible(BibleDB): if verse_file: verse_file.close() if self.stop_import_flag: - self.wizard.incrementProgressBar(u'Import canceled!') return False else: return success diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 8f5c7dc79..cdc81d408 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -44,24 +44,28 @@ class BibleMeta(BaseModel): """ pass + class Testament(BaseModel): """ Bible Testaments """ pass + class Book(BaseModel): """ Song model """ pass + class Verse(BaseModel): """ Topic model """ pass + def init_schema(url): """ Setup a bible database connection and initialise the database schema. @@ -227,7 +231,7 @@ class BibleDB(QtCore.QObject, Manager): def create_chapter(self, book_id, chapter, textlist): """ - Add a chapter and it's verses to a book. + Add a chapter and its verses to a book. ``book_id`` The id of the book being appended. @@ -240,7 +244,7 @@ class BibleDB(QtCore.QObject, Manager): and the value is the verse text. """ log.debug(u'create_chapter %s,%s', book_id, chapter) - # text list has book and chapter as first two elements of the array + # Text list has book and chapter as first two elements of the array. for verse_number, verse_text in textlist.iteritems(): verse = Verse.populate( book_id = book_id, diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 235862ae8..218f7212e 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -240,6 +240,66 @@ class BGExtract(object): return SearchResults(bookname, chapter, verse_list) +class BSExtract(object): + """ + Extract verses from Bibleserver.com + """ + def __init__(self,proxyurl=None): + log.debug(u'init %s', proxyurl) + self.proxyurl = proxyurl + + def get_bible_chapter(self, version, bookname, chapter): + """ + Access and decode bibles via Bibleserver mobile website + + ``version`` + The version of the bible like NIV for New International Version + + ``bookname`` + Text name of bible book e.g. Genesis, 1. John, 1John or Offenbarung + + ``chapter`` + Chapter number + """ + log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter) + chapter_url = u'http://m.bibleserver.com/text/%s/%s%s' % \ + (version, bookname, chapter) + + log.debug(u'URL: %s', chapter_url) + page = None + try: + page = urllib2.urlopen(chapter_url) + Receiver.send_message(u'openlp_process_events') + except urllib2.URLError: + log.exception(u'The web bible page could not be downloaded.') + finally: + if not page: + return None + soup = None + try: + soup = BeautifulSoup(page) + except HTMLParseError: + log.exception(u'BeautifulSoup could not parse the bible page.') + finally: + if not soup: + return None + Receiver.send_message(u'openlp_process_events') + try: + content = soup.find(u'div', u'content').find(u'div').findAll(u'div') + except: + log.exception(u'No verses found.') + finally: + if not content: + return None + verse_number = re.compile(r'v(\d{2})(\d{3})(\d{3}) verse') + verses = {} + for verse in content: + Receiver.send_message(u'openlp_process_events') + versenumber = int(verse_number.sub(r'\3', verse[u'class'])) + verses[versenumber] = verse.contents[1].rstrip(u'\n') + return SearchResults(bookname, chapter, verses) + + class CWExtract(object): """ Extract verses from CrossWalk/BibleStudyTools @@ -333,43 +393,35 @@ class HTTPBible(BibleDB): Init confirms the bible exists and stores the database path. """ BibleDB.__init__(self, parent, **kwargs) - if u'download_source' not in kwargs: - raise KeyError(u'Missing keyword argument "download_source"') - if u'download_name' not in kwargs: - raise KeyError(u'Missing keyword argument "download_name"') self.download_source = kwargs[u'download_source'] self.download_name = kwargs[u'download_name'] + self.proxy_server = None + self.proxy_username = None + self.proxy_password = None if u'proxy_server' in kwargs: self.proxy_server = kwargs[u'proxy_server'] - else: - self.proxy_server = None if u'proxy_username' in kwargs: self.proxy_username = kwargs[u'proxy_username'] - else: - self.proxy_username = None if u'proxy_password' in kwargs: self.proxy_password = kwargs[u'proxy_password'] - else: - self.proxy_password = None def do_import(self): """ Run the import. This method overrides the parent class method. Returns ``True`` on success, ``False`` on failure. """ - self.wizard.ImportProgressBar.setMaximum(2) + self.wizard.importProgressBar.setMaximum(2) self.wizard.incrementProgressBar('Registering bible...') self.create_meta(u'download source', self.download_source) self.create_meta(u'download name', self.download_name) if self.proxy_server: self.create_meta(u'proxy server', self.proxy_server) if self.proxy_username: - # store the proxy userid + # Store the proxy userid. self.create_meta(u'proxy username', self.proxy_username) if self.proxy_password: - # store the proxy password + # Store the proxy password. self.create_meta(u'proxy password', self.proxy_password) - self.wizard.incrementProgressBar('Registered.') return True def get_verses(self, reference_list): @@ -417,7 +469,7 @@ class HTTPBible(BibleDB): ## to request ac and get Acts back. bookname = search_results.book Receiver.send_message(u'openlp_process_events') - # check to see if book/chapter exists + # Check to see if book/chapter exists. db_book = self.get_book(bookname) self.create_chapter(db_book.id, search_results.chapter, search_results.verselist) @@ -434,8 +486,10 @@ class HTTPBible(BibleDB): log.debug(u'source = %s', self.download_source) if self.download_source.lower() == u'crosswalk': ev = CWExtract(self.proxy_server) - else: + elif self.download_source.lower() == u'biblegateway': ev = BGExtract(self.proxy_server) + elif self.download_source.lower() == u'bibleserver': + ev = BSExtract(self.proxy_server) return ev.get_bible_chapter(self.download_name, book, chapter) def get_books(self): diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 9afc4a4b2..93f301713 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -33,10 +33,16 @@ from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib import parse_reference from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta -from opensong import OpenSongBible -from osis import OSISBible from csvbible import CSVBible from http import HTTPBible +from opensong import OpenSongBible +from osis import OSISBible +# Imports that might fail. +try: + from openlp1 import OpenLP1Bible + has_openlp1 = True +except ImportError: + has_openlp1 = False log = logging.getLogger(__name__) @@ -56,11 +62,13 @@ class BibleFormat(object): plus a few helper functions to facilitate generic handling of Bible types for importing. """ + _format_availability = {} Unknown = -1 OSIS = 0 CSV = 1 OpenSong = 2 WebDownload = 3 + OpenLP1 = 4 @staticmethod def get_class(format): @@ -78,6 +86,8 @@ class BibleFormat(object): return OpenSongBible elif format == BibleFormat.WebDownload: return HTTPBible + elif format == BibleFormat.OpenLP1: + return OpenLP1Bible else: return None @@ -90,9 +100,18 @@ class BibleFormat(object): BibleFormat.OSIS, BibleFormat.CSV, BibleFormat.OpenSong, - BibleFormat.WebDownload + BibleFormat.WebDownload, + BibleFormat.OpenLP1 ] + @staticmethod + def set_availability(format, available): + BibleFormat._format_availability[format] = available + + @staticmethod + def get_availability(format): + return BibleFormat._format_availability.get(format, True) + class BibleManager(object): """ @@ -257,17 +276,34 @@ class BibleManager(object): 'Book Chapter:Verse-Chapter:Verse')) return None - def verse_search(self, bible, text): + def verse_search(self, bible, second_bible, text): """ Does a verse search for the given bible and text. ``bible`` The bible to seach in (unicode). + ``second_bible`` + The second bible (unicode). We do not search in this bible. + ``text`` The text to search for (unicode). """ - log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text) + log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text) + # Check if the bible or second_bible is a web bible. + webbible = self.db_cache[bible].get_object(BibleMeta, + u'download source') + second_webbible = u'' + if second_bible: + second_webbible = self.db_cache[second_bible].get_object(BibleMeta, + u'download source') + if webbible or second_webbible: + QtGui.QMessageBox.information(self.parent.mediaItem, + translate('BiblesPlugin.BibleManager', + 'Web Bible cannot be used'), + translate('BiblesPlugin.BibleManager', 'Text Search is not ' + 'available with Web Bibles.')) + return None if text: return self.db_cache[bible].verse_search(text) else: @@ -276,7 +312,7 @@ class BibleManager(object): 'Scripture Reference Error'), translate('BiblesPlugin.BibleManager', 'You did not enter a ' 'search keyword.\nYou can separate different keywords by a ' - 'space to search for all of your keywords and you can seperate ' + 'space to search for all of your keywords and you can separate ' 'them by a comma to search for one of them.')) return None @@ -318,3 +354,7 @@ class BibleManager(object): for bible in self.db_cache: self.db_cache[bible].finalise() +BibleFormat.set_availability(BibleFormat.OpenLP1, has_openlp1) + +__all__ = [u'BibleFormat'] + diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index bb3c1b26d..8fafd0f97 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ ItemCapabilities, translate from openlp.plugins.bibles.forms import BibleImportForm +from openlp.plugins.bibles.lib import get_reference_match log = logging.getLogger(__name__) @@ -47,21 +48,22 @@ class BibleListView(BaseListWithDnD): self.parent().onListViewResize(event.size().width(), event.size().width()) + class BibleMediaItem(MediaManagerItem): """ This is the custom media manager item for Bibles. """ log.info(u'Bible Media Item loaded') - def __init__(self, parent, icon, title): + def __init__(self, parent, plugin, icon): self.PluginNameShort = u'Bible' self.pluginNameVisible = translate('BiblesPlugin.MediaItem', 'Bible') self.IconPath = u'songs/song' self.ListViewWithDnD_class = BibleListView - MediaManagerItem.__init__(self, parent, icon, title) - # place to store the search results for both bibles + MediaManagerItem.__init__(self, parent, plugin, icon) + # Place to store the search results for both bibles. self.search_results = {} - self.dual_search_results = {} + self.second_search_results = {} QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles) @@ -83,7 +85,7 @@ class BibleMediaItem(MediaManagerItem): self.SearchTabWidget.sizePolicy().hasHeightForWidth()) self.SearchTabWidget.setSizePolicy(sizePolicy) self.SearchTabWidget.setObjectName(u'SearchTabWidget') - # Add the Quick Search tab + # Add the Quick Search tab. self.QuickTab = QtGui.QWidget() self.QuickTab.setObjectName(u'QuickTab') self.QuickLayout = QtGui.QGridLayout(self.QuickTab) @@ -144,7 +146,7 @@ class BibleMediaItem(MediaManagerItem): QuickSpacerItem = QtGui.QSpacerItem(20, 35, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.QuickLayout.addItem(QuickSpacerItem, 6, 2, 1, 1) - # Add the Advanced Search tab + # Add the Advanced Search tab. self.AdvancedTab = QtGui.QWidget() self.AdvancedTab.setObjectName(u'AdvancedTab') self.AdvancedLayout = QtGui.QGridLayout(self.AdvancedTab) @@ -226,7 +228,7 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedLayout.addWidget(self.AdvancedMessage, 8, 0, 1, 3) self.SearchTabWidget.addTab(self.AdvancedTab, translate('BiblesPlugin.MediaItem', 'Advanced')) - # Add the search tab widget to the page layout + # Add the search tab widget to the page layout. self.pageLayout.addWidget(self.SearchTabWidget) # Combo Boxes QtCore.QObject.connect(self.AdvancedVersionComboBox, @@ -239,6 +241,10 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'activated(int)'), self.onAdvancedFromVerse) QtCore.QObject.connect(self.AdvancedToChapter, QtCore.SIGNAL(u'activated(int)'), self.onAdvancedToChapter) + QtCore.QObject.connect(self.QuickSearchComboBox, + QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) + QtCore.QObject.connect(self.QuickVersionComboBox, + QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) # Buttons QtCore.QObject.connect(self.AdvancedSearchButton, QtCore.SIGNAL(u'pressed()'), self.onAdvancedSearchButton) @@ -270,7 +276,7 @@ class BibleMediaItem(MediaManagerItem): def configUpdated(self): log.debug(u'configUpdated') - if QtCore.QSettings().value(self.settingsSection + u'/dual bibles', + if QtCore.QSettings().value(self.settingsSection + u'/second bibles', QtCore.QVariant(True)).toBool(): self.AdvancedSecondBibleLabel.setVisible(True) self.AdvancedSecondBibleComboBox.setVisible(True) @@ -287,7 +293,7 @@ class BibleMediaItem(MediaManagerItem): self.QuickVersionLabel.setText( translate('BiblesPlugin.MediaItem', 'Version:')) self.QuickSecondVersionLabel.setText( - translate('BiblesPlugin.MediaItem', 'Dual:')) + translate('BiblesPlugin.MediaItem', 'Second:')) self.QuickSearchLabel.setText( translate('BiblesPlugin.MediaItem', 'Search type:')) self.QuickSearchLabel.setText( @@ -299,7 +305,7 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedVersionLabel.setText( translate('BiblesPlugin.MediaItem', 'Version:')) self.AdvancedSecondBibleLabel.setText( - translate('BiblesPlugin.MediaItem', 'Dual:')) + translate('BiblesPlugin.MediaItem', 'Second:')) self.AdvancedBookLabel.setText( translate('BiblesPlugin.MediaItem', 'Book:')) self.AdvancedChapterLabel.setText( @@ -331,6 +337,7 @@ class BibleMediaItem(MediaManagerItem): log.debug(u'bible manager initialise') self.parent.manager.media = self self.loadBibles() + self.updateAutoCompleter() self.configUpdated() log.debug(u'bible manager initialise complete') @@ -338,7 +345,7 @@ class BibleMediaItem(MediaManagerItem): self.QuickMessage.setText(text) self.AdvancedMessage.setText(text) Receiver.send_message(u'openlp_process_events') - # minor delay to get the events processed + # Minor delay to get the events processed. time.sleep(0.1) def onListViewResize(self, width, height): @@ -358,13 +365,15 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'No Book Found'), translate('BiblesPlugin.MediaItem', 'No matching book could be found in this Bible.')) + self.AdvancedSearchButton.setEnabled(True) def onImportClick(self): if not hasattr(self, u'import_wizard'): self.import_wizard = BibleImportForm(self, self.parent.manager, self.parent) - self.import_wizard.exec_() - self.reloadBibles() + # If the import was not canceled then reload. + if self.import_wizard.exec_(): + self.reloadBibles() def loadBibles(self): log.debug(u'Loading Bibles') @@ -374,8 +383,10 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedSecondBibleComboBox.clear() self.QuickSecondBibleComboBox.addItem(u'') self.AdvancedSecondBibleComboBox.addItem(u'') + # Get all bibles and sort the list. bibles = self.parent.manager.get_bibles().keys() - # load bibles into the combo boxes + bibles.sort() + # Load the bibles into the combo boxes. first = True for bible in bibles: if bible: @@ -393,6 +404,15 @@ class BibleMediaItem(MediaManagerItem): self.loadBibles() def initialiseBible(self, bible): + """ + This initialises the given bible, which means that its book names and + their chapter numbers is added to the combo boxes on the + 'Advanced Search' Tab. This is not of any importance of the + 'Quick Search' Tab. + + ``bible`` + The bible to initialise (unicode). + """ log.debug(u'initialiseBible %s', bible) book_data = self.parent.manager.get_books(bible) self.AdvancedBookComboBox.clear() @@ -423,6 +443,25 @@ class BibleMediaItem(MediaManagerItem): self.adjustComboBox(1, verse_count, self.AdvancedFromVerse) self.adjustComboBox(1, verse_count, self.AdvancedToVerse) + def updateAutoCompleter(self): + """ + This updates the bible book completion list for the search field. The + completion depends on the bible. It is only updated when we are doing a + verse search, otherwise the auto completion list is removed. + """ + books = [] + # We have to do a 'Verse Search'. + if self.QuickSearchComboBox.currentIndex() == 0: + bibles = self.parent.manager.get_bibles() + bible = unicode(self.QuickVersionComboBox.currentText()) + if bible: + book_data = bibles[bible].get_books() + books = [book.name for book in book_data] + books.sort() + completer = QtGui.QCompleter(books) + completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.QuickSearchEdit.setCompleter(completer) + def onAdvancedVersionComboBox(self): self.initialiseBible( unicode(self.AdvancedVersionComboBox.currentText())) @@ -482,6 +521,17 @@ class BibleMediaItem(MediaManagerItem): def adjustComboBox(self, range_from, range_to, combo, restore=False): """ + Adjusts the given como box to the given values. + + ``range_from`` + The first number of the range (int). + + ``range_to`` + The last number of the range (int). + + ``combo`` + The combo box itself (QComboBox). + ``restore`` If True, then the combo's currentText will be restored after adjusting (if possible). @@ -490,92 +540,105 @@ class BibleMediaItem(MediaManagerItem): if restore: old_text = unicode(combo.currentText()) combo.clear() - for i in range(int(range_from), int(range_to) + 1): + for i in range(range_from, range_to + 1): combo.addItem(unicode(i)) if restore and combo.findText(old_text) != -1: combo.setCurrentIndex(combo.findText(old_text)) def onAdvancedSearchButton(self): + """ + Does an advanced search and saves the search results. + """ log.debug(u'Advanced Search Button pressed') self.AdvancedSearchButton.setEnabled(False) bible = unicode(self.AdvancedVersionComboBox.currentText()) - dual_bible = unicode(self.AdvancedSecondBibleComboBox.currentText()) + second_bible = unicode(self.AdvancedSecondBibleComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText()) - chapter_from = int(self.AdvancedFromChapter.currentText()) - chapter_to = int(self.AdvancedToChapter.currentText()) - verse_from = int(self.AdvancedFromVerse.currentText()) - verse_to = int(self.AdvancedToVerse.currentText()) - versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, - chapter_to, verse_to) + chapter_from = self.AdvancedFromChapter.currentText() + chapter_to = self.AdvancedToChapter.currentText() + verse_from = self.AdvancedFromVerse.currentText() + verse_to = self.AdvancedToVerse.currentText() + verse_separator = get_reference_match(u'sep_v_display') + range_separator = get_reference_match(u'sep_r_display') + verse_range = chapter_from + verse_separator + verse_from + \ + range_separator + chapter_to + verse_separator + verse_to + versetext = u'%s %s' % (book, verse_range) self.search_results = self.parent.manager.get_verses(bible, versetext) - if dual_bible: - self.dual_search_results = self.parent.manager.get_verses( - dual_bible, versetext) + if second_bible: + self.second_search_results = self.parent.manager.get_verses( + second_bible, versetext) if self.ClearAdvancedSearchComboBox.currentIndex() == 0: self.listView.clear() if self.listView.count() != 0: + # Check if the first item is a second bible item or not. bitem = self.listView.item(0) - item_dual_bible = self._decodeQtObject(bitem, 'dual_bible') - if item_dual_bible and dual_bible or not item_dual_bible and \ - not dual_bible: - self.displayResults(bible, dual_bible) + item_second_bible = self._decodeQtObject(bitem, 'second_bible') + if item_second_bible and second_bible or not item_second_bible and \ + not second_bible: + self.displayResults(bible, second_bible) elif QtGui.QMessageBox.critical(self, translate('BiblePlugin.MediaItem', 'Error'), translate('BiblePlugin.MediaItem', 'You cannot combine single ' - 'and dual bible verses. Do you want to delete your search ' + 'and second bible verses. Do you want to delete your search ' 'results and start a new search?'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes: self.listView.clear() - self.displayResults(bible, dual_bible) + self.displayResults(bible, second_bible) else: - self.displayResults(bible, dual_bible) + self.displayResults(bible, second_bible) self.AdvancedSearchButton.setEnabled(True) def onQuickSearchButton(self): + """ + Does a quick search and saves the search results. Quick search can + either be "Verse Search" or "Text Search". + """ log.debug(u'Quick Search Button pressed') self.QuickSearchButton.setEnabled(False) bible = unicode(self.QuickVersionComboBox.currentText()) - dual_bible = unicode(self.QuickSecondBibleComboBox.currentText()) + second_bible = unicode(self.QuickSecondBibleComboBox.currentText()) text = unicode(self.QuickSearchEdit.text()) if self.QuickSearchComboBox.currentIndex() == 0: # We are doing a 'Verse Search'. self.search_results = self.parent.manager.get_verses(bible, text) - if dual_bible and self.search_results: - self.dual_search_results = self.parent.manager.get_verses( - dual_bible, text) + if second_bible and self.search_results: + self.second_search_results = self.parent.manager.get_verses( + second_bible, text) else: - # We are doing a ' Text Search'. + # We are doing a 'Text Search'. bibles = self.parent.manager.get_bibles() - self.search_results = self.parent.manager.verse_search(bible, text) - if dual_bible and self.search_results: + self.search_results = self.parent.manager.verse_search(bible, + second_bible, text) + if second_bible and self.search_results: text = [] for verse in self.search_results: text.append((verse.book.name, verse.chapter, verse.verse, verse.verse)) - self.dual_search_results = bibles[dual_bible].get_verses(text) + self.second_search_results = \ + bibles[second_bible].get_verses(text) if self.ClearQuickSearchComboBox.currentIndex() == 0: self.listView.clear() if self.listView.count() != 0 and self.search_results: bitem = self.listView.item(0) - item_dual_bible = self._decodeQtObject(bitem, 'dual_bible') - if item_dual_bible and dual_bible or not item_dual_bible and \ - not dual_bible: - self.displayResults(bible, dual_bible) + item_second_bible = self._decodeQtObject(bitem, 'second_bible') + if item_second_bible and second_bible or not item_second_bible and \ + not second_bible: + self.displayResults(bible, second_bible) elif QtGui.QMessageBox.critical(self, translate('BiblePlugin.MediaItem', 'Error'), translate('BiblePlugin.MediaItem', 'You cannot combine single ' - 'and dual bible verses. Do you want to delete your search ' + 'and second bible verses. Do you want to delete your search ' 'results and start a new search?'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes: self.listView.clear() - self.displayResults(bible, dual_bible) + self.displayResults(bible, second_bible) elif self.search_results: - self.displayResults(bible, dual_bible) + self.displayResults(bible, second_bible) self.QuickSearchButton.setEnabled(True) - def displayResults(self, bible, dual_bible=u''): + def displayResults(self, bible, second_bible=u''): """ Displays the search results in the media manager. All data needed for further action is saved for/in each row. @@ -583,38 +646,41 @@ class BibleMediaItem(MediaManagerItem): version = self.parent.manager.get_meta_data(bible, u'Version') copyright = self.parent.manager.get_meta_data(bible, u'Copyright') permissions = self.parent.manager.get_meta_data(bible, u'Permissions') - if dual_bible: - dual_version = self.parent.manager.get_meta_data(dual_bible, + if second_bible: + second_version = self.parent.manager.get_meta_data(second_bible, u'Version') - dual_copyright = self.parent.manager.get_meta_data(dual_bible, + second_copyright = self.parent.manager.get_meta_data(second_bible, u'Copyright') - dual_permissions = self.parent.manager.get_meta_data(dual_bible, + second_permissions = self.parent.manager.get_meta_data(second_bible, u'Permissions') - if not dual_permissions: - dual_permissions = u'' - # We count the number of rows which are maybe already present. - start_count = self.listView.count() + if not second_permissions: + second_permissions = u'' for count, verse in enumerate(self.search_results): - if dual_bible: - vdict = { - 'book': QtCore.QVariant(verse.book.name), - 'chapter': QtCore.QVariant(verse.chapter), - 'verse': QtCore.QVariant(verse.verse), - 'bible': QtCore.QVariant(bible), - 'version': QtCore.QVariant(version.value), - 'copyright': QtCore.QVariant(copyright.value), - 'permissions': QtCore.QVariant(permissions.value), - 'text': QtCore.QVariant(verse.text), - 'dual_bible': QtCore.QVariant(dual_bible), - 'dual_version': QtCore.QVariant(dual_version.value), - 'dual_copyright': QtCore.QVariant(dual_copyright.value), - 'dual_permissions': QtCore.QVariant(dual_permissions.value), - 'dual_text': QtCore.QVariant( - self.dual_search_results[count].text) - } + if second_bible: + try: + vdict = { + 'book': QtCore.QVariant(verse.book.name), + 'chapter': QtCore.QVariant(verse.chapter), + 'verse': QtCore.QVariant(verse.verse), + 'bible': QtCore.QVariant(bible), + 'version': QtCore.QVariant(version.value), + 'copyright': QtCore.QVariant(copyright.value), + 'permissions': QtCore.QVariant(permissions.value), + 'text': QtCore.QVariant(verse.text), + 'second_bible': QtCore.QVariant(second_bible), + 'second_version': QtCore.QVariant(second_version.value), + 'second_copyright': QtCore.QVariant( + second_copyright.value), + 'second_permissions': QtCore.QVariant( + second_permissions.value), + 'second_text': QtCore.QVariant( + self.second_search_results[count].text) + } + except IndexError: + break bible_text = u' %s %d:%d (%s, %s)' % (verse.book.name, verse.chapter, verse.verse, version.value, - dual_version.value) + second_version.value) else: vdict = { 'book': QtCore.QVariant(verse.book.name), @@ -625,22 +691,20 @@ class BibleMediaItem(MediaManagerItem): 'copyright': QtCore.QVariant(copyright.value), 'permissions': QtCore.QVariant(permissions.value), 'text': QtCore.QVariant(verse.text), - 'dual_bible': QtCore.QVariant(u''), - 'dual_version': QtCore.QVariant(u''), - 'dual_copyright': QtCore.QVariant(u''), - 'dual_permissions': QtCore.QVariant(u''), - 'dual_text': QtCore.QVariant(u'') + 'second_bible': QtCore.QVariant(u''), + 'second_version': QtCore.QVariant(u''), + 'second_copyright': QtCore.QVariant(u''), + 'second_permissions': QtCore.QVariant(u''), + 'second_text': QtCore.QVariant(u'') } - bible_text = u' %s %d:%d (%s)' % (verse.book.name, + bible_text = u'%s %d:%d (%s)' % (verse.book.name, verse.chapter, verse.verse, version.value) bible_verse = QtGui.QListWidgetItem(bible_text) bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(vdict)) self.listView.addItem(bible_verse) - row = self.listView.setCurrentRow(count + start_count) - if row: - row.setSelected(True) + self.listView.selectAll() self.search_results = {} - self.dual_search_results = {} + self.second_search_results = {} def _decodeQtObject(self, bitem, key): reference = bitem.data(QtCore.Qt.UserRole) @@ -649,9 +713,9 @@ class BibleMediaItem(MediaManagerItem): obj = reference[QtCore.QString(key)] if isinstance(obj, QtCore.QVariant): obj = obj.toPyObject() - return unicode(obj) + return unicode(obj).strip() - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): """ Generates and formats the slides for the service item as well as the service item's title. @@ -661,7 +725,7 @@ class BibleMediaItem(MediaManagerItem): if len(items) == 0: return False bible_text = u'' - old_chapter = u'' + old_chapter = -1 raw_footer = [] raw_slides = [] raw_title = [] @@ -676,35 +740,36 @@ class BibleMediaItem(MediaManagerItem): copyright = self._decodeQtObject(bitem, 'copyright') permissions = self._decodeQtObject(bitem, 'permissions') text = self._decodeQtObject(bitem, 'text') - dual_bible = self._decodeQtObject(bitem, 'dual_bible') - dual_version = self._decodeQtObject(bitem, 'dual_version') - dual_copyright = self._decodeQtObject(bitem, 'dual_copyright') - dual_permissions = self._decodeQtObject(bitem, 'dual_permissions') - dual_text = self._decodeQtObject(bitem, 'dual_text') + second_bible = self._decodeQtObject(bitem, 'second_bible') + second_version = self._decodeQtObject(bitem, 'second_version') + second_copyright = self._decodeQtObject(bitem, 'second_copyright') + second_permissions = \ + self._decodeQtObject(bitem, 'second_permissions') + second_text = self._decodeQtObject(bitem, 'second_text') verse_text = self.formatVerse(old_chapter, chapter, verse) footer = u'%s (%s %s %s)' % (book, version, copyright, permissions) if footer not in raw_footer: raw_footer.append(footer) - if dual_bible: - footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright, - dual_permissions) + if second_bible: + footer = u'%s (%s %s %s)' % (book, second_version, + second_copyright, second_permissions) if footer not in raw_footer: raw_footer.append(footer) - bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text, - dual_text) + bible_text = u'%s\u00a0%s\n\n%s\u00a0%s' % (verse_text, text, + verse_text, second_text) raw_slides.append(bible_text) bible_text = u'' # If we are 'Verse Per Slide' then create a new slide. elif self.parent.settings_tab.layout_style == 0: - bible_text = u'%s %s' % (verse_text, text) + bible_text = u'%s\u00a0%s' % (verse_text, text) raw_slides.append(bible_text) bible_text = u'' # If we are 'Verse Per Line' then force a new line. elif self.parent.settings_tab.layout_style == 1: - bible_text = u'%s %s %s\n' % (bible_text, verse_text, text) + bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text) # We have to be 'Continuous'. else: - bible_text = u'%s %s %s\n' % (bible_text, verse_text, text) + bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text) if first_item: start_item = item first_item = False @@ -719,7 +784,7 @@ class BibleMediaItem(MediaManagerItem): raw_slides.append(bible_text) bible_text = u'' # Service Item: Capabilities - if self.parent.settings_tab.layout_style == 2 and not dual_bible: + if self.parent.settings_tab.layout_style == 2 and not second_bible: # Split the line but do not replace line breaks in renderer. service_item.add_capability(ItemCapabilities.NoLineBreaks) service_item.add_capability(ItemCapabilities.AllowsPreview) @@ -749,73 +814,103 @@ class BibleMediaItem(MediaManagerItem): This methode is called, when we have to change the title, because we are at the end of a verse range. E. g. if we want to add Genesis 1:1-6 as well as Daniel 2:14. + + ``start_item`` + The first item of a range. + + ``old_item`` + The last item of a range. """ + verse_separator = get_reference_match(u'sep_v_display') + range_separator = get_reference_match(u'sep_r_display') old_bitem = self.listView.item(old_item.row()) - old_chapter = int(self._decodeQtObject(old_bitem, 'chapter')) - old_verse = int(self._decodeQtObject(old_bitem, 'verse')) + old_chapter = self._decodeQtObject(old_bitem, 'chapter') + old_verse = self._decodeQtObject(old_bitem, 'verse') start_bitem = self.listView.item(start_item.row()) start_book = self._decodeQtObject(start_bitem, 'book') - start_chapter = int(self._decodeQtObject(start_bitem, 'chapter')) - start_verse = int(self._decodeQtObject(start_bitem, 'verse')) + start_chapter = self._decodeQtObject(start_bitem, 'chapter') + start_verse = self._decodeQtObject(start_bitem, 'verse') start_bible = self._decodeQtObject(start_bitem, 'bible') - start_dual_bible = self._decodeQtObject(start_bitem, 'dual_bible') - if start_dual_bible: - if start_verse == old_verse and start_chapter == old_chapter: - title = u'%s %s:%s (%s, %s)' % (start_book, start_chapter, - start_verse, start_bible, start_dual_bible) - elif start_chapter == old_chapter: - title = u'%s %s:%s-%s (%s, %s)' % (start_book, start_chapter, - start_verse, old_verse, start_bible, start_dual_bible) - else: - title = u'%s %s:%s-%s:%s (%s, %s)' % (start_book, start_chapter, - start_verse, old_chapter, old_verse, start_bible, - start_dual_bible) + start_second_bible = self._decodeQtObject(start_bitem, 'second_bible') + if start_second_bible: + bibles = u'%s, %s' % (start_bible, start_second_bible) else: - if start_verse == old_verse and start_chapter == old_chapter: - title = u'%s %s:%s (%s)' % (start_book, start_chapter, - start_verse, start_bible) - elif start_chapter == old_chapter: - title = u'%s %s:%s-%s (%s)' % (start_book, start_chapter, - start_verse, old_verse, start_bible) + bibles = start_bible + if start_chapter == old_chapter: + if start_verse == old_verse: + verse_range = start_chapter + verse_separator + start_verse else: - title = u'%s %s:%s-%s:%s (%s)' % (start_book, start_chapter, - start_verse, old_chapter, old_verse, start_bible) + verse_range = start_chapter + verse_separator + start_verse + \ + range_separator + old_verse + else: + verse_range = start_chapter + verse_separator + start_verse + \ + range_separator + old_chapter + verse_separator + old_verse + title = u'%s %s (%s)' % (start_book, verse_range, bibles) return title def checkTitle(self, item, old_item): """ This methode checks if we are at the end of an verse range. If that is - the case, we return True, else False. E. g. if we added Genesis 1:1-6, - but the next verse is Daniel 2:14. + the case, we return True, otherwise False. E. g. if we added + Genesis 1:1-6, but the next verse is Daniel 2:14, we return True. + + ``item`` + The item we are dealing with at the moment. + + ``old_item`` + The item we were previously dealing with. """ + # Get all the necessary meta data. bitem = self.listView.item(item.row()) book = self._decodeQtObject(bitem, 'book') chapter = int(self._decodeQtObject(bitem, 'chapter')) verse = int(self._decodeQtObject(bitem, 'verse')) bible = self._decodeQtObject(bitem, 'bible') - dual_bible = self._decodeQtObject(bitem, 'dual_bible') + second_bible = self._decodeQtObject(bitem, 'second_bible') old_bitem = self.listView.item(old_item.row()) old_book = self._decodeQtObject(old_bitem, 'book') old_chapter = int(self._decodeQtObject(old_bitem, 'chapter')) old_verse = int(self._decodeQtObject(old_bitem, 'verse')) old_bible = self._decodeQtObject(old_bitem, 'bible') - old_dual_bible = self._decodeQtObject(old_bitem, 'dual_bible') - if old_bible != bible or old_dual_bible != dual_bible or \ + old_second_bible = self._decodeQtObject(old_bitem, 'second_bible') + if old_bible != bible or old_second_bible != second_bible or \ old_book != book: + # The bible, second bible or book has changed. return True elif old_verse + 1 != verse and old_chapter == chapter: + # We are still in the same chapter, but a verse has been skipped. return True elif old_chapter + 1 == chapter and (verse != 1 or old_verse != self.parent.manager.get_verse_count( old_bible, old_book, old_chapter)): + # We are in the following chapter, but the last verse was not the + # last verse of the chapter or the current verse is not the + # first one of the chapter. return True else: return False def formatVerse(self, old_chapter, chapter, verse): + """ + Formats and returns the text, each verse starts with, for the given + chapter and verse. The text is either surrounded by round, square, + curly brackets or no brackets at all. For example:: + + u'{su}1:1{/su}' + + ``old_chapter`` + The previous verse's chapter number (int). + + ``chapter`` + The chapter number (int). + + ``verse`` + The verse number (int). + """ + verse_separator = get_reference_match(u'sep_v_display') if not self.parent.settings_tab.show_new_chapters or \ old_chapter != chapter: - verse_text = u'%s:%s' % (chapter, verse) + verse_text = unicode(chapter) + verse_separator + unicode(verse) else: verse_text = u'%s' % verse if self.parent.settings_tab.display_style == 1: diff --git a/openlp/plugins/bibles/lib/openlp1.py b/openlp/plugins/bibles/lib/openlp1.py new file mode 100644 index 000000000..ba9476fca --- /dev/null +++ b/openlp/plugins/bibles/lib/openlp1.py @@ -0,0 +1,93 @@ +# -*- 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 # +############################################################################### + +import logging +import sqlite + +from PyQt4 import QtCore + +from openlp.core.lib import Receiver, translate +from db import BibleDB + +log = logging.getLogger(__name__) + +class OpenLP1Bible(BibleDB): + """ + This class provides the OpenLPv1 bible importer. + """ + def __init__(self, parent, **kwargs): + """ + Constructor. + """ + log.debug(self.__class__.__name__) + BibleDB.__init__(self, parent, **kwargs) + self.filename = kwargs[u'filename'] + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) + + def do_import(self): + """ + Imports an openlp.org v1 bible. + """ + connection = None + cursor = None + try: + connection = sqlite.connect(self.filename) + cursor = connection.cursor() + except: + return False + # Create all books. + cursor.execute(u'SELECT id, testament_id, name, abbreviation FROM book') + books = cursor.fetchall() + self.wizard.importProgressBar.setMaximum(len(books) + 1) + for book in books: + if self.stop_import_flag: + connection.close() + return False + book_id = int(book[0]) + testament_id = int(book[1]) + name = unicode(book[2], u'cp1252') + abbreviation = unicode(book[3], u'cp1252') + self.create_book(name, abbreviation, testament_id) + # Update the progess bar. + self.wizard.incrementProgressBar(u'%s %s...' % (translate( + 'BiblesPlugin.OpenLP1Import', 'Importing'), name)) + # Import the verses for this book. + cursor.execute(u'SELECT chapter, verse, text || \'\' AS text FROM ' + 'verse WHERE book_id=%s' % book_id) + verses = cursor.fetchall() + for verse in verses: + if self.stop_import_flag: + connection.close() + return False + chapter = int(verse[0]) + verse_number = int(verse[1]) + text = unicode(verse[2], u'cp1252') + self.create_verse(book_id, chapter, verse_number, text) + Receiver.send_message(u'openlp_process_events') + self.session.commit() + connection.close() + return True diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index f1d3efd74..14454a69f 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -44,10 +44,8 @@ class OpenSongBible(BibleDB): Constructor to create and set up an instance of the OpenSongBible class. This class is used to import Bibles from OpenSong's XML format. """ - log.debug(__name__) + log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) - if 'filename' not in kwargs: - raise KeyError(u'You have to supply a file name to import from.') self.filename = kwargs['filename'] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import) @@ -59,7 +57,6 @@ class OpenSongBible(BibleDB): log.debug(u'Starting OpenSong import from "%s"' % self.filename) if not isinstance(self.filename, unicode): self.filename = unicode(self.filename, u'utf8') - self.wizard.incrementProgressBar(u'Preparing for import...') file = None success = True try: @@ -87,10 +84,9 @@ class OpenSongBible(BibleDB): unicode(verse.text) ) Receiver.send_message(u'openlp_process_events') - self.wizard.incrementProgressBar( - QtCore.QString('%s %s %s' % ( - translate('BiblesPlugin.Opensong', 'Importing'), - db_book.name, chapter.attrib[u'n']))) + self.wizard.incrementProgressBar(u'%s %s %s...' % ( + translate('BiblesPlugin.Opensong', 'Importing'), + db_book.name, chapter.attrib[u'n'])) self.session.commit() except IOError: log.exception(u'Loading bible from OpenSong file failed') @@ -99,7 +95,6 @@ class OpenSongBible(BibleDB): if file: file.close() if self.stop_import_flag: - self.wizard.incrementProgressBar(u'Import canceled!') return False else: return success diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index a0b6a1828..f39a4ab0f 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -33,7 +33,7 @@ import re from PyQt4 import QtCore -from openlp.core.lib import Receiver +from openlp.core.lib import Receiver, translate from openlp.core.utils import AppLocation from db import BibleDB @@ -50,11 +50,11 @@ class OSISBible(BibleDB): Constructor to create and set up an instance of the OpenSongBible class. This class is used to import Bibles from OpenSong's XML format. """ - log.debug(__name__) + log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) - if u'filename' not in kwargs: - raise KeyError(u'You have to supply a file name to import from.') self.filename = kwargs[u'filename'] + fbibles = None + self.books = {} self.verse_regex = re.compile( r'(.*?)') self.note_regex = re.compile(r'(.*?)') @@ -72,11 +72,9 @@ class OSISBible(BibleDB): self.divineName_regex = re.compile( r'(.*?)') self.spaces_regex = re.compile(r'([ ]{2,})') - self.books = {} filepath = os.path.join( AppLocation.get_directory(AppLocation.PluginsDir), u'bibles', u'resources', u'osisbooks.csv') - fbibles = None try: fbibles = open(filepath, u'r') for line in fbibles: @@ -96,9 +94,15 @@ class OSISBible(BibleDB): Loads a Bible from file. """ log.debug(u'Starting OSIS import from "%s"' % self.filename) - self.wizard.incrementProgressBar( - u'Detecting encoding (this may take a few minutes)...') detect_file = None + db_book = None + osis = None + success = True + last_chapter = 0 + testament = 1 + match_count = 0 + self.wizard.incrementProgressBar(translate('BiblesPlugin.OsisImport', + 'Detecting encoding (this may take a few minutes)...')) try: detect_file = open(self.filename, u'r') details = chardet.detect(detect_file.read(1048576)) @@ -108,14 +112,8 @@ class OSISBible(BibleDB): finally: if detect_file: detect_file.close() - osis = None - success = True try: osis = codecs.open(self.filename, u'r', details['encoding']) - last_chapter = 0 - testament = 1 - match_count = 0 - db_book = None for file_record in osis: if self.stop_import_flag: break @@ -136,15 +134,15 @@ class OSISBible(BibleDB): testament) if last_chapter == 0: if book == u'Gen': - self.wizard.ImportProgressBar.setMaximum(1188) + self.wizard.importProgressBar.setMaximum(1188) else: - self.wizard.ImportProgressBar.setMaximum(260) + self.wizard.importProgressBar.setMaximum(260) if last_chapter != chapter: if last_chapter != 0: self.session.commit() - self.wizard.incrementProgressBar( - u'Importing %s %s...' % \ - (self.books[match.group(1)][0], chapter)) + self.wizard.incrementProgressBar(u'%s %s %s...' % ( + translate('BiblesPlugin.OsisImport', 'Importing'), + self.books[match.group(1)][0], chapter)) last_chapter = chapter # All of this rigmarol below is because the mod2osis # tool from the Sword library embeds XML in the OSIS @@ -171,7 +169,6 @@ class OSISBible(BibleDB): self.create_verse(db_book.id, chapter, verse, verse_text) Receiver.send_message(u'openlp_process_events') self.session.commit() - self.wizard.incrementProgressBar(u'Finishing import...') if match_count == 0: success = False except (ValueError, IOError): @@ -181,7 +178,6 @@ class OSISBible(BibleDB): if osis: osis.close() if self.stop_import_flag: - self.wizard.incrementProgressBar(u'Import canceled!') return False else: return success diff --git a/openlp/plugins/bibles/resources/biblegateway.csv b/openlp/plugins/bibles/resources/biblegateway.csv index deca46d7c..ad8052704 100644 --- a/openlp/plugins/bibles/resources/biblegateway.csv +++ b/openlp/plugins/bibles/resources/biblegateway.csv @@ -1,80 +1,81 @@ +João Ferreira de Almeida Atualizada,AA +التفسير التطبيقى للكتاب المقدس,ALAB +Shqip,ALB +Amplified Bible,AMP Amuzgo de Guerrero,AMU -Arabic Life Application Bible,ALAB -Bulgarian Bible,BULG -1940 Bulgarian Bible,BG1940 -Chinanteco de Comaltepec,CCO -Cakchiquel Occidental,CKW -Haitian Creole Version,HCV -Slovo na cestu,SNC -Dette er Biblen pÃ¥ dansk,DN1933 -Hoffnung für Alle,HOF -Luther Bibel 1545,LUTH1545 -New International Version,NIV -New American Standard Bible,NASB -The Message,MSG -Amplified Bible,AMP -New Living Translation,NLT -King James Version,KJV -English Standard Version,ESV -Contemporary English Version,CEV -New King James Version,NKJV -New Century Version,NCV -21st Century King James Version,KJ21 -American Standard Version,ASV -Young's Literal Translation,YLT -Darby Translation,DARBY -Holman Christian Standard Bible,HCSB -New International Reader's Version,NIRV -Wycliffe New Testament,WYC -Worldwide English (New Testament),WE -New International Version - UK,NIVUK -Today's New International Version,TNIV +American Standard Version,ASV +La Bible du Semeur,BDS +Български 1940,BG1940 +Български,BULG +Chinanteco de Comaltepec,CCO +Contemporary English Version,CEV +Cakchiquel Occidental,CKW +Hrvatski,CRO +Castilian,CST +聖經和合本 (简体中文),CUVS +聖經和合本 (繁体中文),CUV +Darby Translation,DARBY +Dette er Biblen på dansk,DN1933 +Det Norsk Bibelselskap 1930,DNB1930 +English Standard Version,ESV +GOD’S WORD Translation,GW +Holman Christian Standard Bible,HCSB +Kreyòl ayisyen bib,HCV +Hiligaynon Bible,HLGN +Hoffnung für Alle,HOF +Het Boek,HTB +Icelandic Bible,ICELAND +Jacalteco – Oriental,JAC +Károlyi-biblia,KAR +Kekchi,KEK +21st Century King James Version,KJ21 +King James Version,KJV +La Biblia de las Américas,LBLA +Levande Bibeln,LB +La Parola è Vita,LM +La Nuova Diodati,LND +Louis Segond,LSG +Luther Bibel 1545,LUTH1545 +Māori Bible,MAORI +Македонски Новиот Завет,MNT +The Message,MSG +Mam de Comitancillo Central,MVC +Mam de Todos Santos Cuchumatán,MVJ +New American Standard Bible,NASB +New Century Version,NCV +Náhuatl de Guerrero,NGU +New International Reader's Version,NIRV +New International Version 1984,NIV1984 +New International Version 2010,NIV +New International Version - UK,NIVUK +New King James Version,NKJV +New Living Translation,NLT +Nádej pre kazdého,NPK +Nueva Versión Internacional,NVI +O Livro,OL +Quiché – Centro Occidental,QUT +Reimer 2001,REIMER +Română Cornilescu,RMNN +Новый перевод на русский язык,RUSV +Reina-Valera Antigua,RVA Reina-Valera 1960,RVR1960 -Nueva Versión Internacional,NVI -Reina-Valera 1995,RVR1995 -Castilian,CST -Reina-Valera Antigua,RVA -Biblia en Lenguaje Sencillo,BLS -La Biblia de las Américas,LBLA -Louis Segond,LSG -La Bible du Semeur,BDS -1881 Westcott-Hort New Testament,WHNU -1550 Stephanus New Testament,TR1550 -1894 Scrivener New Testament,TR1894 -The Westminster Leningrad Codex,WLC -Hiligaynon Bible,HLGN -Croatian Bible,CRO -Hungarian Károli,KAR -Icelandic Bible,ICELAND -La Nuova Diodati,LND -La Parola è Vita,LM -Jacalteco, Oriental,JAC -Kekchi,KEK -Korean Bible,KOREAN -Maori Bible,MAORI -Macedonian New Testament,MNT -Mam, Central,MVC -Mam de Todos Santos Chuchumatán,MVJ -Reimer 2001,REIMER -Náhuatl de Guerrero,NGU -Het Boek,HTB -Det Norsk Bibelselskap 1930,DNB1930 -Levande Bibeln,LB -O Livro,OL -João Ferreira de Almeida Atualizada,AA -Quiché, Centro Occidental,QUT -Romanian,RMNN -Romanian,TLCR -Russian Synodal Version,RUSV -Slovo Zhizny,SZ -Nádej pre kazdého,NPK -Albanian Bible,ALB -Levande Bibeln,SVL -Svenska 1917,SV1917 -Swahili New Testament,SNT -Ang Salita ng Diyos,SND -Ukrainian Bible,UKR -Uspanteco,USP -1934 Vietnamese Bible,VIET -Chinese Union Version (Simplified),CUVS -Chinese Union Version (Traditional),CUV \ No newline at end of file +Reina-Valera 1995,RVR1995 +Slovo na cestu,SNC +Ang Salita ng Diyos,SND +Swahili New Testament,SNT +Svenska 1917,SV1917 +Levande Bibeln,SVL +Создать страницу,SZ +Traducción en lenguaje actual,TLA +New Romanian Translation,TLCR +Today’s New International Version 2005,TNIV +Textus Receptus Stephanus 1550,TR1550 +Textus Receptus Scrivener 1894,TR1894 +Українська Біблія. Переклад Івана Огієнка,UKR +Uspanteco,USP +Kinh Thánh tiếng Việt 1934,VIET +Worldwide English (New Testament),WE +Codex Vaticanus Westcott-Hort 1881,WHNU +Westminster Leningrad Codex,WLC +Wycliffe New Testament,WYC +Young's Literal Translation,YLT diff --git a/openlp/plugins/bibles/resources/bibleserver.csv b/openlp/plugins/bibles/resources/bibleserver.csv new file mode 100644 index 000000000..c0d109f97 --- /dev/null +++ b/openlp/plugins/bibles/resources/bibleserver.csv @@ -0,0 +1,39 @@ +عربي, ARA +Bible – překlad 21. století, B21 +Bible du Semeur, BDS +Българската Библия, BLG +Český ekumenický překlad, CEP +Hrvatski, CRO +Священное Писание, CRS +Version La Biblia al Dia, CST +中文和合本(简体), CUVS +Bibelen på hverdagsdansk, DK +Revidierte Elberfelder, ELB +Einheitsübersetzung, EU +Gute Nachricht Bibel, GNB +Hoffnung für alle, HFA +Hungarian, HUN +Het Boek, HTB +La Parola è Vita, ITA +IBS-fordítás (Új Károli), KAR +King James Version, KJV +Luther 1984, LUT +Septuaginta, LXX +Neue Genfer Übersetzung, NGÜ +New International Readers Version, NIRV +New International Version, NIV +Neues Leben, NL +En Levende Bok (NOR), NOR +Nádej pre kazdého, NPK +Noua traducere în limba românã, NTR +Nueva Versión Internacional, NVI +הברית הישנה, OT +Słowo Życia, POL +O Livro, PRT +Новый перевод на русский язык, RUS +Slovo na cestu, SNC +Schlachter 2000, SLT +En Levande Bok (SWE), SVL +Today's New International Version, TNIV +Türkçe, TR +Biblia Vulgata, VUL diff --git a/openlp/plugins/bibles/resources/crosswalkbooks.csv b/openlp/plugins/bibles/resources/crosswalkbooks.csv index 0b6de47de..7957bfdc8 100644 --- a/openlp/plugins/bibles/resources/crosswalkbooks.csv +++ b/openlp/plugins/bibles/resources/crosswalkbooks.csv @@ -24,4 +24,4 @@ New International Reader's Version,nrv The Darby Translation,dby The Webster Bible,wbt The Latin Vulgate,vul -Weymouth New Testament,wnt \ No newline at end of file +Weymouth New Testament,wnt diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 65a73337a..359cc9eae 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -46,7 +46,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Constructor """ QtGui.QDialog.__init__(self, parent) - #self.parent = parent self.setupUi(self) # Connecting signals and slots self.previewButton = QtGui.QPushButton() @@ -124,8 +123,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.slideListView.addItem(slide[1]) theme = self.customSlide.theme_name id = self.themeComboBox.findText(theme, QtCore.Qt.MatchExactly) + # No theme match if id == -1: - id = 0 # Not Found + id = 0 self.themeComboBox.setCurrentIndex(id) else: self.themeComboBox.setCurrentIndex(0) @@ -224,27 +224,24 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): ``edit_all`` Indicates if all slides or only one slide has been edited. """ - if len(slides) == 1: - self.slideListView.currentItem().setText(slides[0]) + if edit_all: + self.slideListView.clear() + for slide in slides: + self.slideListView.addItem(slide) else: - if edit_all: - self.slideListView.clear() - for slide in slides: - self.slideListView.addItem(slide) - else: - old_slides = [] - old_row = self.slideListView.currentRow() - # Create a list with all (old/unedited) slides. - old_slides = [self.slideListView.item(row).text() for row in \ - range(0, self.slideListView.count())] - self.slideListView.clear() - old_slides.pop(old_row) - # Insert all slides to make the old_slides list complete. - for slide in slides: - old_slides.insert(old_row, slide) - for slide in old_slides: - self.slideListView.addItem(slide) - self.slideListView.repaint() + old_slides = [] + old_row = self.slideListView.currentRow() + # Create a list with all (old/unedited) slides. + old_slides = [self.slideListView.item(row).text() for row in \ + range(0, self.slideListView.count())] + self.slideListView.clear() + old_slides.pop(old_row) + # Insert all slides to make the old_slides list complete. + for slide in slides: + old_slides.insert(old_row, slide) + for slide in old_slides: + self.slideListView.addItem(slide) + self.slideListView.repaint() def onDeleteButtonPressed(self): self.slideListView.takeItem(self.slideListView.currentRow()) @@ -264,7 +261,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.titleEdit.setFocus() return False, translate('CustomPlugin.EditCustomForm', 'You need to type in a title.') - # We must have one slide. + # We must have at least one slide. if self.slideListView.count() == 0: return False, translate('CustomPlugin.EditCustomForm', 'You need to add at least one slide') diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index 5f535c8bc..72c7dbb4a 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -50,7 +50,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): def setText(self, text): """ Set the text for slideTextEdit. - + ``text`` The text (unicode). """ @@ -67,7 +67,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): def onSplitButtonPressed(self): """ - Splits a slide in two slides. + Adds a slide split at the cursor. """ if self.slideTextEdit.textCursor().columnNumber() != 0: self.slideTextEdit.insertPlainText(u'\n') diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py index b554f9657..14ca23ee0 100644 --- a/openlp/plugins/custom/lib/customxmlhandler.py +++ b/openlp/plugins/custom/lib/customxmlhandler.py @@ -42,8 +42,8 @@ The basic XML is of the format:: import logging from xml.dom.minidom import Document -from xml.etree.ElementTree import ElementTree, XML, dump -from xml.parsers.expat import ExpatError +from xml.etree.ElementTree import dump +from lxml import etree, objectify log = logging.getLogger(__name__) @@ -55,14 +55,14 @@ class CustomXMLBuilder(object): def __init__(self): """ - Set up the song builder. + Set up the custom builder. """ # Create the minidom document self.custom_xml = Document() def new_document(self): """ - Create a new song XML document. + Create a new custom XML document. """ # Create the base element self.song = self.custom_xml.createElement(u'song') @@ -72,7 +72,7 @@ class CustomXMLBuilder(object): def add_lyrics_to_song(self): """ Set up and add a ```` tag which contains the lyrics of the - song. + custom item. """ # Create the main element self.lyrics = self.custom_xml.createElement(u'lyrics') @@ -93,7 +93,6 @@ class CustomXMLBuilder(object): ``content`` The actual text of the verse to be stored. """ - #log.debug(u'add_verse_to_lyrics %s, %s\n%s' % (type, number, content)) verse = self.custom_xml.createElement(u'verse') verse.setAttribute(u'type', type) verse.setAttribute(u'label', number) @@ -102,7 +101,7 @@ class CustomXMLBuilder(object): cds = self.custom_xml.createCDATASection(content) verse.appendChild(cds) - def dump_xml(self): + def _dump_xml(self): """ Debugging aid to dump XML so that we can see what we have. """ @@ -110,29 +109,30 @@ class CustomXMLBuilder(object): def extract_xml(self): """ - Extract our newly created XML song. + Extract our newly created XML custom. """ return self.custom_xml.toxml(u'utf-8') class CustomXMLParser(object): """ - A class to read in and parse a song's XML. + A class to read in and parse a custom's XML. """ log.info(u'CustomXMLParser Loaded') def __init__(self, xml): """ - Set up our song XML parser. + Set up our custom XML parser. ``xml`` - The XML of the song to be parsed. + The XML of the custom to be parsed. """ self.custom_xml = None + if xml[:5] == u' 1: self.DisplayTypeComboBox.insertItem(0, self.Automatic) self.DisplayTypeComboBox.setCurrentIndex(0) - if QtCore.QSettings().value(self.settingsSection + u'/override app', + if QtCore.QSettings().value(self.settingsSection + u'/override app', QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked: self.PresentationWidget.show() else: @@ -238,7 +238,7 @@ class PresentationMediaItem(MediaManagerItem): SettingsManager.set_list(self.settingsSection, self.settingsSection, self.getFileList()) - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): """ Load the relevant information for displaying the presentation in the slidecontroller. In the case of powerpoints, an image @@ -277,7 +277,7 @@ class PresentationMediaItem(MediaManagerItem): def findControllerByType(self, filename): """ Determine the default application controller to use for the selected - file type. This is used if "Automatic" is set as the preferred + file type. This is used if "Automatic" is set as the preferred controller. Find the first (alphabetic) enabled controller which "supports" the extension. If none found, then look for a controller which "alsosupports" it instead. diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index 6fd901a86..535744369 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -51,7 +51,7 @@ class Controller(object): def add_handler(self, controller, file, is_blank): """ - Add a handler, which is an instance of a presentation and + Add a handler, which is an instance of a presentation and slidecontroller combination. If the slidecontroller has a display then load the presentation. """ @@ -362,7 +362,7 @@ class MessageListener(object): def timeout(self): """ - The presentation may be timed or might be controlled by the + The presentation may be timed or might be controlled by the application directly, rather than through OpenLP. Poll occassionally to check which slide is currently displayed so the slidecontroller view can be updated diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 54b09be32..281e647de 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -108,7 +108,7 @@ class PptviewDocument(PresentationDocument): """ def __init__(self, controller, presentation): """ - Constructor, store information about the file and initialise + Constructor, store information about the file and initialise """ log.debug(u'Init Presentation PowerPoint') PresentationDocument.__init__(self, controller, presentation) diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index a7b16cd5a..d1ebb570c 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -133,7 +133,7 @@ class PresentationTab(SettingsTab): self.settingsSection + u'/' + controller.name, QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0]) self.OverrideAppCheckBox.setChecked(QtCore.QSettings().value( - self.settingsSection + u'/override app', + self.settingsSection + u'/override app', QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]) def save(self): diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 8ee3e2811..300314bde 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -163,30 +163,30 @@ class PresentationPlugin(Plugin): ## Load Button ## self.textStrings[StringContent.Load] = { u'title': translate('PresentationPlugin', 'Load'), - u'tooltip': translate('PresentationPlugin', + u'tooltip': translate('PresentationPlugin', 'Load a new Presentation') } ## Delete Button ## self.textStrings[StringContent.Delete] = { u'title': translate('PresentationPlugin', 'Delete'), - u'tooltip': translate('PresentationPlugin', + u'tooltip': translate('PresentationPlugin', 'Delete the selected Presentation') } ## Preview ## self.textStrings[StringContent.Preview] = { u'title': translate('PresentationPlugin', 'Preview'), - u'tooltip': translate('PresentationPlugin', + u'tooltip': translate('PresentationPlugin', 'Preview the selected Presentation') } ## Live Button ## self.textStrings[StringContent.Live] = { u'title': translate('PresentationPlugin', 'Live'), - u'tooltip': translate('PresentationPlugin', + u'tooltip': translate('PresentationPlugin', 'Send the selected Presentation live') } ## Add to service Button ## self.textStrings[StringContent.Service] = { u'title': translate('PresentationPlugin', 'Service'), - u'tooltip': translate('PresentationPlugin', + u'tooltip': translate('PresentationPlugin', 'Add the selected Presentation to the service') } diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 4302486a3..fe2776802 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -77,7 +77,7 @@ class RemotesPlugin(Plugin): 'a running version of OpenLP on a different computer via a web ' 'browser or through the remote API.') return about_text - + def setPluginTextStrings(self): """ Called to define all translatable texts of the plugin diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 241c6fd95..21958d403 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -108,6 +108,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.TopicsListView.setSortingEnabled(False) self.TopicsListView.setAlternatingRowColors(True) self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE) + self.whitespace = re.compile(r'\W+', re.UNICODE) def initialise(self): self.VerseEditButton.setEnabled(False) @@ -120,38 +121,59 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): order_by_ref=Author.display_name) self.AuthorsSelectionComboItem.clear() self.AuthorsSelectionComboItem.addItem(u'') + self.authors = [] for author in authors: row = self.AuthorsSelectionComboItem.count() self.AuthorsSelectionComboItem.addItem(author.display_name) self.AuthorsSelectionComboItem.setItemData( row, QtCore.QVariant(author.id)) + self.authors.append(author.display_name) + completer = QtGui.QCompleter(self.authors) + completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.AuthorsSelectionComboItem.setCompleter(completer) def loadTopics(self): topics = self.manager.get_all_objects(Topic, order_by_ref=Topic.name) self.SongTopicCombo.clear() self.SongTopicCombo.addItem(u'') + self.topics = [] for topic in topics: row = self.SongTopicCombo.count() self.SongTopicCombo.addItem(topic.name) + self.topics.append(topic.name) self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id)) + completer = QtGui.QCompleter(self.topics) + completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.SongTopicCombo.setCompleter(completer) def loadBooks(self): books = self.manager.get_all_objects(Book, order_by_ref=Book.name) self.SongbookCombo.clear() self.SongbookCombo.addItem(u'') + self.books = [] for book in books: row = self.SongbookCombo.count() self.SongbookCombo.addItem(book.name) + self.books.append(book.name) self.SongbookCombo.setItemData(row, QtCore.QVariant(book.id)) + completer = QtGui.QCompleter(self.books) + completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.SongbookCombo.setCompleter(completer) def loadThemes(self, theme_list): self.ThemeSelectionComboItem.clear() self.ThemeSelectionComboItem.addItem(u'') + self.themes = [] for theme in theme_list: self.ThemeSelectionComboItem.addItem(theme) + self.themes.append(theme) + completer = QtGui.QCompleter(self.themes) + completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.ThemeSelectionComboItem.setCompleter(completer) def newSong(self): log.debug(u'New Song') + self.initialise() self.SongTabWidget.setCurrentIndex(0) self.TitleEditItem.setText(u'') self.AlternativeEdit.setText(u'') @@ -170,8 +192,18 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): # it's a new song to preview is not possible self.previewButton.setVisible(False) - def loadSong(self, id, preview): + def loadSong(self, id, preview=False): + """ + Loads a song. + + ``id`` + The song id (int). + + ``preview`` + Should be ``True`` if the song is also previewed (boolean). + """ log.debug(u'Load Song') + self.initialise() self.SongTabWidget.setCurrentIndex(0) self.loadAuthors() self.loadTopics() @@ -515,17 +547,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if self.AuthorsListView.count() == 0: self.SongTabWidget.setCurrentIndex(1) self.AuthorsListView.setFocus() - answer = QtGui.QMessageBox.warning(self, + QtGui.QMessageBox.critical(self, translate('SongsPlugin.EditSongForm', 'Warning'), translate('SongsPlugin.EditSongForm', - 'You have not added any authors for this song. Do you ' - 'want to add an author now?'), - QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) - if answer == QtGui.QMessageBox.Yes: - return False + 'You need to have an author for this song.')) + return False if self.song.verse_order: order = [] - order_names = self.song.verse_order.split(u' ') + order_names = self.song.verse_order.split() for item in order_names: if len(item) == 1: order.append(item.lower() + u'1') @@ -594,18 +623,38 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ Save and Preview button pressed. The Song is valid so as the plugin to add it to preview to see. + + ``button`` + A button (QPushButton). """ log.debug(u'onPreview') if unicode(button.objectName()) == u'previewButton' and \ self.saveSong(True): Receiver.send_message(u'songs_preview') + def clearCaches(self): + """ + Free up autocompletion memory on dialog exit + """ + self.authors = [] + self.themes = [] + self.books = [] + self.topics = [] + def closePressed(self): + """ + Exit Dialog and do not save + """ Receiver.send_message(u'songs_edit_clear') + self.clearCaches() self.close() def accept(self): + """ + Exit Dialog and save soong if valid + """ log.debug(u'accept') + self.clearCaches() if not self.song: self.song = Song() item = int(self.SongbookCombo.currentIndex()) @@ -630,14 +679,17 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Get all the data from the widgets on the form, and then save it to the database. - ``preview`` - Should be True if song is also previewed. + ``preview`` + Should be ``True`` if the song is also previewed (boolean). """ self.song.title = unicode(self.TitleEditItem.text()) self.song.alternate_title = unicode(self.AlternativeEdit.text()) self.song.copyright = unicode(self.CopyrightEditItem.text()) - self.song.search_title = self.song.title + u'@' + \ - self.song.alternate_title + if self.song.alternate_title: + self.song.search_title = self.song.title + u'@' + \ + self.song.alternate_title + else: + self.song.search_title = self.song.title self.song.comments = unicode(self.CommentsEdit.toPlainText()) self.song.verse_order = unicode(self.VerseOrderEdit.text()) self.song.ccli_number = unicode(self.CCLNumberEdit.text()) @@ -648,6 +700,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Book.name == book_name) else: self.song.book = None + theme_name = unicode(self.ThemeSelectionComboItem.currentText()) + if theme_name: + self.song.theme_name = theme_name + else: + self.song.theme_name = None if self._validate_song(): self.processLyrics() self.processTitle() @@ -679,7 +736,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) bits = verseId.split(u':') sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text())) - text = text + re.sub(r'\W+', u' ', + text = text + whitespace.sub(u' ', unicode(self.VerseListWidget.item(i, 0).text())) + u' ' if (bits[1] > u'1') and (bits[0][0] not in multiple): multiple.append(bits[0][0]) diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index d954bfb1f..8f5f04194 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -29,7 +29,7 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib import VerseType, translate from editversedialog import Ui_EditVerseDialog @@ -131,6 +131,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): def setVerse(self, text, single=False, tag=u'%s:1' % VerseType.to_string(VerseType.Verse)): + self.hasSingleVerse = single if single: verse_type, verse_number = tag.split(u':') verse_type_index = VerseType.from_string(verse_type) @@ -159,3 +160,16 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): text = u'---[%s:1]---\n%s' % (VerseType.to_string(VerseType.Verse), text) return text + + def accept(self): + if self.hasSingleVerse: + value = unicode(self.getVerse()[0]) + else: + value = self.getVerse()[0].split(u'\n')[1] + if len(value) == 0: + QtGui.QMessageBox.critical(self, + translate('SongsPlugin.EditSongForm', 'Error'), + translate('SongsPlugin.EditSongForm', + 'You need to type some text in to the verse.')) + return False + QtGui.QDialog.accept(self) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 67ef4d8c1..f62c88063 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -118,9 +118,6 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): QtCore.QObject.connect(self.songBeamerRemoveButton, QtCore.SIGNAL(u'clicked()'), self.onSongBeamerRemoveButtonClicked) - QtCore.QObject.connect(self.cancelButton, - QtCore.SIGNAL(u'clicked(bool)'), - self.onCancelButtonClicked) QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged) @@ -132,6 +129,15 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.setDefaults() return QtGui.QWizard.exec_(self) + def reject(self): + """ + Stop the import on cancel button, close button or ESC key. + """ + log.debug('Import canceled by user.') + if self.currentId() == 2: + Receiver.send_message(u'songs_stop_import') + self.done(QtGui.QDialog.Rejected) + def validateCurrentPage(self): """ Validate the current page before moving on to the next page. @@ -394,14 +400,6 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): def onSongBeamerRemoveButtonClicked(self): self.removeSelectedItems(self.songBeamerFileListWidget) - def onCancelButtonClicked(self, checked): - """ - Stop the import on pressing the cancel button. - """ - log.debug('Cancel button pressed!') - if self.currentId() == 2: - Receiver.send_message(u'songs_stop_import') - def onCurrentIdChanged(self, id): if id == 2: self.preImport() diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py index 5be8ccfba..aafff1051 100644 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ b/openlp/plugins/songs/forms/songimportwizard.py @@ -350,7 +350,7 @@ class Ui_SongImportWizard(object): else: setattr(self, prefix + u'Layout', importLayout) self.formatComboBox.addItem(u'') - + def disablableWidget(self, page, prefix, obj_prefix): layout = QtGui.QVBoxLayout(page) layout.setMargin(0) diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 7c13e0989..f004ef026 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -405,13 +405,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def mergeAuthors(self, old_author): """ Merges two authors into one author. - + ``old_author`` The author which will be deleted afterwards. """ existing_author = self.manager.get_object_filtered(Author, and_(Author.first_name == old_author.first_name, - Author.last_name == old_author.last_name, + Author.last_name == old_author.last_name, Author.display_name == old_author.display_name)) songs = self.manager.get_all_objects(Song, Song.authors.contains(old_author)) @@ -427,7 +427,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def mergeTopics(self, old_topic): """ Merges two topics into one topic. - + ``old_topic`` The topic which will be deleted afterwards. """ @@ -447,7 +447,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def mergeBooks(self, old_book): """ Merges two books into one book. - + ``old_book`` The book which will be deleted afterwards. """ diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 351d50071..795116b4e 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -62,6 +62,36 @@ class VerseType(object): elif verse_type == VerseType.Other: return translate('SongsPlugin.VerseType', 'Other') + @staticmethod + def expand_string(verse_type): + """ + Return the VerseType for a given string + + ``verse_type`` + The string to return a VerseType for + """ + verse_type = verse_type.lower() + if verse_type == unicode(VerseType.to_string(VerseType.Verse)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Verse') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Chorus') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Bridge)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Bridge') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.PreChorus)).lower()[0]: + return translate('SongsPlugin.VerseType', 'PreChorus') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Intro)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Intro') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Ending)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Ending') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Other)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Other') + @staticmethod def from_string(verse_type): """ @@ -92,7 +122,6 @@ class VerseType(object): unicode(VerseType.to_string(VerseType.Other)).lower(): return VerseType.Other - -from xml import LyricsXML, SongXMLBuilder, SongXMLParser +from xml import LyricsXML, SongXMLBuilder, SongXMLParser, OpenLyricsParser from songstab import SongsTab from mediaitem import SongMediaItem diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py old mode 100755 new mode 100644 index 207756e4b..88b9a8569 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -76,7 +76,12 @@ class CCLIFileImport(SongImport): lines = [] if os.path.isfile(filename): detect_file = open(filename, u'r') - details = chardet.detect(detect_file.read(2048)) + detect_content = detect_file.read(2048) + try: + unicode(detect_content, u'utf-8') + details = {'confidence': 1, 'encoding': 'utf-8'} + except UnicodeDecodeError: + details = chardet.detect(detect_content) detect_file.close() infile = codecs.open(filename, u'r', details['encoding']) lines = infile.readlines() @@ -165,6 +170,7 @@ class CCLIFileImport(SongImport): song_words = line[6:].strip() #Unhandled usr keywords:Type,Version,Admin,Themes,Keys #Process Fields and words sections + check_first_verse_line = False field_list = song_fields.split(u'/t') words_list = song_words.split(u'/t') for counter in range(0, len(field_list)): @@ -176,10 +182,25 @@ class CCLIFileImport(SongImport): verse_type = u'B' else: #Other verse_type = u'O' + check_first_verse_line = True verse_text = unicode(words_list[counter]) verse_text = verse_text.replace("/n", "\n") + verse_lines = verse_text.split(u'\n', 1) + if check_first_verse_line: + if verse_lines[0].startswith(u'(PRE-CHORUS'): + verse_type = u'P' + log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0] ) + verse_text = verse_lines[1] + elif verse_lines[0].startswith(u'(BRIDGE'): + verse_type = u'B' + log.debug(u'USR verse BRIDGE') + verse_text = verse_lines[1] + elif verse_lines[0].startswith(u'('): + verse_type = u'O' + verse_text = verse_lines[1] if len(verse_text) > 0: self.add_verse(verse_text, verse_type) + check_first_verse_line = False #Handle multiple authors author_list = song_author.split(u'/') if len(author_list) < 2: @@ -228,6 +249,7 @@ class CCLIFileImport(SongImport): log.debug(u'TXT file text: %s', textList) self.set_defaults() line_number = 0 + check_first_verse_line = False verse_text = u'' song_comments = u'' song_copyright = u'' @@ -265,16 +287,32 @@ class CCLIFileImport(SongImport): elif verse_desc_parts[0].startswith(u'Br'): verse_type = u'B' else: + #we need to analyse the next line for + #verse type, so set flag verse_type = u'O' + check_first_verse_line = True verse_number = verse_desc_parts[1] else: verse_type = u'O' verse_number = 1 verse_start = True else: - # We have verse content or the start of the - # last part. Add l so as to keep the CRLF - verse_text = verse_text + line + #check first line for verse type + if check_first_verse_line: + if line.startswith(u'(PRE-CHORUS'): + verse_type = u'P' + elif line.startswith(u'(BRIDGE'): + verse_type = u'B' + # Handle all other misc types + elif line.startswith(u'('): + verse_type = u'O' + else: + verse_text = verse_text + line + check_first_verse_line = False + else: + # We have verse content or the start of the + # last part. Add l so as to keep the CRLF + verse_text = verse_text + line else: #line_number=2, copyright if line_number == 2: diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index cb360cf59..6b9b675c5 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -41,7 +41,7 @@ def strip_rtf(blob, encoding): control_word = [] for c in blob: if control: - # for delimiters, set control to False + # for delimiters, set control to False if c == '{': if len(control_word) > 0: depth += 1 diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index cb2d6a6e0..e42cb7fa3 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -25,6 +25,8 @@ ############################################################################### import logging +import locale +import re from PyQt4 import QtCore, QtGui @@ -32,7 +34,7 @@ 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 +from openlp.plugins.songs.lib import SongXMLParser, OpenLyricsParser from openlp.plugins.songs.lib.db import Author, Song log = logging.getLogger(__name__) @@ -42,6 +44,7 @@ class SongListView(BaseListWithDnD): self.PluginName = u'Songs' BaseListWithDnD.__init__(self, parent) + class SongMediaItem(MediaManagerItem): """ This is the custom media manager item for Songs. @@ -53,14 +56,15 @@ 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.singleServiceItem = False - #self.edit_song_form = EditSongForm(self.parent.manager, self) self.song_maintenance_form = SongMaintenanceForm( self.parent.manager, self) # Holds information about whether the edit is remotly triggered and # which Song is required. self.remoteSong = -1 self.editItem = None + self.whitespace = re.compile(r'\W+', re.UNICODE) def requiredIcons(self): MediaManagerItem.requiredIcons(self) @@ -114,6 +118,8 @@ class SongMediaItem(MediaManagerItem): self.SearchButtonLayout.addWidget(self.ClearTextButton) self.pageLayout.addLayout(self.SearchButtonLayout) # Signals and slots + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'plugin_list_refresh'), self.onSearchTextButtonClick) QtCore.QObject.connect(self.SearchTextEdit, QtCore.SIGNAL(u'returnPressed()'), self.onSearchTextButtonClick) QtCore.QObject.connect(self.SearchTextButton, @@ -141,7 +147,7 @@ class SongMediaItem(MediaManagerItem): self.updateServiceOnEdit = QtCore.QSettings().value( self.settingsSection + u'/update service on edit', QtCore.QVariant(u'False')).toBool() - self.AddSongFromServide = QtCore.QSettings().value( + self.addSongFromService = QtCore.QSettings().value( self.settingsSection + u'/add song from service', QtCore.QVariant(u'True')).toBool() @@ -171,8 +177,8 @@ class SongMediaItem(MediaManagerItem): if search_type == 0: log.debug(u'Titles Search') search_results = self.parent.manager.get_all_objects(Song, - Song.search_title.like(u'%' + search_keywords.lower() + u'%'), - Song.search_title.asc()) + Song.search_title.like(u'%' + self.whitespace.sub(u' ', + search_keywords.lower()) + u'%'), Song.search_title.asc()) self.displayResultsSong(search_results) elif search_type == 1: log.debug(u'Lyrics Search') @@ -211,6 +217,7 @@ class SongMediaItem(MediaManagerItem): def displayResultsSong(self, searchresults): log.debug(u'display results Song') self.listView.clear() + searchresults.sort(cmp=self.collateSongTitles) for song in searchresults: author_list = u'' for author in song.authors: @@ -328,7 +335,7 @@ class SongMediaItem(MediaManagerItem): self.parent.manager.delete_object(Song, item_id) self.onSearchTextButtonClick() - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): log.debug(u'generateSlideData (%s:%s)' % (service_item, item)) raw_footer = [] author_list = u'' @@ -355,7 +362,7 @@ class SongMediaItem(MediaManagerItem): if song.lyrics.startswith(u' 0 + new_db = len(cursor.fetchall()) > 0 # Count the number of records we need to import, for the progress bar + cursor.execute(u'-- types int') cursor.execute(u'SELECT COUNT(songid) FROM songs') - count = int(cursor.fetchone()[0]) + count = cursor.fetchone()[0] success = True self.import_wizard.importProgressBar.setMaximum(count) # "cache" our list of authors + cursor.execute(u'-- types int, unicode') cursor.execute(u'SELECT authorid, authorname FROM authors') authors = cursor.fetchall() if new_db: # "cache" our list of tracks + cursor.execute(u'-- types int, unicode') cursor.execute(u'SELECT trackid, fulltrackname FROM tracks') tracks = cursor.fetchall() # Import the songs + cursor.execute(u'-- types int, unicode, unicode, unicode') cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, ' u'copyrightinfo FROM songs') songs = cursor.fetchall() @@ -119,16 +100,19 @@ class OpenLP1SongImport(SongImport): success = False break song_id = song[0] - guess = chardet.detect(song[2]) - title = self.decode_string(song[1], guess) - lyrics = self.decode_string(song[2], guess).replace(u'\r', u'') - copyright = self.decode_string(song[3], guess) + title = song[1] + lyrics = song[2].replace(u'\r\n', u'\n') + copyright = song[3] self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', 'Importing "%s"...')) % title) self.title = title - self.process_song_text(lyrics) + verses = lyrics.split(u'\n\n') + for verse in verses: + if verse.strip() != u'': + self.add_verse(verse.strip()) self.add_copyright(copyright) + cursor.execute(u'-- types int') cursor.execute(u'SELECT authorid FROM songauthors ' u'WHERE songid = %s' % song_id) author_ids = cursor.fetchall() @@ -138,12 +122,13 @@ class OpenLP1SongImport(SongImport): break for author in authors: if author[0] == author_id[0]: - self.parse_author(self.decode_string(author[1], guess)) + self.parse_author(author[1]) break if self.stop_import_flag: success = False break if new_db: + cursor.execute(u'-- types int') cursor.execute(u'SELECT trackid FROM songtracks ' u'WHERE songid = %s ORDER BY listindex' % song_id) track_ids = cursor.fetchall() @@ -153,8 +138,7 @@ class OpenLP1SongImport(SongImport): break for track in tracks: if track[0] == track_id[0]: - self.add_media_file(self.decode_string(track[1], - guess)) + self.add_media_file(track[1]) break if self.stop_import_flag: success = False @@ -162,3 +146,103 @@ class OpenLP1SongImport(SongImport): self.finish() return success + def get_encoding(self): + """ + Detect character encoding of an openlp.org 1.x song database. + """ + # Connect to the database + connection = sqlite.connect(self.import_source, mode=0444) + cursor = connection.cursor() + + detector = UniversalDetector() + # detect charset by authors + cursor.execute(u'SELECT authorname FROM authors') + authors = cursor.fetchall() + for author in authors: + detector.feed(author[0]) + if detector.done: + detector.close() + return detector.result[u'encoding'] + # detect charset by songs + cursor.execute(u'SELECT songtitle, copyrightinfo, ' + u'lyrics || \'\' AS lyrics FROM songs') + songs = cursor.fetchall() + for index in [0, 1, 2]: + for song in songs: + detector.feed(song[index]) + if detector.done: + detector.close() + return detector.result[u'encoding'] + # detect charset by songs + cursor.execute(u'SELECT name FROM sqlite_master ' + u'WHERE type = \'table\' AND name = \'tracks\'') + if len(cursor.fetchall()) > 0: + cursor.execute(u'SELECT fulltrackname FROM tracks') + tracks = cursor.fetchall() + for track in tracks: + detector.feed(track[0]) + if detector.done: + detector.close() + return detector.result[u'encoding'] + detector.close() + guess = detector.result[u'encoding'] + + # map chardet result to compatible windows standard code page + codepage_mapping = {'IBM866': u'cp866', 'TIS-620': u'cp874', + 'SHIFT_JIS': u'cp932', 'GB2312': u'cp936', 'HZ-GB-2312': u'cp936', + 'EUC-KR': u'cp949', 'Big5': u'cp950', 'ISO-8859-2': u'cp1250', + 'windows-1250': u'cp1250', 'windows-1251': u'cp1251', + 'windows-1252': u'cp1252', 'ISO-8859-7': u'cp1253', + 'windows-1253': u'cp1253', 'ISO-8859-8': u'cp1255', + 'windows-1255': u'cp1255'} + if guess in codepage_mapping: + guess = codepage_mapping[guess] + else: + guess = u'cp1252' + + # Show dialog for encoding selection + encodings = [(u'cp1256', translate('SongsPlugin.OpenLP1SongImport', + 'Arabic (CP-1256)')), + (u'cp1257', translate('SongsPlugin.OpenLP1SongImport', + 'Baltic (CP-1257)')), + (u'cp1250', translate('SongsPlugin.OpenLP1SongImport', + 'Central European (CP-1250)')), + (u'cp1251', translate('SongsPlugin.OpenLP1SongImport', + 'Cyrillic (CP-1251)')), + (u'cp1253', translate('SongsPlugin.OpenLP1SongImport', + 'Greek (CP-1253)')), + (u'cp1255', translate('SongsPlugin.OpenLP1SongImport', + 'Hebrew (CP-1255)')), + (u'cp932', translate('SongsPlugin.OpenLP1SongImport', + 'Japanese (CP-932)')), + (u'cp949', translate('SongsPlugin.OpenLP1SongImport', + 'Korean (CP-949)')), + (u'cp936', translate('SongsPlugin.OpenLP1SongImport', + 'Simplified Chinese (CP-936)')), + (u'cp874', translate('SongsPlugin.OpenLP1SongImport', + 'Thai (CP-874)')), + (u'cp950', translate('SongsPlugin.OpenLP1SongImport', + 'Traditional Chinese (CP-950)')), + (u'cp1254', translate('SongsPlugin.OpenLP1SongImport', + 'Turkish (CP-1254)')), + (u'cp1258', translate('SongsPlugin.OpenLP1SongImport', + 'Vietnam (CP-1258)')), + (u'cp1252', translate('SongsPlugin.OpenLP1SongImport', + 'Western European (CP-1252)'))] + encoding_index = 0 + for index in range(len(encodings)): + if guess == encodings[index][0]: + encoding_index = index + break + chosen_encoding = QtGui.QInputDialog.getItem(None, + translate('SongsPlugin.OpenLP1SongImport', + 'Database Character Encoding'), + translate('SongsPlugin.OpenLP1SongImport', + 'The codepage setting is responsible\n' + 'for the correct character representation.\n' + 'Usually you are fine with the preselected choise.'), + [pair[1] for pair in encodings], encoding_index, False) + if not chosen_encoding[1]: + return None + return filter(lambda item: item[1] == chosen_encoding[0], + encodings)[0][0] diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index 6b993994c..662a94f5b 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -152,7 +152,7 @@ class OpenLPSongImport(SongImport): u'Importing song %s of %s' % (song_count, song_total)) new_song = Song() new_song.title = song.title - if has_media_files: + if has_media_files and hasattr(song, 'alternate_title'): new_song.alternate_title = song.alternate_title else: old_titles = song.search_title.split(u'@') diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 26a0abfcc..727af2c7b 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -46,7 +46,7 @@ else: class OooImport(SongImport): """ - Import songs from Impress/Powerpoint docs using Impress + Import songs from Impress/Powerpoint docs using Impress """ def __init__(self, master_manager, **kwargs): """ @@ -122,7 +122,7 @@ class OooImport(SongImport): manager = ctx.ServiceManager self.desktop = manager.createInstanceWithContext( "com.sun.star.frame.Desktop", ctx) - + def start_ooo_process(self): try: if os.name == u'nt': @@ -168,11 +168,11 @@ class OooImport(SongImport): u'Processing file ' + filepath, 0) except: pass - return + return def close_ooo_file(self): """ - Close file. + Close file. """ self.document.close(True) self.document = None @@ -187,7 +187,7 @@ class OooImport(SongImport): def process_pres(self): """ Process the file - """ + """ doc = self.document slides = doc.getDrawPages() text = u'' @@ -195,7 +195,7 @@ class OooImport(SongImport): if self.abort: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return - slide = slides.getByIndex(slide_no) + slide = slides.getByIndex(slide_no) slidetext = u'' for idx in range(slide.getCount()): shape = slide.getByIndex(idx) @@ -209,12 +209,12 @@ class OooImport(SongImport): songs = SongImport.process_songs_text(self.manager, text) for song in songs: song.finish() - return + return def process_doc(self): """ Process the doc file, a paragraph at a time - """ + """ text = u'' paragraphs = self.document.getText().createEnumeration() while paragraphs.hasMoreElements(): diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 47f4ecee5..767fc012a 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -249,7 +249,7 @@ class OpenSongImport(SongImport): words = thisline[1:].strip() if words is None: words = thisline - if not versenum: + if not versenum: versenum = u'1' if versenum is not None: versetag = u'%s%s' % (versetype, versenum) @@ -298,7 +298,7 @@ class OpenSongImport(SongImport): for tag in order: if tag[0].isdigit(): # Assume it's a verse if it has no prefix - tag = u'V' + tag + tag = u'V' + tag elif not re.search('\d+', tag): # Assume it's no.1 if there's no digits tag = tag + u'1' diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index ab91e1923..320e5c88a 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -56,13 +56,13 @@ class SofImport(OooImport): """ Import songs provided on disks with the Songs of Fellowship music books VOLS1_2.RTF, sof3words.rtf and sof4words.rtf - + Use OpenOffice.org Writer for processing the rtf file - The three books are not only inconsistant with each other, they are + The three books are not only inconsistant with each other, they are inconsistant in themselves too with their formatting. Not only this, but the 1+2 book does not space out verses correctly. This script attempts - to sort it out, but doesn't get it 100% right. But better than having to + to sort it out, but doesn't get it 100% right. But better than having to type them all out! It attempts to detect italiced verses, and treats these as choruses in @@ -96,7 +96,7 @@ class SofImport(OooImport): def process_sof_file(self): """ Process the RTF file, a paragraph at a time - """ + """ self.blanklines = 0 self.new_song() paragraphs = self.document.getText().createEnumeration() @@ -113,11 +113,11 @@ class SofImport(OooImport): def process_paragraph(self, paragraph): """ - Process a paragraph. + Process a paragraph. In the first book, a paragraph is a single line. In the latter ones they may contain multiple lines. Each paragraph contains textportions. Each textportion has it's own - styling, e.g. italics, bold etc. + styling, e.g. italics, bold etc. Also check for page breaks, which indicates a new song in books 1+2. In later books, there may not be line breaks, so check for 3 or more newlines @@ -136,7 +136,7 @@ class SofImport(OooImport): self.new_song() text = u'' self.process_paragraph_text(text) - + def process_paragraph_text(self, text): """ Split the paragraph text into multiple lines and process @@ -147,12 +147,12 @@ class SofImport(OooImport): self.new_song() def process_paragraph_line(self, text): - """ + """ Process a single line. Throw away that text which isn't relevant, i.e. stuff that appears at the end of the song. Anything that is OK, append to the current verse """ - text = text.strip() + text = text.strip() if text == u'': self.blanklines += 1 if self.blanklines > 1: @@ -164,7 +164,7 @@ class SofImport(OooImport): if self.skip_to_close_bracket: if text.endswith(u')'): self.skip_to_close_bracket = False - return + return if text.startswith(u'CCL Licence'): self.italics = False return @@ -264,7 +264,7 @@ class SofImport(OooImport): """ Add the author. OpenLP stores them individually so split by 'and', '&' and comma. - However need to check for "Mr and Mrs Smith" and turn it to + However need to check for "Mr and Mrs Smith" and turn it to "Mr Smith" and "Mrs Smith". """ text = text.replace(u' and ', u' & ') @@ -276,7 +276,7 @@ class SofImport(OooImport): we're beyond the second line of first verse, then this indicates a change of verse. Italics are a chorus """ - if self.italics != self.is_chorus and ((len(self.song.verses) > 0) or + if self.italics != self.is_chorus and ((len(self.song.verses) > 0) or (self.currentverse.count(u'\n') > 1)): self.finish_verse() if self.italics: @@ -307,7 +307,7 @@ class SofImport(OooImport): ln = 0 if line: verse = line + u'\n' - else: + else: verse = u'' else: verse += line + u'\n' @@ -320,34 +320,34 @@ class SofImport(OooImport): def uncap_text(self, text): - """ + """ Words in the title are in all capitals, so we lowercase them. - However some of these words, e.g. referring to God need a leading + However some of these words, e.g. referring to God need a leading capital letter. - - There is a complicated word "One", which is sometimes lower and + + There is a complicated word "One", which is sometimes lower and sometimes upper depending on context. Never mind, keep it lower. """ textarr = re.split(u'(\W+)', text) textarr[0] = textarr[0].capitalize() for i in range(1, len(textarr)): # Do not translate these. Fixed strings in SOF song file - if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', - u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', - u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', - u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', - u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', - u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', + if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', + u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', + u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', + u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', + u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', + u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', u'FATHER\'S', u'ELIJAH'): textarr[i] = textarr[i].capitalize() else: textarr[i] = textarr[i].lower() text = u''.join(textarr) return text - + def verse_splits(self, song_number): """ - Because someone at Kingsway forgot to check the 1+2 RTF file, + Because someone at Kingsway forgot to check the 1+2 RTF file, some verses were not formatted correctly. """ if song_number == 11: @@ -369,7 +369,7 @@ class SofImport(OooImport): if song_number == 50: return 8 if song_number == 70: - return 4 + return 4 if song_number == 75: return 8 if song_number == 79: @@ -529,7 +529,7 @@ class SofImport(OooImport): if song_number == 955: return 9 if song_number == 968: - return 8 + return 8 if song_number == 972: return 7 if song_number == 974: diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 44e8805c9..f45fcc268 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`songbeamerimport` module provides the functionality for importing +The :mod:`songbeamerimport` module provides the functionality for importing SongBeamer songs into the OpenLP database. """ import logging @@ -32,6 +32,7 @@ import os import chardet import codecs +from openlp.core.lib import translate from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) @@ -42,19 +43,20 @@ class SongBeamerTypes(object): u'Chorus': u'C', u'Vers': u'V', u'Verse': u'V', - u'Strophe': u'V', + u'Strophe': u'V', u'Intro': u'I', u'Coda': u'E', u'Ending': u'E', u'Bridge': u'B', - u'Interlude': u'B', + u'Interlude': u'B', u'Zwischenspiel': u'B', u'Pre-Chorus': u'P', - u'Pre-Refrain': u'P', + u'Pre-Refrain': u'P', u'Pre-Bridge': u'O', u'Pre-Coda': u'O', - u'Unbekannt': u'O', - u'Unknown': u'O' + u'Unbekannt': u'O', + u'Unknown': u'O', + u'Unbenannt': u'O' } @@ -88,7 +90,7 @@ class SongBeamerImport(SongImport): len(self.import_source)) for file in self.import_source: # TODO: check that it is a valid SongBeamer file - self.current_verse = u'' + self.current_verse = u'' self.current_verse_type = u'V' read_verses = False self.file_name = os.path.split(file)[1] @@ -100,6 +102,7 @@ class SongBeamerImport(SongImport): detect_file.close() infile = codecs.open(file, u'r', details['encoding']) self.songData = infile.readlines() + infile.close() else: return False for line in self.songData: @@ -112,7 +115,7 @@ class SongBeamerImport(SongImport): self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) - self.current_verse = u'' + self.current_verse = u'' self.current_verse_type = u'V' read_verses = True verse_start = True @@ -127,8 +130,9 @@ class SongBeamerImport(SongImport): self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) self.finish() - self.import_wizard.incrementProgressBar( - "Importing %s" % (self.file_name)) + self.import_wizard.incrementProgressBar(u'%s %s...' % + (translate('SongsPlugin.SongBeamerImport', 'Importing'), + self.file_name)) return True def replace_html_tags(self): @@ -263,6 +267,9 @@ class SongBeamerImport(SongImport): pass elif tag_val[0] == u'#Version': pass + elif tag_val[0] == u'#VerseOrder': + # TODO: add the verse order. + pass def check_verse_marks(self, line): """ diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index ea36d55b5..f305b90c7 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -247,7 +247,7 @@ class SongImport(QtCore.QObject): """ Extracts alphanumeric words for searchable fields """ - return re.sub(r'\W+', u' ', text) + return re.sub(r'\W+', u' ', text, re.UNICODE) def finish(self): """ diff --git a/openlp/plugins/songs/lib/test/test_opensongimport.py b/openlp/plugins/songs/lib/test/test_opensongimport.py index b503c65c5..27c7cca48 100644 --- a/openlp/plugins/songs/lib/test/test_opensongimport.py +++ b/openlp/plugins/songs/lib/test/test_opensongimport.py @@ -56,11 +56,11 @@ def test(): assert o.title == u'Martins Test' assert o.alternate_title == u'' assert o.song_number == u'1' - assert [u'C1', u'Chorus 1'] in o.verses - assert [u'C2', u'Chorus 2'] in o.verses - assert not [u'C3', u'Chorus 3'] in o.verses - assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses - assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses + assert [u'C1', u'Chorus 1'] in o.verses + assert [u'C2', u'Chorus 2'] in o.verses + assert not [u'C3', u'Chorus 3'] in o.verses + assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses + assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses assert [u'V3A', u'V3 Line 1\nV3 Line 2'] in o.verses assert [u'RAP1', u'Rap 1 Line 1\nRap 1 Line 2'] in o.verses @@ -80,11 +80,11 @@ def test(): assert o.title == u'Martins Test' assert o.alternate_title == u'' assert o.song_number == u'1' - assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses - assert [u'C1', u'Chorus 1'] in o.verses - assert [u'C2', u'Chorus 2'] in o.verses - assert not [u'C3', u'Chorus 3'] in o.verses - assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses + assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses + assert [u'C1', u'Chorus 1'] in o.verses + assert [u'C2', u'Chorus 2'] in o.verses + assert not [u'C3', u'Chorus 3'] in o.verses + assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses print o.verse_order_list assert o.verse_order_list == [u'V1', u'C1', u'V2', u'C2', u'V3', u'B1', u'V1'] @@ -99,11 +99,11 @@ def test(): assert o.alternate_title == u'' assert o.song_number == u'2' print o.verses - assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses - assert [u'C1', u'Chorus 1'] in o.verses - assert [u'C2', u'Chorus 2'] in o.verses - assert not [u'C3', u'Chorus 3'] in o.verses - assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses + assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses + assert [u'C1', u'Chorus 1'] in o.verses + assert [u'C2', u'Chorus 2'] in o.verses + assert not [u'C3', u'Chorus 3'] in o.verses + assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses print o.verse_order_list assert o.verse_order_list == [u'V1', u'V2', u'B1', u'C1', u'C2'] @@ -120,7 +120,7 @@ def test(): assert o.verse_order_list == [u'V1'] assert o.topics == [u'Worship: Declaration'] print o.verses[0] - assert [u'V1', u'Line 1\nLine 2'] in o.verses + assert [u'V1', u'Line 1\nLine 2'] in o.verses print "Tests passed" diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index ff39a0efa..9d98737dc 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -39,8 +39,11 @@ The basic XML is of the format:: """ import logging +import re from lxml import etree, objectify +from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib.db import Author, Song log = logging.getLogger(__name__) @@ -77,7 +80,6 @@ class SongXMLBuilder(object): ``content`` The actual text of the verse to be stored. """ - # log.debug(u'add_verse_to_lyrics %s, %s\n%s' % (type, number, content)) verse = etree.Element(u'verse', type = unicode(type), label = unicode(number)) verse.text = etree.CDATA(content) @@ -239,3 +241,159 @@ class LyricsXML(object): song_output = u'' + \ u'%s' % lyrics_output return song_output + + +class OpenLyricsParser(object): + """ + This class represents the converter for Song to/from OpenLyrics XML. + """ + def __init__(self, manager): + self.manager = manager + + def song_to_xml(self, song): + """ + 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.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.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) + 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) + + def xml_to_song(self, xml): + """ + Create a Song from OpenLyrics format xml + """ + # No xml get out of here + if not xml: + return 0 + song = Song() + if xml[:5] == u' - &Parameter(s): + &Parameter: ParameterEdit diff --git a/resources/forms/themewizard.ui b/resources/forms/themewizard.ui index 4ca7271d3..9e1f8f9e8 100644 --- a/resources/forms/themewizard.ui +++ b/resources/forms/themewizard.ui @@ -133,138 +133,254 @@ p, li { white-space: pre-wrap; } Set up your theme's background according to the parameters below. - - - QFormLayout::ExpandingFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 8 - - + + 8 20 - - - - Background type: - - - - - - - - Solid Color - - - - - Gradient - - - - - Image - - - - - - - - <Color1> - - - - - - - - - - - - - - <Color2> - - - - - - - - - - - - - - Image: - - - - - + + 8 - - - - + - - - - - :/general/general_open.png:/general/general_open.png + Background type: + + + + + Solid Color + + + + + Gradient + + + + + Image + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - Gradient: + + + + 0 - - - - - - - Horizontal - - - - - Vertical - - - - - Circular - - - - - Top Left - Bottom Right - - - - - Bottom Left - Top Right - - + + + + 8 + + + 8 + + + 0 + + + + + + 103 + 0 + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + 8 + + + 8 + + + 0 + + + + + + 103 + 0 + + + + Starting color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + 103 + 0 + + + + Ending color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + 103 + 0 + + + + Gradient: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + Horizontal + + + + + Vertical + + + + + Circular + + + + + Top Left - Bottom Right + + + + + Bottom Left - Top Right + + + + + + + + + + 8 + + + 8 + + + 0 + + + + + + 103 + 0 + + + + Image: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 8 + + + + + + + + + + + + :/general/general_open.png:/general/general_open.png + + + + + + + @@ -276,30 +392,30 @@ p, li { white-space: pre-wrap; } Define the font and display characteristics for the Display text - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - + 8 8 - - 20 - - - 20 - - + 20 + + + 103 + 0 + + Font: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -313,11 +429,32 @@ p, li { white-space: pre-wrap; } - - - + + + 24 - + + + + + + + + + + + Bold + + + + + + + Italic + + + + @@ -458,20 +595,6 @@ p, li { white-space: pre-wrap; } - - - - Bold Display - - - - - - - Italic Display - - - @@ -491,23 +614,23 @@ p, li { white-space: pre-wrap; } 8 - - 50 - - - 20 - - - 20 - - + 20 + + + 103 + 0 + + Font: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -569,14 +692,29 @@ p, li { white-space: pre-wrap; } Allows additional display formatting information to be defined + + 8 + + + 8 + 20 + + + 103 + 0 + + Horizontal Align: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -643,7 +781,7 @@ p, li { white-space: pre-wrap; } Allows you to change and move the Main and Footer areas. - + 20 @@ -983,129 +1121,114 @@ p, li { white-space: pre-wrap; } View the theme and save it replacing the current one or change the name to create a new theme - - - - 20 - 10 - 82 - 16 - + + + 8 - - Theme name: + + 20 - - Qt::PlainText - - - themeNameEdit - - - - - - 250 - 60 - 48 - 16 - - - - Preview - - - Qt::AlignCenter - - - - - - 117 - 4 - 351 - 23 - - - - - - - 40 - 80 - 464 - 214 - - - - - - - - - - Qt::Horizontal - - - - 58 - 20 - - - - - - - - - 0 - 0 - - - - - 300 - 200 - - - - QFrame::WinPanel - - - QFrame::Sunken - - - 1 - - - - - - true - - - - - - - Qt::Horizontal - - - - 78 - 20 - - - - - - + + + + 8 + + + + + + 103 + 0 + + + + Theme name: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + themeNameEdit + + + + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 58 + 20 + + + + + + + + + 0 + 0 + + + + + 100 + 150 + + + + QFrame::WinPanel + + + QFrame::Sunken + + + 1 + + + + + + true + + + + + + + Qt::Horizontal + + + + 78 + 20 + + + + + + + - - @@ -1124,5 +1247,21 @@ p, li { white-space: pre-wrap; } + + backgroundTypeComboBox + currentIndexChanged(int) + backgroundStackedWidget + setCurrentIndex(int) + + + 178 + 78 + + + 249 + 199 + + + diff --git a/resources/images/general_email.png b/resources/images/general_email.png new file mode 100644 index 000000000..bb3cab8f3 Binary files /dev/null and b/resources/images/general_email.png differ diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 0ecb87bca..e9ec5c0a3 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -39,6 +39,7 @@ general_new.png general_open.png general_save.png + general_email.png slide_close.png @@ -81,6 +82,7 @@ wizard_importsong.bmp wizard_importbible.bmp + wizard_createtheme.bmp service_collapse_all.png diff --git a/resources/images/wizard_createtheme.bmp b/resources/images/wizard_createtheme.bmp new file mode 100644 index 000000000..092c61ad4 Binary files /dev/null and b/resources/images/wizard_createtheme.bmp differ diff --git a/scripts/openlp-remoteclient.py b/scripts/openlp-remoteclient.py old mode 100755 new mode 100644 index 9d047d478..34fef44a8 --- a/scripts/openlp-remoteclient.py +++ b/scripts/openlp-remoteclient.py @@ -47,7 +47,7 @@ def main(): help="Recipient address ", default="localhost") parser.add_option("-e", "--event", - help="Action to be performed", + help="Action to be performed", default="alerts_text") parser.add_option("-m", "--message", help="Message to be passed for the action",