forked from openlp/openlp
Combine patch from previous tree which I messed up. Here is a summary of the changes.
444. By Tim Bentley 23 hours ago Add new event for Theme Loading 443. By Tim Bentley 23 hours ago Add Eventing after Themes loaded to tell plugins the themes have changed 442. By Tim Bentley on 2009-04-04 Store Theme name in list for correct display 441. By Tim Bentley on 2009-04-04 Add ThemeManagerDialog More Rendering improvements 440. By Tim Bentley on 2009-04-04 Add Themes to Bible Tab and default values 439. By Tim Bentley on 2009-04-04 Add rendering for Circles and amend XML schema accordingly 438. By Tim Bentley on 2009-04-04 Renderer now supports linear gradients correctly Update XML to include direction Add Booleans instead of 0/1 to XML schema 437. By Tim Bentley on 2009-04-03 More ThemeManager changes Fix Rendering and theme handling Generate PNG theme on conversion 436. By Tim Bentley on 2009-04-01 Fix up Theme XML code to work with strings and files. Fix Render.py to work with new XML schema 435. By Tim Bentley on 2009-04-01 Import version 2 xml and build object.
This commit is contained in:
parent
9bdafd5659
commit
0e7dfb9fc4
|
@ -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