forked from openlp/openlp
commit
a2d8885d07
@ -23,7 +23,14 @@ from render import Renderer
|
||||
from settingsmanager import SettingsManager
|
||||
from pluginmanager import PluginManager
|
||||
|
||||
__all__ = ['Renderer', 'SettingsManager', 'PluginManager', 'translate']
|
||||
__all__ = ['Renderer', 'SettingsManager', 'PluginManager', 'translate', 'fileToXML']
|
||||
|
||||
def translate(context, text):
|
||||
return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8)
|
||||
|
||||
def fileToXML(xmlfile):
|
||||
file=open(xmlfile)
|
||||
xml =''.join(file.readlines()) # read the file and change list to a string
|
||||
file.close()
|
||||
return xml
|
||||
|
||||
|
@ -41,6 +41,8 @@ class EventType(object):
|
||||
PreviewBeforeShow = 13
|
||||
PreviewAfterShow = 14
|
||||
|
||||
ThemeListChanged = 15
|
||||
|
||||
|
||||
class Event(object):
|
||||
"""
|
||||
@ -49,6 +51,6 @@ class Event(object):
|
||||
def __init__(self, event_type=EventType.Default, payload=None):
|
||||
self.event_type = event_type
|
||||
self.payload = payload
|
||||
|
||||
|
||||
def get_type(self):
|
||||
return self.event_type
|
||||
|
@ -26,21 +26,21 @@ class EventManager(object):
|
||||
A mechanism to send events to all registered endpoints
|
||||
the endpoints are registered and listen with a handle_event method
|
||||
the endpoint will decide whether to do somthing with the event or ignore it
|
||||
|
||||
|
||||
"""
|
||||
global log
|
||||
log=logging.getLogger(u'EventManager')
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.endpoints=[]
|
||||
log.info(u'Initialising')
|
||||
|
||||
|
||||
def register(self, plugin):
|
||||
log.debug(u'plugin %s registered with EventManager'%plugin)
|
||||
log.debug(u'plugin %s registered with EventManager', plugin)
|
||||
self.endpoints.append(plugin)
|
||||
|
||||
|
||||
def post_event(self, event):
|
||||
log.debug(u'post event called for event %s'%event.get_type)
|
||||
log.debug(u'post event called for event %s', event.get_type)
|
||||
for point in self.endpoints:
|
||||
point.handle_event(event)
|
||||
|
||||
|
@ -1,6 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
"""
|
||||
OpenLP - Open Source Lyrics Projection
|
||||
Copyright (c) 2008 Raoul Snyman
|
||||
Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten Tinggaard
|
||||
|
||||
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 xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
"""
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<song version="1.0">
|
||||
<lyrics language="en">
|
||||
@ -11,24 +29,27 @@ from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
</song>
|
||||
|
||||
"""
|
||||
from xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
|
||||
class SongXMLBuilder():
|
||||
def __init__(self):
|
||||
# Create the minidom document
|
||||
# Create the minidom document
|
||||
self.song_xml = Document()
|
||||
|
||||
|
||||
def new_document(self):
|
||||
# Create the <song> base element
|
||||
self.song = self.song_xml.createElement(u'song')
|
||||
self.song_xml.appendChild(self.song)
|
||||
self.song.setAttribute(u'version', u'1.0')
|
||||
|
||||
|
||||
def add_lyrics_to_song(self):
|
||||
# Create the main <lyrics> element
|
||||
self.lyrics = self.song_xml.createElement(u'lyrics')
|
||||
self.lyrics.setAttribute(u'language', u'en')
|
||||
self.song.appendChild(self.lyrics)
|
||||
|
||||
def add_verse_to_lyrics(self, type, number, content):
|
||||
|
||||
def add_verse_to_lyrics(self, type, number, content):
|
||||
"""
|
||||
type - type of verse (Chorus, Verse , Bridge, Custom etc
|
||||
number - number of item eg verse 1
|
||||
@ -36,34 +57,34 @@ class SongXMLBuilder():
|
||||
"""
|
||||
verse = self.song_xml.createElement(u'verse')
|
||||
verse.setAttribute(u'type', type)
|
||||
verse.setAttribute(u'label', number)
|
||||
verse.setAttribute(u'label', number)
|
||||
self.lyrics.appendChild(verse)
|
||||
|
||||
|
||||
# add data as a CDATA section
|
||||
cds = self.song_xml.createCDATASection(content)
|
||||
verse.appendChild(cds)
|
||||
|
||||
|
||||
def dump_xml(self):
|
||||
# Debugging aid to see what we have
|
||||
print self.song_xml.toprettyxml(indent=" ")
|
||||
|
||||
|
||||
def extract_xml(self):
|
||||
# Print our newly created XML
|
||||
return self.song_xml.toxml()
|
||||
|
||||
|
||||
class SongXMLParser():
|
||||
def __init__(self, xml):
|
||||
self.song_xml = ElementTree(element=XML(xml))
|
||||
|
||||
|
||||
def get_verses(self):
|
||||
#return a list of verse's and attributes
|
||||
iter=self.song_xml.getiterator()
|
||||
verse_list = []
|
||||
for element in iter:
|
||||
for element in iter:
|
||||
if element.tag == u'verse':
|
||||
verse_list.append([element.attrib, element.text])
|
||||
return verse_list
|
||||
|
||||
|
||||
def dump_xml(self):
|
||||
# Debugging aid to see what we have
|
||||
print dump(self.song_xml)
|
||||
|
@ -1,16 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
"""
|
||||
OpenLP - Open Source Lyrics Projection
|
||||
Copyright (c) 2008 Raoul Snyman
|
||||
Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten Tinggaard
|
||||
|
||||
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 xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<song version="1.0">
|
||||
<lyrics language="en">
|
||||
<verse type="chorus" label="1">
|
||||
<![CDATA[ ... ]]>
|
||||
</verse>
|
||||
</lyrics>
|
||||
</song>
|
||||
|
||||
For XML Schema see wiki.openlp.org
|
||||
"""
|
||||
from xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
|
||||
class ThemeXMLBuilder():
|
||||
def __init__(self):
|
||||
# Create the minidom document
|
||||
@ -29,12 +42,12 @@ class ThemeXMLBuilder():
|
||||
|
||||
def add_background_transparent(self):
|
||||
# Create the main <lyrics> element
|
||||
background = self.theme_xml.createElement(u'Background')
|
||||
background = self.theme_xml.createElement(u'background')
|
||||
background.setAttribute(u'mode', u'transparent')
|
||||
self.theme.appendChild(background)
|
||||
|
||||
def add_background_solid(self, bkcolor):
|
||||
background = self.theme_xml.createElement(u'Background')
|
||||
background = self.theme_xml.createElement(u'background')
|
||||
background.setAttribute(u'mode', u'opaque')
|
||||
background.setAttribute(u'type', u'solid')
|
||||
self.theme.appendChild(background)
|
||||
@ -44,24 +57,29 @@ class ThemeXMLBuilder():
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
|
||||
def add_background_gradient(self, startcolor, endcolor):
|
||||
background = self.theme_xml.createElement(u'Background')
|
||||
def add_background_gradient(self, startcolor, endcolor, direction):
|
||||
background = self.theme_xml.createElement(u'background')
|
||||
background.setAttribute(u'mode', u'opaque')
|
||||
background.setAttribute(u'type', u'gradient')
|
||||
background.setAttribute(u'type', u'Gradient')
|
||||
self.theme.appendChild(background)
|
||||
|
||||
color = self.theme_xml.createElement(u'startcolor')
|
||||
color = self.theme_xml.createElement(u'startColor')
|
||||
bkc = self.theme_xml.createTextNode(startcolor)
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
|
||||
color = self.theme_xml.createElement(u'endcolor')
|
||||
color = self.theme_xml.createElement(u'endColor')
|
||||
bkc = self.theme_xml.createTextNode(endcolor)
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
|
||||
def add_background_image(self, filename, bordercolor):
|
||||
background = self.theme_xml.createElement(u'Background')
|
||||
color = self.theme_xml.createElement(u'direction')
|
||||
bkc = self.theme_xml.createTextNode(direction)
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
|
||||
def add_background_image(self, filename):
|
||||
background = self.theme_xml.createElement(u'background')
|
||||
background.setAttribute(u'mode', u'opaque')
|
||||
background.setAttribute(u'type', u'image')
|
||||
self.theme.appendChild(background)
|
||||
@ -71,26 +89,62 @@ class ThemeXMLBuilder():
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
|
||||
color = self.theme_xml.createElement(u'bordercolor')
|
||||
bkc = self.theme_xml.createTextNode(bordercolor)
|
||||
color.appendChild(bkc)
|
||||
background.appendChild(color)
|
||||
def add_font(self, fontname, fontcolor, fontproportion, fonttype=u'main'):
|
||||
background = self.theme_xml.createElement(u'font')
|
||||
background.setAttribute(u'type',fonttype)
|
||||
self.theme.appendChild(background)
|
||||
|
||||
name = self.theme_xml.createElement(u'name')
|
||||
fn = self.theme_xml.createTextNode(fontname)
|
||||
name.appendChild(fn)
|
||||
background.appendChild(name)
|
||||
|
||||
def add_verse_to_lyrics(self, type, number, content):
|
||||
"""
|
||||
type - type of verse (Chorus, Verse , Bridge, Custom etc
|
||||
number - number of item eg verse 1
|
||||
content - the text to be stored
|
||||
"""
|
||||
verse = self.theme_xml.createElement(u'verse')
|
||||
verse.setAttribute(u'type', type)
|
||||
verse.setAttribute(u'label', number)
|
||||
self.lyrics.appendChild(verse)
|
||||
name = self.theme_xml.createElement(u'color')
|
||||
fn = self.theme_xml.createTextNode(fontcolor)
|
||||
name.appendChild(fn)
|
||||
background.appendChild(name)
|
||||
|
||||
# add data as a CDATA section
|
||||
cds = self.theme_xml.createCDATASection(content)
|
||||
verse.appendChild(cds)
|
||||
name = self.theme_xml.createElement(u'proportion')
|
||||
fn = self.theme_xml.createTextNode(fontproportion)
|
||||
name.appendChild(fn)
|
||||
background.appendChild(name)
|
||||
|
||||
def add_display(self, shadow, shadowColor, outline, outlineColor, horizontal, vertical, wrap):
|
||||
background = self.theme_xml.createElement(u'display')
|
||||
self.theme.appendChild(background)
|
||||
|
||||
tagElement = self.theme_xml.createElement(u'shadow')
|
||||
tagElement.setAttribute(u'color',shadowColor)
|
||||
tagValue = self.theme_xml.createTextNode(shadow)
|
||||
tagElement.appendChild(tagValue)
|
||||
background.appendChild(tagElement)
|
||||
|
||||
tagElement = self.theme_xml.createElement(u'outline')
|
||||
tagElement.setAttribute(u'color',outlineColor)
|
||||
tagValue = self.theme_xml.createTextNode(outline)
|
||||
tagElement.appendChild(tagValue)
|
||||
background.appendChild(tagElement)
|
||||
|
||||
tagElement = self.theme_xml.createElement(u'horizontalAlign')
|
||||
tagValue = self.theme_xml.createTextNode(horizontal)
|
||||
tagElement.appendChild(tagValue)
|
||||
background.appendChild(tagElement)
|
||||
|
||||
tagElement = self.theme_xml.createElement(u'verticalAlign')
|
||||
tagValue = self.theme_xml.createTextNode(vertical)
|
||||
tagElement.appendChild(tagValue)
|
||||
background.appendChild(tagElement)
|
||||
|
||||
tagElement = self.theme_xml.createElement(u'wrapStyle')
|
||||
tagValue = self.theme_xml.createTextNode(wrap)
|
||||
tagElement.appendChild(tagValue)
|
||||
background.appendChild(tagElement)
|
||||
|
||||
def child_element(self, tag, value):
|
||||
tagElement = self.theme_xml.createElement(tag)
|
||||
tagValue = self.theme_xml.createTextNode(value)
|
||||
tagElement.appendChild(ftagValue)
|
||||
self.background.appendChild(tagElement)
|
||||
|
||||
def dump_xml(self):
|
||||
# Debugging aid to see what we have
|
||||
@ -102,17 +156,35 @@ class ThemeXMLBuilder():
|
||||
|
||||
class ThemeXMLParser():
|
||||
def __init__(self, xml):
|
||||
self.theme_xml = ElementTree(element=XML(xml))
|
||||
|
||||
def get_verses(self):
|
||||
#return a list of verse's and attributes
|
||||
iter=self.theme_xml.getiterator()
|
||||
verse_list = []
|
||||
theme_xml = ElementTree(element=XML(xml))
|
||||
iter=theme_xml.getiterator()
|
||||
master = u''
|
||||
for element in iter:
|
||||
if element.tag == u'verse':
|
||||
verse_list.append([element.attrib, element.text])
|
||||
return verse_list
|
||||
#print element.tag, element.text
|
||||
if len(element.getchildren()) > 0:
|
||||
master= element.tag + u'_'
|
||||
if len(element.attrib) > 0:
|
||||
#print "D", element.tag , element.attrib
|
||||
for e in element.attrib.iteritems():
|
||||
#print "A", master, e[0], e[1]
|
||||
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'):
|
||||
#print "b", master, element.tag, element.text, e[0], e[1]
|
||||
setattr(self, master + element.tag , element.text)
|
||||
setattr(self, master + element.tag +u'_'+ e[0], e[1])
|
||||
else:
|
||||
field = master + e[0]
|
||||
setattr(self, field, e[1])
|
||||
else:
|
||||
#print "c", element.tag
|
||||
if element.tag is not None :
|
||||
field = master + element.tag
|
||||
setattr(self, field, element.text)
|
||||
|
||||
def dump_xml(self):
|
||||
# Debugging aid to see what we have
|
||||
print dump(self.theme_xml)
|
||||
def __str__(self):
|
||||
s = u''
|
||||
for k in dir(self):
|
||||
if k[0:1] != u'_':
|
||||
s+= u'%30s : %s\n' %(k,getattr(self,k))
|
||||
return s
|
||||
|
@ -56,11 +56,11 @@ class Renderer:
|
||||
|
||||
def set_theme(self, theme):
|
||||
self._theme=theme
|
||||
if theme.BackgroundType == 2:
|
||||
self.set_bg_image(theme.BackgroundParameter1)
|
||||
if theme.background_type == u'image':
|
||||
self.set_bg_image(theme.background_filename)
|
||||
|
||||
def set_bg_image(self, filename):
|
||||
log.debug(u"set bg image %s", filename)
|
||||
log.debug(u'set bg image %s', filename)
|
||||
self._bg_image_filename=filename
|
||||
if self._paint is not None:
|
||||
self.scale_bg_image()
|
||||
@ -69,11 +69,13 @@ class Renderer:
|
||||
assert self._paint
|
||||
i=QtGui.QImage(self._bg_image_filename)
|
||||
# rescale and offset
|
||||
imw=i.width();imh=i.height()
|
||||
dcw=self._paint.width()+1;dch=self._paint.height()
|
||||
imw=i.width()
|
||||
imh=i.height()
|
||||
dcw=self._paint.width()+1
|
||||
dch=self._paint.height()
|
||||
imratio=imw/float(imh)
|
||||
dcratio=dcw/float(dch)
|
||||
log.debug(u"Image scaling params %s %s %s %s %s %s", imw, imh, imratio, dcw, dch, dcratio)
|
||||
log.debug(u'Image scaling params %s %s %s %s %s %s', imw, imh, imratio, dcw, dch, dcratio)
|
||||
if imratio > dcratio:
|
||||
scale=dcw/float(imw)
|
||||
elif imratio < dcratio:
|
||||
@ -94,20 +96,20 @@ class Renderer:
|
||||
def set_words_openlp(self, words):
|
||||
# log.debug(u" "set words openlp", words
|
||||
verses=[]
|
||||
words=words.replace("\r\n", "\n")
|
||||
verses_text=words.split('\n\n')
|
||||
words=words.replace(u'\r\n', u'\n')
|
||||
verses_text=words.split(u'\n\n')
|
||||
for v in verses_text:
|
||||
lines=v.split('\n')
|
||||
lines=v.split(u'\n')
|
||||
verses.append(self.split_set_of_lines(lines)[0])
|
||||
self.words=verses
|
||||
verses_text=[]
|
||||
for v in verses:
|
||||
verses_text.append('\n'.join(v).lstrip()) # remove first \n
|
||||
verses_text.append(u'\n'.join(v).lstrip()) # remove first \n
|
||||
|
||||
return verses_text
|
||||
|
||||
def render_screen(self, screennum):
|
||||
log.debug(u"render screen\n %s %s ", screennum, self.words[screennum])
|
||||
log.debug(u'render screen\n %s %s ', screennum, self.words[screennum])
|
||||
import time
|
||||
t=0.0
|
||||
words=self.words[screennum]
|
||||
@ -121,40 +123,49 @@ class Renderer:
|
||||
def _render_background(self):
|
||||
assert(self._theme)
|
||||
assert(self._paint)
|
||||
log.debug(u"render background %s %s", self._theme.BackgroundType)
|
||||
log.debug(u'render background %s ', self._theme.background_type)
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
if self._theme.BackgroundType == 0:
|
||||
p.fillRect(self._paint.rect(), self._theme.BackgroundParameter1)
|
||||
elif self._theme.BackgroundType == 1: # gradient
|
||||
#TODO Add Theme code and fix direction
|
||||
if self._theme.background_type == u'solid':
|
||||
p.fillRect(self._paint.rect(), QtGui.QColor(self._theme.background_color))
|
||||
elif self._theme.background_type == u'Gradient' : # gradient
|
||||
gradient = None
|
||||
if self._theme.background_direction == u'vertical':
|
||||
w = int(self._paint.width())/2
|
||||
gradient = QtGui.QLinearGradient(w, 0, w, self._paint.height()) # vertical
|
||||
elif self._theme.background_direction == u'horizontal':
|
||||
h = int(self._paint.height())/2
|
||||
gradient = QtGui.QLinearGradient(0, h, self._paint.width(), h) # Horizontal
|
||||
else:
|
||||
w = int(self._paint.width())/2
|
||||
h = int(self._paint.height())/2
|
||||
gradient = QtGui.QRadialGradient(w, h, w) # Circular
|
||||
|
||||
gradient.setColorAt(0, QtGui.QColor(self._theme.background_startColor))
|
||||
gradient.setColorAt(1, QtGui.QColor(self._theme.background_endColor))
|
||||
|
||||
gradient = QtGui.QLinearGradient(0, 0, self._paint.width(), self._paint.height())
|
||||
gradient.setColorAt(0, QtGui.QColor(255, 0, 0))
|
||||
gradient.setColorAt(0.5, QtGui.QColor(0, 255, 0))
|
||||
gradient.setColorAt(1, QtGui.QColor(0, 0, 255))
|
||||
p.setBrush(QtGui.QBrush(gradient))
|
||||
rectPath = QtGui.QPainterPath()
|
||||
|
||||
MAX_X = self._paint.width()
|
||||
MAX_Y = self._paint.height()
|
||||
|
||||
max_x = self._paint.width()
|
||||
max_y = self._paint.height()
|
||||
rectPath.moveTo(0, 0)
|
||||
rectPath.lineTo(0, MAX_Y)
|
||||
rectPath.lineTo(MAX_X, MAX_Y)
|
||||
rectPath.lineTo(MAX_X, 0)
|
||||
rectPath.lineTo(0, max_y)
|
||||
rectPath.lineTo(max_x, max_y)
|
||||
rectPath.lineTo(max_x, 0)
|
||||
|
||||
rectPath.closeSubpath()
|
||||
p.drawPath(rectPath)
|
||||
|
||||
elif self._theme.BackgroundType == 2: # image
|
||||
elif self._theme.background_type== u'image': # image
|
||||
r=self._paint.rect()
|
||||
log.debug(r.x(), r.y(), r.width(),r.height())
|
||||
log.debug(self._theme.BackgroundParameter2)
|
||||
if self._theme.BackgroundParameter2 is not None:
|
||||
p.fillRect(self._paint.rect(), self._theme.BackgroundParameter2)
|
||||
log.debug(u'Image size details %d %d %d %d ', r.x(), r.y(), r.width(),r.height())
|
||||
log.debug(u' Background Parameter %d ', self._theme.background_borderColor)
|
||||
if self._theme.Bbackground_borderColor is not None:
|
||||
p.fillRect(self._paint.rect(), self._theme.background_borderColor)
|
||||
p.drawPixmap(self.background_offsetx,self.background_offsety, self.img)
|
||||
p.end()
|
||||
log.debug(u"render background done")
|
||||
log.debug(u'render background done')
|
||||
|
||||
def split_set_of_lines(self, lines):
|
||||
|
||||
@ -221,24 +232,23 @@ class Renderer:
|
||||
|
||||
def _render_lines(self, lines):
|
||||
"""render a set of lines according to the theme, return bounding box"""
|
||||
log.debug(u"_render_lines %s", lines)
|
||||
#log.debug(u'_render_lines %s', lines)
|
||||
|
||||
bbox=self._render_lines_unaligned(lines)
|
||||
print bbox
|
||||
|
||||
t=self._theme
|
||||
x=self._rect.left()
|
||||
if t.VerticalAlign==0: # top align
|
||||
if int(t.display_verticalAlign) == 0: # top align
|
||||
y = self._rect.top()
|
||||
elif t.VerticalAlign==1: # bottom align
|
||||
elif int(t.display_verticalAlign) == 1: # bottom align
|
||||
y=self._rect.bottom()-bbox.height()
|
||||
elif t.VerticalAlign==2: # centre align
|
||||
elif int(t.display_verticalAlign) == 2: # centre align
|
||||
y=self._rect.top()+(self._rect.height()-bbox.height())/2
|
||||
else:
|
||||
assert(0, "Invalid value for theme.VerticalAlign:%d" % t.VerticalAlign)
|
||||
assert(0, u'Invalid value for theme.VerticalAlign:%s' % t.display_verticalAlign)
|
||||
self._render_background()
|
||||
bbox=self._render_lines_unaligned(lines, (x,y))
|
||||
log.debug(u"render lines DONE")
|
||||
log.debug(u'render lines DONE')
|
||||
|
||||
return bbox
|
||||
|
||||
@ -250,7 +260,7 @@ class Renderer:
|
||||
than a screenful (eg. by using split_set_of_lines)
|
||||
|
||||
Returns the bounding box of the text as QRect"""
|
||||
log.debug(u"render unaligned %s", lines)
|
||||
log.debug(u'render unaligned %s', lines)
|
||||
x,y=tlcorner
|
||||
brx=x
|
||||
bry=y
|
||||
@ -269,7 +279,7 @@ class Renderer:
|
||||
p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
|
||||
p.drawRect(retval)
|
||||
p.end()
|
||||
log.debug(u"render unaligned DONE")
|
||||
log.debug(u'render unaligned DONE')
|
||||
|
||||
return retval
|
||||
|
||||
@ -283,7 +293,7 @@ class Renderer:
|
||||
|
||||
Returns the bottom-right corner (of what was rendered) as a tuple(x,y).
|
||||
"""
|
||||
log.debug(u"Render single line '%s' @ %s "%( line, tlcorner))
|
||||
#log.debug(u'Render single line %s @ %s '%( line, tlcorner))
|
||||
x,y=tlcorner
|
||||
# We draw the text to see how big it is and then iterate to make it fit
|
||||
# when we line wrap we do in in the "lyrics" style, so the second line is
|
||||
@ -291,8 +301,8 @@ class Renderer:
|
||||
|
||||
# get the words
|
||||
# log.debug(u" "Getting the words split right"
|
||||
words=line.split(" ")
|
||||
thisline=' '.join(words)
|
||||
words=line.split(u' ')
|
||||
thisline=u' '.join(words)
|
||||
lastword=len(words)
|
||||
lines=[]
|
||||
maxx=self._rect.width(); maxy=self._rect.height();
|
||||
@ -307,25 +317,22 @@ class Renderer:
|
||||
else:
|
||||
lastword-=1
|
||||
thisline=' '.join(words[:lastword])
|
||||
|
||||
# log.debug(u" "This is how they split", lines
|
||||
# log.debug(u" "Now render them"
|
||||
startx=x
|
||||
starty=y
|
||||
rightextent=None
|
||||
t=self._theme
|
||||
align=t.HorizontalAlign
|
||||
wrapstyle=t.WrapStyle
|
||||
align=t.display_horizontalAlign
|
||||
wrapstyle=t.display_wrapStyle
|
||||
|
||||
for linenum in range(len(lines)):
|
||||
line=lines[linenum]
|
||||
#find out how wide line is
|
||||
w,h=self._get_extent_and_render(line, tlcorner=(x,y), dodraw=False)
|
||||
w,h=self._get_extent_and_render(line, tlcorner=(x,y), draw=False)
|
||||
|
||||
if t.Shadow:
|
||||
if t.display_shadow:
|
||||
w+=self._shadow_offset
|
||||
h+=self._shadow_offset
|
||||
if t.Outline:
|
||||
if t.display_outline:
|
||||
w+=2*self._outline_offset # pixels either side
|
||||
h+=2*self._outline_offset # pixels top/bottom
|
||||
if align==0: # left align
|
||||
@ -343,21 +350,22 @@ class Renderer:
|
||||
x=(maxx-w)/2;
|
||||
rightextent=x+w
|
||||
# now draw the text, and any outlines/shadows
|
||||
if t.Shadow:
|
||||
self._get_extent_and_render(line, tlcorner=(x+self._shadow_offset,y+self._shadow_offset), dodraw=True, color = t.ShadowColor)
|
||||
if t.Outline:
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x,y+self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x,y-self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y), dodraw=True, color = t.OutlineColor)
|
||||
if t.display_shadow:
|
||||
self._get_extent_and_render(line, tlcorner=(x+self._shadow_offset,y+self._shadow_offset),
|
||||
draw=True, color = t.display_shadow_color)
|
||||
if t.display_outline:
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x,y+self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x,y-self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y), draw=True, color = t.display_outline_color)
|
||||
if self._outline_offset > 1:
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y+self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y+self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y-self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y-self._outline_offset), dodraw=True, color = t.OutlineColor)
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x+self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, (x-self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
|
||||
|
||||
self._get_extent_and_render(line, tlcorner=(x,y), dodraw=True)
|
||||
# log.debug(u" "Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)"%( linenum, line, x, y,w,h)
|
||||
self._get_extent_and_render(line, tlcorner=(x,y), draw=True)
|
||||
# log.debug(u'Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)' % ( linenum, line, x, y,w,h)
|
||||
y += h
|
||||
if linenum == 0:
|
||||
self._first_line_right_extent=rightextent
|
||||
@ -373,47 +381,48 @@ class Renderer:
|
||||
return brcorner
|
||||
|
||||
# xxx this is what to override for an SDL version
|
||||
def _get_extent_and_render(self, line, tlcorner=(0,0), dodraw=False, color=None, footer = False):
|
||||
def _get_extent_and_render(self, line, tlcorner=(0,0), draw=False, color=None, footer=False):
|
||||
"""Find bounding box of text - as render_single_line.
|
||||
If dodraw is set, actually draw the text to the current DC as well
|
||||
If draw is set, actually draw the text to the current DC as well
|
||||
|
||||
return width and height of text as a tuple (w,h)"""
|
||||
# setup defaults
|
||||
log.debug(u"_get_extent_and_render %s %s %s ", [line], tlcorner, dodraw)
|
||||
#log.debug(u"_get_extent_and_render %s %s %s ", [line], tlcorner, draw)
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
# 'twould be more efficient to set this once when theme changes
|
||||
# or p changes
|
||||
if footer :
|
||||
font=QtGui.QFont(self._theme.FontName,
|
||||
12, # size
|
||||
font=QtGui.QFont(self._theme.font_footer_name,
|
||||
int(self._theme.font_footer_proportion), # size
|
||||
QtGui.QFont.Normal, # weight
|
||||
0)# italic
|
||||
else:
|
||||
font=QtGui.QFont(self._theme.FontName,
|
||||
self._theme.FontProportion, # size
|
||||
font=QtGui.QFont(self._theme.font_main_name,
|
||||
int(self._theme.font_main_proportion), # size
|
||||
QtGui.QFont.Normal, # weight
|
||||
0)# italic
|
||||
# to make the unit tests monitor independent, we have to be able to
|
||||
# specify whether a font proportion is in pixels or points
|
||||
if self._theme.FontUnits.lower() == "pixels":
|
||||
log.debug(u"pixels")
|
||||
if footer:
|
||||
font.setPixelSize(12)
|
||||
else:
|
||||
font.setPixelSize(self._theme.FontProportion)
|
||||
log.debug(u'Font details %s %s %s %s', self._theme.FontName, self._theme.FontProportion, font.family(), font.pointSize())
|
||||
if footer:
|
||||
font.setPixelSize(int(self._theme.font_footer_proportion))
|
||||
else:
|
||||
font.setPixelSize(int(self._theme.font_main_proportion))
|
||||
#log.debug(u'Font details %s %s %s %d', self._theme.font_main_name, self._theme.font_main_proportion, font.family(), font.pointSize())
|
||||
p.setFont(font)
|
||||
if color == None:
|
||||
p.setPen(self._theme.FontColor)
|
||||
if footer:
|
||||
p.setPen(QtGui.QColor(self._theme.font_footer_color))
|
||||
else:
|
||||
p.setPen(QtGui.QColor(self._theme.font_main_color))
|
||||
else:
|
||||
p.setPen(color)
|
||||
p.setPen(QtGui.QColor(color))
|
||||
x,y=tlcorner
|
||||
metrics=QtGui.QFontMetrics(font)
|
||||
# xxx some fudges to make it exactly like wx! Take 'em out later
|
||||
w=metrics.width(line)
|
||||
h=metrics.height()-2
|
||||
if dodraw:
|
||||
if draw:
|
||||
p.drawText(x,y+metrics.height()-metrics.descent()-1, line)
|
||||
p.end()
|
||||
return (w, h)
|
||||
|
@ -35,7 +35,7 @@ blankstylexml=\
|
||||
'''
|
||||
|
||||
class Theme:
|
||||
def __init__(self, xmlfile=None):
|
||||
def __init__(self, xml):
|
||||
""" stores the info about a theme
|
||||
attributes:
|
||||
name : theme name
|
||||
@ -77,11 +77,7 @@ class Theme:
|
||||
"""
|
||||
# init to defaults
|
||||
self._set_from_XML(blankstylexml)
|
||||
if xmlfile != None:
|
||||
# init from xmlfile
|
||||
file=open(xmlfile)
|
||||
t=''.join(file.readlines()) # read the file and change list to a string
|
||||
self._set_from_XML(t)
|
||||
self._set_from_XML(xml)
|
||||
|
||||
def _get_as_string(self):
|
||||
s=""
|
||||
|
@ -18,6 +18,7 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
"""
|
||||
|
||||
from amendthemeform import AmendThemeForm
|
||||
from slidecontroller import SlideController
|
||||
from splashscreen import SplashScreen
|
||||
from alertstab import AlertsTab
|
||||
@ -31,4 +32,4 @@ from thememanager import ThemeManager
|
||||
from mainwindow import MainWindow
|
||||
|
||||
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm',
|
||||
'MainWindow', 'SlideController', 'ServiceManager', 'ThemeManager']
|
||||
'MainWindow', 'SlideController', 'ServiceManager', 'ThemeManager', 'AmendThemeForm']
|
||||
|
@ -39,16 +39,16 @@ class MainWindow(object):
|
||||
|
||||
def __init__(self):
|
||||
self.main_window = QtGui.QMainWindow()
|
||||
self.EventManager = EventManager()
|
||||
self.EventManager = EventManager()
|
||||
self.alert_form = AlertForm()
|
||||
self.about_form = AboutForm()
|
||||
self.settings_form = SettingsForm()
|
||||
|
||||
|
||||
pluginpath = os.path.split(os.path.abspath(__file__))[0]
|
||||
pluginpath = os.path.abspath(os.path.join(pluginpath, '..', '..','plugins'))
|
||||
self.plugin_manager = PluginManager(pluginpath)
|
||||
self.plugin_helpers = {}
|
||||
|
||||
|
||||
self.setupUi()
|
||||
|
||||
log.info(u'Load Plugins')
|
||||
@ -56,7 +56,7 @@ class MainWindow(object):
|
||||
self.plugin_helpers[u'live'] = self.LiveController
|
||||
self.plugin_helpers[u'event'] = self.EventManager
|
||||
self.plugin_helpers[u'theme'] = self.ThemeManagerContents # Theme manger
|
||||
|
||||
|
||||
self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers, self.EventManager)
|
||||
# hook methods have to happen after find_plugins. Find plugins needs the controllers
|
||||
# hence the hooks have moved from setupUI() to here
|
||||
@ -77,9 +77,14 @@ class MainWindow(object):
|
||||
self.plugin_manager.hook_export_menu(self.FileExportMenu)
|
||||
|
||||
# Call the initialise method to setup plugins.
|
||||
log.info(u'initialise plugins')
|
||||
log.info(u'initialise plugins')
|
||||
self.plugin_manager.initialise_plugins()
|
||||
|
||||
|
||||
# Once all components are initialised load the Themes
|
||||
log.info(u'Load Themes')
|
||||
self.ThemeManagerContents.setEventManager(self.EventManager)
|
||||
self.ThemeManagerContents.loadThemes()
|
||||
|
||||
def setupUi(self):
|
||||
self.main_window.setObjectName("main_window")
|
||||
self.main_window.resize(1087, 847)
|
||||
@ -176,7 +181,7 @@ class MainWindow(object):
|
||||
self.ServiceManagerContents = ServiceManager(self)
|
||||
self.ServiceManagerDock.setWidget(self.ServiceManagerContents)
|
||||
self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.ServiceManagerDock)
|
||||
#Theme Manager Defined
|
||||
#Theme Manager Defined
|
||||
self.ThemeManagerDock = QtGui.QDockWidget(self.main_window)
|
||||
ThemeManagerIcon = QtGui.QIcon()
|
||||
ThemeManagerIcon.addPixmap(QtGui.QPixmap(":/system/system_thememanager.png"),
|
||||
@ -184,46 +189,12 @@ class MainWindow(object):
|
||||
self.ThemeManagerDock.setWindowIcon(ThemeManagerIcon)
|
||||
self.ThemeManagerDock.setFloating(False)
|
||||
self.ThemeManagerDock.setObjectName("ThemeManagerDock")
|
||||
|
||||
self.ThemeManagerContents = ThemeManager(self)
|
||||
|
||||
# self.ThemeManagerContents = QtGui.QWidget()
|
||||
# self.ThemeManagerContents.setObjectName("ThemeManagerContents")
|
||||
# self.ThemeManagerLayout = QtGui.QVBoxLayout(self.ThemeManagerContents)
|
||||
# self.ThemeManagerLayout.setSpacing(0)
|
||||
# self.ThemeManagerLayout.setMargin(0)
|
||||
# self.ThemeManagerLayout.setObjectName("ThemeManagerLayout")
|
||||
# self.ThemeManagerToolbar = QtGui.QToolBar(self.ThemeManagerContents)
|
||||
# self.ThemeManagerToolbar.setObjectName("ThemeManagerToolbar")
|
||||
# NewThemeIcon = QtGui.QIcon()
|
||||
# NewThemeIcon.addPixmap(QtGui.QPixmap(":/themes/theme_new.png"),
|
||||
# QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
# self.ThemeNewItem = self.ThemeManagerToolbar.addAction(NewThemeIcon, 'New theme')
|
||||
# EditThemeIcon = QtGui.QIcon()
|
||||
# EditThemeIcon.addPixmap(QtGui.QPixmap(":/themes/theme_edit.png"),
|
||||
# QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
# self.ThemeEditItem = self.ThemeManagerToolbar.addAction(EditThemeIcon, 'Edit theme')
|
||||
# DeleteThemeIcon = QtGui.QIcon()
|
||||
# DeleteThemeIcon.addPixmap(QtGui.QPixmap(":/themes/theme_delete.png"),
|
||||
# QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
# self.ThemeDeleteButton = self.ThemeManagerToolbar.addAction(DeleteThemeIcon, 'Delete theme')
|
||||
# self.ThemeManagerToolbar.addSeparator()
|
||||
# ImportThemeIcon = QtGui.QIcon()
|
||||
# ImportThemeIcon.addPixmap(QtGui.QPixmap(":/themes/theme_import.png"),
|
||||
# QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
# self.ThemeImportButton = self.ThemeManagerToolbar.addAction(ImportThemeIcon, 'Import theme')
|
||||
# ExportThemeIcon = QtGui.QIcon()
|
||||
# ExportThemeIcon.addPixmap(QtGui.QPixmap(":/themes/theme_export.png"),
|
||||
# QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
# self.ThemeExportButton = self.ThemeManagerToolbar.addAction(ExportThemeIcon, 'Export theme')
|
||||
# self.ThemeManagerLayout.addWidget(self.ThemeManagerToolbar)
|
||||
# self.ThemeManagerListView = QtGui.QListView(self.ThemeManagerContents)
|
||||
# self.ThemeManagerListView.setObjectName("ThemeManagerListView")
|
||||
# self.ThemeManagerLayout.addWidget(self.ThemeManagerListView)
|
||||
|
||||
self.ThemeManagerContents = ThemeManager(self)
|
||||
|
||||
self.ThemeManagerDock.setWidget(self.ThemeManagerContents)
|
||||
self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.ThemeManagerDock)
|
||||
|
||||
|
||||
self.FileNewItem = QtGui.QAction(self.main_window)
|
||||
self.FileNewItem.setIcon(self.ServiceManagerContents.Toolbar.getIconFromTitle("New Service"))
|
||||
self.FileNewItem.setObjectName("FileNewItem")
|
||||
|
@ -28,14 +28,20 @@ from PyQt4 import *
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
# from openlp.core.resources import *
|
||||
# from openlp.core.ui import AboutForm, AlertForm, SettingsForm, SlideController
|
||||
from openlp.core import translate
|
||||
from openlp.core.lib import OpenLPToolbar
|
||||
from openlp.core.utils import ConfigHelper
|
||||
#from openlp.core.lib import ThemeItem
|
||||
|
||||
# from openlp.core import PluginManager
|
||||
from openlp.core.ui import AmendThemeForm
|
||||
from openlp.core import translate
|
||||
from openlp.core import Renderer
|
||||
from openlp.core.theme import Theme
|
||||
from openlp.core.lib import Event
|
||||
from openlp.core.lib import EventType
|
||||
from openlp.core.lib import EventManager
|
||||
from openlp.core.lib import OpenLPToolbar
|
||||
from openlp.core.lib import ThemeXMLBuilder
|
||||
from openlp.core.lib import ThemeXMLParser
|
||||
from openlp.core.utils import ConfigHelper
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
class ThemeData(QAbstractItemModel):
|
||||
@ -51,7 +57,7 @@ class ThemeData(QAbstractItemModel):
|
||||
self.items=[]
|
||||
self.rowheight=50
|
||||
self.maximagewidth=self.rowheight*16/9.0;
|
||||
log.info("Starting")
|
||||
log.info(u'Starting')
|
||||
|
||||
def clearItems(self):
|
||||
self.items=[]
|
||||
@ -64,9 +70,10 @@ class ThemeData(QAbstractItemModel):
|
||||
|
||||
def insertRow(self, row, filename):
|
||||
self.beginInsertRows(QModelIndex(),row,row)
|
||||
log.info("insert row %d:%s"%(row,filename))
|
||||
log.info(u'insert row %d:%s'%(row,filename))
|
||||
(prefix, shortfilename) = os.path.split(str(filename))
|
||||
log.info("shortfilename=%s"%(shortfilename))
|
||||
log.info(u'shortfilename=%s'%(shortfilename))
|
||||
theme = shortfilename.split(u'.')
|
||||
# create a preview image
|
||||
if os.path.exists(filename):
|
||||
preview = QPixmap(str(filename))
|
||||
@ -83,8 +90,8 @@ class ThemeData(QAbstractItemModel):
|
||||
p=QPixmap(w,h)
|
||||
p.fill(Qt.transparent)
|
||||
# finally create the row
|
||||
self.items.insert(row,(filename, p, shortfilename))
|
||||
log.info("Items: %s" % self.items)
|
||||
self.items.insert(row,(filename, p, shortfilename, theme[0]))
|
||||
log.info(u'Items: %s' % self.items)
|
||||
self.endInsertRows()
|
||||
|
||||
def removeRow(self, row):
|
||||
@ -106,7 +113,7 @@ class ThemeData(QAbstractItemModel):
|
||||
if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row!
|
||||
return QVariant()
|
||||
if role==Qt.DisplayRole:
|
||||
retval= self.items[row][2]
|
||||
retval= self.items[row][3]
|
||||
elif role == Qt.DecorationRole:
|
||||
retval= self.items[row][1]
|
||||
else:
|
||||
@ -122,7 +129,7 @@ class ThemeData(QAbstractItemModel):
|
||||
yield i
|
||||
|
||||
def item(self, row):
|
||||
log.info("Get Item:%d -> %s" %(row, str(self.items)))
|
||||
log.info(u'Get Item:%d -> %s' %(row, str(self.items)))
|
||||
return self.items[row]
|
||||
|
||||
class ThemeManager(QWidget):
|
||||
@ -138,14 +145,19 @@ class ThemeManager(QWidget):
|
||||
self.Layout = QtGui.QVBoxLayout(self)
|
||||
self.Layout.setSpacing(0)
|
||||
self.Layout.setMargin(0)
|
||||
self.amendThemeForm = AmendThemeForm()
|
||||
self.Toolbar = OpenLPToolbar(self)
|
||||
self.Toolbar.addToolbarButton("New Theme", ":/themes/theme_new.png")
|
||||
self.Toolbar.addToolbarButton("Edit Theme", ":/themes/theme_edit.png")
|
||||
self.Toolbar.addToolbarButton("Delete Theme", ":/themes/theme_delete.png")
|
||||
self.Toolbar.addToolbarButton(translate('ThemeManager',u'New Theme'), ":/themes/theme_new.png",
|
||||
translate('ThemeManager',u'Allows a Theme to be created'), self.onAddTheme)
|
||||
self.Toolbar.addToolbarButton(translate('ThemeManager',u'Edit Theme'), ":/themes/theme_edit.png",
|
||||
translate('ThemeManager',u'Allows a Theme to be amended'), self.onEditTheme)
|
||||
self.Toolbar.addToolbarButton(translate('ThemeManager',u'Delete Theme'), ":/themes/theme_delete.png",
|
||||
translate('ThemeManager',u'Allows a Theme to be deleted'), self.onDeleteTheme)
|
||||
self.Toolbar.addSeparator()
|
||||
self.Toolbar.addToolbarButton("Import Theme", ":/themes/theme_import.png",
|
||||
u'Allows Themes to be imported', self.onImportTheme)
|
||||
self.Toolbar.addToolbarButton("Export Theme", ":/themes/theme_export.png")
|
||||
self.Toolbar.addToolbarButton(translate('ThemeManager',u'Import Theme'), ":/themes/theme_import.png",
|
||||
translate('ThemeManager',u'Allows Themes to be imported'), self.onImportTheme)
|
||||
self.Toolbar.addToolbarButton(translate('ThemeManager',u'Export Theme'), ":/themes/theme_export.png",
|
||||
translate('ThemeManager',u'Allows Themes to be exported'), self.onExportTheme)
|
||||
self.ThemeWidget = QtGui.QWidgetAction(self.Toolbar)
|
||||
self.Toolbar.addAction(self.ThemeWidget)
|
||||
|
||||
@ -161,62 +173,29 @@ class ThemeManager(QWidget):
|
||||
self.themelist= []
|
||||
self.path = os.path.join(ConfigHelper.get_data_path(), u'themes')
|
||||
self.checkThemesExists(self.path)
|
||||
self.loadThemes() # load the themes
|
||||
|
||||
# def addThemeItem(self, item):
|
||||
# """Adds Theme item"""
|
||||
# log.info("addThemeItem")
|
||||
# indexes=self.TreeView.selectedIndexes()
|
||||
# assert len(indexes) <= 1 # can only have one selected index in this view
|
||||
# if indexes == []:
|
||||
# log.info("No row")
|
||||
# row = None
|
||||
# selected_item = None
|
||||
# else:
|
||||
# row=indexes[0].row()
|
||||
# # if currently selected is of correct type, add it to it
|
||||
# log.info("row:%d"%row)
|
||||
# selected_item=self.Theme_data.item(row)
|
||||
# if type(selected_item) == type(item):
|
||||
# log.info("Add to existing item")
|
||||
# selected_item.add(item)
|
||||
# else:
|
||||
# log.info("Create new item")
|
||||
# if row is None:
|
||||
# self.Theme_data.addRow(item)
|
||||
# else:
|
||||
# self.Theme_data.insertRow(row+1, item)
|
||||
#
|
||||
# def removeThemeItem(self):
|
||||
# """Remove currently selected item"""
|
||||
# pass
|
||||
#
|
||||
# def oos_as_text(self):
|
||||
# text=[]
|
||||
# log.info( "oos as text")
|
||||
# log.info("Data:"+str(self.Theme_data))
|
||||
# for i in self.Theme_data:
|
||||
# text.append("# " + str(i))
|
||||
# text.append(i.get_oos_text())
|
||||
# return '\n'.join(text)
|
||||
#
|
||||
# def write_oos(self, filename):
|
||||
# """
|
||||
# Write a full OOS file out - iterate over plugins and call their respective methods
|
||||
# This format is totally arbitrary testing purposes - something sensible needs to go in here!
|
||||
# """
|
||||
# oosfile=open(filename, "w")
|
||||
# oosfile.write("# BEGIN OOS\n")
|
||||
# oosfile.write(self.oos_as_text)
|
||||
# oosfile.write("# END OOS\n")
|
||||
# oosfile.close()
|
||||
def setEventManager(self, eventManager):
|
||||
self.eventManager = eventManager
|
||||
|
||||
def onAddTheme(self):
|
||||
self.amendThemeForm.exec_()
|
||||
|
||||
def onEditTheme(self):
|
||||
self.amendThemeForm.loadTheme(theme)
|
||||
self.amendThemeForm.exec_()
|
||||
|
||||
def onDeleteTheme(self):
|
||||
pass
|
||||
|
||||
def onExportTheme(self):
|
||||
pass
|
||||
|
||||
def onImportTheme(self):
|
||||
files = QtGui.QFileDialog.getOpenFileNames(None,
|
||||
translate('ThemeManager', u'Select Import File'),
|
||||
self.path,
|
||||
u'Theme (*.theme)')
|
||||
log.info(u'New Themes) %s', str(files))
|
||||
log.info(u'New Themes %s', str(files))
|
||||
if len(files) > 0:
|
||||
for file in files:
|
||||
self.unzipTheme(file, self.path)
|
||||
@ -228,9 +207,11 @@ class ThemeManager(QWidget):
|
||||
# self.themelist = [u'African Sunset', u'Snowy Mountains', u'Wilderness', u'Wet and Windy London']
|
||||
for root, dirs, files in os.walk(self.path):
|
||||
for name in files:
|
||||
if name.endswith(u'.bmp'):
|
||||
if name.endswith(u'.png'):
|
||||
self.Theme_data.addRow(os.path.join(self.path, name))
|
||||
|
||||
self.eventManager.post_event(Event(EventType.ThemeListChanged))
|
||||
|
||||
def getThemes(self):
|
||||
return self.themelist
|
||||
|
||||
@ -249,16 +230,99 @@ class ThemeManager(QWidget):
|
||||
os.mkdir(os.path.join(dir, file))
|
||||
else:
|
||||
fullpath = os.path.join(dir, file)
|
||||
names = file.split(u'/')
|
||||
xml_data = zip.read(file)
|
||||
if file.endswith(u'.xml'):
|
||||
self.checkVersion1(fullpath)
|
||||
outfile = open(fullpath, 'w')
|
||||
outfile.write(zip.read(file))
|
||||
outfile.close()
|
||||
if self.checkVersion1(xml_data):
|
||||
filexml = self.migrateVersion122(filename, fullpath, xml_data)
|
||||
outfile = open(fullpath, 'w')
|
||||
outfile.write(filexml)
|
||||
outfile.close()
|
||||
self.generateImage(dir,names[0], filexml)
|
||||
else:
|
||||
if file.endswith(u'.bmp'):
|
||||
if fullpath is not os.path.join(dir, file):
|
||||
outfile = open(fullpath, 'w')
|
||||
outfile.write(zip.read(file))
|
||||
outfile.close()
|
||||
|
||||
def checkVersion1(self, xmlfile):
|
||||
file=open(xmlfile)
|
||||
t=''.join(file.readlines()) # read the file and change list to a string
|
||||
log.debug(u'checkVersion1 ')
|
||||
t = xmlfile
|
||||
tree = ElementTree(element=XML(t)).getroot()
|
||||
print "AA"
|
||||
print tree.find('BackgroundType')
|
||||
print "AAA"
|
||||
if tree.find(u'BackgroundType') is None :
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def migrateVersion122(self, filename , fullpath, xml_data):
|
||||
log.debug(u'migrateVersion122 %s %s', filename , fullpath)
|
||||
t=Theme(xml_data)
|
||||
|
||||
newtheme = ThemeXMLBuilder()
|
||||
newtheme.new_document(t.Name)
|
||||
if t.BackgroundType == 0:
|
||||
newtheme.add_background_solid(str(t.BackgroundParameter1.name()))
|
||||
elif t.BackgroundType == 1:
|
||||
direction = "vertical"
|
||||
if t.BackgroundParameter1.name() == 1:
|
||||
direction = "horizontal"
|
||||
newtheme.add_background_gradient(str(t.BackgroundParameter1.name()), str(t.BackgroundParameter2.name()), direction)
|
||||
else:
|
||||
newtheme.add_background_image(str(t.BackgroundParameter1))
|
||||
|
||||
newtheme.add_font(str(t.FontName), str(t.FontColor.name()), str(t.FontProportion * 2))
|
||||
newtheme.add_font(str(t.FontName), str(t.FontColor.name()), str(12), u'footer')
|
||||
outline = False
|
||||
shadow = False
|
||||
if t.Shadow == 1:
|
||||
shadow = True
|
||||
if t.Outline == 1:
|
||||
outline = True
|
||||
newtheme.add_display(str(shadow), str(t.ShadowColor.name()), str(outline), str(t.OutlineColor.name()),
|
||||
str(t.HorizontalAlign), str(t.VerticalAlign), str(t.WrapStyle))
|
||||
return newtheme.extract_xml()
|
||||
|
||||
def generateImage(self, dir, name, theme_xml):
|
||||
log.debug(u'generateImage %s %s ', dir, theme_xml)
|
||||
theme = ThemeXMLParser(theme_xml)
|
||||
#print theme
|
||||
size=QtCore.QSize(800,600)
|
||||
frame=TstFrame(size)
|
||||
frame=frame
|
||||
paintdest=frame.GetPixmap()
|
||||
r=Renderer()
|
||||
r.set_paint_dest(paintdest)
|
||||
|
||||
r.set_theme(theme) # set default theme
|
||||
r._render_background()
|
||||
r.set_text_rectangle(QtCore.QRect(0,0, size.width()-1, size.height()-1))
|
||||
|
||||
lines=[]
|
||||
lines.append(u'Amazing Grace!')
|
||||
lines.append(u'How sweet the sound')
|
||||
lines.append(u'To save a wretch like me;')
|
||||
lines.append(u'I once was lost but now am found,')
|
||||
lines.append(u'Was blind, but now I see.')
|
||||
|
||||
answer=r._render_lines(lines)
|
||||
r._get_extent_and_render(u'Amazing Grace (John Newton) ', (10, 560), True, None, True)
|
||||
r._get_extent_and_render(u'CCLI xxx (c)Openlp.org', (10, 580), True, None, True)
|
||||
|
||||
im=frame.GetPixmap().toImage()
|
||||
testpathname=os.path.join(dir, name+u'.png')
|
||||
if os.path.exists(testpathname):
|
||||
os.unlink(testpathname)
|
||||
im.save(testpathname, u'png')
|
||||
log.debug(u'Theme image written to %s',testpathname)
|
||||
|
||||
|
||||
class TstFrame:
|
||||
def __init__(self, size):
|
||||
"""Create the DemoPanel."""
|
||||
self.width=size.width();
|
||||
self.height=size.height();
|
||||
# create something to be painted into
|
||||
self._Buffer = QtGui.QPixmap(self.width, self.height)
|
||||
def GetPixmap(self):
|
||||
return self._Buffer
|
||||
|
@ -68,12 +68,14 @@ class BiblesTab(SettingsTab):
|
||||
self.NewChaptersCheckBox = QtGui.QCheckBox(self.VerseDisplayGroupBox)
|
||||
self.NewChaptersCheckBox.setObjectName("NewChaptersCheckBox")
|
||||
self.VerseDisplayLayout.addWidget(self.NewChaptersCheckBox, 1, 0, 1, 1)
|
||||
|
||||
self.DisplayStyleWidget = QtGui.QWidget(self.VerseDisplayGroupBox)
|
||||
self.DisplayStyleWidget.setObjectName(u'DisplayStyleWidget')
|
||||
self.DisplayStyleLayout = QtGui.QHBoxLayout(self.DisplayStyleWidget)
|
||||
self.DisplayStyleLayout.setSpacing(8)
|
||||
self.DisplayStyleLayout.setMargin(0)
|
||||
self.DisplayStyleLayout.setObjectName(u'DisplayStyleLayout')
|
||||
|
||||
self.DisplayStyleLabel = QtGui.QLabel(self.DisplayStyleWidget)
|
||||
self.DisplayStyleLabel.setObjectName(u'DisplayStyleLabel')
|
||||
self.DisplayStyleLayout.addWidget(self.DisplayStyleLabel)
|
||||
@ -85,9 +87,26 @@ class BiblesTab(SettingsTab):
|
||||
self.DisplayStyleComboBox.addItem(QtCore.QString())
|
||||
self.DisplayStyleLayout.addWidget(self.DisplayStyleComboBox)
|
||||
self.VerseDisplayLayout.addWidget(self.DisplayStyleWidget, 2, 0, 1, 1)
|
||||
|
||||
self.BibleThemeWidget = QtGui.QWidget(self.VerseDisplayGroupBox)
|
||||
self.BibleThemeWidget.setObjectName(u'BibleThemeWidget')
|
||||
self.BibleThemeLayout = QtGui.QHBoxLayout(self.BibleThemeWidget)
|
||||
self.BibleThemeLayout.setSpacing(8)
|
||||
self.BibleThemeLayout.setMargin(0)
|
||||
self.BibleThemeLayout.setObjectName(u'BibleThemeLayout')
|
||||
|
||||
self.BibleThemeLabel = QtGui.QLabel(self.BibleThemeWidget)
|
||||
self.BibleThemeLabel.setObjectName(u'BibleThemeLabel')
|
||||
self.BibleThemeLayout.addWidget(self.BibleThemeLabel)
|
||||
self.BibleThemeComboBox = QtGui.QComboBox(self.BibleThemeWidget)
|
||||
self.BibleThemeComboBox.setObjectName(u'BibleThemeComboBox')
|
||||
self.BibleThemeComboBox.addItem(QtCore.QString())
|
||||
self.BibleThemeLayout.addWidget(self.BibleThemeComboBox)
|
||||
self.VerseDisplayLayout.addWidget(self.BibleThemeWidget, 3, 0, 1, 1)
|
||||
|
||||
self.ChangeNoteLabel = QtGui.QLabel(self.VerseDisplayGroupBox)
|
||||
self.ChangeNoteLabel.setObjectName(u'ChangeNoteLabel')
|
||||
self.VerseDisplayLayout.addWidget(self.ChangeNoteLabel, 3, 0, 1, 1)
|
||||
self.VerseDisplayLayout.addWidget(self.ChangeNoteLabel, 4, 0, 1, 1)
|
||||
self.BibleLeftLayout.addWidget(self.VerseDisplayGroupBox)
|
||||
self.BibleLeftSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
@ -132,6 +151,7 @@ class BiblesTab(SettingsTab):
|
||||
self.ParagraphRadioButton.setText(translate('SettingsForm','Paragraph style'))
|
||||
self.NewChaptersCheckBox.setText(translate('SettingsForm', 'Only show new chapter numbers'))
|
||||
self.DisplayStyleLabel.setText(translate('SettingsForm', 'Display Style:'))
|
||||
self.BibleThemeLabel.setText(translate('SettingsForm', 'Bible Theme:'))
|
||||
self.DisplayStyleComboBox.setItemText(0, translate('SettingsForm', 'No brackets'))
|
||||
self.DisplayStyleComboBox.setItemText(1, translate('SettingsForm', '( and )'))
|
||||
self.DisplayStyleComboBox.setItemText(2, translate('SettingsForm', '{ and }'))
|
||||
@ -165,6 +185,7 @@ class BiblesTab(SettingsTab):
|
||||
self.paragraph_style = self.convertStringToBoolean(self.config.get_config('paragraph style', u'True'))
|
||||
self.show_new_chapters = self.convertStringToBoolean(self.config.get_config('display new chapter', u"False"))
|
||||
self.display_style = int(self.config.get_config('display brackets', '0'))
|
||||
self.bible_theme = int(self.config.get_config('bible theme', '0'))
|
||||
self.bible_search = self.convertStringToBoolean(self.config.get_config('search as type', u'True'))
|
||||
if self.paragraph_style:
|
||||
self.ParagraphRadioButton.setChecked(True)
|
||||
@ -173,9 +194,14 @@ class BiblesTab(SettingsTab):
|
||||
self.NewChaptersCheckBox.setChecked(self.show_new_chapters)
|
||||
self.DisplayStyleComboBox.setCurrentIndex(self.display_style)
|
||||
self.BibleSearchCheckBox.setChecked(self.bible_search)
|
||||
if self.bible_theme == 0: # must be new set to first
|
||||
self.BibleThemeComboBox.setCurrentIndex(self.bible_theme)
|
||||
else:
|
||||
pass # TODO need to code
|
||||
|
||||
def save(self):
|
||||
self.config.set_config("paragraph style", str(self.paragraph_style))
|
||||
self.config.set_config("display new chapter", str(self.show_new_chapters))
|
||||
self.config.set_config("display brackets", str(self.display_style))
|
||||
self.config.set_config("search as type", str(self.bible_search))
|
||||
self.config.set_config("bible theme", str(self.bible_theme))
|
||||
|
Loading…
Reference in New Issue
Block a user