diff --git a/documentation/manual/source/glossary.rst b/documentation/manual/source/glossary.rst index 41a8f4ac6..6f4ebcdd6 100644 --- a/documentation/manual/source/glossary.rst +++ b/documentation/manual/source/glossary.rst @@ -48,7 +48,7 @@ Service Manger -------------- The service manager contains the media items in your service file. This is the -area from wich your media items go live, and you can also save, open, and edit +area from which your media items go live, and you can also save, open, and edit services files. .. image:: pics/servicemanager.png 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 1ad17a039..956b6c787 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -38,48 +38,51 @@ log = logging.getLogger(__name__) # TODO make external and configurable in alpha 4 via a settings dialog html_expands = [] -html_expands.append({u'desc':u'Red', u'start tag':u'{r}', - u'start html':u'', - u'end tag':u'{/r}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Black', u'start tag':u'{b}', - u'start html':u'', - u'end tag':u'{/b}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Blue', u'start tag':u'{bl}', - u'start html':u'', - u'end tag':u'{/bl}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Yellow', u'start tag':u'{y}', - u'start html':u'', - u'end tag':u'{/y}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Green', u'start tag':u'{g}', - u'start html':u'', - u'end tag':u'{/g}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Pink', u'start tag':u'{pk}', - u'start html':u'', - u'end tag':u'{/pk}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Orange', u'start tag':u'{o}', - u'start html':u'', - u'end tag':u'{/o}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Purple', u'start tag':u'{pp}', - u'start html':u'', - u'end tag':u'{/pp}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'White', u'start tag':u'{w}', - u'start html':u'', - u'end tag':u'{/w}', u'end html':u'', u'protected':False}) -html_expands.append({u'desc':u'Superscript', u'start tag':u'{su}', - u'start html':u'', u'end tag':u'{/su}', u'end html':u'', - u'protected':True}) -html_expands.append({u'desc':u'Subscript', u'start tag':u'{sb}', - u'start html':u'', u'end tag':u'{/sb}', u'end html':u'', - u'protected':True}) -html_expands.append({u'desc':u'Paragraph', u'start tag':u'{p}', - u'start html':u'

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

', - u'protected':True}) -html_expands.append({u'desc':u'Bold', u'start tag':u'{st}', - u'start html':u'', u'end tag':u'{/st}', u'end html':u'', - u'protected':True}) -html_expands.append({u'desc':u'Italics', u'start tag':u'{it}', - u'start html':u'', u'end tag':u'{/it}', u'end html':u'', - u'protected':True}) +html_expands.append({u'desc': u'Red', u'start tag': u'{r}', + u'start html': u'', + u'end tag': u'{/r}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Black', u'start tag': u'{b}', + u'start html': u'', + u'end tag': u'{/b}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}', + u'start html': u'', + u'end tag': u'{/bl}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}', + u'start html': u'', + u'end tag': u'{/y}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Green', u'start tag': u'{g}', + u'start html': u'', + u'end tag': u'{/g}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}', + u'start html': u'', + u'end tag': u'{/pk}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Orange', u'start tag': u'{o}', + u'start html': u'', + u'end tag': u'{/o}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}', + u'start html': u'', + u'end tag': u'{/pp}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'White', u'start tag': u'{w}', + u'start html': u'', + u'end tag': u'{/w}', u'end html': u'', u'protected': False}) +html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}', + u'start html': u'', u'end tag': u'{/su}', u'end html': u'', + u'protected': True}) +html_expands.append({u'desc': u'Subscript', u'start tag': u'{sb}', + u'start html': u'', u'end tag': u'{/sb}', u'end html': u'', + u'protected': True}) +html_expands.append({u'desc': u'Paragraph', u'start tag': u'{p}', + u'start html': u'

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

