trunk r1129
@ -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
|
||||
|
@ -14,6 +14,8 @@ Contents:
|
||||
introduction
|
||||
glossary
|
||||
dualmonitors
|
||||
mediamanager
|
||||
songs
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
26
documentation/manual/source/mediamanager.rst
Normal file
@ -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.
|
BIN
documentation/manual/source/pics/finishedimport.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
documentation/manual/source/pics/plugins.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
documentation/manual/source/pics/selectsongs.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
documentation/manual/source/pics/songimporter.png
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
documentation/manual/source/pics/songimporterchoices.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
documentation/manual/source/pics/songselectlyrics.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
documentation/manual/source/pics/songselectsongsearch.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
documentation/manual/source/pics/songusage.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
documentation/manual/source/pics/songusagedelete.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
documentation/manual/source/pics/songusagereport.png
Normal file
After Width: | Height: | Size: 55 KiB |
0
documentation/manual/source/pics/vistadisplaysettings.png
Executable file → Normal file
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
0
documentation/manual/source/pics/vistapersonalize.png
Executable file → Normal file
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 139 KiB |
0
documentation/manual/source/pics/winsevendisplay.png
Executable file → Normal file
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
0
documentation/manual/source/pics/winsevenresolution.png
Executable file → Normal file
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 24 KiB |
100
documentation/manual/source/songs.rst
Normal file
@ -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.
|
||||
|
||||
|
@ -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'<span style="-webkit-text-fill-color:red">',
|
||||
u'end tag':u'{/r}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Black', u'start tag':u'{b}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:black">',
|
||||
u'end tag':u'{/b}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Blue', u'start tag':u'{bl}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:blue">',
|
||||
u'end tag':u'{/bl}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Yellow', u'start tag':u'{y}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:yellow">',
|
||||
u'end tag':u'{/y}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Green', u'start tag':u'{g}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:green">',
|
||||
u'end tag':u'{/g}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Pink', u'start tag':u'{pk}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:#CC33CC">',
|
||||
u'end tag':u'{/pk}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Orange', u'start tag':u'{o}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:#CC0033">',
|
||||
u'end tag':u'{/o}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Purple', u'start tag':u'{pp}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:#9900FF">',
|
||||
u'end tag':u'{/pp}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'White', u'start tag':u'{w}',
|
||||
u'start html':u'<span style="-webkit-text-fill-color:white">',
|
||||
u'end tag':u'{/w}', u'end html':u'</span>', u'protected':False})
|
||||
html_expands.append({u'desc':u'Superscript', u'start tag':u'{su}',
|
||||
u'start html':u'<sup>', u'end tag':u'{/su}', u'end html':u'</sup>',
|
||||
u'protected':True})
|
||||
html_expands.append({u'desc':u'Subscript', u'start tag':u'{sb}',
|
||||
u'start html':u'<sub>', u'end tag':u'{/sb}', u'end html':u'</sub>',
|
||||
u'protected':True})
|
||||
html_expands.append({u'desc':u'Paragraph', u'start tag':u'{p}',
|
||||
u'start html':u'<p>', u'end tag':u'{/p}', u'end html':u'</p>',
|
||||
u'protected':True})
|
||||
html_expands.append({u'desc':u'Bold', u'start tag':u'{st}',
|
||||
u'start html':u'<strong>', u'end tag':u'{/st}', u'end html':u'</strong>',
|
||||
u'protected':True})
|
||||
html_expands.append({u'desc':u'Italics', u'start tag':u'{it}',
|
||||
u'start html':u'<em>', u'end tag':u'{/it}', u'end html':u'</em>',
|
||||
u'protected':True})
|
||||
html_expands.append({u'desc': u'Red', u'start tag': u'{r}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:red">',
|
||||
u'end tag': u'{/r}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Black', u'start tag': u'{b}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:black">',
|
||||
u'end tag': u'{/b}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:blue">',
|
||||
u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:yellow">',
|
||||
u'end tag': u'{/y}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Green', u'start tag': u'{g}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:green">',
|
||||
u'end tag': u'{/g}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:#CC33CC">',
|
||||
u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Orange', u'start tag': u'{o}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:#CC0033">',
|
||||
u'end tag': u'{/o}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:#9900FF">',
|
||||
u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'White', u'start tag': u'{w}',
|
||||
u'start html': u'<span style="-webkit-text-fill-color:white">',
|
||||
u'end tag': u'{/w}', u'end html': u'</span>', u'protected': False})
|
||||
html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}',
|
||||
u'start html': u'<sup>', u'end tag': u'{/su}', u'end html': u'</sup>',
|
||||
u'protected': True})
|
||||
html_expands.append({u'desc': u'Subscript', u'start tag': u'{sb}',
|
||||
u'start html': u'<sub>', u'end tag': u'{/sb}', u'end html': u'</sub>',
|
||||
u'protected': True})
|
||||
html_expands.append({u'desc': u'Paragraph', u'start tag': u'{p}',
|
||||
u'start html': u'<p>', u'end tag': u'{/p}', u'end html': u'</p>',
|
||||
u'protected': True})
|
||||
html_expands.append({u'desc': u'Bold', u'start tag': u'{st}',
|
||||
u'start html': u'<strong>', u'end tag': u'{/st}', u'end html': u'</strong>',
|
||||
u'protected': True})
|
||||
html_expands.append({u'desc': u'Italics', u'start tag': u'{it}',
|
||||
u'start html': u'<em>', u'end tag': u'{/it}', u'end html': u'</em>',
|
||||
u'protected': True})
|
||||
html_expands.append({u'desc': u'Underline', u'start tag': u'{u}',
|
||||
u'start html': u'<span style="text-decoration: underline;">',
|
||||
u'end tag': u'{/u}', u'end html': u'</span>', 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
|
||||
|
@ -117,6 +117,7 @@ class Manager(object):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(plugin_name)
|
||||
self.db_url = u''
|
||||
self.is_dirty = False
|
||||
db_type = unicode(
|
||||
settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString())
|
||||
if db_type == u'sqlite':
|
||||
@ -150,12 +151,34 @@ class Manager(object):
|
||||
self.session.add(object_instance)
|
||||
if commit:
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
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
|
||||
@ -205,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
|
||||
@ -220,6 +259,7 @@ class Manager(object):
|
||||
try:
|
||||
self.session.delete(object_instance)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
@ -241,6 +281,7 @@ class Manager(object):
|
||||
query = query.filter(filter_clause)
|
||||
query.delete(synchronize_session=False)
|
||||
self.session.commit()
|
||||
self.is_dirty = True
|
||||
return True
|
||||
except InvalidRequestError:
|
||||
self.session.rollback()
|
||||
@ -251,5 +292,7 @@ class Manager(object):
|
||||
"""
|
||||
VACUUM the database on exit.
|
||||
"""
|
||||
if self.is_dirty:
|
||||
engine = create_engine(self.db_url)
|
||||
if self.db_url.startswith(u'sqlite'):
|
||||
engine.execute("vacuum")
|
||||
|
@ -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,32 @@ 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 +471,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 +496,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 +536,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 +572,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'<div class="lyricstable">' \
|
||||
u'<div id="lyricsshadow" style="opacity:1" ' \
|
||||
u'class="lyricscell lyricsshadow"></div></div>'
|
||||
@ -589,7 +608,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):
|
||||
|
@ -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)
|
||||
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:
|
||||
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
|
||||
|
||||
@ -541,4 +545,3 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
individual service items need to be processed by the plugins
|
||||
"""
|
||||
pass
|
||||
|
||||
|
@ -156,9 +156,11 @@ class PluginManager(object):
|
||||
if plugin.settings_tab:
|
||||
log.debug(u'Inserting settings tab item from %s' %
|
||||
visible_title[u'title'])
|
||||
settingsform.addTab(visible_title[u'title'], plugin.settings_tab)
|
||||
settingsform.addTab(visible_title[u'title'],
|
||||
plugin.settings_tab)
|
||||
else:
|
||||
log.debug(u'No tab settings in %s' % visible_title[u'title'])
|
||||
log.debug(
|
||||
u'No tab settings in %s' % visible_title[u'title'])
|
||||
|
||||
def hook_import_menu(self, import_menu):
|
||||
"""
|
||||
|
@ -29,11 +29,10 @@ format it for the output display.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtGui, QtCore, QtWebKit
|
||||
|
||||
from openlp.core.lib import resize_image, expand_tags, \
|
||||
build_lyrics_format_css, build_lyrics_outline_css, image_to_byte
|
||||
from PyQt4 import QtWebKit
|
||||
|
||||
from openlp.core.lib import expand_tags, build_lyrics_format_css, \
|
||||
build_lyrics_outline_css, Receiver
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -78,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)
|
||||
@ -93,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''
|
||||
@ -115,19 +121,26 @@ class Renderer(object):
|
||||
formatted = []
|
||||
html_text = u''
|
||||
styled_text = u''
|
||||
line_count = 0
|
||||
for line in text:
|
||||
styled_line = expand_tags(line)
|
||||
if styled_text:
|
||||
styled_text += line_end + styled_line
|
||||
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'</div></body></html>'
|
||||
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'<br>'):
|
||||
html_text = html_text[:len(html_text)-4]
|
||||
formatted.append(html_text)
|
||||
html_text = u''
|
||||
styled_text = styled_line
|
||||
html_text += line + line_end
|
||||
if line_break:
|
||||
if html_text.endswith(u'<br>'):
|
||||
html_text = html_text[:len(html_text)-4]
|
||||
formatted.append(html_text)
|
||||
log.debug(u'format_slide - End')
|
||||
|
@ -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,17 +210,21 @@ 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)
|
||||
if not self.force_page:
|
||||
self.display.buildHtml(serviceItem)
|
||||
raw_html = serviceItem.get_rendered_frame(0)
|
||||
preview = self.display.text(raw_html)
|
||||
@ -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):
|
||||
"""
|
||||
|
@ -32,9 +32,7 @@ import logging
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, resize_image, clean_tags, expand_tags
|
||||
from openlp.core.lib import build_icon, clean_tags, expand_tags
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -102,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):
|
||||
@ -214,7 +214,7 @@ class ServiceItem(object):
|
||||
self.service_item_type = ServiceItemType.Text
|
||||
title = title.split(u'\n')[0]
|
||||
self._raw_frames.append(
|
||||
{u'title': title, u'raw_slide': raw_slide, u'verseTag':verse_tag})
|
||||
{u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag})
|
||||
self._new_item()
|
||||
|
||||
def add_from_command(self, path, file_name, image):
|
||||
@ -232,7 +232,7 @@ class ServiceItem(object):
|
||||
"""
|
||||
self.service_item_type = ServiceItemType.Command
|
||||
self._raw_frames.append(
|
||||
{u'title': file_name, u'image':image, u'path': path})
|
||||
{u'title': file_name, u'image': image, u'path': path})
|
||||
self._new_item()
|
||||
|
||||
def get_service_repr(self):
|
||||
@ -243,17 +243,18 @@ class ServiceItem(object):
|
||||
service_header = {
|
||||
u'name': self.name.lower(),
|
||||
u'plugin': self.name,
|
||||
u'theme':self.theme,
|
||||
u'title':self.title,
|
||||
u'icon':self.icon,
|
||||
u'footer':self.raw_footer,
|
||||
u'type':self.service_item_type,
|
||||
u'audit':self.audit,
|
||||
u'notes':self.notes,
|
||||
u'from_plugin':self.from_plugin,
|
||||
u'capabilities':self.capabilities,
|
||||
u'search':self.search_string,
|
||||
u'data':self.data_string
|
||||
u'theme': self.theme,
|
||||
u'title': self.title,
|
||||
u'icon': self.icon,
|
||||
u'footer': self.raw_footer,
|
||||
u'type': self.service_item_type,
|
||||
u'audit': self.audit,
|
||||
u'notes': self.notes,
|
||||
u'from_plugin': self.from_plugin,
|
||||
u'capabilities': self.capabilities,
|
||||
u'search': self.search_string,
|
||||
u'data': self.data_string,
|
||||
u'xml_version': self.xml_version
|
||||
}
|
||||
service_data = []
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
@ -265,7 +266,7 @@ class ServiceItem(object):
|
||||
elif self.service_item_type == ServiceItemType.Command:
|
||||
for slide in self._raw_frames:
|
||||
service_data.append(
|
||||
{u'title':slide[u'title'], u'image':slide[u'image']})
|
||||
{u'title': slide[u'title'], u'image': slide[u'image']})
|
||||
return {u'header': service_header, u'data': service_data}
|
||||
|
||||
def set_from_service(self, serviceitem, path=None):
|
||||
@ -295,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)
|
||||
|
@ -28,52 +28,56 @@ 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 = \
|
||||
'''<?xml version="1.0" encoding="utf-8"?>
|
||||
<theme version="1.0">
|
||||
<name>BlankStyle</name>
|
||||
<background mode="transparent"/>
|
||||
<background type="solid" mode="opaque">
|
||||
<color>#000000</color>
|
||||
<name> </name>
|
||||
<background type="image">
|
||||
<filename></filename>
|
||||
</background>
|
||||
<background type="gradient" mode="opaque">
|
||||
<background type="gradient">
|
||||
<startColor>#000000</startColor>
|
||||
<endColor>#000000</endColor>
|
||||
<direction>vertical</direction>
|
||||
</background>
|
||||
<background type="image" mode="opaque">
|
||||
<filename></filename>
|
||||
<background type="solid">
|
||||
<color>#000000</color>
|
||||
</background>
|
||||
<font type="main">
|
||||
<name>Arial</name>
|
||||
<color>#000000</color>
|
||||
<proportion>30</proportion>
|
||||
<weight>Normal</weight>
|
||||
<color>#FFFFFF</color>
|
||||
<size>30</size>
|
||||
<bold>False</bold>
|
||||
<italics>False</italics>
|
||||
<line_adjustment>0</line_adjustment>
|
||||
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
|
||||
<outline outlineColor="#000000" outlineSize="2">False</outline>
|
||||
<location override="False" x="10" y="10" width="1004" height="690"/>
|
||||
</font>
|
||||
<font type="footer">
|
||||
<name>Arial</name>
|
||||
<color>#000000</color>
|
||||
<proportion>12</proportion>
|
||||
<weight>Normal</weight>
|
||||
<color>#FFFFFF</color>
|
||||
<size>12</size>
|
||||
<bold>False</bold>
|
||||
<italics>False</italics>
|
||||
<line_adjustment>0</line_adjustment>
|
||||
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
|
||||
<outline outlineColor="#000000" outlineSize="2">False</outline>
|
||||
<location override="False" x="10" y="690" width="1004" height="78"/>
|
||||
</font>
|
||||
<display>
|
||||
<shadow color="#000000" size="5">True</shadow>
|
||||
<outline color="#000000" size="2">False</outline>
|
||||
<horizontalAlign>0</horizontalAlign>
|
||||
<verticalAlign>0</verticalAlign>
|
||||
<wrapStyle>0</wrapStyle>
|
||||
<slideTransition>False</slideTransition>
|
||||
</display>
|
||||
</theme>
|
||||
@ -87,10 +91,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 +174,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 +183,21 @@ class ThemeXML(object):
|
||||
``path``
|
||||
The path name to be added.
|
||||
"""
|
||||
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 +219,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 +237,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 +254,15 @@ 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,88 @@ 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', 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 +409,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 +427,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,47 +436,95 @@ 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'_'
|
||||
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' ):
|
||||
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)
|
||||
self._create_attr(master, element.tag + u'_'+ e[0], e[1])
|
||||
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:
|
||||
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:
|
||||
setattr(self, master + field, unicode(value))
|
||||
# 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, tag, unicode(value).strip().lstrip())
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
@ -427,3 +543,58 @@ class ThemeXML(object):
|
||||
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()
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
@ -51,10 +51,11 @@ from advancedtab import AdvancedTab
|
||||
from aboutform import AboutForm
|
||||
from pluginform import PluginForm
|
||||
from settingsform import SettingsForm
|
||||
from shortcutlistform import ShortcutListForm
|
||||
from mediadockmanager import MediaDockManager
|
||||
from servicemanager import ServiceManager
|
||||
from thememanager import ThemeManager
|
||||
|
||||
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm',
|
||||
'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager',
|
||||
'AmendThemeForm', 'MediaDockManager', 'ServiceItemEditForm']
|
||||
'MediaDockManager', 'ServiceItemEditForm']
|
||||
|
@ -81,9 +81,13 @@ 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(u'expandServiceItemCheckBox')
|
||||
self.expandServiceItemCheckBox.setObjectName(
|
||||
u'expandServiceItemCheckBox')
|
||||
self.uiLayout.addWidget(self.expandServiceItemCheckBox)
|
||||
# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftWidget)
|
||||
# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
|
||||
@ -142,7 +146,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(
|
||||
|
@ -90,6 +90,16 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
||||
QtCore.QObject.connect(self.fontMainSizeSpinBox,
|
||||
QtCore.SIGNAL(u'editingFinished()'),
|
||||
self.onFontMainSizeSpinBoxChanged)
|
||||
QtCore.QObject.connect(self.fontMainLineAdjustmentSpinBox,
|
||||
QtCore.SIGNAL(u'editingFinished()'),
|
||||
self.onFontMainLineAdjustmentSpinBoxChanged)
|
||||
QtCore.QObject.connect(self.shadowSpinBox,
|
||||
QtCore.SIGNAL(u'editingFinished()'),
|
||||
self.onShadowSpinBoxChanged)
|
||||
QtCore.QObject.connect(self.outlineSpinBox,
|
||||
QtCore.SIGNAL(u'editingFinished()'),
|
||||
self.onOutlineSpinBoxChanged)
|
||||
|
||||
QtCore.QObject.connect(self.fontFooterSizeSpinBox,
|
||||
QtCore.SIGNAL(u'editingFinished()'),
|
||||
self.onFontFooterSizeSpinBoxChanged)
|
||||
@ -118,12 +128,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
||||
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)'),
|
||||
@ -525,7 +530,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
||||
else:
|
||||
self.gradientComboBox.setCurrentIndex(2)
|
||||
# Font Main Tab
|
||||
self.fontMainComboBox.setCurrentFont(
|
||||
self.mainFontComboBox.setCurrentFont(
|
||||
QtGui.QFont(self.theme.font_main_name))
|
||||
self.fontMainSizeSpinBox.setValue(self.theme.font_main_proportion)
|
||||
if not self.theme.font_main_italics and \
|
||||
|
@ -34,7 +34,8 @@ class Ui_FileRenameDialog(object):
|
||||
FileRenameDialog.resize(400, 87)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(210, 50, 171, 25))
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
|
||||
QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.widget = QtGui.QWidget(FileRenameDialog)
|
||||
self.widget.setGeometry(QtCore.QRect(10, 10, 381, 35))
|
||||
|
@ -30,13 +30,13 @@ import os
|
||||
from PyQt4 import QtCore, QtGui, QtWebKit
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
from openlp.core.lib import Receiver, resize_image, build_html, ServiceItem, \
|
||||
image_to_byte
|
||||
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte
|
||||
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):
|
||||
"""
|
||||
@ -100,7 +100,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 |
|
||||
@ -381,8 +381,8 @@ class MainDisplay(DisplayWidget):
|
||||
if self.isLive:
|
||||
self.setVisible(True)
|
||||
# if was hidden keep it hidden
|
||||
if self.hide_mode and self.isLive:
|
||||
self.hideDisplay(self.hide_mode)
|
||||
if self.hideMode and self.isLive:
|
||||
self.hideDisplay(self.hideMode)
|
||||
preview = QtGui.QImage(self.screen[u'size'].width(),
|
||||
self.screen[u'size'].height(),
|
||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
||||
@ -412,8 +412,8 @@ class MainDisplay(DisplayWidget):
|
||||
if serviceItem.foot_text and serviceItem.foot_text:
|
||||
self.footer(serviceItem.foot_text)
|
||||
# if was hidden keep it hidden
|
||||
if self.hide_mode and self.isLive:
|
||||
self.hideDisplay(self.hide_mode)
|
||||
if self.hideMode and self.isLive:
|
||||
self.hideDisplay(self.hideMode)
|
||||
|
||||
def footer(self, text):
|
||||
"""
|
||||
@ -444,7 +444,7 @@ class MainDisplay(DisplayWidget):
|
||||
self.setVisible(True)
|
||||
if self.phononActive:
|
||||
self.webView.setVisible(True)
|
||||
self.hide_mode = mode
|
||||
self.hideMode = mode
|
||||
|
||||
def showDisplay(self):
|
||||
"""
|
||||
@ -459,9 +459,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):
|
||||
"""
|
||||
|
@ -29,10 +29,12 @@ import logging
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
|
||||
ThemeManager, SlideController, PluginForm, MediaDockManager
|
||||
ThemeManager, SlideController, PluginForm, MediaDockManager, \
|
||||
ShortcutListForm
|
||||
from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
|
||||
SettingsManager, PluginManager, Receiver, translate
|
||||
from openlp.core.utils import AppLocation, add_actions, LanguageManager
|
||||
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
|
||||
ActionList
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -73,6 +75,7 @@ class Ui_MainWindow(object):
|
||||
MainWindow.setSizePolicy(sizePolicy)
|
||||
MainIcon = build_icon(u':/icon/openlp-logo-16x16.png')
|
||||
MainWindow.setWindowIcon(MainIcon)
|
||||
self.setDockNestingEnabled(True)
|
||||
# Set up the main container, which contains all the other form widgets
|
||||
self.MainContent = QtGui.QWidget(MainWindow)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
|
||||
@ -98,6 +101,12 @@ class Ui_MainWindow(object):
|
||||
self.screens)
|
||||
self.LiveController = SlideController(self, self.settingsmanager,
|
||||
self.screens, True)
|
||||
previewVisible = QtCore.QSettings().value(
|
||||
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
|
||||
self.PreviewController.Panel.setVisible(previewVisible)
|
||||
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
|
||||
QtCore.QVariant(True)).toBool()
|
||||
self.LiveController.Panel.setVisible(liveVisible)
|
||||
# Create menu
|
||||
self.MenuBar = QtGui.QMenuBar(MainWindow)
|
||||
self.MenuBar.setGeometry(QtCore.QRect(0, 0, 1087, 27))
|
||||
@ -177,29 +186,34 @@ class Ui_MainWindow(object):
|
||||
self.FileNewItem = QtGui.QAction(MainWindow)
|
||||
self.FileNewItem.setIcon(build_icon(u':/general/general_new.png'))
|
||||
self.FileNewItem.setObjectName(u'FileNewItem')
|
||||
MainWindow.actionList.add_action(self.FileNewItem, u'File')
|
||||
self.FileOpenItem = QtGui.QAction(MainWindow)
|
||||
self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png'))
|
||||
self.FileOpenItem.setObjectName(u'FileOpenItem')
|
||||
MainWindow.actionList.add_action(self.FileOpenItem, u'File')
|
||||
self.FileSaveItem = QtGui.QAction(MainWindow)
|
||||
self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png'))
|
||||
self.FileSaveItem.setObjectName(u'FileSaveItem')
|
||||
MainWindow.actionList.add_action(self.FileSaveItem, u'File')
|
||||
self.FileSaveAsItem = QtGui.QAction(MainWindow)
|
||||
self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
|
||||
MainWindow.actionList.add_action(self.FileSaveAsItem, u'File')
|
||||
self.FileExitItem = QtGui.QAction(MainWindow)
|
||||
self.FileExitItem.setIcon(build_icon(u':/system/system_exit.png'))
|
||||
self.FileExitItem.setObjectName(u'FileExitItem')
|
||||
MainWindow.actionList.add_action(self.FileExitItem, u'File')
|
||||
self.ImportThemeItem = QtGui.QAction(MainWindow)
|
||||
self.ImportThemeItem.setObjectName(u'ImportThemeItem')
|
||||
MainWindow.actionList.add_action(self.ImportThemeItem, u'Import')
|
||||
self.ImportLanguageItem = QtGui.QAction(MainWindow)
|
||||
self.ImportLanguageItem.setObjectName(u'ImportLanguageItem')
|
||||
MainWindow.actionList.add_action(self.ImportLanguageItem, u'Import')
|
||||
self.ExportThemeItem = QtGui.QAction(MainWindow)
|
||||
self.ExportThemeItem.setObjectName(u'ExportThemeItem')
|
||||
MainWindow.actionList.add_action(self.ExportThemeItem, u'Export')
|
||||
self.ExportLanguageItem = QtGui.QAction(MainWindow)
|
||||
self.ExportLanguageItem.setObjectName(u'ExportLanguageItem')
|
||||
self.SettingsConfigureItem = QtGui.QAction(MainWindow)
|
||||
self.SettingsConfigureItem.setIcon(
|
||||
build_icon(u':/system/system_settings.png'))
|
||||
self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
|
||||
MainWindow.actionList.add_action(self.ExportLanguageItem, u'Export')
|
||||
self.ViewMediaManagerItem = QtGui.QAction(MainWindow)
|
||||
self.ViewMediaManagerItem.setCheckable(True)
|
||||
self.ViewMediaManagerItem.setChecked(self.MediaManagerDock.isVisible())
|
||||
@ -212,6 +226,7 @@ class Ui_MainWindow(object):
|
||||
self.ViewThemeManagerItem.setIcon(
|
||||
build_icon(u':/system/system_thememanager.png'))
|
||||
self.ViewThemeManagerItem.setObjectName(u'ViewThemeManagerItem')
|
||||
MainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View')
|
||||
self.ViewServiceManagerItem = QtGui.QAction(MainWindow)
|
||||
self.ViewServiceManagerItem.setCheckable(True)
|
||||
self.ViewServiceManagerItem.setChecked(
|
||||
@ -219,28 +234,49 @@ class Ui_MainWindow(object):
|
||||
self.ViewServiceManagerItem.setIcon(
|
||||
build_icon(u':/system/system_servicemanager.png'))
|
||||
self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem')
|
||||
MainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View')
|
||||
self.ViewPreviewPanel = QtGui.QAction(MainWindow)
|
||||
self.ViewPreviewPanel.setCheckable(True)
|
||||
self.ViewPreviewPanel.setChecked(previewVisible)
|
||||
self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
|
||||
MainWindow.actionList.add_action(self.ViewPreviewPanel, u'View')
|
||||
self.ViewLivePanel = QtGui.QAction(MainWindow)
|
||||
self.ViewLivePanel.setCheckable(True)
|
||||
self.ViewLivePanel.setChecked(liveVisible)
|
||||
self.ViewLivePanel.setObjectName(u'ViewLivePanel')
|
||||
MainWindow.actionList.add_action(self.ViewLivePanel, u'View')
|
||||
self.ModeDefaultItem = QtGui.QAction(MainWindow)
|
||||
self.ModeDefaultItem.setCheckable(True)
|
||||
self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
|
||||
MainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode')
|
||||
self.ModeSetupItem = QtGui.QAction(MainWindow)
|
||||
self.ModeSetupItem.setCheckable(True)
|
||||
self.ModeSetupItem.setObjectName(u'ModeLiveItem')
|
||||
MainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode')
|
||||
self.ModeLiveItem = QtGui.QAction(MainWindow)
|
||||
self.ModeLiveItem.setCheckable(True)
|
||||
self.ModeLiveItem.setObjectName(u'ModeLiveItem')
|
||||
MainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode')
|
||||
self.ModeGroup = QtGui.QActionGroup(MainWindow)
|
||||
self.ModeGroup.addAction(self.ModeDefaultItem)
|
||||
self.ModeGroup.addAction(self.ModeSetupItem)
|
||||
self.ModeGroup.addAction(self.ModeLiveItem)
|
||||
self.ModeDefaultItem.setChecked(True)
|
||||
self.ToolsAddToolItem = QtGui.QAction(MainWindow)
|
||||
self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
|
||||
self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
|
||||
MainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools')
|
||||
self.SettingsPluginListItem = QtGui.QAction(MainWindow)
|
||||
self.SettingsPluginListItem.setIcon(
|
||||
build_icon(u':/system/settings_plugin_list.png'))
|
||||
self.SettingsPluginListItem.setObjectName(u'SettingsPluginListItem')
|
||||
self.HelpDocumentationItem = QtGui.QAction(MainWindow)
|
||||
self.HelpDocumentationItem.setIcon(
|
||||
build_icon(u':/system/system_help_contents.png'))
|
||||
self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
|
||||
self.HelpDocumentationItem.setEnabled(False)
|
||||
self.HelpAboutItem = QtGui.QAction(MainWindow)
|
||||
self.HelpAboutItem.setIcon(
|
||||
build_icon(u':/system/system_about.png'))
|
||||
self.HelpAboutItem.setObjectName(u'HelpAboutItem')
|
||||
self.HelpOnlineHelpItem = QtGui.QAction(MainWindow)
|
||||
self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
|
||||
self.HelpOnlineHelpItem.setEnabled(False)
|
||||
self.HelpWebSiteItem = QtGui.QAction(MainWindow)
|
||||
self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
|
||||
MainWindow.actionList.add_action(self.SettingsPluginListItem,
|
||||
u'Settings')
|
||||
#i18n Language Items
|
||||
self.AutoLanguageItem = QtGui.QAction(MainWindow)
|
||||
self.AutoLanguageItem.setObjectName(u'AutoLanguageItem')
|
||||
self.AutoLanguageItem.setCheckable(True)
|
||||
MainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings')
|
||||
self.LanguageGroup = QtGui.QActionGroup(MainWindow)
|
||||
qmList = LanguageManager.get_qm_list()
|
||||
savedLanguage = LanguageManager.get_language()
|
||||
@ -253,37 +289,34 @@ class Ui_MainWindow(object):
|
||||
languageItem.setChecked(True)
|
||||
add_actions(self.LanguageGroup, [languageItem])
|
||||
self.LanguageGroup.setDisabled(LanguageManager.auto_language)
|
||||
self.ToolsAddToolItem = QtGui.QAction(MainWindow)
|
||||
self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
|
||||
self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
|
||||
self.ViewPreviewPanel = QtGui.QAction(MainWindow)
|
||||
self.ViewPreviewPanel.setCheckable(True)
|
||||
previewVisible = QtCore.QSettings().value(
|
||||
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
|
||||
self.ViewPreviewPanel.setChecked(previewVisible)
|
||||
self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
|
||||
self.PreviewController.Panel.setVisible(previewVisible)
|
||||
self.ViewLivePanel = QtGui.QAction(MainWindow)
|
||||
self.ViewLivePanel.setCheckable(True)
|
||||
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
|
||||
QtCore.QVariant(True)).toBool()
|
||||
self.ViewLivePanel.setChecked(liveVisible)
|
||||
self.ViewLivePanel.setObjectName(u'ViewLivePanel')
|
||||
self.LiveController.Panel.setVisible(liveVisible)
|
||||
self.ModeDefaultItem = QtGui.QAction(MainWindow)
|
||||
self.ModeDefaultItem.setCheckable(True)
|
||||
self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
|
||||
self.ModeSetupItem = QtGui.QAction(MainWindow)
|
||||
self.ModeSetupItem.setCheckable(True)
|
||||
self.ModeSetupItem.setObjectName(u'ModeLiveItem')
|
||||
self.ModeLiveItem = QtGui.QAction(MainWindow)
|
||||
self.ModeLiveItem.setCheckable(True)
|
||||
self.ModeLiveItem.setObjectName(u'ModeLiveItem')
|
||||
self.ModeGroup = QtGui.QActionGroup(MainWindow)
|
||||
self.ModeGroup.addAction(self.ModeDefaultItem)
|
||||
self.ModeGroup.addAction(self.ModeSetupItem)
|
||||
self.ModeGroup.addAction(self.ModeLiveItem)
|
||||
self.ModeDefaultItem.setChecked(True)
|
||||
self.SettingsShortcutsItem = QtGui.QAction(MainWindow)
|
||||
self.SettingsShortcutsItem.setIcon(
|
||||
build_icon(u':/system/system_configure_shortcuts.png'))
|
||||
self.SettingsShortcutsItem.setObjectName(u'SettingsShortcutsItem')
|
||||
self.SettingsConfigureItem = QtGui.QAction(MainWindow)
|
||||
self.SettingsConfigureItem.setIcon(
|
||||
build_icon(u':/system/system_settings.png'))
|
||||
self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
|
||||
MainWindow.actionList.add_action(self.SettingsShortcutsItem,
|
||||
u'Settings')
|
||||
self.HelpDocumentationItem = QtGui.QAction(MainWindow)
|
||||
self.HelpDocumentationItem.setIcon(
|
||||
build_icon(u':/system/system_help_contents.png'))
|
||||
self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
|
||||
self.HelpDocumentationItem.setEnabled(False)
|
||||
MainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help')
|
||||
self.HelpAboutItem = QtGui.QAction(MainWindow)
|
||||
self.HelpAboutItem.setIcon(
|
||||
build_icon(u':/system/system_about.png'))
|
||||
self.HelpAboutItem.setObjectName(u'HelpAboutItem')
|
||||
MainWindow.actionList.add_action(self.HelpAboutItem, u'Help')
|
||||
self.HelpOnlineHelpItem = QtGui.QAction(MainWindow)
|
||||
self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
|
||||
self.HelpOnlineHelpItem.setEnabled(False)
|
||||
MainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help')
|
||||
self.HelpWebSiteItem = QtGui.QAction(MainWindow)
|
||||
self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
|
||||
MainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help')
|
||||
add_actions(self.FileImportMenu,
|
||||
(self.ImportThemeItem, self.ImportLanguageItem))
|
||||
add_actions(self.FileExportMenu,
|
||||
@ -303,7 +336,7 @@ class Ui_MainWindow(object):
|
||||
add_actions(self.SettingsLanguageMenu, self.LanguageGroup.actions())
|
||||
add_actions(self.SettingsMenu, (self.SettingsPluginListItem,
|
||||
self.SettingsLanguageMenu.menuAction(), None,
|
||||
self.SettingsConfigureItem))
|
||||
self.SettingsShortcutsItem, self.SettingsConfigureItem))
|
||||
add_actions(self.ToolsMenu,
|
||||
(self.ToolsAddToolItem, None))
|
||||
add_actions(self.HelpMenu,
|
||||
@ -394,6 +427,8 @@ class Ui_MainWindow(object):
|
||||
translate('OpenLP.MainWindow', '&Theme'))
|
||||
self.ExportLanguageItem.setText(
|
||||
translate('OpenLP.MainWindow', '&Language'))
|
||||
self.SettingsShortcutsItem.setText(
|
||||
translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
|
||||
self.SettingsConfigureItem.setText(
|
||||
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
|
||||
self.ViewMediaManagerItem.setText(
|
||||
@ -488,6 +523,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
log.info(u'MainWindow loaded')
|
||||
|
||||
actionList = ActionList()
|
||||
|
||||
def __init__(self, screens, applicationVersion):
|
||||
"""
|
||||
This constructor sets up the interface, the various managers, and the
|
||||
@ -495,6 +532,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
QtGui.QMainWindow.__init__(self)
|
||||
self.screens = screens
|
||||
self.actionList = ActionList()
|
||||
self.applicationVersion = applicationVersion
|
||||
# Set up settings sections for the main application
|
||||
# (not for use by plugins)
|
||||
@ -506,6 +544,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.settingsmanager = SettingsManager(screens)
|
||||
self.aboutForm = AboutForm(self, applicationVersion)
|
||||
self.settingsForm = SettingsForm(self.screens, self, self)
|
||||
self.shortcutForm = ShortcutListForm(self)
|
||||
self.recentFiles = QtCore.QStringList()
|
||||
# Set up the path with plugins
|
||||
pluginpath = AppLocation.get_directory(AppLocation.PluginsDir)
|
||||
@ -551,7 +590,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.QObject.connect(self.SettingsPluginListItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked)
|
||||
QtCore.QObject.connect(self.SettingsConfigureItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked)
|
||||
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
|
||||
QtCore.QObject.connect(self.SettingsShortcutsItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onSettingsShortcutsItemClicked)
|
||||
QtCore.QObject.connect(self.FileNewItem, QtCore.SIGNAL(u'triggered()'),
|
||||
self.ServiceManagerContents.onNewService)
|
||||
QtCore.QObject.connect(self.FileOpenItem,
|
||||
@ -563,7 +604,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.QObject.connect(self.FileSaveAsItem,
|
||||
QtCore.SIGNAL(u'triggered()'),
|
||||
self.ServiceManagerContents.onSaveService)
|
||||
#i18n set signals for languages
|
||||
# i18n set signals for languages
|
||||
QtCore.QObject.connect(self.AutoLanguageItem,
|
||||
QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage)
|
||||
self.LanguageGroup.triggered.connect(LanguageManager.set_language)
|
||||
@ -583,15 +624,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'maindisplay_status_text'), self.showStatusMessage)
|
||||
#warning cyclic dependency
|
||||
#RenderManager needs to call ThemeManager and
|
||||
#ThemeManager needs to call RenderManager
|
||||
# warning cyclic dependency
|
||||
# RenderManager needs to call ThemeManager and
|
||||
# ThemeManager needs to call RenderManager
|
||||
self.RenderManager = RenderManager(
|
||||
self.ThemeManagerContents, self.screens)
|
||||
#Define the media Dock Manager
|
||||
# Define the media Dock Manager
|
||||
self.mediaDockManager = MediaDockManager(self.MediaToolBox)
|
||||
log.info(u'Load Plugins')
|
||||
#make the controllers available to the plugins
|
||||
# make the controllers available to the plugins
|
||||
self.plugin_helpers[u'preview'] = self.PreviewController
|
||||
self.plugin_helpers[u'live'] = self.LiveController
|
||||
self.plugin_helpers[u'render'] = self.RenderManager
|
||||
@ -712,12 +753,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.pluginForm.load()
|
||||
self.pluginForm.exec_()
|
||||
|
||||
def onOptionsSettingsItemClicked(self):
|
||||
def onSettingsConfigureItemClicked(self):
|
||||
"""
|
||||
Show the Settings dialog
|
||||
"""
|
||||
self.settingsForm.exec_()
|
||||
|
||||
def onSettingsShortcutsItemClicked(self):
|
||||
"""
|
||||
Show the shortcuts dialog
|
||||
"""
|
||||
self.shortcutForm.exec_(self.actionList)
|
||||
|
||||
def onModeDefaultItemClicked(self):
|
||||
"""
|
||||
Put OpenLP into "Default" view mode.
|
||||
@ -808,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):
|
||||
|
@ -107,7 +107,8 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
if self.pluginListWidget.currentItem() is None:
|
||||
self._clearDetails()
|
||||
return
|
||||
plugin_name_plural = self.pluginListWidget.currentItem().text().split(u' ')[0]
|
||||
plugin_name_plural = \
|
||||
self.pluginListWidget.currentItem().text().split(u' ')[0]
|
||||
self.activePlugin = None
|
||||
for plugin in self.parent.plugin_manager.plugins:
|
||||
name_string = plugin.getString(StringContent.Name)
|
||||
|
@ -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(
|
||||
@ -203,13 +204,13 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.orderToolbar.addSeparator()
|
||||
self.orderToolbar.addToolbarButton(
|
||||
translate('OpenLP.ServiceManager', '&Expand all'),
|
||||
u':/services/service_top.png',
|
||||
u':/services/service_expand_all.png',
|
||||
translate('OpenLP.ServiceManager',
|
||||
'Expand all the service items.'),
|
||||
self.onExpandAll)
|
||||
self.orderToolbar.addToolbarButton(
|
||||
translate('OpenLP.ServiceManager', '&Collapse all'),
|
||||
u':/services/service_bottom.png',
|
||||
u':/services/service_collapse_all.png',
|
||||
translate('OpenLP.ServiceManager',
|
||||
'Collapse all the service items.'),
|
||||
self.onCollapseAll)
|
||||
@ -306,8 +307,8 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.editAction.setVisible(False)
|
||||
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'):
|
||||
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit)\
|
||||
and serviceItem[u'service_item'].edit_id:
|
||||
self.editAction.setVisible(True)
|
||||
if serviceItem[u'service_item']\
|
||||
.is_capable(ItemCapabilities.AllowsMaintain):
|
||||
@ -441,7 +442,8 @@ class ServiceManager(QtGui.QWidget):
|
||||
if setSelected:
|
||||
setSelected = False
|
||||
serviceIterator.value().setSelected(True)
|
||||
elif serviceIterator.value() and serviceIterator.value().isSelected():
|
||||
elif serviceIterator.value() and \
|
||||
serviceIterator.value().isSelected():
|
||||
serviceIterator.value().setSelected(False)
|
||||
setSelected = True
|
||||
serviceIterator += 1
|
||||
@ -761,7 +763,8 @@ class ServiceManager(QtGui.QWidget):
|
||||
serviceitem.set_from_service(item, self.servicePath)
|
||||
self.validateItem(serviceitem)
|
||||
self.addServiceItem(serviceitem)
|
||||
if serviceitem.is_capable(ItemCapabilities.OnLoadUpdate):
|
||||
if serviceitem.is_capable(
|
||||
ItemCapabilities.OnLoadUpdate):
|
||||
Receiver.send_message(u'%s_service_load' %
|
||||
serviceitem.name.lower(), serviceitem)
|
||||
try:
|
||||
@ -786,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):
|
||||
"""
|
||||
@ -861,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):
|
||||
"""
|
||||
@ -870,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
|
||||
@ -888,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()
|
||||
@ -980,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):
|
||||
"""
|
||||
@ -1025,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:
|
||||
|
114
openlp/core/ui/shortcutlistdialog.py
Normal file
@ -0,0 +1,114 @@
|
||||
# -*- 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_ShortcutListDialog(object):
|
||||
def setupUi(self, shortcutListDialog):
|
||||
shortcutListDialog.setObjectName(u'shortcutListDialog')
|
||||
shortcutListDialog.resize(500, 438)
|
||||
self.shortcutListLayout = QtGui.QVBoxLayout(shortcutListDialog)
|
||||
self.shortcutListLayout.setSpacing(8)
|
||||
self.shortcutListLayout.setMargin(8)
|
||||
self.shortcutListLayout.setObjectName(u'shortcutListLayout')
|
||||
self.shortcutListTreeWidget = QtGui.QTreeWidget(shortcutListDialog)
|
||||
self.shortcutListTreeWidget.setAlternatingRowColors(True)
|
||||
self.shortcutListTreeWidget.setObjectName(u'shortcutListTreeWidget')
|
||||
self.shortcutListTreeWidget.setColumnCount(2)
|
||||
self.shortcutListTreeWidget.setSelectionBehavior(
|
||||
QtGui.QAbstractItemView.SelectRows)
|
||||
self.shortcutListLayout.addWidget(self.shortcutListTreeWidget)
|
||||
self.shortcutLayout = QtGui.QVBoxLayout()
|
||||
self.shortcutLayout.setSpacing(8)
|
||||
self.shortcutLayout.setContentsMargins(0, -1, -1, -1)
|
||||
self.shortcutLayout.setObjectName(u'shortcutLayout')
|
||||
self.defaultRadioButton = QtGui.QRadioButton(shortcutListDialog)
|
||||
self.defaultRadioButton.setChecked(True)
|
||||
self.defaultRadioButton.setObjectName(u'defaultRadioButton')
|
||||
self.shortcutLayout.addWidget(self.defaultRadioButton)
|
||||
self.customShortcutLayout = QtGui.QHBoxLayout()
|
||||
self.customShortcutLayout.setSpacing(8)
|
||||
self.customShortcutLayout.setObjectName(u'customShortcutLayout')
|
||||
self.customRadioButton = QtGui.QRadioButton(shortcutListDialog)
|
||||
self.customRadioButton.setObjectName(u'customRadioButton')
|
||||
self.customShortcutLayout.addWidget(self.customRadioButton)
|
||||
self.shortcutPushButton = QtGui.QPushButton(shortcutListDialog)
|
||||
self.shortcutPushButton.setMinimumSize(QtCore.QSize(84, 0))
|
||||
self.shortcutPushButton.setIcon(
|
||||
build_icon(u':/system/system_configure_shortcuts.png'))
|
||||
self.shortcutPushButton.setCheckable(True)
|
||||
self.shortcutPushButton.setChecked(False)
|
||||
self.shortcutPushButton.setObjectName(u'shortcutPushButton')
|
||||
self.customShortcutLayout.addWidget(self.shortcutPushButton)
|
||||
self.clearShortcutToolButton = QtGui.QToolButton(shortcutListDialog)
|
||||
self.clearShortcutToolButton.setMinimumSize(QtCore.QSize(0, 16))
|
||||
self.clearShortcutToolButton.setText(u'')
|
||||
self.clearShortcutToolButton.setIcon(
|
||||
build_icon(u':/system/clear_shortcut.png'))
|
||||
self.clearShortcutToolButton.setObjectName(u'clearShortcutToolButton')
|
||||
self.customShortcutLayout.addWidget(self.clearShortcutToolButton)
|
||||
self.customShortcutSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.customShortcutLayout.addItem(self.customShortcutSpacer)
|
||||
self.shortcutLayout.addLayout(self.customShortcutLayout)
|
||||
self.shortcutListLayout.addLayout(self.shortcutLayout)
|
||||
self.shortcutListButtonBox = QtGui.QDialogButtonBox(shortcutListDialog)
|
||||
self.shortcutListButtonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.shortcutListButtonBox.setStandardButtons(
|
||||
QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok |
|
||||
QtGui.QDialogButtonBox.Reset)
|
||||
self.shortcutListButtonBox.setObjectName(u'shortcutListButtonBox')
|
||||
self.shortcutListLayout.addWidget(self.shortcutListButtonBox)
|
||||
|
||||
self.retranslateUi(shortcutListDialog)
|
||||
QtCore.QObject.connect(
|
||||
self.shortcutListButtonBox,
|
||||
QtCore.SIGNAL(u'accepted()'),
|
||||
shortcutListDialog.accept
|
||||
)
|
||||
QtCore.QObject.connect(
|
||||
self.shortcutListButtonBox,
|
||||
QtCore.SIGNAL(u'rejected()'),
|
||||
shortcutListDialog.reject
|
||||
)
|
||||
QtCore.QMetaObject.connectSlotsByName(shortcutListDialog)
|
||||
|
||||
def retranslateUi(self, shortcutListDialog):
|
||||
shortcutListDialog.setWindowTitle(
|
||||
translate('OpenLP.ShortcutListDialog', 'Customize Shortcuts'))
|
||||
self.shortcutListTreeWidget.setHeaderLabels([
|
||||
translate('OpenLP.ShortcutListDialog', 'Action'),
|
||||
translate('OpenLP.ShortcutListDialog', 'Shortcut')
|
||||
])
|
||||
self.defaultRadioButton.setText(
|
||||
translate('OpenLP.ShortcutListDialog', 'Default: %s'))
|
||||
self.customRadioButton.setText(
|
||||
translate('OpenLP.ShortcutListDialog', 'Custom:'))
|
||||
self.shortcutPushButton.setText(
|
||||
translate('OpenLP.ShortcutListDialog', 'None'))
|
||||
|
110
openlp/core/ui/shortcutlistform.py
Normal file
@ -0,0 +1,110 @@
|
||||
# -*- 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 re
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.utils import translate
|
||||
from shortcutlistdialog import Ui_ShortcutListDialog
|
||||
|
||||
REMOVE_AMPERSAND = re.compile(r'&{1}')
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
"""
|
||||
The shortcut list dialog
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Do some initialisation stuff
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.actionList = None
|
||||
self.captureShortcut = False
|
||||
QtCore.QObject.connect(
|
||||
self.shortcutPushButton,
|
||||
QtCore.SIGNAL(u'toggled(bool)'),
|
||||
self.onShortcutPushButtonClicked
|
||||
)
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
Qt = QtCore.Qt
|
||||
if not self.captureShortcut:
|
||||
return
|
||||
key = event.key()
|
||||
if key == Qt.Key_Shift or key == Qt.Key_Control or \
|
||||
key == Qt.Key_Meta or key == Qt.Key_Alt:
|
||||
return
|
||||
key_string = QtGui.QKeySequence(key).toString()
|
||||
if event.modifiers() & Qt.ControlModifier == Qt.ControlModifier:
|
||||
key_string = u'Ctrl+' + key_string
|
||||
if event.modifiers() & Qt.AltModifier == Qt.AltModifier:
|
||||
key_string = u'Alt+' + key_string
|
||||
if event.modifiers() & Qt.ShiftModifier == Qt.ShiftModifier:
|
||||
key_string = u'Shift+' + key_string
|
||||
key_sequence = QtGui.QKeySequence(key_string)
|
||||
existing_key = QtGui.QKeySequence("Ctrl+Shift+F8")
|
||||
if key_sequence == existing_key:
|
||||
QtGui.QMessageBox.warning(
|
||||
self,
|
||||
translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
|
||||
unicode(translate('OpenLP.ShortcutListDialog', 'The shortcut '
|
||||
'"%s" is already assigned to another action, please '
|
||||
'use a different shortcut.')) % key_sequence.toString(),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
|
||||
QtGui.QMessageBox.Ok
|
||||
)
|
||||
else:
|
||||
self.shortcutPushButton.setText(key_sequence.toString())
|
||||
self.shortcutPushButton.setChecked(False)
|
||||
self.captureShortcut = False
|
||||
|
||||
def exec_(self, actionList):
|
||||
self.actionList = actionList
|
||||
self.refreshActions()
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def refreshActions(self):
|
||||
self.shortcutListTreeWidget.clear()
|
||||
for category in self.actionList.categories:
|
||||
item = QtGui.QTreeWidgetItem([category.name])
|
||||
for action in category.actions:
|
||||
actionText = REMOVE_AMPERSAND.sub('', unicode(action.text()))
|
||||
shortcutText = action.shortcut().toString()
|
||||
actionItem = QtGui.QTreeWidgetItem([actionText, shortcutText])
|
||||
actionItem.setIcon(0, action.icon())
|
||||
item.addChild(actionItem)
|
||||
item.setExpanded(True)
|
||||
self.shortcutListTreeWidget.addTopLevelItem(item)
|
||||
|
||||
def onShortcutPushButtonClicked(self, toggled):
|
||||
self.captureShortcut = toggled
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4.phonon import Phonon
|
||||
@ -332,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.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick)
|
||||
if isLive:
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
||||
@ -392,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):
|
||||
"""
|
||||
@ -434,8 +433,12 @@ class SlideController(QtGui.QWidget):
|
||||
request = unicode(self.sender().text())
|
||||
slideno = self.slideList[request]
|
||||
if slideno > self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount())
|
||||
self.PreviewListWidget.selectRow(
|
||||
self.PreviewListWidget.rowCount() - 1)
|
||||
else:
|
||||
if slideno + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(slideno + 1, 0))
|
||||
self.PreviewListWidget.selectRow(slideno)
|
||||
self.onSlideSelected()
|
||||
|
||||
@ -527,6 +530,9 @@ class SlideController(QtGui.QWidget):
|
||||
log.debug(u'addServiceManagerItem live = %s' % self.isLive)
|
||||
# If service item is the same as the current on only change slide
|
||||
if item.__eq__(self.serviceItem):
|
||||
if slideno + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(slideno + 1, 0))
|
||||
self.PreviewListWidget.selectRow(slideno)
|
||||
self.onSlideSelected()
|
||||
return
|
||||
@ -608,8 +614,12 @@ class SlideController(QtGui.QWidget):
|
||||
self.PreviewListWidget.setColumnWidth(0,
|
||||
self.PreviewListWidget.viewport().size().width())
|
||||
if slideno > self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount())
|
||||
self.PreviewListWidget.selectRow(
|
||||
self.PreviewListWidget.rowCount() - 1)
|
||||
else:
|
||||
if slideno + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(slideno + 1, 0))
|
||||
self.PreviewListWidget.selectRow(slideno)
|
||||
self.enableToolBar(serviceItem)
|
||||
# Pass to display for viewing
|
||||
@ -668,6 +678,9 @@ class SlideController(QtGui.QWidget):
|
||||
[self.serviceItem, self.isLive, index])
|
||||
self.updatePreview()
|
||||
else:
|
||||
if index + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(index + 1, 0))
|
||||
self.PreviewListWidget.selectRow(index)
|
||||
self.onSlideSelected()
|
||||
|
||||
@ -780,8 +793,10 @@ class SlideController(QtGui.QWidget):
|
||||
row = self.PreviewListWidget.currentRow()
|
||||
self.selectedRow = 0
|
||||
if row > -1 and row < self.PreviewListWidget.rowCount():
|
||||
if self.serviceItem.is_command() and self.isLive:
|
||||
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
|
||||
if self.serviceItem.is_command():
|
||||
if self.isLive:
|
||||
Receiver.send_message(
|
||||
u'%s_slide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive, row])
|
||||
self.updatePreview()
|
||||
else:
|
||||
@ -799,22 +814,24 @@ class SlideController(QtGui.QWidget):
|
||||
"""
|
||||
The slide has been changed. Update the slidecontroller accordingly
|
||||
"""
|
||||
if row + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(row + 1, 0))
|
||||
self.PreviewListWidget.selectRow(row)
|
||||
self.updatePreview()
|
||||
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
|
||||
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()
|
||||
@ -844,6 +861,9 @@ class SlideController(QtGui.QWidget):
|
||||
else:
|
||||
Receiver.send_message('servicemanager_next_item')
|
||||
return
|
||||
if row + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(row + 1, 0))
|
||||
self.PreviewListWidget.selectRow(row)
|
||||
self.onSlideSelected()
|
||||
|
||||
@ -867,6 +887,9 @@ class SlideController(QtGui.QWidget):
|
||||
row = self.PreviewListWidget.rowCount() - 1
|
||||
else:
|
||||
row = 0
|
||||
if row + 1 < self.PreviewListWidget.rowCount():
|
||||
self.PreviewListWidget.scrollToItem(
|
||||
self.PreviewListWidget.item(row + 1, 0))
|
||||
self.PreviewListWidget.selectRow(row)
|
||||
self.onSlideSelected()
|
||||
|
||||
@ -918,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):
|
||||
"""
|
||||
|
650
openlp/core/ui/themeform.py
Normal file
@ -0,0 +1,650 @@
|
||||
# -*- 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
|
||||
QtCore.QObject.connect(self.backgroundTypeComboBox,
|
||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||
self.onBackgroundComboBox)
|
||||
QtCore.QObject.connect(self.gradientComboBox,
|
||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||
self.onGradientComboBox)
|
||||
QtCore.QObject.connect(self.color1PushButton,
|
||||
QtCore.SIGNAL(u'pressed()'),
|
||||
self.onColor1PushButtonClicked)
|
||||
QtCore.QObject.connect(self.color2PushButton,
|
||||
QtCore.SIGNAL(u'pressed()'),
|
||||
self.onColor2PushButtonClicked)
|
||||
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_1', self.color1PushButton)
|
||||
self.backgroundPage.registerField(
|
||||
u'color_2', self.color2PushButton)
|
||||
self.backgroundPage.registerField(
|
||||
u'background_image', self.imageLineEdit)
|
||||
self.backgroundPage.registerField(
|
||||
u'gradient', self.gradientComboBox)
|
||||
self.mainAreaPage.registerField(
|
||||
u'mainFontComboBox', self.mainFontComboBox)
|
||||
self.mainAreaPage.registerField(
|
||||
u'mainColorPushButton', self.mainColorPushButton)
|
||||
self.mainAreaPage.registerField(
|
||||
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):
|
||||
"""
|
||||
Run the wizard.
|
||||
"""
|
||||
self.setDefaults()
|
||||
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.setField(u'background_type', QtCore.QVariant(0))
|
||||
self.color1PushButton.setVisible(True)
|
||||
self.color1Label.setVisible(True)
|
||||
self.color1PushButton.setStyleSheet(u'background-color: %s' %
|
||||
self.theme.background_color)
|
||||
self.color1Label.setText(
|
||||
translate('OpenLP.ThemeForm', 'Color:'))
|
||||
self.color2PushButton.setVisible(False)
|
||||
self.color2Label.setVisible(False)
|
||||
self.gradientLabel.setVisible(False)
|
||||
self.gradientComboBox.setVisible(False)
|
||||
self.imageLabel.setVisible(False)
|
||||
self.imageLineEdit.setVisible(False)
|
||||
self.imageBrowseButton.setVisible(False)
|
||||
self.imageLineEdit.setText(u'')
|
||||
elif self.theme.background_type == \
|
||||
BackgroundType.to_string(BackgroundType.Gradient):
|
||||
self.setField(u'background_type', QtCore.QVariant(1))
|
||||
self.color1PushButton.setVisible(True)
|
||||
self.color1Label.setVisible(True)
|
||||
self.color1PushButton.setStyleSheet(u'background-color: %s' %
|
||||
self.theme.background_start_color)
|
||||
self.color1Label.setText(
|
||||
translate('OpenLP.ThemeForm', 'First color:'))
|
||||
self.color2PushButton.setVisible(True)
|
||||
self.color2Label.setVisible(True)
|
||||
self.color2PushButton.setStyleSheet(u'background-color: %s' %
|
||||
self.theme.background_end_color)
|
||||
self.color2Label.setText(
|
||||
translate('OpenLP.ThemeForm', 'Second color:'))
|
||||
self.gradientLabel.setVisible(True)
|
||||
self.gradientComboBox.setVisible(True)
|
||||
self.imageLabel.setVisible(False)
|
||||
self.imageLineEdit.setVisible(False)
|
||||
self.imageBrowseButton.setVisible(False)
|
||||
self.imageLineEdit.setText(u'')
|
||||
else:
|
||||
self.setField(u'background_type', QtCore.QVariant(2))
|
||||
self.color1PushButton.setVisible(False)
|
||||
self.color1Label.setVisible(False)
|
||||
self.color2PushButton.setVisible(False)
|
||||
self.color2Label.setVisible(False)
|
||||
self.gradientLabel.setVisible(False)
|
||||
self.gradientComboBox.setVisible(False)
|
||||
self.imageLineEdit.setVisible(True)
|
||||
self.imageLabel.setVisible(True)
|
||||
self.imageBrowseButton.setVisible(True)
|
||||
self.imageLineEdit.setText(self.theme.background_filename)
|
||||
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 onColor1PushButtonClicked(self):
|
||||
"""
|
||||
Background / Gradient 1 Color button pushed.
|
||||
"""
|
||||
if self.theme.background_type == \
|
||||
BackgroundType.to_string(BackgroundType.Solid):
|
||||
self.theme.background_color = \
|
||||
self._colorButton(self.theme.background_color)
|
||||
else:
|
||||
self.theme.background_start_color = \
|
||||
self._colorButton(self.theme.background_start_color)
|
||||
self.setBackgroundTabValues()
|
||||
|
||||
def onColor2PushButtonClicked(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 onMainFontComboBox(self):
|
||||
"""
|
||||
Main Font Combo box changed
|
||||
"""
|
||||
self.theme.font_main_name = self.mainFontComboBox.currentFont().family()
|
||||
|
||||
def onMainColourPushButtonClicked(self):
|
||||
self.theme.font_main_color = \
|
||||
self._colorButton(self.theme.font_main_color)
|
||||
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.
|
||||
"""
|
||||
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
|
||||
self.accepted = True
|
||||
# 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
|
||||
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
|
@ -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_()
|
||||
|
||||
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,19 +459,20 @@ 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.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,59 @@ 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 +670,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 +685,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 +718,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 +738,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 +768,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
|
||||
|
@ -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())
|
||||
|
547
openlp/core/ui/themewizard.py
Normal file
@ -0,0 +1,547 @@
|
||||
# -*- 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'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.welcomeLayout = QtGui.QHBoxLayout(self.welcomePage)
|
||||
self.welcomeLayout.setSpacing(8)
|
||||
self.welcomeLayout.setMargin(0)
|
||||
self.welcomeLayout.setObjectName(u'welcomeLayout')
|
||||
self.importBibleImage = QtGui.QLabel(self.welcomePage)
|
||||
self.importBibleImage.setMinimumSize(QtCore.QSize(163, 0))
|
||||
self.importBibleImage.setMaximumSize(QtCore.QSize(163, 16777215))
|
||||
self.importBibleImage.setLineWidth(0)
|
||||
self.importBibleImage.setText(u'')
|
||||
self.importBibleImage.setPixmap(QtGui.QPixmap(u':/wizards/wizard_importbible.bmp'))
|
||||
self.importBibleImage.setIndent(0)
|
||||
self.importBibleImage.setObjectName(u'importBibleImage')
|
||||
self.welcomeLayout.addWidget(self.importBibleImage)
|
||||
self.welcomePageLayout = QtGui.QVBoxLayout()
|
||||
self.welcomePageLayout.setSpacing(8)
|
||||
self.welcomePageLayout.setObjectName(u'welcomePageLayout')
|
||||
self.titleLabel = QtGui.QLabel(self.welcomePage)
|
||||
self.titleLabel.setObjectName(u'titleLabel')
|
||||
self.welcomePageLayout.addWidget(self.titleLabel)
|
||||
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
|
||||
self.welcomePageLayout.addItem(spacerItem)
|
||||
self.informationLabel = QtGui.QLabel(self.welcomePage)
|
||||
self.informationLabel.setWordWrap(True)
|
||||
self.informationLabel.setMargin(10)
|
||||
self.informationLabel.setObjectName(u'informationLabel')
|
||||
self.welcomePageLayout.addWidget(self.informationLabel)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.welcomePageLayout.addItem(spacerItem1)
|
||||
self.welcomeLayout.addLayout(self.welcomePageLayout)
|
||||
ThemeWizard.addPage(self.welcomePage)
|
||||
self.backgroundPage = QtGui.QWizardPage()
|
||||
self.backgroundPage.setObjectName(u'backgroundPage')
|
||||
self.backgroundLayout = QtGui.QFormLayout(self.backgroundPage)
|
||||
self.backgroundLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
|
||||
self.backgroundLayout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.backgroundLayout.setMargin(20)
|
||||
self.backgroundLayout.setSpacing(8)
|
||||
self.backgroundLayout.setObjectName(u'backgroundLayout')
|
||||
self.backgroundTypeLabel = QtGui.QLabel(self.backgroundPage)
|
||||
self.backgroundTypeLabel.setObjectName(u'backgroundTypeLabel')
|
||||
self.backgroundLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.backgroundTypeLabel)
|
||||
self.backgroundTypeComboBox = QtGui.QComboBox(self.backgroundPage)
|
||||
self.backgroundTypeComboBox.setObjectName(u'backgroundTypeComboBox')
|
||||
self.backgroundTypeComboBox.addItem(u'')
|
||||
self.backgroundTypeComboBox.addItem(u'')
|
||||
self.backgroundTypeComboBox.addItem(u'')
|
||||
self.backgroundLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backgroundTypeComboBox)
|
||||
self.color1Label = QtGui.QLabel(self.backgroundPage)
|
||||
self.color1Label.setObjectName(u'color1Label')
|
||||
self.backgroundLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.color1Label)
|
||||
self.color1PushButton = QtGui.QPushButton(self.backgroundPage)
|
||||
self.color1PushButton.setText(u'')
|
||||
self.color1PushButton.setObjectName(u'color1PushButton')
|
||||
self.backgroundLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.color1PushButton)
|
||||
self.color2Label = QtGui.QLabel(self.backgroundPage)
|
||||
self.color2Label.setObjectName(u'color2Label')
|
||||
self.backgroundLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.color2Label)
|
||||
self.color2PushButton = QtGui.QPushButton(self.backgroundPage)
|
||||
self.color2PushButton.setText(u'')
|
||||
self.color2PushButton.setObjectName(u'color2PushButton')
|
||||
self.backgroundLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.color2PushButton)
|
||||
self.imageLabel = QtGui.QLabel(self.backgroundPage)
|
||||
self.imageLabel.setObjectName(u'imageLabel')
|
||||
self.backgroundLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.imageLabel)
|
||||
self.imageLayout = QtGui.QHBoxLayout()
|
||||
self.imageLayout.setSpacing(8)
|
||||
self.imageLayout.setObjectName(u'imageLayout')
|
||||
self.imageLineEdit = QtGui.QLineEdit(self.backgroundPage)
|
||||
self.imageLineEdit.setObjectName(u'imageLineEdit')
|
||||
self.imageLayout.addWidget(self.imageLineEdit)
|
||||
self.imageBrowseButton = QtGui.QToolButton(self.backgroundPage)
|
||||
self.imageBrowseButton.setText(u'')
|
||||
self.imageBrowseButton.setIcon(build_icon(u':/general/general_open.png'))
|
||||
self.imageBrowseButton.setObjectName(u'imageBrowseButton')
|
||||
self.imageLayout.addWidget(self.imageBrowseButton)
|
||||
self.backgroundLayout.setLayout(3, QtGui.QFormLayout.FieldRole, self.imageLayout)
|
||||
self.gradientLabel = QtGui.QLabel(self.backgroundPage)
|
||||
self.gradientLabel.setObjectName(u'gradientLabel')
|
||||
self.backgroundLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.gradientLabel)
|
||||
self.gradientComboBox = QtGui.QComboBox(self.backgroundPage)
|
||||
self.gradientComboBox.setObjectName(u'gradientComboBox')
|
||||
self.gradientComboBox.addItem(u'')
|
||||
self.gradientComboBox.addItem(u'')
|
||||
self.gradientComboBox.addItem(u'')
|
||||
self.gradientComboBox.addItem(u'')
|
||||
self.gradientComboBox.addItem(u'')
|
||||
self.backgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.gradientComboBox)
|
||||
ThemeWizard.addPage(self.backgroundPage)
|
||||
self.mainAreaPage = QtGui.QWizardPage()
|
||||
self.mainAreaPage.setObjectName(u'mainAreaPage')
|
||||
self.formLayout = QtGui.QFormLayout(self.mainAreaPage)
|
||||
self.formLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||
self.formLayout.setContentsMargins(-1, 20, 20, 20)
|
||||
self.formLayout.setSpacing(8)
|
||||
self.formLayout.setObjectName(u'formLayout')
|
||||
self.mainFontLabel = QtGui.QLabel(self.mainAreaPage)
|
||||
self.mainFontLabel.setObjectName(u'mainFontLabel')
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.mainFontLabel)
|
||||
self.mainFontComboBox = QtGui.QFontComboBox(self.mainAreaPage)
|
||||
self.mainFontComboBox.setObjectName(u'mainFontComboBox')
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.mainFontComboBox)
|
||||
self.mainColorLabel = QtGui.QLabel(self.mainAreaPage)
|
||||
self.mainColorLabel.setObjectName(u'mainColorLabel')
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.mainColorLabel)
|
||||
self.mainColorPushButton = QtGui.QPushButton(self.mainAreaPage)
|
||||
self.mainColorPushButton.setText(u'')
|
||||
self.mainColorPushButton.setObjectName(u'mainColorPushButton')
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.mainColorPushButton)
|
||||
self.mainSizeLabel = QtGui.QLabel(self.mainAreaPage)
|
||||
self.mainSizeLabel.setObjectName(u'mainSizeLabel')
|
||||
self.formLayout.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.formLayout.setLayout(2, QtGui.QFormLayout.FieldRole, self.mainSizeLayout)
|
||||
self.lineSpacingLabel = QtGui.QLabel(self.mainAreaPage)
|
||||
self.lineSpacingLabel.setObjectName(u'lineSpacingLabel')
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.lineSpacingLabel)
|
||||
self.lineSpacingSpinBox = QtGui.QSpinBox(self.mainAreaPage)
|
||||
self.lineSpacingSpinBox.setMinimum(-50)
|
||||
self.lineSpacingSpinBox.setMaximum(50)
|
||||
self.lineSpacingSpinBox.setObjectName(u'lineSpacingSpinBox')
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.lineSpacingSpinBox)
|
||||
self.outlineCheckBox = QtGui.QCheckBox(self.mainAreaPage)
|
||||
self.outlineCheckBox.setObjectName(u'outlineCheckBox')
|
||||
self.formLayout.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.formLayout.setLayout(4, QtGui.QFormLayout.FieldRole, self.outlineLayout)
|
||||
self.shadowCheckBox = QtGui.QCheckBox(self.mainAreaPage)
|
||||
self.shadowCheckBox.setObjectName(u'shadowCheckBox')
|
||||
self.formLayout.setWidget(5, QtGui.QFormLayout.LabelRole, self.shadowCheckBox)
|
||||
self.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.formLayout.setLayout(5, QtGui.QFormLayout.FieldRole, self.shadowLayout)
|
||||
self.boldCheckBox = QtGui.QCheckBox(self.mainAreaPage)
|
||||
self.boldCheckBox.setObjectName(u'boldCheckBox')
|
||||
self.formLayout.setWidget(6, QtGui.QFormLayout.FieldRole, self.boldCheckBox)
|
||||
self.italicsCheckBox = QtGui.QCheckBox(self.mainAreaPage)
|
||||
self.italicsCheckBox.setObjectName(u'italicsCheckBox')
|
||||
self.formLayout.setWidget(7, QtGui.QFormLayout.FieldRole, self.italicsCheckBox)
|
||||
ThemeWizard.addPage(self.mainAreaPage)
|
||||
self.footerAreaPage = QtGui.QWizardPage()
|
||||
self.footerAreaPage.setObjectName(u'footerAreaPage')
|
||||
self.footerLayout = QtGui.QFormLayout(self.footerAreaPage)
|
||||
self.footerLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
|
||||
self.footerLayout.setContentsMargins(50, 20, 20, 20)
|
||||
self.footerLayout.setSpacing(8)
|
||||
self.footerLayout.setObjectName(u'footerLayout')
|
||||
self.footerFontLabel = QtGui.QLabel(self.footerAreaPage)
|
||||
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.formLayout_2 = QtGui.QFormLayout(self.alignmentPage)
|
||||
self.formLayout_2.setMargin(20)
|
||||
self.formLayout_2.setObjectName(u'formLayout_2')
|
||||
self.horizontalLabel = QtGui.QLabel(self.alignmentPage)
|
||||
self.horizontalLabel.setObjectName(u'horizontalLabel')
|
||||
self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.horizontalLabel)
|
||||
self.horizontalComboBox = QtGui.QComboBox(self.alignmentPage)
|
||||
self.horizontalComboBox.setEditable(False)
|
||||
self.horizontalComboBox.setObjectName(u'horizontalComboBox')
|
||||
self.horizontalComboBox.addItem(u'')
|
||||
self.horizontalComboBox.addItem(u'')
|
||||
self.horizontalComboBox.addItem(u'')
|
||||
self.formLayout_2.setWidget(0, QtGui.QFormLayout.FieldRole, self.horizontalComboBox)
|
||||
self.verticalLabel = QtGui.QLabel(self.alignmentPage)
|
||||
self.verticalLabel.setObjectName(u'verticalLabel')
|
||||
self.formLayout_2.setWidget(1, QtGui.QFormLayout.LabelRole, self.verticalLabel)
|
||||
self.verticalComboBox = QtGui.QComboBox(self.alignmentPage)
|
||||
self.verticalComboBox.setObjectName(u'verticalComboBox')
|
||||
self.verticalComboBox.addItem(u'')
|
||||
self.verticalComboBox.addItem(u'')
|
||||
self.verticalComboBox.addItem(u'')
|
||||
self.formLayout_2.setWidget(1, QtGui.QFormLayout.FieldRole, self.verticalComboBox)
|
||||
self.transitionsCheckBox = QtGui.QCheckBox(self.alignmentPage)
|
||||
self.transitionsCheckBox.setObjectName(u'transitionsCheckBox')
|
||||
self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.transitionsCheckBox)
|
||||
ThemeWizard.addPage(self.alignmentPage)
|
||||
self.areaPositionPage = QtGui.QWizardPage()
|
||||
self.areaPositionPage.setObjectName(u'areaPositionPage')
|
||||
self.gridLayout_2 = QtGui.QGridLayout(self.areaPositionPage)
|
||||
self.gridLayout_2.setMargin(20)
|
||||
self.gridLayout_2.setSpacing(8)
|
||||
self.gridLayout_2.setObjectName(u'gridLayout_2')
|
||||
self.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.gridLayout_2.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.gridLayout_2.addWidget(self.footerPositionGroupBox, 1, 1, 1, 1)
|
||||
ThemeWizard.addPage(self.areaPositionPage)
|
||||
self.previewPage = QtGui.QWizardPage()
|
||||
self.previewPage.setObjectName(u'previewPage')
|
||||
self.themeNameLabel = QtGui.QLabel(self.previewPage)
|
||||
self.themeNameLabel.setGeometry(QtCore.QRect(20, 10, 82, 16))
|
||||
self.themeNameLabel.setTextFormat(QtCore.Qt.PlainText)
|
||||
self.themeNameLabel.setObjectName(u'themeNameLabel')
|
||||
self.previewLabel = QtGui.QLabel(self.previewPage)
|
||||
self.previewLabel.setGeometry(QtCore.QRect(250, 60, 48, 16))
|
||||
self.previewLabel.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.previewLabel.setObjectName(u'previewLabel')
|
||||
self.themeNameEdit = QtGui.QLineEdit(self.previewPage)
|
||||
self.themeNameEdit.setGeometry(QtCore.QRect(117, 4, 351, 23))
|
||||
self.themeNameEdit.setObjectName(u'themeNameEdit')
|
||||
self.groupBox = QtGui.QGroupBox(self.previewPage)
|
||||
self.groupBox.setGeometry(QtCore.QRect(40, 80, 464, 214))
|
||||
self.groupBox.setTitle(u'')
|
||||
self.groupBox.setObjectName(u'groupBox')
|
||||
self.horizontalLayout = QtGui.QHBoxLayout(self.groupBox)
|
||||
self.horizontalLayout.setObjectName(u'horizontalLayout')
|
||||
spacerItem2 = QtGui.QSpacerItem(58, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem2)
|
||||
self.previewBoxLabel = QtGui.QLabel(self.groupBox)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.previewBoxLabel.sizePolicy().hasHeightForWidth())
|
||||
self.previewBoxLabel.setSizePolicy(sizePolicy)
|
||||
self.previewBoxLabel.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.previewBoxLabel.setFrameShape(QtGui.QFrame.WinPanel)
|
||||
self.previewBoxLabel.setFrameShadow(QtGui.QFrame.Sunken)
|
||||
self.previewBoxLabel.setLineWidth(1)
|
||||
self.previewBoxLabel.setText(u'')
|
||||
self.previewBoxLabel.setScaledContents(True)
|
||||
self.previewBoxLabel.setObjectName(u'previewBoxLabel')
|
||||
self.horizontalLayout.addWidget(self.previewBoxLabel)
|
||||
spacerItem3 = QtGui.QSpacerItem(78, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem3)
|
||||
ThemeWizard.addPage(self.previewPage)
|
||||
self.themeNameLabel.setBuddy(self.themeNameEdit)
|
||||
|
||||
self.retranslateUi(ThemeWizard)
|
||||
QtCore.QObject.connect(ThemeWizard, QtCore.SIGNAL(u'accepted()'), ThemeWizard.accept)
|
||||
QtCore.QMetaObject.connectSlotsByName(ThemeWizard)
|
||||
|
||||
def retranslateUi(self, ThemeWizard):
|
||||
ThemeWizard.setWindowTitle(translate('OpenLP.ThemeForm', 'Theme Wizard'))
|
||||
self.titleLabel.setText(translate('OpenLP.ThemeForm', '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n'
|
||||
'<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n'
|
||||
'p, li { white-space: pre-wrap; }\n'
|
||||
'</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:normal;\">\n'
|
||||
'<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:14pt; font-weight:600;\">Welcome to the Theme Wizard</span></p></body></html>'))
|
||||
self.informationLabel.setText(translate('OpenLP.ThemeForm', 'This wizard will help you to maintain Themes . Click the next button below to start the process by setting up your background.'))
|
||||
self.backgroundPage.setTitle(translate('OpenLP.ThemeForm', 'Set Up Background'))
|
||||
self.backgroundPage.setSubTitle(translate('OpenLP.ThemeForm', 'Set up your theme\'s background according to the parameters below.'))
|
||||
self.backgroundTypeLabel.setText(translate('OpenLP.ThemeForm', 'Background type:'))
|
||||
self.backgroundTypeComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Solid Color'))
|
||||
self.backgroundTypeComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Gradient'))
|
||||
self.backgroundTypeComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Image'))
|
||||
self.color1Label.setText(translate('OpenLP.ThemeForm', '<Color1>'))
|
||||
self.color2Label.setText(translate('OpenLP.ThemeForm', '<Color2>'))
|
||||
self.imageLabel.setText(translate('OpenLP.ThemeForm', 'Image:'))
|
||||
self.gradientLabel.setText(translate('OpenLP.ThemeForm', 'Gradient:'))
|
||||
self.gradientComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Horizontal'))
|
||||
self.gradientComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Vertical'))
|
||||
self.gradientComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Circular'))
|
||||
self.gradientComboBox.setItemText(3, translate('OpenLP.ThemeForm', 'Top Left - Bottom Right'))
|
||||
self.gradientComboBox.setItemText(4, translate('OpenLP.ThemeForm', 'Bottom Left - Top Right'))
|
||||
self.mainAreaPage.setTitle(translate('OpenLP.ThemeForm', 'Main Area Font Details'))
|
||||
self.mainAreaPage.setSubTitle(translate('OpenLP.ThemeForm', 'Define the font and display characteristics for the Display text'))
|
||||
self.mainFontLabel.setText(translate('OpenLP.ThemeForm', 'Font:'))
|
||||
self.mainColorLabel.setText(translate('OpenLP.ThemeForm', 'Color:'))
|
||||
self.mainSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:'))
|
||||
self.mainSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt'))
|
||||
self.mainLineCountLabel.setText(translate('OpenLP.ThemeForm', '(%d lines per slide)'))
|
||||
self.lineSpacingLabel.setText(translate('OpenLP.ThemeForm', 'Line Spacing:'))
|
||||
self.lineSpacingSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt'))
|
||||
self.outlineCheckBox.setText(translate('OpenLP.ThemeForm', '&Outline:'))
|
||||
self.outlineSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:'))
|
||||
self.outlineSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt'))
|
||||
self.shadowCheckBox.setText(translate('OpenLP.ThemeForm', '&Shadow:'))
|
||||
self.shadowSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:'))
|
||||
self.shadowSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt'))
|
||||
self.boldCheckBox.setText(translate('OpenLP.ThemeForm', 'Bold Display'))
|
||||
self.italicsCheckBox.setText(translate('OpenLP.ThemeForm', 'Italic Display'))
|
||||
self.footerAreaPage.setTitle(translate('OpenLP.ThemeForm', 'Footer Area Font Details'))
|
||||
self.footerAreaPage.setSubTitle(translate('OpenLP.ThemeForm', 'Define the font and display characteristics for the Footer text'))
|
||||
self.footerFontLabel.setText(translate('OpenLP.ThemeForm', 'Font:'))
|
||||
self.footerColorLabel.setText(translate('OpenLP.ThemeForm', 'Color:'))
|
||||
self.footerSizeLabel.setText(translate('OpenLP.ThemeForm', 'Size:'))
|
||||
self.footerSizeSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'pt'))
|
||||
self.alignmentPage.setTitle(translate('OpenLP.ThemeForm', 'Text Formatting Details'))
|
||||
self.alignmentPage.setSubTitle(translate('OpenLP.ThemeForm', 'Allows additional display formatting information to be defined'))
|
||||
self.horizontalLabel.setText(translate('OpenLP.ThemeForm', 'Horizontal Align:'))
|
||||
self.horizontalComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Left'))
|
||||
self.horizontalComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Right'))
|
||||
self.horizontalComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Center'))
|
||||
self.verticalLabel.setText(translate('OpenLP.ThemeForm', 'Vertcal Align:'))
|
||||
self.verticalComboBox.setItemText(0, translate('OpenLP.ThemeForm', 'Top'))
|
||||
self.verticalComboBox.setItemText(1, translate('OpenLP.ThemeForm', 'Middle'))
|
||||
self.verticalComboBox.setItemText(2, translate('OpenLP.ThemeForm', 'Bottom'))
|
||||
self.transitionsCheckBox.setText(translate('OpenLP.ThemeForm', 'Transitions'))
|
||||
self.areaPositionPage.setTitle(translate('OpenLP.ThemeForm', 'Output Area Locations'))
|
||||
self.areaPositionPage.setSubTitle(translate('OpenLP.ThemeForm', 'Allows you to change and move the Main and Footer areas.'))
|
||||
self.mainPositionGroupBox.setTitle(translate('OpenLP.ThemeForm', '&Main Area'))
|
||||
self.mainDefaultPositionCheckBox.setText(translate('OpenLP.ThemeForm', '&Use default location'))
|
||||
self.nainXLabel.setText(translate('OpenLP.ThemeForm', 'X position:'))
|
||||
self.mainXSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.mainYSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.mainYLabel.setText(translate('OpenLP.ThemeForm', 'Y position:'))
|
||||
self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.mainWidthLabel.setText(translate('OpenLP.ThemeForm', 'Width:'))
|
||||
self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.mainHeightLabel.setText(translate('OpenLP.ThemeForm', 'Height:'))
|
||||
self.footerPositionGroupBox.setTitle(translate('OpenLP.ThemeForm', 'Footer Area'))
|
||||
self.footerXLabel.setText(translate('OpenLP.ThemeForm', 'X position:'))
|
||||
self.footerXSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.footerYLabel.setText(translate('OpenLP.ThemeForm', 'Y position:'))
|
||||
self.footerYSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.footerWidthLabel.setText(translate('OpenLP.ThemeForm', 'Width:'))
|
||||
self.footerWidthSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.footerHeightLabel.setText(translate('OpenLP.ThemeForm', 'Height:'))
|
||||
self.footerHeightSpinBox.setSuffix(translate('OpenLP.ThemeForm', 'px'))
|
||||
self.footerDefaultPositionCheckBox.setText(translate('OpenLP.ThemeForm', 'Use default location'))
|
||||
self.previewPage.setTitle(translate('OpenLP.ThemeForm', 'Save and Preview'))
|
||||
self.previewPage.setSubTitle(translate('OpenLP.ThemeForm', 'View the theme and save it replacing the current one or change the name to create a new theme'))
|
||||
self.themeNameLabel.setText(translate('OpenLP.ThemeForm', 'Theme name:'))
|
||||
self.previewLabel.setText(translate('OpenLP.ThemeForm', 'Preview'))
|
@ -276,6 +276,7 @@ def get_images_filter():
|
||||
return images_filter
|
||||
|
||||
from languagemanager import LanguageManager
|
||||
from actions import ActionList
|
||||
|
||||
__all__ = [u'AppLocation', u'check_latest_version', u'add_actions',
|
||||
u'get_filesystem_encoding', u'LanguageManager']
|
||||
u'get_filesystem_encoding', u'LanguageManager', u'ActionList']
|
||||
|
184
openlp/core/utils/actions.py
Normal file
@ -0,0 +1,184 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.utils.actions` module provides action list classes used
|
||||
by the shortcuts system.
|
||||
"""
|
||||
|
||||
class ActionCategory(object):
|
||||
"""
|
||||
The :class:`~openlp.core.utils.ActionCategory` class encapsulates a
|
||||
category for the :class:`~openlp.core.utils.CategoryList` class.
|
||||
"""
|
||||
def __init__(self, name, weight=0):
|
||||
self.name = name
|
||||
self.weight = weight
|
||||
self.actions = CategoryActionList()
|
||||
|
||||
|
||||
class CategoryActionList(object):
|
||||
"""
|
||||
The :class:`~openlp.core.utils.CategoryActionList` class provides a sorted
|
||||
list of actions within a category.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.index = 0
|
||||
self.actions = []
|
||||
|
||||
def __getitem__(self, key):
|
||||
for weight, action in self.actions:
|
||||
if action.text() == key:
|
||||
return action
|
||||
raise KeyError(u'Action "%s" does not exist.' % key)
|
||||
|
||||
def __contains__(self, item):
|
||||
return self.has_key(item)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.actions)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
"""
|
||||
Python 3 "next" method.
|
||||
"""
|
||||
if self.index >= len(self.actions):
|
||||
raise StopIteration
|
||||
else:
|
||||
self.index += 1
|
||||
return self.actions[self.index - 1][1]
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Python 2 "next" method.
|
||||
"""
|
||||
return self.__next__()
|
||||
|
||||
def has_key(self, key):
|
||||
for weight, action in self.actions:
|
||||
if action.text() == key:
|
||||
return True
|
||||
return False
|
||||
|
||||
def append(self, name):
|
||||
weight = 0
|
||||
if len(self.actions) > 0:
|
||||
weight = self.actions[-1][0] + 1
|
||||
self.add(name, weight)
|
||||
|
||||
def add(self, action, weight=0):
|
||||
self.actions.append((weight, action))
|
||||
self.actions.sort(key=lambda act: act[0])
|
||||
|
||||
|
||||
class CategoryList(object):
|
||||
"""
|
||||
The :class:`~openlp.core.utils.CategoryList` class encapsulates a category
|
||||
list for the :class:`~openlp.core.utils.ActionList` class and provides an
|
||||
iterator interface for walking through the list of actions in this category.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.index = 0
|
||||
self.categories = []
|
||||
|
||||
def __getitem__(self, key):
|
||||
for category in self.categories:
|
||||
if category.name == key:
|
||||
return category
|
||||
raise KeyError(u'Category "%s" does not exist.' % key)
|
||||
|
||||
def __contains__(self, item):
|
||||
return self.has_key(item)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.categories)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
"""
|
||||
Python 3 "next" method for iterator.
|
||||
"""
|
||||
if self.index >= len(self.categories):
|
||||
raise StopIteration
|
||||
else:
|
||||
self.index += 1
|
||||
return self.categories[self.index - 1]
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Python 2 "next" method for iterator.
|
||||
"""
|
||||
return self.__next__()
|
||||
|
||||
def has_key(self, key):
|
||||
for category in self.categories:
|
||||
if category.name == key:
|
||||
return True
|
||||
return False
|
||||
|
||||
def append(self, name, actions=None):
|
||||
weight = 0
|
||||
if len(self.categories) > 0:
|
||||
weight = self.categories[-1].weight + 1
|
||||
if actions:
|
||||
self.add(name, weight, actions)
|
||||
else:
|
||||
self.add(name, weight)
|
||||
|
||||
def add(self, name, weight=0, actions=None):
|
||||
category = ActionCategory(name, weight)
|
||||
if actions:
|
||||
for action in actions:
|
||||
if isinstance(action, tuple):
|
||||
category.actions.add(action[0], action[1])
|
||||
else:
|
||||
category.actions.append(action)
|
||||
self.categories.append(category)
|
||||
self.categories.sort(key=lambda cat: cat.weight)
|
||||
|
||||
|
||||
class ActionList(object):
|
||||
"""
|
||||
The :class:`~openlp.core.utils.ActionList` class contains a list of menu
|
||||
actions and categories associated with those actions. Each category also
|
||||
has a weight by which it is sorted when iterating through the list of
|
||||
actions or categories.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.categories = CategoryList()
|
||||
|
||||
def add_action(self, action, category=u'Default', weight=None):
|
||||
if category not in self.categories:
|
||||
self.categories.append(category)
|
||||
if weight is None:
|
||||
self.categories[category].actions.append(action)
|
||||
else:
|
||||
self.categories[category].actions.add(action, weight)
|
@ -85,7 +85,11 @@ class AlertsPlugin(Plugin):
|
||||
self.liveController.alertTab = self.alertsTab
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Tidy up on exit
|
||||
"""
|
||||
log.info(u'Alerts Finalising')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
self.toolsAlertItem.setVisible(False)
|
||||
|
||||
@ -117,11 +121,3 @@ class AlertsPlugin(Plugin):
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('AlertsPlugin', 'Alerts')
|
||||
}
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Time to tidy up on exit
|
||||
"""
|
||||
log.info(u'Alerts Finalising')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
|
@ -52,7 +52,11 @@ class BiblePlugin(Plugin):
|
||||
self.exportBibleItem.setVisible(True)
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Tidy up on exit
|
||||
"""
|
||||
log.info(u'Plugin Finalise')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
self.importBibleItem.setVisible(False)
|
||||
self.exportBibleItem.setVisible(False)
|
||||
@ -172,11 +176,3 @@ class BiblePlugin(Plugin):
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Add the selected Bible to the service')
|
||||
}
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Time to tidy up on exit
|
||||
"""
|
||||
log.info(u'Bible Finalising')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
|
@ -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()
|
||||
if bible_type == BibleFormat.WebDownload:
|
||||
self.ImportProgressLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Finished import.'))
|
||||
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',
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -213,7 +213,7 @@ class BGExtract(object):
|
||||
finally:
|
||||
if not page:
|
||||
return None
|
||||
cleaner = [(re.compile(' |<br />'), lambda match: '')]
|
||||
cleaner = [(re.compile(' |<br />|\'\+\''), 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)
|
||||
|
@ -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)
|
||||
# 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()
|
||||
|
||||
|
@ -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,12 +364,14 @@ 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_()
|
||||
# If the import was not canceled then reload.
|
||||
if self.import_wizard.exec_():
|
||||
self.reloadBibles()
|
||||
|
||||
def loadBibles(self):
|
||||
@ -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,19 +642,18 @@ 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:
|
||||
if second_bible:
|
||||
try:
|
||||
vdict = {
|
||||
'book': QtCore.QVariant(verse.book.name),
|
||||
'chapter': QtCore.QVariant(verse.chapter),
|
||||
@ -605,16 +663,20 @@ class BibleMediaItem(MediaManagerItem):
|
||||
'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)
|
||||
'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)
|
||||
|
@ -59,7 +59,7 @@ class CustomPlugin(Plugin):
|
||||
return CustomTab(self.name, visible_name[u'title'])
|
||||
|
||||
def getMediaManagerItem(self):
|
||||
# Create the CustomManagerItem object
|
||||
# Create the ManagerItem object
|
||||
return CustomMediaItem(self, self, self.icon)
|
||||
|
||||
def about(self):
|
||||
@ -76,7 +76,7 @@ class CustomPlugin(Plugin):
|
||||
|
||||
Returns True if the theme is being used, otherwise returns False.
|
||||
"""
|
||||
if self.custommanager.get_all_objects(CustomSlide,
|
||||
if self.manager.get_all_objects(CustomSlide,
|
||||
CustomSlide.theme_name == theme):
|
||||
return True
|
||||
return False
|
||||
@ -92,11 +92,11 @@ class CustomPlugin(Plugin):
|
||||
``newTheme``
|
||||
The new name the plugin should now use.
|
||||
"""
|
||||
customsUsingTheme = self.custommanager.get_all_objects(CustomSlide,
|
||||
customsUsingTheme = self.manager.get_all_objects(CustomSlide,
|
||||
CustomSlide.theme_name == oldTheme)
|
||||
for custom in customsUsingTheme:
|
||||
custom.theme_name = newTheme
|
||||
self.custommanager.save_object(custom)
|
||||
self.manager.save_object(custom)
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
|
@ -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)
|
||||
@ -162,12 +162,10 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
sxml.add_verse_to_lyrics(u'custom', unicode(count),
|
||||
unicode(self.slideListView.item(i).text()))
|
||||
count += 1
|
||||
self.customSlide.title = unicode(self.titleEdit.displayText(), u'utf-8')
|
||||
self.customSlide.title = unicode(self.titleEdit.text())
|
||||
self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
|
||||
self.customSlide.credits = unicode(self.creditEdit.displayText(),
|
||||
u'utf-8')
|
||||
self.customSlide.theme_name = unicode(self.themeComboBox.currentText(),
|
||||
u'utf-8')
|
||||
self.customSlide.credits = unicode(self.creditEdit.text())
|
||||
self.customSlide.theme_name = unicode(self.themeComboBox.currentText())
|
||||
return self.manager.save_object(self.customSlide)
|
||||
|
||||
def onUpButtonPressed(self):
|
||||
@ -266,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')
|
||||
|
@ -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')
|
||||
|
@ -43,6 +43,7 @@ import logging
|
||||
|
||||
from xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
from lxml import etree, objectify
|
||||
from xml.parsers.expat import ExpatError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -55,14 +56,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 <song> base element
|
||||
self.song = self.custom_xml.createElement(u'song')
|
||||
@ -72,7 +73,7 @@ class CustomXMLBuilder(object):
|
||||
def add_lyrics_to_song(self):
|
||||
"""
|
||||
Set up and add a ``<lyrics>`` tag which contains the lyrics of the
|
||||
song.
|
||||
custom item.
|
||||
"""
|
||||
# Create the main <lyrics> element
|
||||
self.lyrics = self.custom_xml.createElement(u'lyrics')
|
||||
@ -93,7 +94,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 +102,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 +110,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'<?xml':
|
||||
xml = xml[38:]
|
||||
try:
|
||||
self.custom_xml = ElementTree(
|
||||
element=XML(unicode(xml).encode('unicode-escape')))
|
||||
except ExpatError:
|
||||
self.custom_xml = objectify.fromstring(xml)
|
||||
except etree.XMLSyntaxError:
|
||||
log.exception(u'Invalid xml %s', xml)
|
||||
|
||||
def get_verses(self):
|
||||
@ -146,11 +147,10 @@ class CustomXMLParser(object):
|
||||
if element.tag == u'verse':
|
||||
if element.text is None:
|
||||
element.text = u''
|
||||
verse_list.append([element.attrib,
|
||||
unicode(element.text).decode('unicode-escape')])
|
||||
verse_list.append([element.attrib, unicode(element.text)])
|
||||
return verse_list
|
||||
|
||||
def dump_xml(self):
|
||||
def _dump_xml(self):
|
||||
"""
|
||||
Debugging aid to dump XML so that we can see what we have.
|
||||
"""
|
||||
|
@ -74,9 +74,9 @@ class CustomMediaItem(MediaManagerItem):
|
||||
def initialise(self):
|
||||
self.loadCustomListView(self.manager.get_all_objects(
|
||||
CustomSlide, order_by_ref=CustomSlide.title))
|
||||
#Called to redisplay the song list screen edith 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.
|
||||
# Called to redisplay the custom list screen edith from a search
|
||||
# or from the exit of the Custom edit dialog. If remote editing is
|
||||
# active trigger it and clean up so it will not update again.
|
||||
if self.remoteTriggered == u'L':
|
||||
self.onAddClick()
|
||||
if self.remoteTriggered == u'P':
|
||||
@ -140,11 +140,11 @@ class CustomMediaItem(MediaManagerItem):
|
||||
id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
for item in self.listView.selectedIndexes()]
|
||||
for id in id_list:
|
||||
self.parent.custommanager.delete_object(CustomSlide, id)
|
||||
self.parent.manager.delete_object(CustomSlide, id)
|
||||
for row in row_list:
|
||||
self.listView.takeItem(row)
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
raw_slides = []
|
||||
raw_footer = []
|
||||
slide = None
|
||||
@ -162,10 +162,10 @@ class CustomMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.AllowsEdit)
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
customSlide = self.parent.custommanager.get_object(CustomSlide, item_id)
|
||||
customSlide = self.parent.manager.get_object(CustomSlide, item_id)
|
||||
title = customSlide.title
|
||||
credit = customSlide.credits
|
||||
service_item.editId = item_id
|
||||
service_item.edit_id = item_id
|
||||
theme = customSlide.theme_name
|
||||
if theme:
|
||||
service_item.theme = theme
|
||||
|
@ -154,7 +154,7 @@ class ImageMediaItem(MediaManagerItem):
|
||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
||||
self.listView.addItem(item_name)
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
items = self.listView.selectedIndexes()
|
||||
if items:
|
||||
service_item.title = unicode(
|
||||
@ -163,6 +163,8 @@ class ImageMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
service_item.add_capability(ItemCapabilities.AllowsAdditions)
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
for item in items:
|
||||
bitem = self.listView.item(item.row())
|
||||
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
|
||||
|
@ -56,7 +56,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
u':/media/media_video.png').toImage()
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
self.singleServiceItem = False
|
||||
self.serviceItemIconName = u':/media/media_video.png'
|
||||
self.serviceItemIconName = u':/media/image_clapperboard.png'
|
||||
|
||||
def retranslateUi(self):
|
||||
self.OnNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
||||
@ -116,7 +116,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
self.parent.liveController.display.video(filename, 0, True)
|
||||
self.resetButton.setVisible(True)
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
if item is None:
|
||||
item = self.listView.currentItem()
|
||||
if item is None:
|
||||
@ -125,6 +125,8 @@ class MediaMediaItem(MediaManagerItem):
|
||||
service_item.title = unicode(
|
||||
translate('MediaPlugin.MediaItem', 'Media'))
|
||||
service_item.add_capability(ItemCapabilities.RequiresMedia)
|
||||
# force a nonexistent theme
|
||||
service_item.theme = -1
|
||||
frame = u':/media/image_clapperboard.png'
|
||||
(path, name) = os.path.split(filename)
|
||||
service_item.add_from_command(path, name, frame)
|
||||
|
@ -80,5 +80,3 @@ class MediaTab(SettingsTab):
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/use phonon',
|
||||
QtCore.QVariant(self.usePhonon))
|
||||
Receiver.send_message(u'config_screen_changed')
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import mimetypes
|
||||
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
@ -45,6 +46,7 @@ class MediaPlugin(Plugin):
|
||||
self.dnd_id = u'Media'
|
||||
self.audio_list = u''
|
||||
self.video_list = u''
|
||||
mimetypes.init()
|
||||
for mimetype in Phonon.BackendCapabilities.availableMimeTypes():
|
||||
mimetype = unicode(mimetype)
|
||||
type = mimetype.split(u'audio/x-')
|
||||
@ -60,13 +62,18 @@ class MediaPlugin(Plugin):
|
||||
self.video_list, mimetype = self._addToList(self.video_list,
|
||||
type, mimetype)
|
||||
|
||||
def _addToList(self, list, value, type):
|
||||
def _addToList(self, list, value, mimetype):
|
||||
# Is it a media type
|
||||
if len(value) == 2:
|
||||
if list.find(value[1]) == -1:
|
||||
list += u'*.%s ' % value[1]
|
||||
self.serviceManager.supportedSuffixes(value[1])
|
||||
type = u''
|
||||
return list, type
|
||||
extensions = mimetypes.guess_all_extensions(unicode(mimetype))
|
||||
# we have an extension
|
||||
if extensions:
|
||||
for extension in extensions:
|
||||
if list.find(extension) == -1:
|
||||
list += u'*%s ' % extension
|
||||
self.serviceManager.supportedSuffixes(extension[1:])
|
||||
mimetype = u''
|
||||
return list, mimetype
|
||||
|
||||
def getSettingsTab(self):
|
||||
return MediaTab(self.name)
|
||||
|
@ -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
|
||||
|
@ -61,7 +61,8 @@ class PresentationPlugin(Plugin):
|
||||
Create the settings Tab
|
||||
"""
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
return PresentationTab(self.name, visible_name[u'title'], self.controllers)
|
||||
return PresentationTab(self.name, visible_name[u'title'],
|
||||
self.controllers)
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
|
@ -43,7 +43,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
"""
|
||||
log.info(u'%s EditSongForm loaded', __name__)
|
||||
|
||||
def __init__(self, parent, songmanager):
|
||||
def __init__(self, parent, manager):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
@ -100,7 +100,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
QtCore.QObject.connect(self.ButtonBox,
|
||||
QtCore.SIGNAL(u'clicked(QAbstractButton*)'), self.onPreview)
|
||||
# Create other objects and forms
|
||||
self.songmanager = songmanager
|
||||
self.manager = manager
|
||||
self.verse_form = EditVerseForm(self)
|
||||
self.initialise()
|
||||
self.AuthorsListView.setSortingEnabled(False)
|
||||
@ -116,7 +116,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.TopicRemoveButton.setEnabled(False)
|
||||
|
||||
def loadAuthors(self):
|
||||
authors = self.songmanager.get_all_objects(Author,
|
||||
authors = self.manager.get_all_objects(Author,
|
||||
order_by_ref=Author.display_name)
|
||||
self.AuthorsSelectionComboItem.clear()
|
||||
self.AuthorsSelectionComboItem.addItem(u'')
|
||||
@ -127,8 +127,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
row, QtCore.QVariant(author.id))
|
||||
|
||||
def loadTopics(self):
|
||||
topics = self.songmanager.get_all_objects(Topic,
|
||||
order_by_ref=Topic.name)
|
||||
topics = self.manager.get_all_objects(Topic, order_by_ref=Topic.name)
|
||||
self.SongTopicCombo.clear()
|
||||
self.SongTopicCombo.addItem(u'')
|
||||
for topic in topics:
|
||||
@ -137,7 +136,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id))
|
||||
|
||||
def loadBooks(self):
|
||||
books = self.songmanager.get_all_objects(Book, order_by_ref=Book.name)
|
||||
books = self.manager.get_all_objects(Book, order_by_ref=Book.name)
|
||||
self.SongbookCombo.clear()
|
||||
self.SongbookCombo.addItem(u'')
|
||||
for book in books:
|
||||
@ -153,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'')
|
||||
@ -171,21 +171,30 @@ 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()
|
||||
self.loadBooks()
|
||||
self.song = self.songmanager.get_object(Song, id)
|
||||
self.song = self.manager.get_object(Song, id)
|
||||
self.TitleEditItem.setText(self.song.title)
|
||||
if self.song.alternate_title:
|
||||
self.AlternativeEdit.setText(self.song.alternate_title)
|
||||
else:
|
||||
self.AlternativeEdit.setText(u'')
|
||||
if self.song.song_book_id != 0:
|
||||
book_name = self.songmanager.get_object(Book,
|
||||
self.song.song_book_id)
|
||||
book_name = self.manager.get_object(Book, self.song.song_book_id)
|
||||
id = self.SongbookCombo.findText(
|
||||
unicode(book_name.name), QtCore.Qt.MatchExactly)
|
||||
if id == -1:
|
||||
@ -299,7 +308,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
else:
|
||||
author = Author.populate(first_name=text.rsplit(u' ', 1)[0],
|
||||
last_name=text.rsplit(u' ', 1)[1], display_name=text)
|
||||
self.songmanager.save_object(author)
|
||||
self.manager.save_object(author)
|
||||
author_item = QtGui.QListWidgetItem(
|
||||
unicode(author.display_name))
|
||||
author_item.setData(QtCore.Qt.UserRole,
|
||||
@ -311,7 +320,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
return
|
||||
elif item > 0:
|
||||
item_id = (self.AuthorsSelectionComboItem.itemData(item)).toInt()[0]
|
||||
author = self.songmanager.get_object(Author, item_id)
|
||||
author = self.manager.get_object(Author, item_id)
|
||||
if self.AuthorsListView.findItems(unicode(author.display_name),
|
||||
QtCore.Qt.MatchExactly):
|
||||
QtGui.QMessageBox.warning(self,
|
||||
@ -354,7 +363,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
|
||||
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
|
||||
topic = Topic.populate(name=text)
|
||||
self.songmanager.save_object(topic)
|
||||
self.manager.save_object(topic)
|
||||
topic_item = QtGui.QListWidgetItem(unicode(topic.name))
|
||||
topic_item.setData(QtCore.Qt.UserRole,
|
||||
QtCore.QVariant(topic.id))
|
||||
@ -365,7 +374,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
return
|
||||
elif item > 0:
|
||||
item_id = (self.SongTopicCombo.itemData(item)).toInt()[0]
|
||||
topic = self.songmanager.get_object(Topic, item_id)
|
||||
topic = self.manager.get_object(Topic, item_id)
|
||||
if self.TopicsListView.findItems(unicode(topic.name),
|
||||
QtCore.Qt.MatchExactly):
|
||||
QtGui.QMessageBox.warning(self,
|
||||
@ -596,9 +605,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
"""
|
||||
Save and Preview button pressed.
|
||||
The Song is valid so as the plugin to add it to preview to see.
|
||||
|
||||
``button``
|
||||
A button (QPushButton).
|
||||
"""
|
||||
log.debug(u'onPreview')
|
||||
if unicode(button.objectName()) == u'previewButton' and self.saveSong():
|
||||
if unicode(button.objectName()) == u'previewButton' and \
|
||||
self.saveSong(True):
|
||||
Receiver.send_message(u'songs_preview')
|
||||
|
||||
def closePressed(self):
|
||||
@ -619,33 +632,44 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
|
||||
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
|
||||
book = Book.populate(name=text, publisher=u'')
|
||||
self.songmanager.save_object(book)
|
||||
self.manager.save_object(book)
|
||||
else:
|
||||
return
|
||||
if self.saveSong():
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
self.close()
|
||||
|
||||
def saveSong(self):
|
||||
def saveSong(self, preview=False):
|
||||
"""
|
||||
Get all the data from the widgets on the form, and then save it to the
|
||||
database.
|
||||
|
||||
``preview``
|
||||
Should be ``True`` if the song is also previewed (boolean).
|
||||
"""
|
||||
self.song.title = unicode(self.TitleEditItem.text())
|
||||
self.song.alternate_title = unicode(self.AlternativeEdit.text())
|
||||
self.song.copyright = unicode(self.CopyrightEditItem.text())
|
||||
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())
|
||||
self.song.song_number = unicode(self.songBookNumberEdit.text())
|
||||
book_name = unicode(self.SongbookCombo.currentText())
|
||||
if book_name:
|
||||
self.song.book = self.songmanager.get_object_filtered(Book,
|
||||
self.song.book = self.manager.get_object_filtered(Book,
|
||||
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()
|
||||
@ -653,15 +677,15 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
for row in range(self.AuthorsListView.count()):
|
||||
item = self.AuthorsListView.item(row)
|
||||
authorId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.song.authors.append(self.songmanager.get_object(Author,
|
||||
self.song.authors.append(self.manager.get_object(Author,
|
||||
authorId))
|
||||
self.song.topics = []
|
||||
for row in range(self.TopicsListView.count()):
|
||||
item = self.TopicsListView.item(row)
|
||||
topicId = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.song.topics.append(self.songmanager.get_object(Topic,
|
||||
topicId))
|
||||
self.songmanager.save_object(self.song)
|
||||
self.song.topics.append(self.manager.get_object(Topic, topicId))
|
||||
self.manager.save_object(self.song)
|
||||
if not preview:
|
||||
self.song = None
|
||||
return True
|
||||
return False
|
||||
|
@ -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:
|
||||
|
@ -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.'))
|
||||
|
@ -36,13 +36,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
def __init__(self, songmanager, parent=None):
|
||||
def __init__(self, manager, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.songmanager = songmanager
|
||||
self.manager = manager
|
||||
self.authorform = AuthorsForm(self)
|
||||
self.topicform = TopicsForm(self)
|
||||
self.bookform = SongBookForm(self)
|
||||
@ -85,12 +85,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
del_text, err_text, sel_text):
|
||||
item_id = self._getCurrentItemId(list_widget)
|
||||
if item_id != -1:
|
||||
item = self.songmanager.get_object(item_class, item_id)
|
||||
item = self.manager.get_object(item_class, item_id)
|
||||
if item and len(item.songs) == 0:
|
||||
if QtGui.QMessageBox.warning(self, dlg_title, del_text,
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes:
|
||||
self.songmanager.delete_object(item_class, item.id)
|
||||
self.manager.delete_object(item_class, item.id)
|
||||
reset_func()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self, dlg_title, err_text)
|
||||
@ -102,7 +102,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
Reloads the Authors list.
|
||||
"""
|
||||
self.AuthorsListWidget.clear()
|
||||
authors = self.songmanager.get_all_objects(Author,
|
||||
authors = self.manager.get_all_objects(Author,
|
||||
order_by_ref=Author.display_name)
|
||||
for author in authors:
|
||||
if author.display_name:
|
||||
@ -124,8 +124,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
Reloads the Topics list.
|
||||
"""
|
||||
self.TopicsListWidget.clear()
|
||||
topics = self.songmanager.get_all_objects(Topic,
|
||||
order_by_ref=Topic.name)
|
||||
topics = self.manager.get_all_objects(Topic, order_by_ref=Topic.name)
|
||||
for topic in topics:
|
||||
topic_name = QtGui.QListWidgetItem(topic.name)
|
||||
topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
|
||||
@ -142,7 +141,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
Reloads the Books list.
|
||||
"""
|
||||
self.BooksListWidget.clear()
|
||||
books = self.songmanager.get_all_objects(Book, order_by_ref=Book.name)
|
||||
books = self.manager.get_all_objects(Book, order_by_ref=Book.name)
|
||||
for book in books:
|
||||
book_name = QtGui.QListWidgetItem(u'%s (%s)' % (book.name,
|
||||
book.publisher))
|
||||
@ -160,7 +159,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
Returns False if the given Author is already in the list otherwise
|
||||
True.
|
||||
"""
|
||||
authors = self.songmanager.get_all_objects(Author,
|
||||
authors = self.manager.get_all_objects(Author,
|
||||
and_(Author.first_name == new_author.first_name,
|
||||
Author.last_name == new_author.last_name,
|
||||
Author.display_name == new_author.display_name))
|
||||
@ -182,7 +181,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
"""
|
||||
Returns False if the given Topic is already in the list otherwise True.
|
||||
"""
|
||||
topics = self.songmanager.get_all_objects(Topic,
|
||||
topics = self.manager.get_all_objects(Topic,
|
||||
Topic.name == new_topic.name)
|
||||
if len(topics) > 0:
|
||||
# If we edit an existing Topic, we need to make sure that we do
|
||||
@ -202,7 +201,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
"""
|
||||
Returns False if the given Book is already in the list otherwise True.
|
||||
"""
|
||||
books = self.songmanager.get_all_objects(Book,
|
||||
books = self.manager.get_all_objects(Book,
|
||||
and_(Book.name == new_book.name,
|
||||
Book.publisher == new_book.publisher))
|
||||
if len(books) > 0:
|
||||
@ -227,7 +226,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
last_name=unicode(self.authorform.LastNameEdit.text()),
|
||||
display_name=unicode(self.authorform.DisplayEdit.text()))
|
||||
if self.checkAuthor(author):
|
||||
if self.songmanager.save_object(author):
|
||||
if self.manager.save_object(author):
|
||||
self.resetAuthors()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -244,7 +243,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
if self.topicform.exec_():
|
||||
topic = Topic.populate(name=unicode(self.topicform.NameEdit.text()))
|
||||
if self.checkTopic(topic):
|
||||
if self.songmanager.save_object(topic):
|
||||
if self.manager.save_object(topic):
|
||||
self.resetTopics()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -262,7 +261,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
book = Book.populate(name=unicode(self.bookform.NameEdit.text()),
|
||||
publisher=unicode(self.bookform.PublisherEdit.text()))
|
||||
if self.checkBook(book):
|
||||
if self.songmanager.save_object(book):
|
||||
if self.manager.save_object(book):
|
||||
self.resetBooks()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -278,7 +277,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
def onAuthorEditButtonClick(self):
|
||||
author_id = self._getCurrentItemId(self.AuthorsListWidget)
|
||||
if author_id != -1:
|
||||
author = self.songmanager.get_object(Author, author_id)
|
||||
author = self.manager.get_object(Author, author_id)
|
||||
self.authorform.setAutoDisplayName(False)
|
||||
self.authorform.FirstNameEdit.setText(author.first_name)
|
||||
self.authorform.LastNameEdit.setText(author.last_name)
|
||||
@ -295,7 +294,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
author.display_name = unicode(
|
||||
self.authorform.DisplayEdit.text())
|
||||
if self.checkAuthor(author, True):
|
||||
if self.songmanager.save_object(author):
|
||||
if self.manager.save_object(author):
|
||||
self.resetAuthors()
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
else:
|
||||
@ -330,14 +329,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
def onTopicEditButtonClick(self):
|
||||
topic_id = self._getCurrentItemId(self.TopicsListWidget)
|
||||
if topic_id != -1:
|
||||
topic = self.songmanager.get_object(Topic, topic_id)
|
||||
topic = self.manager.get_object(Topic, topic_id)
|
||||
self.topicform.NameEdit.setText(topic.name)
|
||||
# Save the topic's name for the case that he has to be restored.
|
||||
temp_name = topic.name
|
||||
if self.topicform.exec_(False):
|
||||
topic.name = unicode(self.topicform.NameEdit.text())
|
||||
if self.checkTopic(topic, True):
|
||||
if self.songmanager.save_object(topic):
|
||||
if self.manager.save_object(topic):
|
||||
self.resetTopics()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -367,7 +366,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
def onBookEditButtonClick(self):
|
||||
book_id = self._getCurrentItemId(self.BooksListWidget)
|
||||
if book_id != -1:
|
||||
book = self.songmanager.get_object(Book, book_id)
|
||||
book = self.manager.get_object(Book, book_id)
|
||||
if book.publisher is None:
|
||||
book.publisher = u''
|
||||
self.bookform.NameEdit.setText(book.name)
|
||||
@ -380,7 +379,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
book.name = unicode(self.bookform.NameEdit.text())
|
||||
book.publisher = unicode(self.bookform.PublisherEdit.text())
|
||||
if self.checkBook(book, True):
|
||||
if self.songmanager.save_object(book):
|
||||
if self.manager.save_object(book):
|
||||
self.resetBooks()
|
||||
else:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -410,11 +409,11 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
``old_author``
|
||||
The author which will be deleted afterwards.
|
||||
"""
|
||||
existing_author = self.songmanager.get_object_filtered(Author,
|
||||
existing_author = self.manager.get_object_filtered(Author,
|
||||
and_(Author.first_name == old_author.first_name,
|
||||
Author.last_name == old_author.last_name,
|
||||
Author.display_name == old_author.display_name))
|
||||
songs = self.songmanager.get_all_objects(Song,
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.authors.contains(old_author))
|
||||
for song in songs:
|
||||
# We check if the song has already existing_author as author. If
|
||||
@ -422,8 +421,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
if existing_author not in song.authors:
|
||||
song.authors.append(existing_author)
|
||||
song.authors.remove(old_author)
|
||||
self.songmanager.save_object(song)
|
||||
self.songmanager.delete_object(Author, old_author.id)
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Author, old_author.id)
|
||||
|
||||
def mergeTopics(self, old_topic):
|
||||
"""
|
||||
@ -432,9 +431,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
``old_topic``
|
||||
The topic which will be deleted afterwards.
|
||||
"""
|
||||
existing_topic = self.songmanager.get_object_filtered(Topic,
|
||||
existing_topic = self.manager.get_object_filtered(Topic,
|
||||
Topic.name == old_topic.name)
|
||||
songs = self.songmanager.get_all_objects(Song,
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.topics.contains(old_topic))
|
||||
for song in songs:
|
||||
# We check if the song has already existing_topic as topic. If that
|
||||
@ -442,8 +441,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
if existing_topic not in song.topics:
|
||||
song.topics.append(existing_topic)
|
||||
song.topics.remove(old_topic)
|
||||
self.songmanager.save_object(song)
|
||||
self.songmanager.delete_object(Topic, old_topic.id)
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Topic, old_topic.id)
|
||||
|
||||
def mergeBooks(self, old_book):
|
||||
"""
|
||||
@ -452,15 +451,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
||||
``old_book``
|
||||
The book which will be deleted afterwards.
|
||||
"""
|
||||
existing_book = self.songmanager.get_object_filtered(Book,
|
||||
existing_book = self.manager.get_object_filtered(Book,
|
||||
and_(Book.name == old_book.name,
|
||||
Book.publisher == old_book.publisher))
|
||||
songs = self.songmanager.get_all_objects(Song,
|
||||
songs = self.manager.get_all_objects(Song,
|
||||
Song.song_book_id == old_book.id)
|
||||
for song in songs:
|
||||
song.song_book_id = existing_book.id
|
||||
self.songmanager.save_object(song)
|
||||
self.songmanager.delete_object(Book, old_book.id)
|
||||
self.manager.save_object(song)
|
||||
self.manager.delete_object(Book, old_book.id)
|
||||
|
||||
def onAuthorDeleteButtonClick(self):
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -213,12 +213,16 @@ class CCLIFileImport(SongImport):
|
||||
Verse lyrics
|
||||
<Empty line>
|
||||
<Empty line>
|
||||
Song CCLI number # e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
|
||||
Song copyright # e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
|
||||
Song CCLI number
|
||||
# e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
|
||||
Song copyright
|
||||
# e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
|
||||
Song authors # e.g. Lenny LeBlanc | Paul Baloche
|
||||
Licencing info # e.g. For use solely with the SongSelect Terms of Use.
|
||||
Licencing info
|
||||
# e.g. For use solely with the SongSelect Terms of Use.
|
||||
All rights Reserved. www.ccli.com
|
||||
CCLI Licence number of user # e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
|
||||
CCLI Licence number of user
|
||||
# e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
|
||||
|
||||
"""
|
||||
log.debug(u'TXT file text: %s', textList)
|
||||
|
@ -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'<?xml version='):
|
||||
songXML = SongXMLParser(song.lyrics)
|
||||
verseList = songXML.get_verses()
|
||||
#no verse list or only 1 space (in error)
|
||||
# no verse list or only 1 space (in error)
|
||||
if not song.verse_order or not song.verse_order.strip():
|
||||
for verse in verseList:
|
||||
verseTag = u'%s:%s' % (
|
||||
@ -357,7 +365,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.add_from_text(
|
||||
verse[1][:30], unicode(verse[1]), verseTag)
|
||||
else:
|
||||
#Loop through the verse list and expand the song accordingly.
|
||||
# Loop through the verse list and expand the song accordingly.
|
||||
for order in song.verse_order.upper().split(u' '):
|
||||
if len(order) == 0:
|
||||
break
|
||||
@ -389,31 +397,43 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.audit = [
|
||||
song.title, author_audit, song.copyright, unicode(song.ccli_number)
|
||||
]
|
||||
service_item.data_string = {u'title':song.search_title, u'authors':author_list}
|
||||
service_item.data_string = {u'title':song.search_title,
|
||||
u'authors':author_list}
|
||||
service_item.xml_version = self.openLyrics.song_to_xml(song)
|
||||
return True
|
||||
|
||||
def serviceLoad(self, item):
|
||||
"""
|
||||
Triggered by a song being loaded by the service item
|
||||
"""
|
||||
log.debug(u'serviceLoad')
|
||||
if item.data_string:
|
||||
search_results = self.parent.manager.get_all_objects(Song,
|
||||
Song.search_title.like(u'%' +
|
||||
item.data_string[u'title'].split(u'@')[0] + u'%'),
|
||||
Song.search_title ==
|
||||
item.data_string[u'title'].split(u'@')[0].lower() ,
|
||||
Song.search_title.asc())
|
||||
author_list = item.data_string[u'authors'].split(u',')
|
||||
author_list = item.data_string[u'authors'].split(u', ')
|
||||
editId = 0
|
||||
uuid = 0
|
||||
uuid = item._uuid
|
||||
if search_results:
|
||||
for song in search_results:
|
||||
count = 0
|
||||
for author in song.authors:
|
||||
if author.display_name in author_list:
|
||||
count += 1
|
||||
# All Authors the same
|
||||
if count == len(author_list):
|
||||
editId = song.id
|
||||
uuid = item._uuid
|
||||
else:
|
||||
# Authors different
|
||||
if self.addSongFromService:
|
||||
editId = self.openLyrics. \
|
||||
xml_to_song(item.xml_version)
|
||||
else:
|
||||
# Title does not match
|
||||
if self.addSongFromService:
|
||||
editId = self.openLyrics.xml_to_song(item.xml_version)
|
||||
# Update service with correct song id
|
||||
if editId != 0:
|
||||
Receiver.send_message(u'service_item_update',
|
||||
u'%s:%s' %(editId, uuid))
|
||||
|
||||
|
@ -74,7 +74,8 @@ class OpenLP1SongImport(SongImport):
|
||||
decoded = unicode(raw, codec)
|
||||
self.last_encoding = codec
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Error in detecting openlp.org 1.x database encoding.')
|
||||
log.exception(
|
||||
u'Error in detecting openlp.org 1.x database encoding.')
|
||||
try:
|
||||
decoded = unicode(raw, self.last_encoding)
|
||||
except UnicodeDecodeError:
|
||||
@ -152,7 +153,8 @@ class OpenLP1SongImport(SongImport):
|
||||
break
|
||||
for track in tracks:
|
||||
if track[0] == track_id[0]:
|
||||
self.add_media_file(self.decode_string(track[1], guess))
|
||||
self.add_media_file(self.decode_string(track[1],
|
||||
guess))
|
||||
break
|
||||
if self.stop_import_flag:
|
||||
success = False
|
||||
|
@ -229,14 +229,16 @@ class OpenSongImport(SongImport):
|
||||
# drop the square brackets
|
||||
right_bracket = thisline.find(u']')
|
||||
content = thisline[1:right_bracket].upper()
|
||||
# have we got any digits? If so, versenumber is everything from the digits
|
||||
# have we got any digits?
|
||||
# If so, versenumber is everything from the digits
|
||||
# to the end (even if there are some alpha chars on the end)
|
||||
match = re.match(u'(.*)(\d+.*)', content)
|
||||
if match is not None:
|
||||
versetype = match.group(1)
|
||||
versenum = match.group(2)
|
||||
else:
|
||||
# otherwise we assume number 1 and take the whole prefix as versetype
|
||||
# otherwise we assume number 1 and take the whole prefix as
|
||||
# the versetype
|
||||
versetype = content
|
||||
versenum = u'1'
|
||||
continue
|
||||
@ -301,6 +303,7 @@ class OpenSongImport(SongImport):
|
||||
# Assume it's no.1 if there's no digits
|
||||
tag = tag + u'1'
|
||||
if not versetags.has_key(tag):
|
||||
log.info(u'Got order %s but not in versetags, dropping this item from presentation order', tag)
|
||||
log.info(u'Got order %s but not in versetags, dropping this'
|
||||
u'item from presentation order', tag)
|
||||
else:
|
||||
self.verse_order_list.append(tag)
|
||||
|
@ -57,6 +57,7 @@ class SongBeamerTypes(object):
|
||||
u'Unknown': u'O'
|
||||
}
|
||||
|
||||
|
||||
class SongBeamerImport(SongImport):
|
||||
"""
|
||||
Import Song Beamer files(s)
|
||||
@ -66,6 +67,7 @@ class SongBeamerImport(SongImport):
|
||||
def __init__(self, master_manager, **kwargs):
|
||||
"""
|
||||
Initialise the import.
|
||||
|
||||
``master_manager``
|
||||
The song manager for the running OpenLP installation.
|
||||
"""
|
||||
@ -88,6 +90,7 @@ class SongBeamerImport(SongImport):
|
||||
# TODO: check that it is a valid SongBeamer file
|
||||
self.current_verse = u''
|
||||
self.current_verse_type = u'V'
|
||||
read_verses = False
|
||||
self.file_name = os.path.split(file)[1]
|
||||
self.import_wizard.incrementProgressBar(
|
||||
"Importing %s" % (self.file_name), 0)
|
||||
@ -100,134 +103,182 @@ class SongBeamerImport(SongImport):
|
||||
else:
|
||||
return False
|
||||
for line in self.songData:
|
||||
line = line.strip()
|
||||
if line.startswith('#'):
|
||||
log.debug(u'find tag: %s' % line)
|
||||
if not self.parse_tags(line):
|
||||
return False
|
||||
elif line.startswith('---'):
|
||||
log.debug(u'find ---')
|
||||
if len(self.current_verse) > 0:
|
||||
# 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'<b>', u'{st}'),
|
||||
(u'</b>', u'{/st}'),
|
||||
(u'<i>', u'{it}'),
|
||||
(u'</i>', u'{/it}'),
|
||||
(u'<u>', u'{u}'),
|
||||
(u'</u>', u'{/u}'),
|
||||
(u'<br>', u'{st}'),
|
||||
(u'</br>', u'{st}'),
|
||||
(u'</ br>', u'{st}'),
|
||||
(u'<p>', u'{p}'),
|
||||
(u'</p>', u'{/p}'),
|
||||
(u'<super>', u'{su}'),
|
||||
(u'</super>', u'{/su}'),
|
||||
(u'<sub>', u'{sb}'),
|
||||
(u'</sub>', u'{/sb}'),
|
||||
(u'<wordwrap>', u''),
|
||||
(u'</wordwrap>', u''),
|
||||
(u'<strike>', u''),
|
||||
(u'</strike>', 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
|
||||
# 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
|
||||
|
@ -47,8 +47,9 @@ class SongImport(QtCore.QObject):
|
||||
"""
|
||||
Initialise and create defaults for properties
|
||||
|
||||
song_manager is an instance of a SongManager, through which all
|
||||
database access is performed
|
||||
``manager``
|
||||
An instance of a SongManager, through which all database access is
|
||||
performed.
|
||||
"""
|
||||
self.manager = manager
|
||||
self.stop_import_flag = False
|
||||
@ -253,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):
|
||||
@ -296,7 +298,8 @@ class SongImport(QtCore.QObject):
|
||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||
for i, current_verse_tag in enumerate(self.verse_order_list):
|
||||
if verses_changed_to_other.has_key(current_verse_tag):
|
||||
self.verse_order_list[i] = verses_changed_to_other[current_verse_tag]
|
||||
self.verse_order_list[i] = \
|
||||
verses_changed_to_other[current_verse_tag]
|
||||
song.verse_order = u' '.join(self.verse_order_list)
|
||||
song.copyright = self.copyright
|
||||
song.comments = self.comments
|
||||
|
@ -56,8 +56,10 @@ class SongsTab(SettingsTab):
|
||||
self.SongUpdateOnEditCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
|
||||
self.SongUpdateOnEditCheckBox.setObjectName(u'SongUpdateOnEditCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SongUpdateOnEditCheckBox)
|
||||
self.SongAddFromServiceCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
|
||||
self.SongAddFromServiceCheckBox.setObjectName(u'SongAddFromServiceCheckBox')
|
||||
self.SongAddFromServiceCheckBox = QtGui.QCheckBox(
|
||||
self.SongsModeGroupBox)
|
||||
self.SongAddFromServiceCheckBox.setObjectName(
|
||||
u'SongAddFromServiceCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SongAddFromServiceCheckBox)
|
||||
self.SongsLayout.setWidget(
|
||||
0, QtGui.QFormLayout.LabelRole, self.SongsModeGroupBox)
|
||||
@ -83,7 +85,8 @@ class SongsTab(SettingsTab):
|
||||
'Display verses on live tool bar'))
|
||||
self.SongUpdateOnEditCheckBox.setText(
|
||||
translate('SongsPlugin.SongsTab', 'Update service from song edit'))
|
||||
self.SongAddFromServiceCheckBox.setText(translate('SongsPlugin.SongsTab',
|
||||
self.SongAddFromServiceCheckBox.setText(
|
||||
translate('SongsPlugin.SongsTab',
|
||||
'Add missing songs when opening service'))
|
||||
|
||||
def onSearchAsTypeCheckBoxChanged(self, check_state):
|
||||
@ -132,6 +135,8 @@ class SongsTab(SettingsTab):
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'search as type', QtCore.QVariant(self.song_search))
|
||||
settings.setValue(u'display songbar', QtCore.QVariant(self.song_bar))
|
||||
settings.setValue(u'update service on edit', QtCore.QVariant(self.update_edit))
|
||||
settings.setValue(u'add song from service', QtCore.QVariant(self.update_load))
|
||||
settings.setValue(u'update service on edit',
|
||||
QtCore.QVariant(self.update_edit))
|
||||
settings.setValue(u'add song from service',
|
||||
QtCore.QVariant(self.update_load))
|
||||
settings.endGroup()
|
||||
|
@ -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'<?xml version="1.0" encoding="UTF-8"?>' + \
|
||||
u'<song version="1.0">%s</song>' % 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'<song version="0.7" createdIn="OpenLP 2.0"/>')
|
||||
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'<?xml':
|
||||
xml = xml[38:]
|
||||
song_xml = objectify.fromstring(xml)
|
||||
properties = song_xml.properties
|
||||
song.copyright = unicode(properties.copyright.text)
|
||||
song.verse_order = unicode(properties.verseOrder.text)
|
||||
if song.verse_order == u'None':
|
||||
song.verse_order = u''
|
||||
song.topics = []
|
||||
song.book = None
|
||||
theme_name = None
|
||||
try:
|
||||
song.ccli_number = unicode(properties.ccliNo.text)
|
||||
except:
|
||||
song.ccli_number = u''
|
||||
try:
|
||||
theme_name = unicode(properties.themes.theme)
|
||||
except:
|
||||
pass
|
||||
if theme_name:
|
||||
song.theme_name = theme_name
|
||||
else:
|
||||
song.theme_name = u''
|
||||
# Process Titles
|
||||
for title in properties.titles.title:
|
||||
if not song.title:
|
||||
song.title = unicode(title.text)
|
||||
song.search_title = unicode(song.title)
|
||||
song.alternate_title = u''
|
||||
else:
|
||||
song.alternate_title = unicode(title.text)
|
||||
song.search_title += u'@' + song.alternate_title
|
||||
song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'',
|
||||
unicode(song.search_title)).lower()
|
||||
# Process Lyrics
|
||||
sxml = SongXMLBuilder()
|
||||
search_text = u''
|
||||
for lyrics in song_xml.lyrics:
|
||||
for verse in song_xml.lyrics.verse:
|
||||
text = u''
|
||||
for line in verse.lines.line:
|
||||
line = unicode(line)
|
||||
if not text:
|
||||
text = line
|
||||
else:
|
||||
text += u'\n' + line
|
||||
type = VerseType.expand_string(verse.attrib[u'name'][0])
|
||||
sxml.add_verse_to_lyrics(type, verse.attrib[u'name'][1], text)
|
||||
search_text = search_text + text
|
||||
song.search_lyrics = search_text.lower()
|
||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||
song.comments = u''
|
||||
song.song_number = u''
|
||||
# Process Authors
|
||||
for author in properties.authors.author:
|
||||
self._process_author(author.text, song)
|
||||
self.manager.save_object(song)
|
||||
return song.id
|
||||
|
||||
def _add_text_to_element(self, tag, parent, text=None, label=None):
|
||||
if label:
|
||||
element = etree.Element(tag, name = unicode(label))
|
||||
else:
|
||||
element = etree.Element(tag)
|
||||
if text:
|
||||
element.text = unicode(text)
|
||||
parent.append(element)
|
||||
return element
|
||||
|
||||
def _dump_xml(self, xml):
|
||||
"""
|
||||
Debugging aid to dump XML so that we can see what we have.
|
||||
"""
|
||||
return etree.tostring(xml, encoding=u'UTF-8',
|
||||
xml_declaration=True, pretty_print=True)
|
||||
|
||||
def _extract_xml(self, xml):
|
||||
"""
|
||||
Extract our newly created XML song.
|
||||
"""
|
||||
return etree.tostring(xml, encoding=u'UTF-8',
|
||||
xml_declaration=True)
|
||||
|
||||
def _process_author(self, name, song):
|
||||
"""
|
||||
Find or create an Author from display_name.
|
||||
"""
|
||||
name = unicode(name)
|
||||
author = self.manager.get_object_filtered(Author,
|
||||
Author.display_name == name)
|
||||
if author:
|
||||
# should only be one! so take the first
|
||||
song.authors.append(author)
|
||||
else:
|
||||
# Need a new author
|
||||
new_author = Author.populate(first_name=name.rsplit(u' ', 1)[0],
|
||||
last_name=name.rsplit(u' ', 1)[1], display_name=name)
|
||||
self.manager.save_object(new_author)
|
||||
song.authors.append(new_author)
|
||||
|
@ -25,6 +25,7 @@
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -55,6 +56,7 @@ class SongsPlugin(Plugin):
|
||||
self.manager = Manager(u'songs', init_schema)
|
||||
self.icon_path = u':/plugins/plugin_songs.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
self.whitespace = re.compile(r'\W+')
|
||||
|
||||
def getSettingsTab(self):
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
@ -63,6 +65,7 @@ class SongsPlugin(Plugin):
|
||||
def initialise(self):
|
||||
log.info(u'Songs Initialising')
|
||||
Plugin.initialise(self)
|
||||
self.toolsReindexItem.setVisible(True)
|
||||
self.mediaItem.displayResultsSong(
|
||||
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
|
||||
|
||||
@ -106,6 +109,57 @@ class SongsPlugin(Plugin):
|
||||
# No menu items for now.
|
||||
pass
|
||||
|
||||
def addToolsMenuItem(self, tools_menu):
|
||||
"""
|
||||
Give the alerts plugin the opportunity to add items to the
|
||||
**Tools** menu.
|
||||
|
||||
``tools_menu``
|
||||
The actual **Tools** menu item, so that your actions can
|
||||
use it as their parent.
|
||||
"""
|
||||
log.info(u'add tools menu')
|
||||
self.toolsReindexItem = QtGui.QAction(tools_menu)
|
||||
self.toolsReindexItem.setIcon(build_icon(u':/plugins/plugin_songs.png'))
|
||||
self.toolsReindexItem.setObjectName(u'toolsReindexItem')
|
||||
self.toolsReindexItem.setText(
|
||||
translate('SongsPlugin', '&Re-index Songs'))
|
||||
self.toolsReindexItem.setStatusTip(
|
||||
translate('SongsPlugin', 'Re-index the songs database to improve '
|
||||
'searching and ordering.'))
|
||||
tools_menu.addAction(self.toolsReindexItem)
|
||||
QtCore.QObject.connect(self.toolsReindexItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onToolsReindexItemTriggered)
|
||||
self.toolsReindexItem.setVisible(False)
|
||||
|
||||
def onToolsReindexItemTriggered(self):
|
||||
"""
|
||||
Rebuild the search title of each song.
|
||||
"""
|
||||
maxSongs = self.manager.get_object_count(Song)
|
||||
progressDialog = QtGui.QProgressDialog(
|
||||
translate('SongsPlugin', 'Reindexing songs...'),
|
||||
translate('SongsPlugin', 'Cancel'),
|
||||
0, maxSongs + 1, self.formparent)
|
||||
progressDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||
songs = self.manager.get_all_objects(Song)
|
||||
counter = 0
|
||||
for song in songs:
|
||||
counter += 1
|
||||
if song.title is None:
|
||||
song.title = u''
|
||||
if song.alternate_title is None:
|
||||
song.alternate_title = u''
|
||||
song.search_title = self.whitespace.sub(u' ', \
|
||||
song.title.lower()) + u' ' + \
|
||||
self.whitespace.sub(u' ', song.alternate_title.lower())
|
||||
progressDialog.setValue(counter)
|
||||
self.manager.save_objects(songs)
|
||||
counter += 1
|
||||
progressDialog.setValue(counter)
|
||||
self.mediaItem.displayResultsSong(
|
||||
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
|
||||
|
||||
def onSongImportItemClicked(self):
|
||||
if self.mediaItem:
|
||||
self.mediaItem.onImportClick()
|
||||
@ -206,4 +260,6 @@ class SongsPlugin(Plugin):
|
||||
"""
|
||||
log.info(u'Songs Finalising')
|
||||
self.manager.finalise()
|
||||
self.toolsReindexItem.setVisible(False)
|
||||
Plugin.finalise(self)
|
||||
|
||||
|
@ -34,11 +34,11 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
def __init__(self, songusagemanager, parent):
|
||||
def __init__(self, manager, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.songusagemanager = songusagemanager
|
||||
self.manager = manager
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
@ -53,6 +53,6 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog):
|
||||
QtGui.QMessageBox.Cancel)
|
||||
if ret == QtGui.QMessageBox.Ok:
|
||||
deleteDate = self.deleteCalendar.selectedDate().toPyDate()
|
||||
self.songusagemanager.delete_all_objects(SongUsageItem,
|
||||
self.manager.delete_all_objects(SongUsageItem,
|
||||
SongUsageItem.usagedate <= deleteDate)
|
||||
self.close()
|
||||
|
@ -76,7 +76,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
|
||||
filename = u'usage_detail_%s_%s.txt' % (
|
||||
self.fromDate.selectedDate().toString(u'ddMMyyyy'),
|
||||
self.toDate.selectedDate().toString(u'ddMMyyyy'))
|
||||
usage = self.plugin.songusagemanager.get_all_objects(
|
||||
usage = self.plugin.manager.get_all_objects(
|
||||
SongUsageItem, and_(
|
||||
SongUsageItem.usagedate >= self.fromDate.selectedDate().toPyDate(),
|
||||
SongUsageItem.usagedate < self.toDate.selectedDate().toPyDate()),
|
||||
|
@ -29,7 +29,8 @@ from datetime import datetime
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, \
|
||||
translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.songusage.forms import SongUsageDetailForm, \
|
||||
SongUsageDeleteForm
|
||||
@ -44,7 +45,7 @@ class SongUsagePlugin(Plugin):
|
||||
Plugin.__init__(self, u'SongUsage', u'1.9.3', plugin_helpers)
|
||||
self.weight = -4
|
||||
self.icon = build_icon(u':/plugins/plugin_songusage.png')
|
||||
self.songusagemanager = None
|
||||
self.manager = None
|
||||
self.songusageActive = False
|
||||
|
||||
def addToolsMenuItem(self, tools_menu):
|
||||
@ -115,15 +116,20 @@ class SongUsagePlugin(Plugin):
|
||||
self.settingsSection + u'/active',
|
||||
QtCore.QVariant(False)).toBool()
|
||||
self.SongUsageStatus.setChecked(self.SongUsageActive)
|
||||
if self.songusagemanager is None:
|
||||
self.songusagemanager = Manager(u'songusage', init_schema)
|
||||
self.SongUsagedeleteform = SongUsageDeleteForm(self.songusagemanager,
|
||||
if self.manager is None:
|
||||
self.manager = Manager(u'songusage', init_schema)
|
||||
self.SongUsagedeleteform = SongUsageDeleteForm(self.manager,
|
||||
self.formparent)
|
||||
self.SongUsagedetailform = SongUsageDetailForm(self, self.formparent)
|
||||
self.SongUsageMenu.menuAction().setVisible(True)
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Tidy up on exit
|
||||
"""
|
||||
log.info(u'Plugin Finalise')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
self.SongUsageMenu.menuAction().setVisible(False)
|
||||
#stop any events being processed
|
||||
self.SongUsageActive = False
|
||||
@ -148,7 +154,7 @@ class SongUsagePlugin(Plugin):
|
||||
song_usage_item.authors = u''
|
||||
for author in audit[1]:
|
||||
song_usage_item.authors += author + u' '
|
||||
self.songusagemanager.save_object(song_usage_item)
|
||||
self.manager.save_object(song_usage_item)
|
||||
|
||||
def onSongUsageDelete(self):
|
||||
self.SongUsagedeleteform.exec_()
|
||||
@ -176,11 +182,3 @@ class SongUsagePlugin(Plugin):
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('SongUsagePlugin', 'SongUsage')
|
||||
}
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Time to tidy up on exit
|
||||
"""
|
||||
log.info(u'SongUsage Finalising')
|
||||
self.manager.finalise()
|
||||
Plugin.finalise(self)
|
||||
|
@ -1,73 +0,0 @@
|
||||
[bibles]
|
||||
display new chapter = False
|
||||
display brackets = 0
|
||||
dual bibles = False
|
||||
db type = sqlite
|
||||
bible theme =
|
||||
verse layout style = 1
|
||||
status = 1
|
||||
data path = bibles
|
||||
|
||||
[media]
|
||||
status = 1
|
||||
|
||||
[alerts]
|
||||
font color = #ffffff
|
||||
background color = #660000
|
||||
font face = Sans Serif
|
||||
timeout = 5
|
||||
|
||||
[remotes]
|
||||
remote port = 4316
|
||||
|
||||
[presentations]
|
||||
status = 1
|
||||
impress = 0
|
||||
data path = presentations
|
||||
powerpoint = 0
|
||||
powerpoint viewer = 0
|
||||
|
||||
[custom]
|
||||
status = 1
|
||||
display footer = True
|
||||
data path = custom
|
||||
db type = sqlite
|
||||
|
||||
[themes]
|
||||
global theme =
|
||||
data path = themes
|
||||
theme level = 1
|
||||
|
||||
[images]
|
||||
status = 1
|
||||
data path = images
|
||||
loop delay = 5
|
||||
|
||||
[user interface]
|
||||
theme manager = True
|
||||
media manager = True
|
||||
preview panel = True
|
||||
service manager = True
|
||||
|
||||
[servicemanager]
|
||||
data path = servicemanager
|
||||
|
||||
[general]
|
||||
monitor = 0
|
||||
run environment = dev
|
||||
ccli number =
|
||||
blank warning = False
|
||||
show splash = True
|
||||
last version test = 2010-02-05
|
||||
songselect username =
|
||||
save prompt = False
|
||||
songselect password =
|
||||
auto open = False
|
||||
|
||||
[songs]
|
||||
status = 1
|
||||
search as type = False
|
||||
display songbar = True
|
||||
data path = songs
|
||||
db type = sqlite
|
||||
|
Before Width: | Height: | Size: 343 KiB |
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<theme version="1.0"><name>Bible Readings</name><background mode="opaque" type="image"><filename>open6_2.jpg</filename></background><font type="main"><name>Arial</name><color>#ffffff</color><proportion>40</proportion><proportion>40</proportion><location override="False"/></font><font type="footer"><name>Arial</name><color>#ffffff</color><proportion>12</proportion><proportion>12</proportion><location override="False"/></font><display><shadow color="#000000">False</shadow><outline color="#000000">False</outline><horizontalAlign>2</horizontalAlign><verticalAlign>1</verticalAlign><wrapStyle>0</wrapStyle></display></theme>
|
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 42 KiB |
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<theme version="1.0">
|
||||
<name>
|
||||
Blue
|
||||
</name>
|
||||
<background mode="opaque" type="solid">
|
||||
<color>
|
||||
#0000ff
|
||||
</color>
|
||||
</background>
|
||||
<font type="main">
|
||||
<name>
|
||||
DejaVu Sans Mono
|
||||
</name>
|
||||
<color>
|
||||
#ffff00
|
||||
</color>
|
||||
<proportion>
|
||||
45
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<font type="footer">
|
||||
<name>
|
||||
DejaVu Sans Mono
|
||||
</name>
|
||||
<color>
|
||||
#ffff00
|
||||
</color>
|
||||
<proportion>
|
||||
12
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<display>
|
||||
<shadow color="#000000">
|
||||
False
|
||||
</shadow>
|
||||
<outline color="#000000">
|
||||
False
|
||||
</outline>
|
||||
<horizontalAlign>
|
||||
0
|
||||
</horizontalAlign>
|
||||
<verticalAlign>
|
||||
1
|
||||
</verticalAlign>
|
||||
<wrapStyle>
|
||||
0
|
||||
</wrapStyle>
|
||||
</display>
|
||||
</theme>
|
Before Width: | Height: | Size: 45 KiB |
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<theme version="1.0">
|
||||
<name>
|
||||
theme1
|
||||
</name>
|
||||
<background mode="opaque" type="solid">
|
||||
<color>
|
||||
#400080
|
||||
</color>
|
||||
</background>
|
||||
<font type="main">
|
||||
<name>
|
||||
Tahoma
|
||||
</name>
|
||||
<color>
|
||||
#0080ff
|
||||
</color>
|
||||
<proportion>
|
||||
45
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<font type="footer">
|
||||
<name>
|
||||
Tahoma
|
||||
</name>
|
||||
<color>
|
||||
#0080ff
|
||||
</color>
|
||||
<proportion>
|
||||
12
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<display>
|
||||
<shadow color="#000000">
|
||||
False
|
||||
</shadow>
|
||||
<outline color="#000000">
|
||||
False
|
||||
</outline>
|
||||
<horizontalAlign>
|
||||
0
|
||||
</horizontalAlign>
|
||||
<verticalAlign>
|
||||
0
|
||||
</verticalAlign>
|
||||
<wrapStyle>
|
||||
0
|
||||
</wrapStyle>
|
||||
</display>
|
||||
</theme>
|
Before Width: | Height: | Size: 108 KiB |
@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<theme version="1.0">
|
||||
<name>
|
||||
theme2
|
||||
</name>
|
||||
<background mode="opaque" type="gradient">
|
||||
<startColor>
|
||||
#ff8000
|
||||
</startColor>
|
||||
<endColor>
|
||||
#0000ff
|
||||
</endColor>
|
||||
<direction>
|
||||
vertical
|
||||
</direction>
|
||||
</background>
|
||||
<font type="main">
|
||||
<name>
|
||||
Tahoma
|
||||
</name>
|
||||
<color>
|
||||
#ffffff
|
||||
</color>
|
||||
<proportion>
|
||||
45
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<font type="footer">
|
||||
<name>
|
||||
Tahoma
|
||||
</name>
|
||||
<color>
|
||||
#ffffff
|
||||
</color>
|
||||
<proportion>
|
||||
12
|
||||
</proportion>
|
||||
<weight>
|
||||
Normal
|
||||
</weight>
|
||||
<italics>
|
||||
False
|
||||
</italics>
|
||||
<location override="False"/>
|
||||
</font>
|
||||
<display>
|
||||
<shadow color="#000000">
|
||||
True
|
||||
</shadow>
|
||||
<outline color="#000000">
|
||||
True
|
||||
</outline>
|
||||
<horizontalAlign>
|
||||
0
|
||||
</horizontalAlign>
|
||||
<verticalAlign>
|
||||
0
|
||||
</verticalAlign>
|
||||
<wrapStyle>
|
||||
0
|
||||
</wrapStyle>
|
||||
</display>
|
||||
</theme>
|
Before Width: | Height: | Size: 462 KiB |
Before Width: | Height: | Size: 47 KiB |
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<theme version="1.0"><name>theme3</name><background mode="opaque" type="image"><filename>sunset2.jpg</filename></background><font type="main"><name>DejaVu Sans Mono</name><color>#ffff00</color><proportion>32</proportion><weight>Normal</weight><italics>False</italics><location override="False"/></font><font type="footer"><name>DejaVu Sans Mono</name><color>#ffff00</color><proportion>12</proportion><weight>Normal</weight><italics>False</italics><location override="False"/></font><display><shadow color="#000000">False</shadow><outline color="#000000">False</outline><horizontalAlign>1</horizontalAlign><verticalAlign>2</verticalAlign><wrapStyle>0</wrapStyle></display></theme>
|
@ -1,23 +0,0 @@
|
||||
[custom]
|
||||
db type = sqlite
|
||||
|
||||
[bibles]
|
||||
db type = sqlite
|
||||
|
||||
[main]
|
||||
themes path = themes
|
||||
data path = /home/raoul/.openlp/data
|
||||
|
||||
[songs]
|
||||
db type = sqlite
|
||||
file name = songs.sqlite
|
||||
data path = songs
|
||||
|
||||
[presentations]
|
||||
suffix name = ppt,pps,odi
|
||||
|
||||
[images]
|
||||
suffix name = jpg,gif,png,bmp
|
||||
|
||||
[videos]
|
||||
suffix name = avi,mpeg
|
@ -1,24 +0,0 @@
|
||||
[custom]
|
||||
db type = sqlite
|
||||
|
||||
[bibles]
|
||||
db type = sqlite
|
||||
|
||||
[main]
|
||||
themes path = themes
|
||||
data path = /home/<username>/.openlp/data
|
||||
|
||||
[songs]
|
||||
file name = songs.sqlite
|
||||
data path = songs
|
||||
db type = sqlite
|
||||
|
||||
[presentations]
|
||||
suffix name = ppt,pps,odi
|
||||
|
||||
|
||||
[images]
|
||||
suffix name = jpg,gif,png,bmp
|
||||
|
||||
[videos]
|
||||
suffix name = avi,mpeg
|
@ -1,23 +0,0 @@
|
||||
[custom]
|
||||
db type = sqlite
|
||||
|
||||
[bibles]
|
||||
db type = sqlite
|
||||
|
||||
[main]
|
||||
themes path = themes
|
||||
data path = c:\\Documents and Settings\\<username>\\Application Data\\.openlp\\data
|
||||
|
||||
[songs]
|
||||
file name = songs.sqlite
|
||||
data path = songs
|
||||
db type = sqlite
|
||||
|
||||
[presentations]
|
||||
suffix name = ppt,pps,odi
|
||||
|
||||
[images]
|
||||
suffix name = jpg,gif,png,bmp
|
||||
|
||||
[videos]
|
||||
suffix name = avi,mpeg
|