', + u'protected': True}) +html_expands.append({u'desc': u'Bold', u'start tag': u'{st}', + u'start html': u'', u'end tag': u'{/st}', u'end html': u'', + u'protected': True}) +html_expands.append({u'desc': u'Italics', u'start tag': u'{it}', + u'start html': u'', u'end tag': u'{/it}', u'end html': u'', + u'protected': True}) +html_expands.append({u'desc': u'Underline', u'start tag': u'{u}', + u'start html': u'', + u'end tag': u'{/u}', u'end html': u'', u'protected': True}) def translate(context, text, comment=None): """ @@ -303,6 +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 spelltextedit import SpellTextEdit from eventreceiver import Receiver from imagemanager import ImageManager @@ -317,7 +322,6 @@ from htmlbuilder import build_html, build_lyrics_format_css, \ build_lyrics_outline_css from toolbar import OpenLPToolbar from dockwidget import OpenLPDockWidget -from theme import ThemeLevel, ThemeXML from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index e59a9737b..8afa02111 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -158,6 +158,27 @@ class Manager(object): log.exception(u'Object save failed') return False + def save_objects(self, object_list, commit=True): + """ + Save a list of objects to the database + + ``object_list`` + The list of objects to save + + ``commit`` + Commit the session with this object + """ + try: + self.session.add_all(object_list) + if commit: + self.session.commit() + self.is_dirty = True + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object list save failed') + return False + def get_object(self, object_class, key=None): """ Return the details of an object @@ -207,6 +228,22 @@ class Manager(object): return query.order_by(order_by_ref).all() return query.all() + def get_object_count(self, object_class, filter_clause=None): + """ + Returns a count of the number of objects in the database. + + ``object_class`` + The type of objects to return. + + ``filter_clause`` + The filter governing selection of objects to return. Defaults to + None. + """ + query = self.session.query(object_class) + if filter_clause is not None: + query = query.filter(filter_clause) + return query.count() + def delete_object(self, object_class, key): """ Delete an object from the database @@ -257,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 dc3a48565..9bbaa65d1 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -25,8 +25,11 @@ ############################################################################### import logging + from PyQt4 import QtWebKit +from openlp.core.lib import BackgroundType, BackgroundGradientType + log = logging.getLogger(__name__) HTMLSRC = u""" @@ -368,16 +371,36 @@ def build_background_css(item, width, height): theme = item.themedata background = u'background-color: black' if theme: - if theme.background_type == u'solid': + if theme.background_type == \ + BackgroundType.to_string(BackgroundType.Solid): background = u'background-color: %s' % theme.background_color else: - if theme.background_direction == u'horizontal': + if theme.background_direction == BackgroundGradientType.to_string \ + (BackgroundGradientType.Horizontal): background = \ u'background: ' \ u'-webkit-gradient(linear, left top, left bottom, ' \ 'from(%s), to(%s))' % (theme.background_start_color, theme.background_end_color) - elif theme.background_direction == u'vertical': + 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 \ + (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 \ + (BackgroundGradientType.Vertical): background = \ u'background: -webkit-gradient(linear, left top, ' \ u'right top, from(%s), to(%s))' % \ @@ -452,17 +475,17 @@ def build_lyrics_css(item, webkitvers): lyricsmain += build_lyrics_outline_css(theme) else: outline = build_lyrics_outline_css(theme) - if theme.display_shadow: - if theme.display_outline and webkitvers < 534.3: + if theme.font_main_shadow: + if theme.font_main_outline and webkitvers < 534.3: shadow = u'padding-left: %spx; padding-top: %spx;' % \ - (int(theme.display_shadow_size) + - (int(theme.display_outline_size) * 2), - theme.display_shadow_size) + (int(theme.font_main_shadow_size) + + (int(theme.font_main_outline_size) * 2), + theme.font_main_shadow_size) shadow += build_lyrics_outline_css(theme, True) else: lyricsmain += u' text-shadow: %s %spx %spx;' % \ - (theme.display_shadow_color, theme.display_shadow_size, - theme.display_shadow_size) + (theme.font_main_shadow_color, theme.font_main_shadow_size, + theme.font_main_shadow_size) lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow) return lyrics_css @@ -477,14 +500,14 @@ def build_lyrics_outline_css(theme, is_shadow=False): `is_shadow` If true, use the shadow colors instead """ - if theme.display_outline: - size = float(theme.display_outline_size) / 16 + if theme.font_main_outline: + size = float(theme.font_main_outline_size) / 16 if is_shadow: - fill_color = theme.display_shadow_color - outline_color = theme.display_shadow_color + fill_color = theme.font_main_shadow_color + outline_color = theme.font_main_shadow_color else: fill_color = theme.font_main_color - outline_color = theme.display_outline_color + outline_color = theme.font_main_outline_color return u' -webkit-text-stroke: %sem %s; ' \ u'-webkit-text-fill-color: %s; ' % (size, outline_color, fill_color) else: @@ -517,23 +540,23 @@ def build_lyrics_format_css(theme, width, height): valign = u'middle' else: valign = u'top' - if theme.display_outline: - left_margin = int(theme.display_outline_size) * 2 + if theme.font_main_outline: + left_margin = int(theme.font_main_outline_size) * 2 else: left_margin = 0 lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \ 'text-align: %s; vertical-align: %s; font-family: %s; ' \ 'font-size: %spt; color: %s; line-height: %d%%; margin:0;' \ 'padding:0; padding-left:%spx; width: %spx; height: %spx; ' % \ - (align, valign, theme.font_main_name, theme.font_main_proportion, + (align, valign, theme.font_main_name, theme.font_main_size, theme.font_main_color, 100 + int(theme.font_main_line_adjustment), left_margin, width, height) - if theme.display_outline: + if theme.font_main_outline: if webkit_version() < 534.3: lyrics += u' letter-spacing: 1px;' if theme.font_main_italics: lyrics += u' font-style:italic; ' - if theme.font_main_weight == u'Bold': + if theme.font_main_bold: lyrics += u' font-weight:bold; ' return lyrics @@ -553,7 +576,7 @@ def build_lyrics_html(item, webkitvers): # display:table/display:table-cell are required for each lyric block. lyrics = u'' theme = item.themedata - if webkitvers < 534.4 and theme and theme.display_outline: + if webkitvers < 534.4 and theme and theme.font_main_outline: lyrics += u'
' \ u'
' @@ -589,7 +612,7 @@ def build_footer_css(item, height): bottom = height - int(item.footer.y()) - int(item.footer.height()) lyrics_html = style % (item.footer.x(), bottom, item.footer.width(), theme.font_footer_name, - theme.font_footer_proportion, theme.font_footer_color) + theme.font_footer_size, theme.font_footer_color) return lyrics_html def build_alert_css(alertTab, width): diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 0e0660bda..307ee84df 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): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 2d563962e..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,36 +506,36 @@ 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 + # Turn off the remote edit update message indicator QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'Invalid Service Item'), 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/renderer.py b/openlp/core/lib/renderer.py index f9a768205..68839f16d 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -32,7 +32,7 @@ import logging from PyQt4 import QtWebKit from openlp.core.lib import expand_tags, build_lyrics_format_css, \ - build_lyrics_outline_css + build_lyrics_outline_css, Receiver log = logging.getLogger(__name__) @@ -77,9 +77,9 @@ class Renderer(object): self._rect_footer = rect_footer self.page_width = self._rect.width() self.page_height = self._rect.height() - if self._theme.display_shadow: - self.page_width -= int(self._theme.display_shadow_size) - self.page_height -= int(self._theme.display_shadow_size) + if self._theme.font_main_shadow: + self.page_width -= int(self._theme.font_main_shadow_size) + self.page_height -= int(self._theme.font_main_shadow_size) self.web = QtWebKit.QWebView() self.web.setVisible(False) self.web.resize(self.page_width, self.page_height) @@ -92,13 +92,20 @@ class Renderer(object): (build_lyrics_format_css(self._theme, self.page_width, self.page_height), build_lyrics_outline_css(self._theme)) - def format_slide(self, words, line_break): + def format_slide(self, words, line_break, force_page=False): """ Figure out how much text can appear on a slide, using the current theme settings. ``words`` The words to be fitted on the slide. + + ``line_break`` + Add line endings after each line of text used for bibles. + + ``force_page`` + Flag to tell message lines in page. + """ log.debug(u'format_slide - Start') line_end = u'' @@ -114,13 +121,19 @@ class Renderer(object): formatted = [] html_text = u'' styled_text = u'' + line_count = 0 for line in text: + if line_count != -1: + line_count += 1 styled_line = expand_tags(line) + line_end styled_text += styled_line html = self.page_shell + styled_text + u'' self.web.setHtml(html) # Text too long so go to next page if self.web_frame.contentsSize().height() > self.page_height: + if force_page and line_count > 0: + Receiver.send_message(u'theme_line_count', line_count) + line_count = -1 if html_text.endswith(u'
'): html_text = html_text[:len(html_text)-4] formatted.append(html_text) diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index bf561b4b3..81cde12a0 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -67,8 +67,9 @@ class RenderManager(object): self.service_theme = u'' self.theme_level = u'' self.override_background = None - self.themedata = None + self.theme_data = None self.alertTab = None + self.force_page = False def update_display(self): """ @@ -80,7 +81,7 @@ class RenderManager(object): self.display.imageManager = self.image_manager self.display.setup() self.renderer.bg_frame = None - self.themedata = None + self.theme_data = None self.image_manager.update_display(self.width, self.height) def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): @@ -99,7 +100,7 @@ class RenderManager(object): self.theme_level = theme_level self.global_theme_data = \ self.theme_manager.getThemeData(self.global_theme) - self.themedata = None + self.theme_data = None def set_service_theme(self, service_theme): """ @@ -109,7 +110,7 @@ class RenderManager(object): The service-level theme to be set. """ self.service_theme = service_theme - self.themedata = None + self.theme_data = None def set_override_theme(self, theme, overrideLevels=False): """ @@ -146,19 +147,19 @@ class RenderManager(object): self.theme = self.service_theme else: self.theme = self.global_theme - if self.theme != self.renderer.theme_name or self.themedata is None \ + if self.theme != self.renderer.theme_name or self.theme_data is None \ or overrideLevels: log.debug(u'theme is now %s', self.theme) # Force the theme to be the one passed in. if overrideLevels: - self.themedata = theme + self.theme_data = theme else: - self.themedata = self.theme_manager.getThemeData(self.theme) + self.theme_data = self.theme_manager.getThemeData(self.theme) self.calculate_default(self.screens.current[u'size']) - self.renderer.set_theme(self.themedata) - self.build_text_rectangle(self.themedata) - self.image_manager.add_image(self.themedata.theme_name, - self.themedata.background_filename) + self.renderer.set_theme(self.theme_data) + self.build_text_rectangle(self.theme_data) + self.image_manager.add_image(self.theme_data.theme_name, + self.theme_data.background_filename) return self.renderer._rect, self.renderer._rect_footer def build_text_rectangle(self, theme): @@ -187,14 +188,19 @@ class RenderManager(object): theme.font_footer_height - 1) self.renderer.set_text_rectangle(main_rect, footer_rect) - def generate_preview(self, themedata): + def generate_preview(self, theme_data, force_page=False): """ Generate a preview of a theme. - ``themedata`` + ``theme_data`` The theme to generated a preview for. + + ``force_page`` + Flag to tell message lines per page need to be generated. """ log.debug(u'generate preview') + # save value for use in format_slide + self.force_page = force_page # set the default image size for previews self.calculate_default(self.screens.preview[u'size']) verse = u'The Lord said to {r}Noah{/r}: \n' \ @@ -204,23 +210,27 @@ class RenderManager(object): 'Get those children out of the muddy, muddy \n' \ '{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \ 'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n' + # make big page for theme edit dialog to get line count + if self.force_page: + verse = verse + verse + verse footer = [] footer.append(u'Arky Arky (Unknown)' ) footer.append(u'Public Domain') footer.append(u'CCLI 123456') # build a service item to generate preview serviceItem = ServiceItem() - serviceItem.theme = themedata + serviceItem.theme = theme_data serviceItem.add_from_text(u'', verse, footer) serviceItem.render_manager = self serviceItem.raw_footer = footer serviceItem.render(True) - self.display.buildHtml(serviceItem) - raw_html = serviceItem.get_rendered_frame(0) - preview = self.display.text(raw_html) - # Reset the real screen size for subsequent render requests - self.calculate_default(self.screens.current[u'size']) - return preview + if not self.force_page: + self.display.buildHtml(serviceItem) + raw_html = serviceItem.get_rendered_frame(0) + preview = self.display.text(raw_html) + # Reset the real screen size for subsequent render requests + self.calculate_default(self.screens.current[u'size']) + return preview def format_slide(self, words, line_break): """ @@ -228,9 +238,12 @@ class RenderManager(object): ``words`` The words to go on the slides. + + ``line_break`` + Add line endings after each line of text used for bibles. """ log.debug(u'format slide') - return self.renderer.format_slide(words, line_break) + return self.renderer.format_slide(words, line_break, self.force_page) def calculate_default(self, screen): """ diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index ab57e4328..b9394030a 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -100,6 +100,8 @@ class ServiceItem(object): self.bg_image_bytes = None self.search_string = u'' self.data_string = u'' + self.edit_id = None + self.xml_version = None self._new_item() def _new_item(self): @@ -251,7 +253,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: @@ -293,6 +296,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 fcd3c60ab..130eb817d 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -28,52 +28,55 @@ Provide the theme XML and handling functions for OpenLP v2 themes. """ import os 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 +log = logging.getLogger(__name__) + BLANK_THEME_XML = \ ''' - BlankStyle - - - #000000 + + + - + #000000 #000000 vertical - - + + #000000 Arial - #000000 - 30 - Normal + #FFFFFF + 40 + False False 0 + True + False Arial - #000000 - 12 - Normal + #FFFFFF + 12 + False False 0 + True + False - True - False 0 0 - 0 False @@ -87,10 +90,76 @@ class ThemeLevel(object): Service = 2 Song = 3 +class BackgroundType(object): + Solid = 0 + Gradient = 1 + Image = 2 + + @staticmethod + def to_string(type): + if type == BackgroundType.Solid: + return u'solid' + elif type == BackgroundType.Gradient: + return u'gradient' + elif type == BackgroundType.Image: + return u'image' + + @staticmethod + def from_string(type_string): + if type_string == u'solid': + return BackgroundType.Solid + elif type_string == u'gradient': + return BackgroundType.Gradient + elif type_string == u'image': + return BackgroundType.Image + +class BackgroundGradientType(object): + Horizontal = 0 + Vertical = 1 + Circular = 2 + LeftTop = 3 + LeftBottom = 4 + + @staticmethod + def to_string(type): + if type == BackgroundGradientType.Horizontal: + return u'horizontal' + elif type == BackgroundGradientType.Vertical: + return u'vertical' + elif type == BackgroundGradientType.Circular: + return u'circular' + elif type == BackgroundGradientType.LeftTop: + return u'leftTop' + elif type == BackgroundGradientType.LeftBottom: + return u'leftBottom' + + @staticmethod + def from_string(type_string): + if type_string == u'horizontal': + return BackgroundGradientType.Horizontal + elif type_string == u'vertical': + return BackgroundGradientType.Vertical + elif type_string == u'circular': + return BackgroundGradientType.Circular + elif type_string == u'leftTop': + return BackgroundGradientType.LeftTop + elif type_string == u'leftBottom': + return BackgroundGradientType.LeftBottom + +class HorizontalType(object): + Left = 0 + Center = 1 + Right = 2 + +class VerticalType(object): + Top = 0 + Middle = 1 + Bottom = 2 + boolean_list = [u'italics', u'override', u'outline', u'shadow', u'slide_transition'] -integer_list = [u'proportion', u'line_adjustment', u'x', u'height', u'y', +integer_list = [u'size', u'line_adjustment', u'x', u'height', u'y', u'width', u'shadow_size', u'outline_size', u'horizontal_align', u'vertical_align', u'wrap_style'] @@ -104,6 +173,7 @@ class ThemeXML(object): """ # Create the minidom document self.theme_xml = Document() + self.parse_xml(BLANK_THEME_XML) def extend_image_filename(self, path): """ @@ -112,19 +182,21 @@ class ThemeXML(object): ``path`` The path name to be added. """ - if self.background_filename and path: - self.theme_name = self.theme_name.strip() - self.background_filename = self.background_filename.strip() - self.background_filename = os.path.join(path, self.theme_name, - self.background_filename) + if self.background_type == u'image': + if self.background_filename and path: + self.theme_name = self.theme_name.strip() + self.background_filename = self.background_filename.strip() + self.background_filename = os.path.join(path, self.theme_name, + self.background_filename) - def new_document(self, name): + def _new_document(self, name): """ Create a new theme XML document. """ + self.theme_xml = Document() self.theme = self.theme_xml.createElement(u'theme') self.theme_xml.appendChild(self.theme) - self.theme.setAttribute(u'version', u'1.0') + self.theme.setAttribute(u'version', u'2.0') self.name = self.theme_xml.createElement(u'name') text_node = self.theme_xml.createTextNode(name) self.name.appendChild(text_node) @@ -146,10 +218,9 @@ class ThemeXML(object): The color of the background. """ background = self.theme_xml.createElement(u'background') - background.setAttribute(u'mode', u'opaque') background.setAttribute(u'type', u'solid') self.theme.appendChild(background) - self.child_element(background, u'color', bkcolor) + self.child_element(background, u'color', unicode(bkcolor)) def add_background_gradient(self, startcolor, endcolor, direction): """ @@ -165,15 +236,14 @@ class ThemeXML(object): The direction of the gradient. """ background = self.theme_xml.createElement(u'background') - background.setAttribute(u'mode', u'opaque') background.setAttribute(u'type', u'gradient') self.theme.appendChild(background) # Create startColor element - self.child_element(background, u'startColor', startcolor) + self.child_element(background, u'startColor', unicode(startcolor)) # Create endColor element - self.child_element(background, u'endColor', endcolor) + self.child_element(background, u'endColor', unicode(endcolor)) # Create direction element - self.child_element(background, u'direction', direction) + self.child_element(background, u'direction', unicode(direction)) def add_background_image(self, filename): """ @@ -183,15 +253,16 @@ class ThemeXML(object): The file name of the image. """ background = self.theme_xml.createElement(u'background') - background.setAttribute(u'mode', u'opaque') background.setAttribute(u'type', u'image') self.theme.appendChild(background) - #Create Filename element + # Create Filename element self.child_element(background, u'filename', filename) - def add_font(self, name, color, proportion, override, fonttype=u'main', - weight=u'Normal', italics=u'False', line_adjustment=0, - xpos=0, ypos=0, width=0, height=0): + 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): """ Add a Font. @@ -201,7 +272,7 @@ class ThemeXML(object): ``color`` The colour of the font. - ``proportion`` + ``size`` The size of the font. ``override`` @@ -227,45 +298,6 @@ class ThemeXML(object): ``height`` The height of the text block. - """ - background = self.theme_xml.createElement(u'font') - background.setAttribute(u'type', fonttype) - self.theme.appendChild(background) - #Create Font name element - self.child_element(background, u'name', name) - #Create Font color element - self.child_element(background, u'color', color) - #Create Proportion name element - self.child_element(background, u'proportion', proportion) - #Create weight name element - self.child_element(background, u'weight', weight) - #Create italics name element - self.child_element(background, u'italics', italics) - #Create indentation name element - self.child_element( - background, u'line_adjustment', unicode(line_adjustment)) - - #Create Location element - element = self.theme_xml.createElement(u'location') - element.setAttribute(u'override', override) - if override == u'True': - element.setAttribute(u'x', xpos) - element.setAttribute(u'y', ypos) - element.setAttribute(u'width', width) - element.setAttribute(u'height', height) - background.appendChild(element) - - def add_display(self, shadow, shadow_color, outline, outline_color, - horizontal, vertical, wrap, transition, shadow_pixel=5, - outline_pixel=2): - """ - Add a Display options. - - ``shadow`` - Whether or not to show a shadow. - - ``shadow_color`` - The colour of the shadow. ``outline`` Whether or not to show an outline. @@ -273,53 +305,87 @@ class ThemeXML(object): ``outline_color`` The colour of the outline. + ``outline_size`` + How big the Shadow is + + ``shadow`` + Whether or not to show a shadow. + + ``shadow_color`` + The colour of the shadow. + + ``shadow_size`` + How big the Shadow is + + """ + background = self.theme_xml.createElement(u'font') + background.setAttribute(u'type', fonttype) + self.theme.appendChild(background) + # Create Font name element + self.child_element(background, u'name', name) + # Create Font color element + self.child_element(background, u'color', unicode(color)) + # Create Proportion name element + self.child_element(background, u'size', unicode(size)) + # Create weight name element + self.child_element(background, u'bold', unicode(bold)) + # Create italics name element + self.child_element(background, u'italics', unicode(italics)) + # Create indentation name element + self.child_element( + background, u'line_adjustment', unicode(line_adjustment)) + # Create Location element + element = self.theme_xml.createElement(u'location') + element.setAttribute(u'override', unicode(override)) + element.setAttribute(u'x', unicode(xpos)) + element.setAttribute(u'y', unicode(ypos)) + element.setAttribute(u'width', unicode(width)) + element.setAttribute(u'height', unicode(height)) + background.appendChild(element) + # Shadow + element = self.theme_xml.createElement(u'shadow') + element.setAttribute(u'shadowColor', unicode(shadow_color)) + element.setAttribute(u'shadowSize', unicode(shadow_pixel)) + value = self.theme_xml.createTextNode(unicode(shadow)) + element.appendChild(value) + background.appendChild(element) + # Outline + element = self.theme_xml.createElement(u'outline') + element.setAttribute(u'outlineColor', unicode(outline_color)) + element.setAttribute(u'outlineSize', unicode(outline_pixel)) + value = self.theme_xml.createTextNode(unicode(outline)) + element.appendChild(value) + background.appendChild(element) + + def add_display(self, horizontal, vertical, transition): + """ + Add a Display options. + ``horizontal`` The horizontal alignment of the text. ``vertical`` The vertical alignment of the text. - ``wrap`` - Wrap style. - ``transition`` Whether the slide transition is active. """ background = self.theme_xml.createElement(u'display') self.theme.appendChild(background) - # Shadow - element = self.theme_xml.createElement(u'shadow') - element.setAttribute(u'color', shadow_color) - element.setAttribute(u'size', unicode(shadow_pixel)) - value = self.theme_xml.createTextNode(shadow) - element.appendChild(value) - background.appendChild(element) - # Outline - element = self.theme_xml.createElement(u'outline') - element.setAttribute(u'color', outline_color) - element.setAttribute(u'size', unicode(outline_pixel)) - value = self.theme_xml.createTextNode(outline) - element.appendChild(value) - background.appendChild(element) # Horizontal alignment element = self.theme_xml.createElement(u'horizontalAlign') - value = self.theme_xml.createTextNode(horizontal) + value = self.theme_xml.createTextNode(unicode(horizontal)) element.appendChild(value) background.appendChild(element) # Vertical alignment element = self.theme_xml.createElement(u'verticalAlign') - value = self.theme_xml.createTextNode(vertical) - element.appendChild(value) - background.appendChild(element) - # Wrap style - element = self.theme_xml.createElement(u'wrapStyle') - value = self.theme_xml.createTextNode(wrap) + value = self.theme_xml.createTextNode(unicode(vertical)) element.appendChild(value) background.appendChild(element) # Slide Transition element = self.theme_xml.createElement(u'slideTransition') - value = self.theme_xml.createTextNode(transition) + value = self.theme_xml.createTextNode(unicode(transition)) element.appendChild(value) background.appendChild(element) @@ -342,12 +408,14 @@ class ThemeXML(object): """ Print out the XML string. """ + self._build_xml_from_attrs() return self.theme_xml.toxml(u'utf-8').decode(u'utf-8') def extract_formatted_xml(self): """ Pull out the XML string formatted for human consumption """ + self._build_xml_from_attrs() return self.theme_xml.toprettyxml(indent=u' ', newl=u'\n', encoding=u'utf-8') @@ -358,8 +426,7 @@ class ThemeXML(object): ``xml`` The XML string to parse. """ - self.parse_xml(BLANK_THEME_XML) - self.parse_xml(xml) + self.parse_xml(unicode(xml)) def parse_xml(self, xml): """ @@ -368,51 +435,97 @@ class ThemeXML(object): ``xml`` The XML string to parse. """ - theme_xml = ElementTree(element=XML(xml.encode(u'ascii', - u'xmlcharrefreplace'))) + # remove encoding string + line = xml.find(u'?>') + if line: + xml = xml[line + 2:] + try: + theme_xml = objectify.fromstring(xml) + except etree.XMLSyntaxError: + log.exception(u'Invalid xml %s', xml) + return xml_iter = theme_xml.getiterator() - master = u'' for element in xml_iter: - if not isinstance(element.text, unicode): - element.text = unicode(str(element.text), u'utf-8') - if element.getchildren(): - master = element.tag + u'_' + parent = element.getparent() + master = u'' + if parent is not None: + if element.getparent().tag == u'font': + master = element.getparent().tag + u'_' + \ + element.getparent().attrib[u'type'] + # set up Outline and Shadow Tags and move to font_main + 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) + master = element.getparent().tag + if element.getparent().tag == u'background': + master = element.getparent().tag + if element.getparent().attrib: + for attr in element.getparent().attrib: + self._create_attr(master, attr, \ + element.getparent().attrib[attr]) + if master: + self._create_attr(master, element.tag, element.text) + if element.attrib: + 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 not attr.startswith(element.tag): + base_element = element.tag + u'_' + attr + self._create_attr(master, base_element, + element.attrib[attr]) else: - # background transparent tags have no children so special case - if element.tag == u'background': - for e in element.attrib.iteritems(): - self._create_attr(element.tag , e[0], e[1]) - if element.attrib: - for e in element.attrib.iteritems(): - if master == u'font_' and e[0] == u'type': - master += e[1] + u'_' - elif master == u'display_' and (element.tag == u'shadow' - or element.tag == u'outline'): - self._create_attr(master, element.tag, element.text) - self._create_attr(master, element.tag + u'_'+ e[0], - e[1]) - else: - field = master + e[0] - self._create_attr(master, e[0], e[1]) + if element.tag == u'name': + self._create_attr(u'theme', element.tag, element.text) + + def _translate_tags(self, master, element, value): + """ + Clean up XML removing and redefining tags + """ + master = master.strip().lstrip() + element = element.strip().lstrip() + value = unicode(value).strip().lstrip() + if master == u'display': + if element == u'wrapStyle': + return True, None, None, None + if element.startswith(u'shadow') or element.startswith(u'outline'): + master = u'font_main' + # fix bold font + if element == u'weight': + element = u'bold' + if value == u'Normal': + value = False else: - if element.tag: - element.text = element.text.strip().lstrip() - self._create_attr(master , element.tag, element.text) + value = True + if element == u'proportion': + element = u'size' + return False, master, element, value def _create_attr(self, master , element, value): """ Create the attributes with the correct data types and name format """ + reject, master, element, value = \ + self._translate_tags(master, element, value) + if reject: + return field = self._de_hump(element) + tag = master + u'_' + field if field in boolean_list: - setattr(self, master + field, str_to_bool(value)) + setattr(self, tag, str_to_bool(value)) elif field in integer_list: - setattr(self, master + field, int(value)) + setattr(self, tag, int(value)) else: + # make string value unicode + if not isinstance(value, unicode): + value = unicode(str(value), u'utf-8') # None means an empty string so lets have one. if value == u'None': value = u'' - setattr(self, master + field, unicode(value)) + setattr(self, tag, unicode(value).strip().lstrip()) def __str__(self): """ @@ -428,6 +541,61 @@ 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): + """ + Build the XML from the varables in the object + """ + self._new_document(self.theme_name) + if self.background_type == \ + BackgroundType.to_string(BackgroundType.Solid): + self.add_background_solid(self.background_color) + elif self.background_type == \ + BackgroundType.to_string(BackgroundType.Gradient): + self.add_background_gradient( + self.background_start_color, + self.background_end_color, + self.background_direction) + else: + filename = \ + os.path.split(self.background_filename)[1] + self.add_background_image(filename) + self.add_font(self.font_main_name, + self.font_main_color, + self.font_main_size, + self.font_main_override, u'main', + self.font_main_bold, + self.font_main_italics, + self.font_main_line_adjustment, + self.font_main_x, + self.font_main_y, + self.font_main_width, + self.font_main_height, + self.font_main_outline, + self.font_main_outline_color, + self.font_main_outline_size, + self.font_main_shadow, + self.font_main_shadow_color, + self.font_main_shadow_size) + self.add_font(self.font_footer_name, + self.font_footer_color, + self.font_footer_size, + self.font_footer_override, u'footer', + self.font_footer_bold, + self.font_footer_italics, + 0, # line adjustment + self.font_footer_x, + self.font_footer_y, + self.font_footer_width, + self.font_footer_height, + self.font_footer_outline, + self.font_footer_outline_color, + self.font_footer_outline_size, + self.font_footer_shadow, + self.font_footer_shadow_color, + self.font_footer_shadow_size) + self.add_display(self.display_horizontal_align, + self.display_vertical_align, + self.display_slide_transition) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 37265f3d1..377999553 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -37,12 +37,12 @@ class HideMode(object): Theme = 2 Screen = 3 +from themeform import ThemeForm from filerenameform import FileRenameForm from maindisplay import MainDisplay from servicenoteform import ServiceNoteForm from serviceitemeditform import ServiceItemEditForm from screen import ScreenList -from amendthemeform import AmendThemeForm from slidecontroller import SlideController from splashscreen import SplashScreen from generaltab import GeneralTab @@ -58,4 +58,4 @@ from thememanager import ThemeManager __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', - 'AmendThemeForm', 'MediaDockManager', 'ServiceItemEditForm'] + 'MediaDockManager', 'ServiceItemEditForm'] diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index ffcade344..df3add595 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -81,6 +81,10 @@ class AdvancedTab(SettingsTab): self.doubleClickLiveCheckBox = QtGui.QCheckBox(self.uiGroupBox) self.doubleClickLiveCheckBox.setObjectName(u'doubleClickLiveCheckBox') self.uiLayout.addWidget(self.doubleClickLiveCheckBox) +# self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox) +# self.expandServiceItemCheckBox.setObjectName( +# u'expandServiceItemCheckBox') +# self.uiLayout.addWidget(self.expandServiceItemCheckBox) self.leftLayout.addWidget(self.uiGroupBox) self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox) self.expandServiceItemCheckBox.setObjectName( @@ -143,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 1e0404f10..000000000 --- a/openlp/core/ui/amendthemeform.py +++ /dev/null @@ -1,717 +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.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) - QtCore.QObject.connect(self.shadowSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onShadowSpinBoxChanged) - QtCore.QObject.connect(self.outlineSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onOutlineSpinBoxChanged) - # 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.fontMainComboBox.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/maindisplay.py b/openlp/core/ui/maindisplay.py index 84b484878..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 @@ -36,6 +37,7 @@ from openlp.core.ui import HideMode log = logging.getLogger(__name__) #http://www.steveheffernan.com/html5-video-player/demo-video-player.html +#http://html5demos.com/two-videos class DisplayWidget(QtGui.QGraphicsView): """ @@ -99,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 | @@ -228,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): @@ -380,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) @@ -411,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): """ @@ -443,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): """ @@ -458,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 c63f3a7fc..3833f1697 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -627,7 +627,7 @@ 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) @@ -635,7 +635,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # 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'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 @@ -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() @@ -855,7 +855,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.plugin_manager.finalise_plugins() # Save settings self.saveSettings() - #Close down the display + # Close down the display self.LiveController.display.close() def serviceChanged(self, reset=False, serviceName=None): diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 98494861a..85dff6b91 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -116,6 +116,7 @@ class ServiceManager(QtGui.QWidget): self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) self.layout.setMargin(0) + self.expandTabs = False # Create the top toolbar self.toolbar = OpenLPToolbar(self) self.toolbar.addToolbarButton( @@ -307,7 +308,7 @@ class ServiceManager(QtGui.QWidget): self.maintainAction.setVisible(False) self.notesAction.setVisible(False) if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit)\ - and hasattr(serviceItem[u'service_item'], u'editId'): + and serviceItem[u'service_item'].edit_id: self.editAction.setVisible(True) if serviceItem[u'service_item']\ .is_capable(ItemCapabilities.AllowsMaintain): @@ -758,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) @@ -788,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): """ @@ -817,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)) @@ -829,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: @@ -843,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() @@ -863,7 +866,7 @@ class ServiceManager(QtGui.QWidget): editId, uuid = message.split(u':') for item in self.serviceItems: if item[u'service_item']._uuid == uuid: - item[u'service_item'].editId = editId + item[u'service_item'].edit_id = editId def replaceServiceItem(self, newItem): """ @@ -872,7 +875,7 @@ class ServiceManager(QtGui.QWidget): """ newItem.render() for itemcount, item in enumerate(self.serviceItems): - if item[u'service_item'].editId == newItem.editId and \ + if item[u'service_item'].edit_id == newItem.edit_id and \ item[u'service_item'].name == newItem.name: newItem.merge(item[u'service_item']) item[u'service_item'] = newItem @@ -890,8 +893,8 @@ class ServiceManager(QtGui.QWidget): ``expand`` Override the default expand settings. (Tristate) """ - log.debug(u'addServiceItem') - if expand == None: + # if not passed set to config value + if expand is None: expand = self.expandTabs sitem = self.findServiceItem()[0] item.render() @@ -982,7 +985,7 @@ class ServiceManager(QtGui.QWidget): .is_capable(ItemCapabilities.AllowsEdit): Receiver.send_message(u'%s_edit' % self.serviceItems[item][u'service_item'].name.lower(), u'L:%s' % - self.serviceItems[item][u'service_item'].editId ) + self.serviceItems[item][u'service_item'].edit_id ) def findServiceItem(self): """ @@ -1027,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: @@ -1082,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 61fc78cd3..f667c6d3c 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(): @@ -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() @@ -942,7 +941,15 @@ class SlideController(QtGui.QWidget): """ self.songEdit = True Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(), - u'P:%s' % self.serviceItem.editId) + 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): """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py new file mode 100644 index 000000000..b091427bf --- /dev/null +++ b/openlp/core/ui/themeform.py @@ -0,0 +1,622 @@ +# -*- 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 + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import translate, BackgroundType, BackgroundGradientType, \ + Receiver +from openlp.core.utils import get_images_filter +from themewizard import Ui_ThemeWizard + +log = logging.getLogger(__name__) + +class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): + """ + This is the Bible Import Wizard, which allows easy importing of Bibles + into OpenLP from other formats like OSIS, CSV and OpenSong. + """ + log.info(u'ThemeWizardForm loaded') + + def __init__(self, parent): + """ + Instantiate the wizard, and run any extra setup we need to. + + ``parent`` + The QWidget-derived parent of the wizard. + """ + QtGui.QWizard.__init__(self, parent) + self.thememanager = parent + 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.colorButton, + QtCore.SIGNAL(u'pressed()'), + self.onColorButtonClicked) + QtCore.QObject.connect(self.gradientStartButton, + QtCore.SIGNAL(u'pressed()'), + self.onGradientStartButtonClicked) + QtCore.QObject.connect(self.gradientEndButton, + QtCore.SIGNAL(u'pressed()'), + self.onGradientEndButtonClicked) + QtCore.QObject.connect(self.imageBrowseButton, + QtCore.SIGNAL(u'pressed()'), + self.onImageBrowseButtonClicked) + QtCore.QObject.connect(self.mainColorPushButton, + QtCore.SIGNAL(u'pressed()'), + self.onMainColourPushButtonClicked) + QtCore.QObject.connect(self.outlineColorPushButton, + QtCore.SIGNAL(u'pressed()'), + self.onOutlineColourPushButtonClicked) + QtCore.QObject.connect(self.shadowColorPushButton, + QtCore.SIGNAL(u'pressed()'), + self.onShadowColourPushButtonClicked) + QtCore.QObject.connect(self.outlineCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onOutlineCheckCheckBoxChanged) + QtCore.QObject.connect(self.shadowCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onShadowCheckCheckBoxChanged) + QtCore.QObject.connect(self.footerColorPushButton, + QtCore.SIGNAL(u'pressed()'), + self.onFooterColourPushButtonClicked) + QtCore.QObject.connect(self.mainDefaultPositionCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onMainDefaultPositionCheckBox) + QtCore.QObject.connect(self.footerDefaultPositionCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onFooterDefaultPositionCheckBox) + QtCore.QObject.connect(self, + QtCore.SIGNAL(u'currentIdChanged(int)'), + self.pageChanged) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'theme_line_count'), + self.updateLinesText) + QtCore.QObject.connect(self.mainSizeSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.calculateLines) + QtCore.QObject.connect(self.mainSizeSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.calculateLines) + QtCore.QObject.connect(self.lineSpacingSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.calculateLines) + QtCore.QObject.connect(self.lineSpacingSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.calculateLines) + QtCore.QObject.connect(self.outlineSizeSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.calculateLines) + QtCore.QObject.connect(self.outlineSizeSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.calculateLines) + QtCore.QObject.connect(self.shadowSizeSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.calculateLines) + QtCore.QObject.connect(self.shadowSizeSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.calculateLines) + QtCore.QObject.connect(self.mainFontComboBox, + QtCore.SIGNAL(u'activated(int)'), + self.calculateLines) + + def pageChanged(self, pageId): + """ + Detects Page changes and updates as approprate. + """ + if pageId == 6: + self.updateTheme() + frame = self.thememanager.generateImage(self.theme) + self.previewBoxLabel.setPixmap(QtGui.QPixmap.fromImage(frame)) + + def setDefaults(self): + """ + Set up display at start of theme edit. + """ + self.restart() + self.accepted = False + self.setBackgroundTabValues() + self.setMainAreaTabValues() + self.setFooterAreaTabValues() + self.setAlignmentTabValues() + self.setPositionTabValues() + self.setPreviewTabValues() + + def registerFields(self): + """ + Map field names to screen names, + """ + self.backgroundPage.registerField( + u'background_type', self.backgroundTypeComboBox) + self.backgroundPage.registerField( + u'color', self.colorButton) + self.backgroundPage.registerField( + 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'mainColorPushButton', self.mainColorPushButton) + self.mainAreaPage.registerField( + u'mainSizeSpinBox', self.mainSizeSpinBox) + self.mainAreaPage.registerField( + u'lineSpacingSpinBox', self.lineSpacingSpinBox) + self.mainAreaPage.registerField( + u'outlineCheckBox', self.outlineCheckBox) + self.mainAreaPage.registerField( + u'outlineColorPushButton', self.outlineColorPushButton) + self.mainAreaPage.registerField( + u'outlineSizeSpinBox', self.outlineSizeSpinBox) + self.mainAreaPage.registerField( + u'shadowCheckBox', self.shadowCheckBox) + self.mainAreaPage.registerField( + u'boldCheckBox', self.boldCheckBox) + self.mainAreaPage.registerField( + u'italicsCheckBox', self.italicsCheckBox) + self.mainAreaPage.registerField( + u'shadowColorPushButton', self.shadowColorPushButton) + self.mainAreaPage.registerField( + u'shadowSizeSpinBox', self.shadowSizeSpinBox) + self.mainAreaPage.registerField( + u'footerSizeSpinBox', self.footerSizeSpinBox) + self.areaPositionPage.registerField( + u'mainPositionX', self.mainXSpinBox) + self.areaPositionPage.registerField( + u'mainPositionY', self.mainYSpinBox) + self.areaPositionPage.registerField( + u'mainPositionWidth', self.mainWidthSpinBox) + self.areaPositionPage.registerField( + u'mainPositionHeight', self.mainHeightSpinBox) + self.areaPositionPage.registerField( + u'footerPositionX', self.footerXSpinBox) + self.areaPositionPage.registerField( + u'footerPositionY', self.footerYSpinBox) + self.areaPositionPage.registerField( + u'footerPositionWidth', self.footerWidthSpinBox) + self.areaPositionPage.registerField( + u'footerPositionHeight', self.footerHeightSpinBox) + self.backgroundPage.registerField( + u'horizontal', self.horizontalComboBox) + self.backgroundPage.registerField( + u'vertical', self.verticalComboBox) + self.backgroundPage.registerField( + u'slideTransition', self.transitionsCheckBox) + self.backgroundPage.registerField( + u'name', self.themeNameEdit) + + def calculateLines(self): + """ + Calculate the number of lines on a page by rendering text + """ + # Do not trigger on start up + if self.page != 0: + self.updateTheme() + frame = self.thememanager.generateImage(self.theme, True) + + def updateLinesText(self, lines): + """ + Updates the lines on a page on the wizard + """ + self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', \ + '(%d lines per slide)' % int(lines)))) + + def onOutlineCheckCheckBoxChanged(self, state): + """ + Change state as Outline check box changed + """ + if state == QtCore.Qt.Checked: + self.theme.font_main_outline = True + else: + self.theme.font_main_outline = False + self.outlineColorPushButton.setEnabled(self.theme.font_main_outline) + self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline) + self.calculateLines() + + def onShadowCheckCheckBoxChanged(self, state): + """ + Change state as Shadow check box changed + """ + if state == QtCore.Qt.Checked: + self.theme.font_main_shadow = True + else: + self.theme.font_main_shadow = False + self.shadowColorPushButton.setEnabled(self.theme.font_main_shadow) + self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow) + self.calculateLines() + + def onMainDefaultPositionCheckBox(self, value): + """ + Change state as Main Area Position check box changed + """ + if value == QtCore.Qt.Checked: + self.theme.font_main_override = False + else: + self.theme.font_main_override = True + self.mainXSpinBox.setEnabled(self.theme.font_main_override) + self.mainYSpinBox.setEnabled(self.theme.font_main_override) + self.mainHeightSpinBox.setEnabled(self.theme.font_main_override) + self.mainWidthSpinBox.setEnabled(self.theme.font_main_override) + + def onFooterDefaultPositionCheckBox(self, value): + """ + Change state as Footer Area Position check box changed + """ + if value == QtCore.Qt.Checked: + self.theme.font_footer_override = False + else: + self.theme.font_footer_override = True + self.footerXSpinBox.setEnabled(self.theme.font_footer_override) + self.footerYSpinBox.setEnabled(self.theme.font_footer_override) + self.footerHeightSpinBox.setEnabled(self.theme.font_footer_override) + self.footerWidthSpinBox.setEnabled(self.theme.font_footer_override) + + def exec_(self, edit=False): + """ + Run the wizard. + """ + self.updateThemeAllowed = False + self.setDefaults() + self.updateThemeAllowed = True + if edit: + self.next() + return QtGui.QWizard.exec_(self) + + def initializePage(self, id): + """ + Set up the pages for Initial run through dialog + """ + log.debug(u'initializePage %s' % id) + self.page = id + if id == 1: + self.setBackgroundTabValues() + elif id == 2: + self.setMainAreaTabValues() + elif id == 3: + self.setFooterAreaTabValues() + elif id == 4: + self.setAlignmentTabValues() + elif id == 5: + self.setPositionTabValues() + + def setBackgroundTabValues(self): + """ + Handle the display and State of the background display tab. + """ + if self.theme.background_type == \ + BackgroundType.to_string(BackgroundType.Solid): + self.colorButton.setStyleSheet(u'background-color: %s' % + self.theme.background_color) + self.setField(u'background_type', QtCore.QVariant(0)) + elif self.theme.background_type == \ + BackgroundType.to_string(BackgroundType.Gradient): + self.gradientStartButton.setStyleSheet(u'background-color: %s' % + self.theme.background_start_color) + self.gradientEndButton.setStyleSheet(u'background-color: %s' % + self.theme.background_end_color) + self.setField(u'background_type', QtCore.QVariant(1)) + else: + 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)) + elif self.theme.background_direction == \ + BackgroundGradientType.to_string(BackgroundGradientType.Vertical): + self.setField(u'gradient', QtCore.QVariant(1)) + elif self.theme.background_direction == \ + BackgroundGradientType.to_string(BackgroundGradientType.Circular): + self.setField(u'gradient', QtCore.QVariant(2)) + elif self.theme.background_direction == \ + BackgroundGradientType.to_string(BackgroundGradientType.LeftTop): + self.setField(u'gradient', QtCore.QVariant(3)) + else: + self.setField(u'gradient', QtCore.QVariant(4)) + + def setMainAreaTabValues(self): + """ + Handle the display and State of the Main Area tab. + """ + self.mainFontComboBox.setCurrentFont( + QtGui.QFont(self.theme.font_main_name)) + self.mainColorPushButton.setStyleSheet(u'background-color: %s' % + self.theme.font_main_color) + self.setField(u'mainSizeSpinBox', \ + QtCore.QVariant(self.theme.font_main_size)) + self.setField(u'lineSpacingSpinBox', \ + QtCore.QVariant(self.theme.font_main_line_adjustment)) + self.setField(u'outlineCheckBox', \ + QtCore.QVariant(self.theme.font_main_outline)) + self.outlineColorPushButton.setStyleSheet(u'background-color: %s' % + self.theme.font_main_outline_color) + self.setField(u'outlineSizeSpinBox', \ + QtCore.QVariant(self.theme.font_main_outline_size)) + self.setField(u'shadowCheckBox', \ + QtCore.QVariant(self.theme.font_main_shadow)) + self.shadowColorPushButton.setStyleSheet(u'background-color: %s' % + self.theme.font_main_shadow_color) + self.setField(u'shadowSizeSpinBox', \ + QtCore.QVariant(self.theme.font_main_shadow_size)) + self.setField(u'boldCheckBox', \ + QtCore.QVariant(self.theme.font_main_bold)) + self.setField(u'italicsCheckBox', \ + QtCore.QVariant(self.theme.font_main_italics)) + # Set up field states + if self.theme.font_main_outline: + self.setField(u'outlineCheckBox', QtCore.QVariant(False)) + else: + self.setField(u'outlineCheckBox', QtCore.QVariant(True)) + self.outlineColorPushButton.setEnabled(self.theme.font_main_outline) + self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline) + if self.theme.font_main_shadow: + self.setField(u'shadowCheckBox', QtCore.QVariant(False)) + else: + self.setField(u'shadowCheckBox', QtCore.QVariant(True)) + self.shadowColorPushButton.setEnabled(self.theme.font_main_shadow) + self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow) + + def setFooterAreaTabValues(self): + """ + Handle the display and State of the Footer Area tab. + """ + self.footerFontComboBox.setCurrentFont( + QtGui.QFont(self.theme.font_main_name)) + self.footerColorPushButton.setStyleSheet(u'background-color: %s' % + self.theme.font_footer_color) + self.setField(u'footerSizeSpinBox', \ + QtCore.QVariant(self.theme.font_footer_size)) + + def setPositionTabValues(self): + """ + Handle the display and State of the Position tab. + """ + # Main Area + if self.theme.font_main_override: + self.mainDefaultPositionCheckBox.setChecked(False) + else: + self.mainDefaultPositionCheckBox.setChecked(True) + self.setField(u'mainPositionX', \ + QtCore.QVariant(self.theme.font_main_x)) + self.setField(u'mainPositionY', \ + QtCore.QVariant(self.theme.font_main_y)) + self.setField(u'mainPositionHeight', \ + QtCore.QVariant(self.theme.font_main_height)) + self.setField(u'mainPositionWidth', \ + QtCore.QVariant(self.theme.font_main_width)) + # Footer + if self.theme.font_footer_override: + self.footerDefaultPositionCheckBox.setChecked(False) + else: + self.footerDefaultPositionCheckBox.setChecked(True) + self.setField(u'footerPositionX', \ + QtCore.QVariant(self.theme.font_footer_x)) + self.setField(u'footerPositionY', \ + QtCore.QVariant(self.theme.font_footer_y)) + self.setField(u'footerPositionHeight', \ + QtCore.QVariant(self.theme.font_footer_height)) + self.setField(u'footerPositionWidth', \ + QtCore.QVariant(self.theme.font_footer_width)) + + def setAlignmentTabValues(self): + """ + Define the Tab Alignments Page + """ + self.setField(u'horizontal', \ + QtCore.QVariant(self.theme.display_horizontal_align)) + self.setField(u'vertical', \ + QtCore.QVariant(self.theme.display_vertical_align)) + self.setField(u'slideTransition', \ + QtCore.QVariant(self.theme.display_slide_transition)) + + def setPreviewTabValues(self): + self.setField(u'name', QtCore.QVariant(self.theme.theme_name)) + if len(self.theme.theme_name) > 1: + self.themeNameEdit.setEnabled(False) + else: + self.themeNameEdit.setEnabled(True) + + def onBackgroundComboBox(self, index): + """ + Background style Combo box has changed. + """ + self.theme.background_type = BackgroundType.to_string(index) + self.setBackgroundTabValues() + + def onGradientComboBox(self, index): + """ + Background gradient Combo box has changed. + """ + self.theme.background_direction = \ + BackgroundGradientType.to_string(index) + self.setBackgroundTabValues() + + def onColorButtonClicked(self): + """ + Background / Gradient 1 Color button pushed. + """ + self.theme.background_color = \ + self._colorButton(self.theme.background_color) + self.setBackgroundTabValues() + + 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. + """ + self.theme.background_end_color = \ + self._colorButton(self.theme.background_end_color) + self.setBackgroundTabValues() + + def onImageBrowseButtonClicked(self): + """ + Background Image button pushed. + """ + images_filter = get_images_filter() + images_filter = '%s;;%s (*.*) (*)' % (images_filter, + translate('OpenLP.ThemeForm', 'All Files')) + filename = QtGui.QFileDialog.getOpenFileName(self, + translate('OpenLP.ThemeForm', 'Select Image'), u'', + images_filter) + if filename: + self.theme.background_filename = unicode(filename) + self.setBackgroundTabValues() + + def onMainColourPushButtonClicked(self): + self.theme.font_main_color = \ + self._colorButton(self.theme.font_main_color) + self.setMainAreaTabValues() + + def onOutlineColourPushButtonClicked(self): + self.theme.font_main_outline_color = \ + self._colorButton(self.theme.font_main_outline_color) + self.setMainAreaTabValues() + + def onShadowColourPushButtonClicked(self): + self.theme.font_main_shadow_color = \ + self._colorButton(self.theme.font_main_shadow_color) + self.setMainAreaTabValues() + + def onFooterColourPushButtonClicked(self): + self.theme.font_footer_color = \ + self._colorButton(self.theme.font_footer_color) + self.setFooterAreaTabValues() + + def updateTheme(self): + """ + 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 = \ + unicode(self.mainFontComboBox.currentFont().family()) + self.theme.font_main_size = \ + self.field(u'mainSizeSpinBox').toInt()[0] + self.theme.font_main_line_adjustment = \ + self.field(u'lineSpacingSpinBox').toInt()[0] + self.theme.font_main_outline_size = \ + self.field(u'outlineSizeSpinBox').toInt()[0] + self.theme.font_main_shadow_size = \ + self.field(u'shadowSizeSpinBox').toInt()[0] + self.theme.font_main_bold = \ + self.field(u'boldCheckBox').toBool() + self.theme.font_main_italics = \ + self.field(u'italicsCheckBox').toBool() + # footer page + self.theme.font_footer_name = \ + unicode(self.footerFontComboBox.currentFont().family()) + self.theme.font_footer_size = \ + self.field(u'footerSizeSpinBox').toInt()[0] + # position page + self.theme.font_main_x = self.field(u'mainPositionX').toInt()[0] + self.theme.font_main_y = self.field(u'mainPositionY').toInt()[0] + self.theme.font_main_height = \ + self.field(u'mainPositionHeight').toInt()[0] + self.theme.font_main_width = self.field(u'mainPositionWidth').toInt()[0] + self.theme.font_footer_x = self.field(u'footerPositionX').toInt()[0] + self.theme.font_footer_y = self.field(u'footerPositionY').toInt()[0] + self.theme.font_footer_height = \ + self.field(u'footerPositionHeight').toInt()[0] + self.theme.font_footer_width = \ + self.field(u'footerPositionWidth').toInt()[0] + # position page + self.theme.display_horizontal_align = \ + self.horizontalComboBox.currentIndex() + self.theme.display_vertical_align = \ + self.verticalComboBox.currentIndex() + self.theme.display_slide_transition = \ + self.field(u'slideTransition').toBool() + + def accept(self): + """ + Lets save the them as Finish has been pressed + """ + # Some reason getting double submission. + # Hack to stop it for now. + if self.accepted: + return + # Save the theme name + self.theme.theme_name = \ + unicode(self.field(u'name').toString()) + if not self.theme.theme_name: + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeForm', 'Theme Name Missing'), + translate('OpenLP.ThemeForm', + 'There is no name for this theme. ' + 'Please enter one.'), + (QtGui.QMessageBox.Ok), + QtGui.QMessageBox.Ok) + return + if self.theme.theme_name == u'-1' or self.theme.theme_name == u'None': + QtGui.QMessageBox.critical(self, + translate('OpenLP.ThemeForm', 'Theme Name Invalid'), + translate('OpenLP.ThemeForm', + 'Invalid theme name. ' + 'Please enter one.'), + (QtGui.QMessageBox.Ok), + QtGui.QMessageBox.Ok) + return + self.accepted = True + saveFrom = None + saveTo = None + if self.theme.background_type == \ + BackgroundType.to_string(BackgroundType.Image): + filename = \ + os.path.split(unicode(self.theme.background_filename))[1] + saveTo = os.path.join(self.path, self.theme.theme_name, filename) + saveFrom = self.theme.background_filename + if self.thememanager.saveTheme(self.theme, saveFrom, saveTo): + return QtGui.QDialog.accept(self) + + def _colorButton(self, field): + """ + Handle Color buttons + """ + new_color = QtGui.QColorDialog.getColor( + QtGui.QColor(field), self) + if new_color.isValid(): + field = new_color.name() + return field diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 2f060b12f..da8597cc0 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -32,10 +32,11 @@ import logging from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtCore, QtGui -from openlp.core.ui import AmendThemeForm, FileRenameForm +from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.theme import Theme from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ - build_icon, Receiver, SettingsManager, translate, check_item_selected + build_icon, Receiver, SettingsManager, translate, check_item_selected, \ + BackgroundType, BackgroundGradientType from openlp.core.utils import AppLocation, get_filesystem_encoding log = logging.getLogger(__name__) @@ -52,7 +53,7 @@ class ThemeManager(QtGui.QWidget): self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) self.layout.setMargin(0) - self.amendThemeForm = AmendThemeForm(self) + self.themeForm = ThemeForm(self) self.fileRenameForm = FileRenameForm(self) self.toolbar = OpenLPToolbar(self) self.toolbar.addToolbarButton( @@ -125,7 +126,7 @@ class ThemeManager(QtGui.QWidget): self.checkThemesExists(self.path) self.thumbPath = os.path.join(self.path, u'thumbnails') self.checkThemesExists(self.thumbPath) - self.amendThemeForm.path = self.path + self.themeForm.path = self.path self.oldBackgroundImage = None self.editingDefault = False # Last little bits of setting up @@ -180,7 +181,7 @@ class ThemeManager(QtGui.QWidget): '%s (default)')) % newName self.themeListWidget.item(count).setText(name) - def changeGlobalFromScreen(self, index = -1): + def changeGlobalFromScreen(self, index=-1): """ Change the global theme when a theme is double clicked upon in the Theme Manager list @@ -213,10 +214,10 @@ class ThemeManager(QtGui.QWidget): Loads a new theme with the default settings and then launches the theme editing form for the user to make their customisations. """ - theme = self.createThemeFromXml(self.baseTheme(), self.path) - self.amendThemeForm.loadTheme(theme) + theme = ThemeXML() self.saveThemeName = u'' - self.amendThemeForm.exec_() + self.themeForm.theme = theme + self.themeForm.exec_() def onRenameTheme(self): """ @@ -242,67 +243,23 @@ class ThemeManager(QtGui.QWidget): self.saveThemeName = u'' if self.fileRenameForm.exec_(): newThemeName = unicode(self.fileRenameForm.FileNameEdit.text()) - oldThemeData = self.getThemeData(oldThemeName) - self.cloneThemeData(oldThemeData, newThemeName) + themeData = self.getThemeData(oldThemeName) + self.cloneThemeData(themeData, newThemeName) self.loadThemes() - def cloneThemeData(self, oldThemeData, newThemeName): + def cloneThemeData(self, themeData, newThemeName): """ + Takes a theme and makes a new copy of it as well as saving it. """ log.debug(u'cloneThemeData') - new_theme = ThemeXML() - new_theme.new_document(newThemeName) - save_from = None - save_to = None - if oldThemeData.background_type == u'solid': - new_theme.add_background_solid( - unicode(oldThemeData.background_color)) - elif oldThemeData.background_type == u'gradient': - new_theme.add_background_gradient( - unicode(oldThemeData.background_start_color), - unicode(oldThemeData.background_end_color), - oldThemeData.background_direction) - else: - filename = \ - os.path.split(unicode(oldThemeData.background_filename))[1] - new_theme.add_background_image(filename) - save_to = os.path.join(self.path, newThemeName, filename) - save_from = oldThemeData.background_filename - new_theme.add_font(unicode(oldThemeData.font_main_name), - unicode(oldThemeData.font_main_color), - unicode(oldThemeData.font_main_proportion), - unicode(oldThemeData.font_main_override), u'main', - unicode(oldThemeData.font_main_weight), - unicode(oldThemeData.font_main_italics), - unicode(oldThemeData.font_main_line_adjustment), - unicode(oldThemeData.font_main_x), - unicode(oldThemeData.font_main_y), - unicode(oldThemeData.font_main_width), - unicode(oldThemeData.font_main_height)) - new_theme.add_font(unicode(oldThemeData.font_footer_name), - unicode(oldThemeData.font_footer_color), - unicode(oldThemeData.font_footer_proportion), - unicode(oldThemeData.font_footer_override), u'footer', - unicode(oldThemeData.font_footer_weight), - unicode(oldThemeData.font_footer_italics), - 0, # line adjustment - unicode(oldThemeData.font_footer_x), - unicode(oldThemeData.font_footer_y), - unicode(oldThemeData.font_footer_width), - unicode(oldThemeData.font_footer_height)) - new_theme.add_display(unicode(oldThemeData.display_shadow), - unicode(oldThemeData.display_shadow_color), - unicode(oldThemeData.display_outline), - unicode(oldThemeData.display_outline_color), - unicode(oldThemeData.display_horizontal_align), - unicode(oldThemeData.display_vertical_align), - unicode(oldThemeData.display_wrap_style), - unicode(oldThemeData.display_slide_transition), - unicode(oldThemeData.display_shadow_size), - unicode(oldThemeData.display_outline_size)) - theme = new_theme.extract_xml() - pretty_theme = new_theme.extract_formatted_xml() - self.saveTheme(newThemeName, theme, pretty_theme, save_from, save_to) + saveTo = None + saveFrom = None + if themeData.background_type == u'image': + saveTo = os.path.join(self.path, newThemeName, + os.path.split(unicode(themeData.background_filename))[1]) + saveFrom = themeData.background_filename + themeData.theme_name = newThemeName + self.saveTheme(themeData, saveFrom, saveTo) def onEditTheme(self): """ @@ -320,10 +277,10 @@ class ThemeManager(QtGui.QWidget): unicode(item.data(QtCore.Qt.UserRole).toString())) if theme.background_type == u'image': self.oldBackgroundImage = theme.background_filename - self.amendThemeForm.loadTheme(theme) self.saveThemeName = unicode( item.data(QtCore.Qt.UserRole).toString()) - self.amendThemeForm.exec_() + self.themeForm.theme = theme + self.themeForm.exec_(True) def onDeleteTheme(self): """ @@ -340,7 +297,8 @@ class ThemeManager(QtGui.QWidget): # confirm deletion answer = QtGui.QMessageBox.question(self, translate('OpenLP.ThemeManager', 'Delete Confirmation'), - translate('OpenLP.ThemeManager', 'Delete theme?'), + unicode(translate('OpenLP.ThemeManager', 'Delete %s theme?')) + % theme, QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: @@ -462,6 +420,7 @@ class ThemeManager(QtGui.QWidget): self.themelist = [] self.themeListWidget.clear() dirList = os.listdir(self.path) + dirList.sort() for name in dirList: if name.endswith(u'.png'): # check to see file is in theme root directory @@ -500,20 +459,21 @@ class ThemeManager(QtGui.QWidget): """ return self.themelist - def getThemeData(self, themename): + def getThemeData(self, themeName): """ Returns a theme object from an XML file - ``themename`` + ``themeName`` Name of the theme to load from file """ - log.debug(u'getthemedata for theme %s', themename) - xml_file = os.path.join(self.path, unicode(themename), - unicode(themename) + u'.xml') - xml = get_text_file_string(xml_file) + log.debug(u'getthemedata for theme %s', themeName) + xmlFile = os.path.join(self.path, unicode(themeName), + unicode(themeName) + u'.xml') + xml = get_text_file_string(xmlFile) if not xml: - xml = self.baseTheme() - return self.createThemeFromXml(xml, self.path) + return self.baseTheme() + else: + return self.createThemeFromXml(xml, self.path) def checkThemesExists(self, dir): """ @@ -584,7 +544,8 @@ class ThemeManager(QtGui.QWidget): outfile = open(fullpath, u'wb') outfile.write(zip.read(file)) if filexml: - self.generateAndSaveImage(dir, themename, filexml) + theme = self.createThemeFromXml(filexml, self.path) + self.generateAndSaveImage(dir, themename, theme) else: QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeManager', 'Error'), @@ -631,50 +592,60 @@ class ThemeManager(QtGui.QWidget): """ theme = Theme(xml_data) newtheme = ThemeXML() - newtheme.new_document(theme.Name) + newtheme.theme_name = theme.Name if theme.BackgroundType == 0: - newtheme.add_background_solid(unicode( - theme.BackgroundParameter1.name())) + newtheme.background_type = \ + BackgroundType.to_string(BackgroundType.Solid) + newtheme.background_color = \ + unicode(theme.BackgroundParameter1.name()) elif theme.BackgroundType == 1: - direction = u'vertical' + newtheme.background_type = \ + BackgroundType.to_string(BackgroundType.Gradient) + newtheme.background_direction = \ + BackgroundGradientType. \ + to_string(BackgroundGradientType.Horizontal) if theme.BackgroundParameter3.name() == 1: - direction = u'horizontal' - newtheme.add_background_gradient( - unicode(theme.BackgroundParameter1.name()), - unicode(theme.BackgroundParameter2.name()), direction) + newtheme.background_direction = \ + BackgroundGradientType. \ + to_string(BackgroundGradientType.Horizontal) + newtheme.background_start_color = \ + unicode(theme.BackgroundParameter1.name()) + newtheme.background_end_color = \ + unicode(theme.BackgroundParameter2.name()) else: - newtheme.add_background_image(unicode(theme.BackgroundParameter1)) - newtheme.add_font(unicode(theme.FontName), - unicode(theme.FontColor.name()), - unicode(theme.FontProportion * 3), u'False') - newtheme.add_font(unicode(theme.FontName), - unicode(theme.FontColor.name()), - unicode(12), u'False', u'footer') - outline = False - shadow = False + newtheme.background_type = \ + BackgroundType.to_string(BackgroundType.Image) + newtheme.background_filename = unicode(theme.BackgroundParameter1) + newtheme.font_main_name = theme.FontName + newtheme.font_main_color = unicode(theme.FontColor.name()) + newtheme.font_main_size = theme.FontProportion * 3 + newtheme.font_footer_name = theme.FontName + newtheme.font_footer_color = unicode(theme.FontColor.name()) + newtheme.font_main_shadow = False if theme.Shadow == 1: - shadow = True + newtheme.font_main_shadow = True + newtheme.font_main_shadow_color = unicode(theme.ShadowColor.name()) if theme.Outline == 1: - outline = True + newtheme.font_main_outline = True + newtheme.font_main_outline_color = \ + unicode(theme.OutlineColor.name()) vAlignCorrection = 0 if theme.VerticalAlign == 2: vAlignCorrection = 1 elif theme.VerticalAlign == 1: vAlignCorrection = 2 - newtheme.add_display(unicode(shadow), - unicode(theme.ShadowColor.name()), - unicode(outline), unicode(theme.OutlineColor.name()), - unicode(theme.HorizontalAlign), unicode(vAlignCorrection), - unicode(theme.WrapStyle), unicode(0)) + newtheme.display_horizontal_align = theme.HorizontalAlign + newtheme.display_vertical_align = vAlignCorrection return newtheme.extract_xml() - def saveTheme(self, name, theme_xml, theme_pretty_xml, image_from, - image_to): + def saveTheme(self, theme, imageFrom, imageTo): """ Called by thememaintenance Dialog to save the theme and to trigger the reload of the theme list """ - log.debug(u'saveTheme %s %s', name, theme_xml) + name = theme.theme_name + theme_pretty_xml = theme.extract_formatted_xml() + log.debug(u'saveTheme %s %s', name, theme_pretty_xml) theme_dir = os.path.join(self.path, name) if not os.path.exists(theme_dir): os.mkdir(os.path.join(self.path, name)) @@ -700,8 +671,8 @@ class ThemeManager(QtGui.QWidget): self.deleteTheme(self.saveThemeName) if result == QtGui.QMessageBox.Yes: # Save the theme, overwriting the existing theme if necessary. - if image_to and self.oldBackgroundImage and \ - image_to != self.oldBackgroundImage: + if imageTo and self.oldBackgroundImage and \ + imageTo != self.oldBackgroundImage: try: os.remove(self.oldBackgroundImage) except OSError: @@ -715,15 +686,15 @@ class ThemeManager(QtGui.QWidget): finally: if outfile: outfile.close() - if image_from and image_from != image_to: + if imageFrom and imageFrom != imageTo: try: encoding = get_filesystem_encoding() shutil.copyfile( - unicode(image_from).encode(encoding), - unicode(image_to).encode(encoding)) + unicode(imageFrom).encode(encoding), + unicode(imageTo).encode(encoding)) except IOError: log.exception(u'Failed to save theme image') - self.generateAndSaveImage(self.path, name, theme_xml) + self.generateAndSaveImage(self.path, name, theme) self.loadThemes() # Check if we need to set a new service theme if editedServiceTheme: @@ -748,14 +719,15 @@ class ThemeManager(QtGui.QWidget): self.global_theme) self.editingDefault = False self.pushThemes() + return True else: # Don't close the dialog - allow the user to change the name of # the theme or to cancel the theme dialog completely. return False - def generateAndSaveImage(self, dir, name, theme_xml): - log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml) - theme = self.createThemeFromXml(theme_xml, dir) + def generateAndSaveImage(self, dir, name, theme): + log.debug(u'generateAndSaveImage %s %s', dir, name) + theme_xml = theme.extract_xml() frame = self.generateImage(theme) samplepathname = os.path.join(self.path, name + u'.png') if os.path.exists(samplepathname): @@ -767,12 +739,18 @@ class ThemeManager(QtGui.QWidget): pixmap.save(thumb, u'png') log.debug(u'Theme image written to %s', samplepathname) - def generateImage(self, themedata): + def generateImage(self, themeData, forcePage=False): """ Call the RenderManager to build a Sample Image + + ``themeData`` + The theme to generated a preview for. + + ``forcePage`` + Flag to tell message lines per page need to be generated. """ - log.debug(u'generateImage \n%s ', themedata) - return self.parent.RenderManager.generate_preview(themedata) + log.debug(u'generateImage \n%s ', themeData) + return self.parent.renderManager.generate_preview(themeData, forcePage) def getPreviewImage(self, theme): """ @@ -791,25 +769,16 @@ class ThemeManager(QtGui.QWidget): """ log.debug(u'base theme created') newtheme = ThemeXML() - newtheme.new_document( - unicode(translate('OpenLP.ThemeManager', 'New Theme'))) - newtheme.add_background_solid(u'#000000') - newtheme.add_font(unicode(QtGui.QFont().family()), u'#FFFFFF', - u'30', u'False') - newtheme.add_font(unicode(QtGui.QFont().family()), u'#FFFFFF', - u'12', u'False', u'footer') - newtheme.add_display(u'False', u'#FFFFFF', u'False', - unicode(u'#FFFFFF'), u'0', u'0', u'0', u'False') - return newtheme.extract_xml() + return newtheme - def createThemeFromXml(self, theme_xml, path): + def createThemeFromXml(self, themeXml, path): """ Return a theme object using information parsed from XML - ``theme_xml`` + ``themeXml`` The XML data to load into the theme """ theme = ThemeXML() - theme.parse(theme_xml) + theme.parse(themeXml) theme.extend_image_filename(path) return 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 new file mode 100644 index 000000000..234c9de5e --- /dev/null +++ b/openlp/core/ui/themewizard.py @@ -0,0 +1,757 @@ +# -*- 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 translate, build_icon + +class Ui_ThemeWizard(object): + def setupUi(self, 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) + 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.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) + 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) + 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.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.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.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.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.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.mainAreaLayout.setWidget(0, + QtGui.QFormLayout.LabelRole, self.mainFontLabel) + self.mainFontComboBox = QtGui.QFontComboBox(self.mainAreaPage) + self.mainFontComboBox.setObjectName(u'mainFontComboBox') + self.mainAreaLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.mainFontComboBox) + self.mainColorLabel = QtGui.QLabel(self.mainAreaPage) + self.mainColorLabel.setObjectName(u'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.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.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.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.mainSizeSpinBox.sizePolicy().hasHeightForWidth()) + self.mainSizeSpinBox.setSizePolicy(sizePolicy) + self.mainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) + self.mainSizeSpinBox.setMaximum(999) + self.mainSizeSpinBox.setProperty(u'value', 16) + self.mainSizeSpinBox.setObjectName(u'mainSizeSpinBox') + self.mainSizeLayout.addWidget(self.mainSizeSpinBox) + self.mainLineCountLabel = QtGui.QLabel(self.mainAreaPage) + self.mainLineCountLabel.setObjectName(u'mainLineCountLabel') + self.mainSizeLayout.addWidget(self.mainLineCountLabel) + self.mainAreaLayout.setLayout(2, + QtGui.QFormLayout.FieldRole, self.mainSizeLayout) + self.lineSpacingLabel = QtGui.QLabel(self.mainAreaPage) + self.lineSpacingLabel.setObjectName(u'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.mainAreaLayout.setWidget(3, + QtGui.QFormLayout.FieldRole, self.lineSpacingSpinBox) + self.outlineCheckBox = QtGui.QCheckBox(self.mainAreaPage) + self.outlineCheckBox.setObjectName(u'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) + self.outlineColorPushButton.setEnabled(True) + self.outlineColorPushButton.setText(u'') + self.outlineColorPushButton.setObjectName(u'outlineColorPushButton') + self.outlineLayout.addWidget(self.outlineColorPushButton) + self.outlineSizeLabel = QtGui.QLabel(self.mainAreaPage) + self.outlineSizeLabel.setObjectName(u'outlineSizeLabel') + self.outlineLayout.addWidget(self.outlineSizeLabel) + self.outlineSizeSpinBox = QtGui.QSpinBox(self.mainAreaPage) + self.outlineSizeSpinBox.setObjectName(u'outlineSizeSpinBox') + self.outlineLayout.addWidget(self.outlineSizeSpinBox) + self.mainAreaLayout.setLayout(4, + QtGui.QFormLayout.FieldRole, self.outlineLayout) + self.shadowCheckBox = QtGui.QCheckBox(self.mainAreaPage) + self.shadowCheckBox.setObjectName(u'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) + self.shadowColorPushButton.setEnabled(True) + self.shadowColorPushButton.setText(u'') + self.shadowColorPushButton.setObjectName(u'shadowColorPushButton') + self.shadowLayout.addWidget(self.shadowColorPushButton) + self.shadowSizeLabel = QtGui.QLabel(self.mainAreaPage) + self.shadowSizeLabel.setObjectName(u'shadowSizeLabel') + self.shadowLayout.addWidget(self.shadowSizeLabel) + self.shadowSizeSpinBox = QtGui.QSpinBox(self.mainAreaPage) + self.shadowSizeSpinBox.setObjectName(u'shadowSizeSpinBox') + self.shadowLayout.addWidget(self.shadowSizeSpinBox) + 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.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.footerFontComboBox = QtGui.QFontComboBox(self.footerAreaPage) + self.footerFontComboBox.setObjectName(u'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.footerColorPushButton = QtGui.QPushButton(self.footerAreaPage) + self.footerColorPushButton.setText(u'') + self.footerColorPushButton.setObjectName(u'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.footerSizeSpinBox = QtGui.QSpinBox(self.footerAreaPage) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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) + ThemeWizard.addPage(self.footerAreaPage) + self.alignmentPage = QtGui.QWizardPage() + self.alignmentPage.setObjectName(u'alignmentPage') + 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.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.alignmentLayout.setWidget(0, + QtGui.QFormLayout.FieldRole, self.horizontalComboBox) + self.verticalLabel = QtGui.QLabel(self.alignmentPage) + self.verticalLabel.setObjectName(u'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.alignmentLayout.setWidget(1, + QtGui.QFormLayout.FieldRole, self.verticalComboBox) + self.transitionsCheckBox = QtGui.QCheckBox(self.alignmentPage) + self.transitionsCheckBox.setObjectName(u'transitionsCheckBox') + self.alignmentLayout.setWidget(2, + QtGui.QFormLayout.FieldRole, self.transitionsCheckBox) + ThemeWizard.addPage(self.alignmentPage) + self.areaPositionPage = QtGui.QWizardPage() + self.areaPositionPage.setObjectName(u'areaPositionPage') + 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') + self.mainPositionLayout = QtGui.QFormLayout(self.mainPositionGroupBox) + self.mainPositionLayout.setMargin(8) + self.mainPositionLayout.setSpacing(8) + self.mainPositionLayout.setObjectName(u'mainPositionLayout') + 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.nainXLabel = QtGui.QLabel(self.mainPositionGroupBox) + self.nainXLabel.setObjectName(u'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.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.mainYSpinBox = QtGui.QSpinBox(self.mainPositionGroupBox) + self.mainYSpinBox.setEnabled(False) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.mainYLabel = QtGui.QLabel(self.mainPositionGroupBox) + self.mainYLabel.setObjectName(u'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.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.mainWidthLabel = QtGui.QLabel(self.mainPositionGroupBox) + self.mainWidthLabel.setObjectName(u'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.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.mainHeightLabel = QtGui.QLabel(self.mainPositionGroupBox) + self.mainHeightLabel.setObjectName(u'mainHeightLabel') + 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.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.footerXSpinBox = QtGui.QSpinBox(self.footerPositionGroupBox) + self.footerXSpinBox.setEnabled(False) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.footerYLabel = QtGui.QLabel(self.footerPositionGroupBox) + self.footerYLabel.setObjectName(u'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.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + 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.footerWidthLabel = QtGui.QLabel(self.footerPositionGroupBox) + self.footerWidthLabel.setObjectName(u'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.footerHeightLabel = QtGui.QLabel(self.footerPositionGroupBox) + self.footerHeightLabel.setObjectName(u'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.footerDefaultPositionCheckBox.setChecked(True) + 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.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.themeNameLayout.addWidget(self.themeNameLabel) + self.themeNameEdit = QtGui.QLineEdit(self.previewPage) + self.themeNameEdit.setObjectName(u'themeNameEdit') + 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()) + self.previewBoxLabel.setSizePolicy(sizePolicy) + 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.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) + 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.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/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 2e11c30ad..749f1f938 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -133,7 +133,7 @@ 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'), @@ -142,7 +142,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 'the Bible to use in the import.')) 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'), @@ -153,7 +153,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 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'), @@ -168,7 +168,7 @@ 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'), @@ -176,7 +176,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 'You need to specify a version name for your Bible.')) self.VersionNameEdit.setFocus() return False - elif license_copyright == u'': + elif not license_copyright: QtGui.QMessageBox.critical(self, translate('BiblesPlugin.ImportWizardForm', 'Empty Copyright'), @@ -207,9 +207,11 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 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))) + bibles = [unicode(translate('BiblesPlugin.ImportWizardForm', bible)) for + bible in self.web_bible_list[index].keys()] + bibles.sort() + for bible in bibles: + self.BibleComboBox.addItem(bible) def onOsisFileButtonClicked(self): """ @@ -317,7 +319,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): """ Load the list of Crosswalk and BibleGateway bibles. """ - #Load and store Crosswalk Bibles + # Load and store Crosswalk Bibles. filepath = AppLocation.get_directory(AppLocation.PluginsDir) filepath = os.path.join(filepath, u'bibles', u'resources') books_file = None @@ -341,7 +343,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): finally: if books_file: books_file.close() - #Load and store BibleGateway Bibles + # Load and store BibleGateway Bibles. books_file = None try: self.web_bible_list[WebDownload.BibleGateway] = {} @@ -379,12 +381,18 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): Receiver.send_message(u'openlp_process_events') def preImport(self): + 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...')) + 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): @@ -395,26 +403,26 @@ 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 + # 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()) @@ -438,8 +446,14 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard): 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', 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/db.py b/openlp/plugins/bibles/lib/db.py index 8f5c7dc79..9852ed16b 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. @@ -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 e6a474f5c..fa47dd7f5 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -213,7 +213,7 @@ class BGExtract(object): finally: if not page: return None - cleaner = [(re.compile(' |
'), lambda match: '')] + cleaner = [(re.compile(' |
|\'\+\''), lambda match: '')] soup = None try: soup = BeautifulSoup(page, markupMassage=cleaner) @@ -364,12 +364,11 @@ class HTTPBible(BibleDB): 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 +416,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) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 9afc4a4b2..6b4d7c800 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -257,17 +257,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: @@ -317,4 +334,3 @@ class BibleManager(object): """ for bible in self.db_cache: self.db_cache[bible].finalise() - diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index bb3c1b26d..949035c0b 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -47,21 +47,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 +84,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 +145,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 +227,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 +240,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 +275,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 +292,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 +304,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 +336,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 +344,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 +364,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 +382,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 +403,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 +442,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 +520,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,16 +539,19 @@ 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()) @@ -508,74 +560,81 @@ class BibleMediaItem(MediaManagerItem): versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, chapter_to, verse_to) 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 +642,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 +687,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) @@ -651,7 +711,7 @@ class BibleMediaItem(MediaManagerItem): obj = obj.toPyObject() return unicode(obj) - 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 +721,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,22 +736,22 @@ 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) + second_text) raw_slides.append(bible_text) bible_text = u'' # If we are 'Verse Per Slide' then create a new slide. @@ -719,7 +779,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,6 +809,12 @@ 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. """ old_bitem = self.listView.item(old_item.row()) old_chapter = int(self._decodeQtObject(old_bitem, 'chapter')) @@ -758,18 +824,18 @@ class BibleMediaItem(MediaManagerItem): start_chapter = int(self._decodeQtObject(start_bitem, 'chapter')) start_verse = int(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: + start_second_bible = self._decodeQtObject(start_bitem, 'second_bible') + if start_second_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) + start_verse, start_bible, start_second_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) + start_verse, old_verse, start_bible, start_second_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) else: if start_verse == old_verse and start_chapter == old_chapter: title = u'%s %s:%s (%s)' % (start_book, start_chapter, @@ -785,34 +851,62 @@ class BibleMediaItem(MediaManagerItem): 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). + """ if not self.parent.settings_tab.show_new_chapters or \ old_chapter != chapter: verse_text = u'%s:%s' % (chapter, verse) diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 65a73337a..c5281574b 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) @@ -264,7 +264,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/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 2846a98df..247e5e837 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -152,6 +152,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def newSong(self): log.debug(u'New Song') + self.initialise() self.SongTabWidget.setCurrentIndex(0) self.TitleEditItem.setText(u'') self.AlternativeEdit.setText(u'') @@ -170,8 +171,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() @@ -594,6 +605,9 @@ 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 \ @@ -631,13 +645,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): database. ``preview`` - Should be True if song is also previewed. + 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 +665,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() diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index b32712d8d..d954bfb1f 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -60,7 +60,6 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): def contextMenu(self, point): item = self.serviceManagerList.itemAt(point) - print item def insertVerse(self, title, num=1): if self.verseTextEdit.textCursor().columnNumber() != 0: diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 014c66a51..67ef4d8c1 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -507,8 +507,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): filenames=self.getListOfFiles( self.songBeamerFileListWidget) ) - success = importer.do_import() - if success: + if importer.do_import(): # reload songs self.importProgressLabel.setText( translate('SongsPlugin.SongImportForm', 'Finished import.')) diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 7c13e0989..e057bb516 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -405,7 +405,7 @@ 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. """ @@ -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/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 4ca391f20..6de559e28 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -32,7 +32,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__) @@ -53,8 +53,8 @@ class SongMediaItem(MediaManagerItem): self.ListViewWithDnD_class = SongListView MediaManagerItem.__init__(self, parent, self, icon) self.edit_song_form = EditSongForm(self, self.parent.manager) + self.openLyrics = OpenLyricsParser(self.parent.manager) self.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 @@ -114,6 +114,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 +143,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() @@ -192,6 +194,7 @@ class SongMediaItem(MediaManagerItem): Handle the exit from the edit dialog and trigger remote updates of songs """ + log.debug(u'onSongListLoad') # Called to redisplay the song list screen edit from a search # or from the exit of the Song edit dialog. If remote editing is active # Trigger it and clean up so it will not update again. @@ -259,6 +262,7 @@ class SongMediaItem(MediaManagerItem): Receiver.send_message(u'songs_load_list') def onNewClick(self): + log.debug(u'onNewClick') self.edit_song_form.newSong() self.edit_song_form.exec_() @@ -266,6 +270,7 @@ class SongMediaItem(MediaManagerItem): self.song_maintenance_form.exec_() def onRemoteEditClear(self): + log.debug(u'onRemoteEditClear') self.remoteTriggered = None self.remoteSong = -1 @@ -275,6 +280,7 @@ class SongMediaItem(MediaManagerItem): the Song Id in the payload along with an indicator to say which type of display is required. """ + log.debug(u'onRemoteEdit %s' % songid) fields = songid.split(u':') valid = self.parent.manager.get_object(Song, fields[1]) if valid: @@ -287,6 +293,7 @@ class SongMediaItem(MediaManagerItem): """ Edit a song """ + log.debug(u'onEditClick') if check_item_selected(self.listView, translate('SongsPlugin.MediaItem', 'You must select an item to edit.')): @@ -323,7 +330,8 @@ 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'' author_audit = [] @@ -345,11 +353,11 @@ class SongMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.AddIfNewItem) song = self.parent.manager.get_object(Song, item_id) service_item.theme = song.theme_name - service_item.editId = item_id + service_item.edit_id = item_id if song.lyrics.startswith(u' 0: - self.add_verse(self.current_verse, + # Just make sure that the line is of the type 'Unicode'. + line = unicode(line).strip() + if line.startswith(u'#') and not read_verses: + self.parse_tags(line) + elif line.startswith(u'---'): + if self.current_verse: + self.replace_html_tags() + self.add_verse(self.current_verse, self.current_verse_type) self.current_verse = u'' self.current_verse_type = u'V' - self.read_verse = True - self.verse_start = True - elif self.read_verse: - if self.verse_start: - self.check_verse_marks(line) - self.verse_start = False + read_verses = True + verse_start = True + elif read_verses: + if verse_start: + verse_start = False + if not self.check_verse_marks(line): + self.current_verse = u'%s\n' % line else: self.current_verse += u'%s\n' % line - if len(self.current_verse) > 0: + if self.current_verse: + 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)) return True + def replace_html_tags(self): + """ + This can be called to replace SongBeamer's specific (html) tags with + OpenLP's specific (html) tags. + """ + tag_pairs = [ + (u'', u'{st}'), + (u'', u'{/st}'), + (u'', u'{it}'), + (u'', u'{/it}'), + (u'', u'{u}'), + (u'', u'{/u}'), + (u'
', u'{st}'), + (u'
', u'{st}'), + (u'', u'{st}'), + (u'

', u'{p}'), + (u'

', u'{/p}'), + (u'', u'{su}'), + (u'', u'{/su}'), + (u'', u'{sb}'), + (u'', u'{/sb}'), + (u'', u''), + (u'', u''), + (u'', u''), + (u'', u'') + ] + for pair in tag_pairs: + self.current_verse = self.current_verse.replace(pair[0], pair[1]) + # TODO: check for unsupported tags (see wiki) and remove them as well. + def parse_tags(self, line): - tag_val = line.split('=') - if len(tag_val[0]) == 0 or len(tag_val[1]) == 0: - return True - if tag_val[0] == '#(c)': + """ + Parses a meta data line. + + ``line`` + The line in the file. It should consist of a tag and a value + for this tag (unicode):: + + u'#Title=Nearer my God to Thee' + """ + tag_val = line.split(u'=', 1) + if len(tag_val) == 1: + return + if not tag_val[0] or not tag_val[1]: + return + if tag_val[0] == u'#(c)': self.add_copyright(tag_val[1]) - elif tag_val[0] == '#AddCopyrightInfo': + elif tag_val[0] == u'#AddCopyrightInfo': pass - elif tag_val[0] == '#Author': - #TODO split Authors - self.add_author(tag_val[1]) - elif tag_val[0] == '#BackgroundImage': + elif tag_val[0] == u'#Author': + self.parse_author(tag_val[1]) + elif tag_val[0] == u'#BackgroundImage': pass - elif tag_val[0] == '#Bible': + elif tag_val[0] == u'#Bible': pass - elif tag_val[0] == '#Categories': + elif tag_val[0] == u'#Categories': self.topics = line.split(',') - elif tag_val[0] == '#CCLI': + elif tag_val[0] == u'#CCLI': self.ccli_number = tag_val[1] - elif tag_val[0] == '#Chords': + elif tag_val[0] == u'#Chords': pass - elif tag_val[0] == '#ChurchSongID': + elif tag_val[0] == u'#ChurchSongID': pass - elif tag_val[0] == '#ColorChords': + elif tag_val[0] == u'#ColorChords': pass - elif tag_val[0] == '#Comments': + elif tag_val[0] == u'#Comments': self.comments = tag_val[1] - elif tag_val[0] == '#Editor': + elif tag_val[0] == u'#Editor': pass - elif tag_val[0] == '#Font': + elif tag_val[0] == u'#Font': pass - elif tag_val[0] == '#FontLang2': + elif tag_val[0] == u'#FontLang2': pass - elif tag_val[0] == '#FontSize': + elif tag_val[0] == u'#FontSize': pass - elif tag_val[0] == '#Format': + elif tag_val[0] == u'#Format': pass - elif tag_val[0] == '#Format_PreLine': + elif tag_val[0] == u'#Format_PreLine': pass - elif tag_val[0] == '#Format_PrePage': + elif tag_val[0] == u'#Format_PrePage': pass - elif tag_val[0] == '#ID': + elif tag_val[0] == u'#ID': pass - elif tag_val[0] == '#Key': + elif tag_val[0] == u'#Key': pass - elif tag_val[0] == '#Keywords': + elif tag_val[0] == u'#Keywords': pass - elif tag_val[0] == '#LangCount': + elif tag_val[0] == u'#LangCount': pass - elif tag_val[0] == '#Melody': - #TODO split Authors - self.add_author(tag_val[1]) - elif tag_val[0] == '#NatCopyright': + elif tag_val[0] == u'#Melody': + self.parse_author(tag_val[1]) + elif tag_val[0] == u'#NatCopyright': pass - elif tag_val[0] == '#OTitle': + elif tag_val[0] == u'#OTitle': pass - elif tag_val[0] == '#OutlineColor': + elif tag_val[0] == u'#OutlineColor': pass - elif tag_val[0] == '#OutlinedFont': + elif tag_val[0] == u'#OutlinedFont': pass - elif tag_val[0] == '#QuickFind': + elif tag_val[0] == u'#QuickFind': pass - elif tag_val[0] == '#Rights': + elif tag_val[0] == u'#Rights': song_book_pub = tag_val[1] - elif tag_val[0] == '#Songbook': + elif tag_val[0] == u'#Songbook': book_num = tag_val[1].split(' / ') self.song_book_name = book_num[0] if len(book_num) == book_num[1]: self.song_number = u'' - elif tag_val[0] == '#Speed': + elif tag_val[0] == u'#Speed': pass - elif tag_val[0] == '#TextAlign': + elif tag_val[0] == u'#TextAlign': pass - elif tag_val[0] == '#Title': + elif tag_val[0] == u'#Title': self.title = u'%s' % tag_val[1] - elif tag_val[0] == '#TitleAlign': + elif tag_val[0] == u'#TitleAlign': pass - elif tag_val[0] == '#TitleFontSize': + elif tag_val[0] == u'#TitleFontSize': pass - elif tag_val[0] == '#TitleLang2': + elif tag_val[0] == u'#TitleLang2': pass - elif tag_val[0] == '#TitleLang3': + elif tag_val[0] == u'#TitleLang3': pass - elif tag_val[0] == '#TitleLang4': + elif tag_val[0] == u'#TitleLang4': pass - elif tag_val[0] == '#Translation': + elif tag_val[0] == u'#Translation': pass - elif tag_val[0] == '#Transpose': + elif tag_val[0] == u'#Transpose': pass - elif tag_val[0] == '#TransposeAccidental': + elif tag_val[0] == u'#TransposeAccidental': pass - elif tag_val[0] == '#Version': + elif tag_val[0] == u'#Version': pass - else: - pass - return True def check_verse_marks(self, line): - marks = line.split(' ') + """ + Check and add the verse's MarkType. Returns ``True`` if the given line + contains a correct verse mark otherwise ``False``. + + ``line`` + The line to check for marks (unicode). + """ + marks = line.split(u' ') if len(marks) <= 2 and marks[0] in SongBeamerTypes.MarkTypes: self.current_verse_type = SongBeamerTypes.MarkTypes[marks[0]] if len(marks) == 2: - #TODO: may check, because of only digits are allowed - self.current_verse_type += marks[1] + # If we have a digit, we append it to current_verse_type. + if marks[1].isdigit(): + self.current_verse_type += marks[1] + return True + else: + return False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 2c1de83a2..ea36d55b5 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -254,7 +254,8 @@ class SongImport(QtCore.QObject): All fields have been set to this song. Write it away """ if not self.authors: - self.authors.append(u'Author unknown') + self.authors.append(unicode(translate('SongsPlugin.SongImport', + 'Author unknown'))) self.commit_song() def commit_song(self): diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index ff39a0efa..655ea1e3c 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,153 @@ 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' - Wizard - + ThemeWizard + 0 0 - 559 - 487 + 550 + 386 @@ -20,16 +20,16 @@ QWizard::ModernStyle - QWizard::HaveCustomButton1|QWizard::NoBackButtonOnStartPage + QWizard::IndependentPages|QWizard::NoBackButtonOnStartPage - + - + 8 @@ -37,7 +37,7 @@ 0 - + 163 @@ -65,12 +65,12 @@ - + 8 - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -81,7 +81,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -97,9 +97,9 @@ p, li { white-space: pre-wrap; } - + - This wizard will help you to maintain Themes . Click the next button below to start the process.. + This wizard will help you to maintain Themes . Click the next button below to start the process by setting up your background. true @@ -110,7 +110,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -126,53 +126,34 @@ p, li { white-space: pre-wrap; } - + - Select Import Source + Set Up Background - Select the import format, and where to import from. + Set up your theme's background according to the parameters below. - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 8 - - + + 20 + + + + + 8 + - + - Background: + Background type: - - - - Opaque - - - - - Transparent - - - - - - - - - - - - Background Type: - - - - - + Solid Color @@ -190,277 +171,494 @@ p, li { white-space: pre-wrap; } - - - - - - - <Color1> + + + Qt::Horizontal - - - - - - + + + 40 + 20 + - + - - - - - - <Color2> + + + + 0 + + + + + 8 - - - - - - + + 8 - - - - - - - - - - Gradient : + + 0 - - - - - - - Horizontal - + + + + + 103 + 0 + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + - - - Vertical - + + + + + + - - - Circular - + + + + + + 8 + + + 8 + + + 0 + + + + + + 103 + 0 + + + + Starting color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + - - - - - - - - - - Image: + + + + + + + + + + + + 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 + + + + + + + + - + Main Area Font Details - Define the font and display charaistics for the Display text + Define the font and display characteristics for the Display text - - - - - Font: - - - - - - - - - - Font Color: - - - - - - - - - - - - - - Size: - - - - - - - - 0 - 0 - - + + + 8 + + + 8 + + + 20 + + + - 70 + 103 0 - - pt - - - 999 - - - 16 - - - - - - - Wrap Indentation - - - - - - - - - - TextLabel - - - - - - - Show Outline: - - - - - - - - - - - - - - Outline Color: - - - - - - - - - - - - - - Show Shadow: - - - - - - - - - - - - - - Shadow Color: - - - - - - - - - - - - - - - Footer Area Font Details - - - Define the font and display charaistics for the Footer text - - - - Font: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + - + - + - Font Color: + Color: - - - + + + 24 - + + + + + + + + + + + Bold + + + + + + + Italic + + + + - + Size: - + + + 8 + + + 0 + + + + + + 0 + 0 + + + + + 70 + 0 + + + + pt + + + 999 + + + 16 + + + + + + + (%d lines per slide) + + + + + + + + + Line Spacing: + + + + + + + pt + + + -50 + + + 50 + + + + + + + &Outline: + + + + + + + + + true + + + + + + + + + + Size: + + + + + + + pt + + + + + + + + + &Shadow: + + + + + + + + + true + + + + + + + + + + Size: + + + + + + + pt + + + + + + + + + + Footer Area Font Details + + + Define the font and display characteristics for the Footer text + + + + QFormLayout::ExpandingFieldsGrow + + + 8 + + + 8 + + + 20 + + + + + + 103 + 0 + + + + Font: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Color: + + + + + + + + + + + + + + Size: + + + + + 0 @@ -484,374 +682,504 @@ p, li { white-space: pre-wrap; } - - + + + + + Text Formatting Details + + + Allows additional display formatting information to be defined + + + + 8 + + + 8 + + + 20 + + + + + + 103 + 0 + + - Show Outline: + Horizontal Align: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + + false + + + + Left + + + + + Right + + + + + Center + + + + + + - + Vertcal Align: - - - - Shadow Color: - + + + + + Top + + + + + Middle + + + + + Bottom + + - - + + - - - - - - - - Show Shadow: - - - - - - - - - - - - - - Outline Color: - - - - - - - + Transitions - + - Text Display Layout + Output Area Locations Allows you to change and move the Main and Footer areas. - - - - - + + + 20 + + + 8 + + + + + + 248 + 0 + - - false + + &Main Area + + + 8 + + + 8 + + + 8 + + + + + &Use default location + + + true + + + false + + + + + + + X position: + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + 0 + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + + + + + Y position: + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + + + + + Width: + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + + + + + Height: + + + + - - - - - - Main Area - - - - - - - Footer Area - - - - - - - X Position: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - 0 - - - - - - - X Position: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - 0 - - - - - - - Y Position: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - - - - - Y Position: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - 0 - - - - - - - Width: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - - - - - Width: - - - - - - - - 78 - 0 - - - - px - - - 9999 - - - - - - - Height: - - - - - - - - 0 - 0 - - - - - 78 - 0 - - - - px - - - 9999 - - - - - - - Height: - - - - - - - - 78 - 0 - - - - px - - - 9999 - - - - - - - - - Use Default Location: + + + + + 248 + 0 + + + Footer Area + + + + 8 + + + 8 + + + 8 + + + + + X position: + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + 0 + + + + + + + Y position: + + + + + + + false + + + + 0 + 0 + + + + + 78 + 0 + + + + px + + + 9999 + + + 0 + + + + + + + Width: + + + + + + + false + + + + 78 + 0 + + + + px + + + 9999 + + + + + + + Height: + + + + + + + false + + + + 78 + 0 + + + + px + + + 9999 + + + + + + + Use default location + + + true + + + + - + Save and Preview View the theme and save it replacing the current one or change the name to create a new theme - - - + + + 8 + + + 20 + + + + + 8 + - + + + + 103 + 0 + + - Theme Name: + Theme name: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + themeNameEdit - + - - + + + + 0 + - - - Preview + + + Qt::Horizontal - - Qt::AlignCenter + + + 58 + 20 + - + - + 0 @@ -860,8 +1188,8 @@ p, li { white-space: pre-wrap; } - 300 - 225 + 100 + 150 @@ -881,6 +1209,19 @@ p, li { white-space: pre-wrap; } + + + + Qt::Horizontal + + + + 78 + 20 + + + + @@ -889,5 +1230,38 @@ p, li { white-space: pre-wrap; } - + + + ThemeWizard + accepted() + ThemeWizard + accept() + + + 455 + 368 + + + 483 + 401 + + + + + backgroundTypeComboBox + currentIndexChanged(int) + backgroundStackedWidget + setCurrentIndex(int) + + + 178 + 78 + + + 249 + 199 + + + + diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 0ecb87bca..2a3282461 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -81,6 +81,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