← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/ThemeManager into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/ThemeManager into lp:openlp.

Requested reviews:
    openlp.org Core (openlp-core)
-- 
https://code.launchpad.net/~trb143/openlp/ThemeManager/+merge/5233
Your team openlp.org Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2009-02-28 23:19:45 +0000
+++ openlp/core/__init__.py	2009-04-03 19:32:00 +0000
@@ -23,7 +23,14 @@
 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
+

=== modified file 'openlp/core/lib/event.py' (properties changed: -x to +x)
--- openlp/core/lib/event.py	2009-03-23 20:18:06 +0000
+++ openlp/core/lib/event.py	2009-04-05 18:46:42 +0000
@@ -41,6 +41,8 @@
     PreviewBeforeShow  = 13
     PreviewAfterShow   = 14
 
+    ThemeListChanged = 15
+
 
 class Event(object):
     """
@@ -49,6 +51,6 @@
     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

=== modified file 'openlp/core/lib/eventmanager.py'
--- openlp/core/lib/eventmanager.py	2009-03-25 20:30:48 +0000
+++ openlp/core/lib/eventmanager.py	2009-03-30 19:58:34 +0000
@@ -26,21 +26,21 @@
     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)
 

=== modified file 'openlp/core/lib/songxmlhandler.py'
--- openlp/core/lib/songxmlhandler.py	2009-03-14 07:08:15 +0000
+++ openlp/core/lib/songxmlhandler.py	2009-03-31 20:16:54 +0000
@@ -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 @@
 </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 @@
         """
         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)

=== modified file 'openlp/core/lib/themexmlhandler.py'
--- openlp/core/lib/themexmlhandler.py	2009-03-28 20:12:22 +0000
+++ openlp/core/lib/themexmlhandler.py	2009-04-04 17:36:15 +0000
@@ -1,16 +1,29 @@
-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>
-
-"""
+# -*- 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
+
+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 @@
 
     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 @@
         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 @@
         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_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)
-
-        # add data as a CDATA section
-        cds = self.theme_xml.createCDATASection(content)
-        verse.appendChild(cds)
+    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)
+
+        name = self.theme_xml.createElement(u'color')
+        fn = self.theme_xml.createTextNode(fontcolor)
+        name.appendChild(fn)
+        background.appendChild(name)
+
+        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 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

=== modified file 'openlp/core/render.py'
--- openlp/core/render.py	2009-03-29 16:51:42 +0000
+++ openlp/core/render.py	2009-04-04 17:36:15 +0000
@@ -56,11 +56,11 @@
 
     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 @@
         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 @@
     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 @@
     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
-
-            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))
+        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))
+
             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 @@
 
     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 @@
         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 @@
             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 @@
 
         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 @@
 
         # 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 @@
             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 @@
                 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 @@
         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)

=== modified file 'openlp/core/theme/theme.py'
--- openlp/core/theme/theme.py	2009-03-29 14:38:23 +0000
+++ openlp/core/theme/theme.py	2009-04-03 19:32:00 +0000
@@ -35,7 +35,7 @@
 '''
 
 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 @@
         """
         # 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=""

=== modified file 'openlp/core/ui/__init__.py'
--- openlp/core/ui/__init__.py	2009-03-22 07:11:05 +0000
+++ openlp/core/ui/__init__.py	2009-04-04 17:36:15 +0000
@@ -18,6 +18,7 @@
 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 mainwindow import MainWindow
 
 __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm',
-           'MainWindow', 'SlideController', 'ServiceManager', 'ThemeManager']
+           'MainWindow', 'SlideController', 'ServiceManager', 'ThemeManager', 'AmendThemeForm']

=== added file 'openlp/core/ui/amendthemedialog.py'
--- openlp/core/ui/amendthemedialog.py	1970-01-01 00:00:00 +0000
+++ openlp/core/ui/amendthemedialog.py	2009-04-04 17:36:15 +0000
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'amendthemedialog.ui'
+#
+# Created: Sat Apr  4 18:09:38 2009
+#      by: PyQt4 UI code generator 4.4.4
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore, QtGui
+
+class Ui_AmendThemeDialog(object):
+    def setupUi(self, AmendThemeDialog):
+        AmendThemeDialog.setObjectName("AmendThemeDialog")
+        AmendThemeDialog.resize(752, 533)
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icon/openlp.org-icon-32.bmp"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        AmendThemeDialog.setWindowIcon(icon)
+        self.ThemeButtonBox = QtGui.QDialogButtonBox(AmendThemeDialog)
+        self.ThemeButtonBox.setGeometry(QtCore.QRect(580, 500, 156, 26))
+        self.ThemeButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
+        self.ThemeButtonBox.setObjectName("ThemeButtonBox")
+        self.layoutWidget = QtGui.QWidget(AmendThemeDialog)
+        self.layoutWidget.setGeometry(QtCore.QRect(30, 70, 691, 401))
+        self.layoutWidget.setObjectName("layoutWidget")
+        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.layoutWidget)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.LeftSide = QtGui.QWidget(self.layoutWidget)
+        self.LeftSide.setObjectName("LeftSide")
+        self.tabWidget = QtGui.QTabWidget(self.LeftSide)
+        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 341, 401))
+        self.tabWidget.setObjectName("tabWidget")
+        self.BackgroundTab = QtGui.QWidget()
+        self.BackgroundTab.setObjectName("BackgroundTab")
+        self.layoutWidget1 = QtGui.QWidget(self.BackgroundTab)
+        self.layoutWidget1.setGeometry(QtCore.QRect(10, 10, 321, 351))
+        self.layoutWidget1.setObjectName("layoutWidget1")
+        self.gridLayout = QtGui.QGridLayout(self.layoutWidget1)
+        self.gridLayout.setObjectName("gridLayout")
+        self.BackgroundLabel = QtGui.QLabel(self.layoutWidget1)
+        self.BackgroundLabel.setObjectName("BackgroundLabel")
+        self.gridLayout.addWidget(self.BackgroundLabel, 0, 0, 1, 2)
+        self.BackgroundComboBox = QtGui.QComboBox(self.layoutWidget1)
+        self.BackgroundComboBox.setObjectName("BackgroundComboBox")
+        self.BackgroundComboBox.addItem(QtCore.QString())
+        self.BackgroundComboBox.addItem(QtCore.QString())
+        self.gridLayout.addWidget(self.BackgroundComboBox, 0, 2, 1, 2)
+        self.BackgroundTypeLabel = QtGui.QLabel(self.layoutWidget1)
+        self.BackgroundTypeLabel.setObjectName("BackgroundTypeLabel")
+        self.gridLayout.addWidget(self.BackgroundTypeLabel, 1, 0, 1, 2)
+        self.BackgroundTypeComboBox = QtGui.QComboBox(self.layoutWidget1)
+        self.BackgroundTypeComboBox.setObjectName("BackgroundTypeComboBox")
+        self.BackgroundTypeComboBox.addItem(QtCore.QString())
+        self.BackgroundTypeComboBox.addItem(QtCore.QString())
+        self.BackgroundTypeComboBox.addItem(QtCore.QString())
+        self.gridLayout.addWidget(self.BackgroundTypeComboBox, 1, 2, 1, 2)
+        self.Color1Label = QtGui.QLabel(self.layoutWidget1)
+        self.Color1Label.setObjectName("Color1Label")
+        self.gridLayout.addWidget(self.Color1Label, 2, 0, 1, 1)
+        self.Color1PushButton = QtGui.QPushButton(self.layoutWidget1)
+        self.Color1PushButton.setObjectName("Color1PushButton")
+        self.gridLayout.addWidget(self.Color1PushButton, 2, 2, 1, 2)
+        self.Color2Label = QtGui.QLabel(self.layoutWidget1)
+        self.Color2Label.setObjectName("Color2Label")
+        self.gridLayout.addWidget(self.Color2Label, 3, 0, 1, 1)
+        self.Color2PushButton = QtGui.QPushButton(self.layoutWidget1)
+        self.Color2PushButton.setObjectName("Color2PushButton")
+        self.gridLayout.addWidget(self.Color2PushButton, 3, 2, 1, 2)
+        self.ImageLabel = QtGui.QLabel(self.layoutWidget1)
+        self.ImageLabel.setObjectName("ImageLabel")
+        self.gridLayout.addWidget(self.ImageLabel, 4, 0, 1, 1)
+        self.ImageLineEdit = QtGui.QLineEdit(self.layoutWidget1)
+        self.ImageLineEdit.setObjectName("ImageLineEdit")
+        self.gridLayout.addWidget(self.ImageLineEdit, 4, 1, 1, 2)
+        self.ImagePushButton = QtGui.QPushButton(self.layoutWidget1)
+        icon1 = QtGui.QIcon()
+        icon1.addPixmap(QtGui.QPixmap(":/services/service_open.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.ImagePushButton.setIcon(icon1)
+        self.ImagePushButton.setObjectName("ImagePushButton")
+        self.gridLayout.addWidget(self.ImagePushButton, 4, 3, 1, 1)
+        self.GradientLabel = QtGui.QLabel(self.layoutWidget1)
+        self.GradientLabel.setObjectName("GradientLabel")
+        self.gridLayout.addWidget(self.GradientLabel, 5, 0, 1, 1)
+        self.GradientComboBox = QtGui.QComboBox(self.layoutWidget1)
+        self.GradientComboBox.setObjectName("GradientComboBox")
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.gridLayout.addWidget(self.GradientComboBox, 5, 2, 1, 2)
+        self.tabWidget.addTab(self.BackgroundTab, "")
+        self.FontTab = QtGui.QWidget()
+        self.FontTab.setObjectName("FontTab")
+        self.MainFontGroupBox = QtGui.QGroupBox(self.FontTab)
+        self.MainFontGroupBox.setGeometry(QtCore.QRect(20, 20, 307, 119))
+        self.MainFontGroupBox.setObjectName("MainFontGroupBox")
+        self.gridLayout_2 = QtGui.QGridLayout(self.MainFontGroupBox)
+        self.gridLayout_2.setObjectName("gridLayout_2")
+        self.MainFontlabel = QtGui.QLabel(self.MainFontGroupBox)
+        self.MainFontlabel.setObjectName("MainFontlabel")
+        self.gridLayout_2.addWidget(self.MainFontlabel, 0, 0, 1, 1)
+        self.MainFontComboBox = QtGui.QFontComboBox(self.MainFontGroupBox)
+        self.MainFontComboBox.setObjectName("MainFontComboBox")
+        self.gridLayout_2.addWidget(self.MainFontComboBox, 0, 1, 1, 2)
+        self.MainFontColorLabel = QtGui.QLabel(self.MainFontGroupBox)
+        self.MainFontColorLabel.setObjectName("MainFontColorLabel")
+        self.gridLayout_2.addWidget(self.MainFontColorLabel, 1, 0, 1, 1)
+        self.MainFontColorPushButton = QtGui.QPushButton(self.MainFontGroupBox)
+        self.MainFontColorPushButton.setObjectName("MainFontColorPushButton")
+        self.gridLayout_2.addWidget(self.MainFontColorPushButton, 1, 2, 1, 1)
+        self.MainFontSize = QtGui.QLabel(self.MainFontGroupBox)
+        self.MainFontSize.setObjectName("MainFontSize")
+        self.gridLayout_2.addWidget(self.MainFontSize, 2, 0, 1, 1)
+        self.MainFontSizeLineEdit = QtGui.QLineEdit(self.MainFontGroupBox)
+        self.MainFontSizeLineEdit.setObjectName("MainFontSizeLineEdit")
+        self.gridLayout_2.addWidget(self.MainFontSizeLineEdit, 2, 1, 1, 1)
+        self.MainFontlSlider = QtGui.QSlider(self.MainFontGroupBox)
+        self.MainFontlSlider.setProperty("value", QtCore.QVariant(15))
+        self.MainFontlSlider.setMaximum(40)
+        self.MainFontlSlider.setOrientation(QtCore.Qt.Horizontal)
+        self.MainFontlSlider.setTickPosition(QtGui.QSlider.TicksBelow)
+        self.MainFontlSlider.setTickInterval(5)
+        self.MainFontlSlider.setObjectName("MainFontlSlider")
+        self.gridLayout_2.addWidget(self.MainFontlSlider, 2, 2, 1, 1)
+        self.FooterFontGroupBox = QtGui.QGroupBox(self.FontTab)
+        self.FooterFontGroupBox.setGeometry(QtCore.QRect(20, 170, 307, 119))
+        self.FooterFontGroupBox.setObjectName("FooterFontGroupBox")
+        self.gridLayout_3 = QtGui.QGridLayout(self.FooterFontGroupBox)
+        self.gridLayout_3.setObjectName("gridLayout_3")
+        self.FooterFontlabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FooterFontlabel.setObjectName("FooterFontlabel")
+        self.gridLayout_3.addWidget(self.FooterFontlabel, 0, 0, 1, 1)
+        self.FooterFontComboBox = QtGui.QFontComboBox(self.FooterFontGroupBox)
+        self.FooterFontComboBox.setObjectName("FooterFontComboBox")
+        self.gridLayout_3.addWidget(self.FooterFontComboBox, 0, 1, 1, 2)
+        self.FooterFontColorLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FooterFontColorLabel.setObjectName("FooterFontColorLabel")
+        self.gridLayout_3.addWidget(self.FooterFontColorLabel, 1, 0, 1, 1)
+        self.FooterColorPushButton = QtGui.QPushButton(self.FooterFontGroupBox)
+        self.FooterColorPushButton.setObjectName("FooterColorPushButton")
+        self.gridLayout_3.addWidget(self.FooterColorPushButton, 1, 2, 1, 1)
+        self.FooterFontSize = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FooterFontSize.setObjectName("FooterFontSize")
+        self.gridLayout_3.addWidget(self.FooterFontSize, 2, 0, 1, 1)
+        self.FooterFontSizeLineEdit = QtGui.QLineEdit(self.FooterFontGroupBox)
+        self.FooterFontSizeLineEdit.setObjectName("FooterFontSizeLineEdit")
+        self.gridLayout_3.addWidget(self.FooterFontSizeLineEdit, 2, 1, 1, 1)
+        self.FooterFontlSlider = QtGui.QSlider(self.FooterFontGroupBox)
+        self.FooterFontlSlider.setProperty("value", QtCore.QVariant(15))
+        self.FooterFontlSlider.setMaximum(40)
+        self.FooterFontlSlider.setOrientation(QtCore.Qt.Horizontal)
+        self.FooterFontlSlider.setTickPosition(QtGui.QSlider.TicksBelow)
+        self.FooterFontlSlider.setTickInterval(5)
+        self.FooterFontlSlider.setObjectName("FooterFontlSlider")
+        self.gridLayout_3.addWidget(self.FooterFontlSlider, 2, 2, 1, 1)
+        self.tabWidget.addTab(self.FontTab, "")
+        self.OptionsTab = QtGui.QWidget()
+        self.OptionsTab.setObjectName("OptionsTab")
+        self.ShadowGroupBox = QtGui.QGroupBox(self.OptionsTab)
+        self.ShadowGroupBox.setGeometry(QtCore.QRect(20, 10, 301, 80))
+        self.ShadowGroupBox.setObjectName("ShadowGroupBox")
+        self.layoutWidget2 = QtGui.QWidget(self.ShadowGroupBox)
+        self.layoutWidget2.setGeometry(QtCore.QRect(10, 20, 281, 54))
+        self.layoutWidget2.setObjectName("layoutWidget2")
+        self.formLayout = QtGui.QFormLayout(self.layoutWidget2)
+        self.formLayout.setObjectName("formLayout")
+        self.ShadowCheckBox = QtGui.QCheckBox(self.layoutWidget2)
+        self.ShadowCheckBox.setObjectName("ShadowCheckBox")
+        self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.ShadowCheckBox)
+        self.ShadowColorLabel = QtGui.QLabel(self.layoutWidget2)
+        self.ShadowColorLabel.setObjectName("ShadowColorLabel")
+        self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.ShadowColorLabel)
+        self.ShadowColorPushButton = QtGui.QPushButton(self.layoutWidget2)
+        self.ShadowColorPushButton.setObjectName("ShadowColorPushButton")
+        self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.ShadowColorPushButton)
+        self.AlignmentGroupBox = QtGui.QGroupBox(self.OptionsTab)
+        self.AlignmentGroupBox.setGeometry(QtCore.QRect(10, 200, 321, 161))
+        self.AlignmentGroupBox.setObjectName("AlignmentGroupBox")
+        self.gridLayout_4 = QtGui.QGridLayout(self.AlignmentGroupBox)
+        self.gridLayout_4.setObjectName("gridLayout_4")
+        self.HorizontalLabel = QtGui.QLabel(self.AlignmentGroupBox)
+        self.HorizontalLabel.setObjectName("HorizontalLabel")
+        self.gridLayout_4.addWidget(self.HorizontalLabel, 0, 0, 1, 1)
+        self.HorizontalComboBox = QtGui.QComboBox(self.AlignmentGroupBox)
+        self.HorizontalComboBox.setObjectName("HorizontalComboBox")
+        self.HorizontalComboBox.addItem(QtCore.QString())
+        self.HorizontalComboBox.addItem(QtCore.QString())
+        self.HorizontalComboBox.addItem(QtCore.QString())
+        self.gridLayout_4.addWidget(self.HorizontalComboBox, 0, 1, 1, 1)
+        self.VerticalLabel = QtGui.QLabel(self.AlignmentGroupBox)
+        self.VerticalLabel.setObjectName("VerticalLabel")
+        self.gridLayout_4.addWidget(self.VerticalLabel, 1, 0, 1, 1)
+        self.VerticalComboBox = QtGui.QComboBox(self.AlignmentGroupBox)
+        self.VerticalComboBox.setObjectName("VerticalComboBox")
+        self.VerticalComboBox.addItem(QtCore.QString())
+        self.VerticalComboBox.addItem(QtCore.QString())
+        self.VerticalComboBox.addItem(QtCore.QString())
+        self.gridLayout_4.addWidget(self.VerticalComboBox, 1, 1, 1, 1)
+        self.OutlineGroupBox = QtGui.QGroupBox(self.OptionsTab)
+        self.OutlineGroupBox.setGeometry(QtCore.QRect(20, 110, 301, 80))
+        self.OutlineGroupBox.setObjectName("OutlineGroupBox")
+        self.layoutWidget_3 = QtGui.QWidget(self.OutlineGroupBox)
+        self.layoutWidget_3.setGeometry(QtCore.QRect(10, 20, 281, 54))
+        self.layoutWidget_3.setObjectName("layoutWidget_3")
+        self.OutlineformLayout = QtGui.QFormLayout(self.layoutWidget_3)
+        self.OutlineformLayout.setObjectName("OutlineformLayout")
+        self.OutlineCheckBox = QtGui.QCheckBox(self.layoutWidget_3)
+        self.OutlineCheckBox.setObjectName("OutlineCheckBox")
+        self.OutlineformLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.OutlineCheckBox)
+        self.OutlineColorLabel = QtGui.QLabel(self.layoutWidget_3)
+        self.OutlineColorLabel.setObjectName("OutlineColorLabel")
+        self.OutlineformLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.OutlineColorLabel)
+        self.OutlineColorPushButton = QtGui.QPushButton(self.layoutWidget_3)
+        self.OutlineColorPushButton.setObjectName("OutlineColorPushButton")
+        self.OutlineformLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.OutlineColorPushButton)
+        self.tabWidget.addTab(self.OptionsTab, "")
+        self.horizontalLayout_2.addWidget(self.LeftSide)
+        self.RightSide = QtGui.QWidget(self.layoutWidget)
+        self.RightSide.setObjectName("RightSide")
+        self.ThemePreView = QtGui.QGraphicsView(self.RightSide)
+        self.ThemePreView.setGeometry(QtCore.QRect(0, 30, 341, 341))
+        self.ThemePreView.setObjectName("ThemePreView")
+        self.horizontalLayout_2.addWidget(self.RightSide)
+        self.layoutWidget3 = QtGui.QWidget(AmendThemeDialog)
+        self.layoutWidget3.setGeometry(QtCore.QRect(50, 20, 441, 41))
+        self.layoutWidget3.setObjectName("layoutWidget3")
+        self.horizontalLayout = QtGui.QHBoxLayout(self.layoutWidget3)
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.ThemeNameLabel = QtGui.QLabel(self.layoutWidget3)
+        self.ThemeNameLabel.setObjectName("ThemeNameLabel")
+        self.horizontalLayout.addWidget(self.ThemeNameLabel)
+        self.ThemeNameEdit = QtGui.QLineEdit(self.layoutWidget3)
+        self.ThemeNameEdit.setObjectName("ThemeNameEdit")
+        self.horizontalLayout.addWidget(self.ThemeNameEdit)
+
+        self.retranslateUi(AmendThemeDialog)
+        self.tabWidget.setCurrentIndex(1)
+        QtCore.QMetaObject.connectSlotsByName(AmendThemeDialog)
+
+    def retranslateUi(self, AmendThemeDialog):
+        AmendThemeDialog.setWindowTitle(QtGui.QApplication.translate("AmendThemeDialog", "Theme Maintance", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Background:", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundComboBox.setItemText(0, QtGui.QApplication.translate("AmendThemeDialog", "Opaque", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundComboBox.setItemText(1, QtGui.QApplication.translate("AmendThemeDialog", "Transparent", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundTypeLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Background Type:", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundTypeComboBox.setItemText(0, QtGui.QApplication.translate("AmendThemeDialog", "Solid Color", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundTypeComboBox.setItemText(1, QtGui.QApplication.translate("AmendThemeDialog", "Gradient", None, QtGui.QApplication.UnicodeUTF8))
+        self.BackgroundTypeComboBox.setItemText(2, QtGui.QApplication.translate("AmendThemeDialog", "Image", None, QtGui.QApplication.UnicodeUTF8))
+        self.Color1Label.setText(QtGui.QApplication.translate("AmendThemeDialog", "<Color1>", None, QtGui.QApplication.UnicodeUTF8))
+        self.Color2Label.setText(QtGui.QApplication.translate("AmendThemeDialog", "<Color2>", None, QtGui.QApplication.UnicodeUTF8))
+        self.ImageLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Image:", None, QtGui.QApplication.UnicodeUTF8))
+        self.GradientLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Gradient :", None, QtGui.QApplication.UnicodeUTF8))
+        self.GradientComboBox.setItemText(0, QtGui.QApplication.translate("AmendThemeDialog", "Horizontal", None, QtGui.QApplication.UnicodeUTF8))
+        self.GradientComboBox.setItemText(1, QtGui.QApplication.translate("AmendThemeDialog", "Vertical", None, QtGui.QApplication.UnicodeUTF8))
+        self.GradientComboBox.setItemText(2, QtGui.QApplication.translate("AmendThemeDialog", "Circular", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.BackgroundTab), QtGui.QApplication.translate("AmendThemeDialog", "Background", None, QtGui.QApplication.UnicodeUTF8))
+        self.MainFontGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Main Font", None, QtGui.QApplication.UnicodeUTF8))
+        self.MainFontlabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font:", None, QtGui.QApplication.UnicodeUTF8))
+        self.MainFontColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font Color", None, QtGui.QApplication.UnicodeUTF8))
+        self.MainFontSize.setText(QtGui.QApplication.translate("AmendThemeDialog", "Size:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FooterFontGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Footer Font", None, QtGui.QApplication.UnicodeUTF8))
+        self.FooterFontlabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FooterFontColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font Color", None, QtGui.QApplication.UnicodeUTF8))
+        self.FooterFontSize.setText(QtGui.QApplication.translate("AmendThemeDialog", "Size:", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.FontTab), QtGui.QApplication.translate("AmendThemeDialog", "Font", None, QtGui.QApplication.UnicodeUTF8))
+        self.ShadowGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Shadow", None, QtGui.QApplication.UnicodeUTF8))
+        self.ShadowCheckBox.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use Shadow", None, QtGui.QApplication.UnicodeUTF8))
+        self.ShadowColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Shadow Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.AlignmentGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Alignment", None, QtGui.QApplication.UnicodeUTF8))
+        self.HorizontalLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Horizontal Align:", None, QtGui.QApplication.UnicodeUTF8))
+        self.HorizontalComboBox.setItemText(0, QtGui.QApplication.translate("AmendThemeDialog", "Left", None, QtGui.QApplication.UnicodeUTF8))
+        self.HorizontalComboBox.setItemText(1, QtGui.QApplication.translate("AmendThemeDialog", "Right", None, QtGui.QApplication.UnicodeUTF8))
+        self.HorizontalComboBox.setItemText(2, QtGui.QApplication.translate("AmendThemeDialog", "Center", None, QtGui.QApplication.UnicodeUTF8))
+        self.VerticalLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Vertical Align:", None, QtGui.QApplication.UnicodeUTF8))
+        self.VerticalComboBox.setItemText(0, QtGui.QApplication.translate("AmendThemeDialog", "Top", None, QtGui.QApplication.UnicodeUTF8))
+        self.VerticalComboBox.setItemText(1, QtGui.QApplication.translate("AmendThemeDialog", "Middle", None, QtGui.QApplication.UnicodeUTF8))
+        self.VerticalComboBox.setItemText(2, QtGui.QApplication.translate("AmendThemeDialog", "Bottom", None, QtGui.QApplication.UnicodeUTF8))
+        self.OutlineGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Outline", None, QtGui.QApplication.UnicodeUTF8))
+        self.OutlineCheckBox.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use Outline", None, QtGui.QApplication.UnicodeUTF8))
+        self.OutlineColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Outline Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.OptionsTab), QtGui.QApplication.translate("AmendThemeDialog", "Display Options", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeNameLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Theme Name", None, QtGui.QApplication.UnicodeUTF8))
+

=== added file 'openlp/core/ui/amendthemeform.py'
--- openlp/core/ui/amendthemeform.py	1970-01-01 00:00:00 +0000
+++ openlp/core/ui/amendthemeform.py	2009-04-04 17:36:15 +0000
@@ -0,0 +1,37 @@
+# -*- 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 Martin Thompson, Tim Bentley,
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+import logging
+
+from PyQt4 import QtCore, QtGui
+
+#from openlp.core.resources import *
+
+from amendthemedialog import Ui_AmendThemeDialog
+
+log = logging.getLogger(u'AmendThemeForm')
+
+class AmendThemeForm(QtGui.QDialog,  Ui_AmendThemeDialog):
+
+    def __init__(self, parent=None):
+        QtGui.QDialog.__init__(self, parent)
+        self.setupUi(self)
+
+    def loadTheme(self, theme):
+        pass

=== modified file 'openlp/core/ui/mainwindow.py' (properties changed: -x to +x)
--- openlp/core/ui/mainwindow.py	2009-03-23 19:17:07 +0000
+++ openlp/core/ui/mainwindow.py	2009-04-05 18:33:56 +0000
@@ -39,16 +39,16 @@
 
     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 @@
         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 @@
         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 @@
         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 @@
         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")

=== modified file 'openlp/core/ui/thememanager.py' (properties changed: -x to +x)
--- openlp/core/ui/thememanager.py	2009-03-28 20:12:22 +0000
+++ openlp/core/ui/thememanager.py	2009-04-05 18:33:56 +0000
@@ -28,14 +28,20 @@
 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.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
-#from openlp.core.lib import ThemeItem
-
-# from openlp.core import PluginManager
+
+
 import logging
 
 class ThemeData(QAbstractItemModel):
@@ -51,7 +57,7 @@
         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 @@
 
     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 @@
             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 @@
         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 @@
             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 @@
         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 @@
         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 @@
 #        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 @@
                     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

=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
--- openlp/plugins/bibles/lib/biblestab.py	2009-03-09 12:49:55 +0000
+++ openlp/plugins/bibles/lib/biblestab.py	2009-04-04 10:24:39 +0000
@@ -68,12 +68,14 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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))

=== added file 'resources/forms/amendthemedialog.ui'
--- resources/forms/amendthemedialog.ui	1970-01-01 00:00:00 +0000
+++ resources/forms/amendthemedialog.ui	2009-04-04 17:36:15 +0000
@@ -0,0 +1,547 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AmendThemeDialog</class>
+ <widget class="QWidget" name="AmendThemeDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>752</width>
+    <height>533</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Theme Maintance</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../images/openlp-2.qrc">
+    <normaloff>:/icon/openlp.org-icon-32.bmp</normaloff>:/icon/openlp.org-icon-32.bmp</iconset>
+  </property>
+  <widget class="QDialogButtonBox" name="ThemeButtonBox">
+   <property name="geometry">
+    <rect>
+     <x>580</x>
+     <y>500</y>
+     <width>156</width>
+     <height>26</height>
+    </rect>
+   </property>
+   <property name="standardButtons">
+    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+   </property>
+  </widget>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>30</x>
+     <y>70</y>
+     <width>691</width>
+     <height>401</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="horizontalLayout_2">
+    <item>
+     <widget class="QWidget" name="LeftSide" native="true">
+      <widget class="QTabWidget" name="tabWidget">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>0</y>
+         <width>341</width>
+         <height>401</height>
+        </rect>
+       </property>
+       <property name="currentIndex">
+        <number>1</number>
+       </property>
+       <widget class="QWidget" name="BackgroundTab">
+        <attribute name="title">
+         <string>Background</string>
+        </attribute>
+        <widget class="QWidget" name="layoutWidget">
+         <property name="geometry">
+          <rect>
+           <x>10</x>
+           <y>10</y>
+           <width>321</width>
+           <height>351</height>
+          </rect>
+         </property>
+         <layout class="QGridLayout" name="gridLayout">
+          <item row="0" column="0" colspan="2">
+           <widget class="QLabel" name="BackgroundLabel">
+            <property name="text">
+             <string>Background:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="2" colspan="2">
+           <widget class="QComboBox" name="BackgroundComboBox">
+            <item>
+             <property name="text">
+              <string>Opaque</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Transparent</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="0" colspan="2">
+           <widget class="QLabel" name="BackgroundTypeLabel">
+            <property name="text">
+             <string>Background Type:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2" colspan="2">
+           <widget class="QComboBox" name="BackgroundTypeComboBox">
+            <item>
+             <property name="text">
+              <string>Solid Color</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Gradient</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Image</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="Color1Label">
+            <property name="text">
+             <string>&lt;Color1&gt;</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2" colspan="2">
+           <widget class="QPushButton" name="Color1PushButton">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QLabel" name="Color2Label">
+            <property name="text">
+             <string>&lt;Color2&gt;</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="2" colspan="2">
+           <widget class="QPushButton" name="Color2PushButton">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0">
+           <widget class="QLabel" name="ImageLabel">
+            <property name="text">
+             <string>Image:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="1" colspan="2">
+           <widget class="QLineEdit" name="ImageLineEdit"/>
+          </item>
+          <item row="4" column="3">
+           <widget class="QPushButton" name="ImagePushButton">
+            <property name="text">
+             <string/>
+            </property>
+            <property name="icon">
+             <iconset resource="../images/openlp-2.qrc">
+              <normaloff>:/services/service_open.png</normaloff>:/services/service_open.png</iconset>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0">
+           <widget class="QLabel" name="GradientLabel">
+            <property name="text">
+             <string>Gradient :</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="2" colspan="2">
+           <widget class="QComboBox" name="GradientComboBox">
+            <item>
+             <property name="text">
+              <string>Horizontal</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Vertical</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Circular</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+       <widget class="QWidget" name="FontTab">
+        <attribute name="title">
+         <string>Font</string>
+        </attribute>
+        <widget class="QGroupBox" name="MainFontGroupBox">
+         <property name="geometry">
+          <rect>
+           <x>20</x>
+           <y>20</y>
+           <width>307</width>
+           <height>119</height>
+          </rect>
+         </property>
+         <property name="title">
+          <string>Main Font</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="0" column="0">
+           <widget class="QLabel" name="MainFontlabel">
+            <property name="text">
+             <string>Font:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" colspan="2">
+           <widget class="QFontComboBox" name="MainFontComboBox"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="MainFontColorLabel">
+            <property name="text">
+             <string>Font Color</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QPushButton" name="MainFontColorPushButton">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="MainFontSize">
+            <property name="text">
+             <string>Size:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="MainFontSizeLineEdit"/>
+          </item>
+          <item row="2" column="2">
+           <widget class="QSlider" name="MainFontlSlider">
+            <property name="value">
+             <number>15</number>
+            </property>
+            <property name="maximum">
+             <number>40</number>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="tickPosition">
+             <enum>QSlider::TicksBelow</enum>
+            </property>
+            <property name="tickInterval">
+             <number>5</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QGroupBox" name="FooterFontGroupBox">
+         <property name="geometry">
+          <rect>
+           <x>20</x>
+           <y>170</y>
+           <width>307</width>
+           <height>119</height>
+          </rect>
+         </property>
+         <property name="title">
+          <string>Footer Font</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_3">
+          <item row="0" column="0">
+           <widget class="QLabel" name="FooterFontlabel">
+            <property name="text">
+             <string>Font:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" colspan="2">
+           <widget class="QFontComboBox" name="FooterFontComboBox"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="FooterFontColorLabel">
+            <property name="text">
+             <string>Font Color</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QPushButton" name="FooterColorPushButton">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="FooterFontSize">
+            <property name="text">
+             <string>Size:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="FooterFontSizeLineEdit"/>
+          </item>
+          <item row="2" column="2">
+           <widget class="QSlider" name="FooterFontlSlider">
+            <property name="value">
+             <number>15</number>
+            </property>
+            <property name="maximum">
+             <number>40</number>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="tickPosition">
+             <enum>QSlider::TicksBelow</enum>
+            </property>
+            <property name="tickInterval">
+             <number>5</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+       <widget class="QWidget" name="OptionsTab">
+        <attribute name="title">
+         <string>Display Options</string>
+        </attribute>
+        <widget class="QGroupBox" name="ShadowGroupBox">
+         <property name="geometry">
+          <rect>
+           <x>20</x>
+           <y>10</y>
+           <width>301</width>
+           <height>80</height>
+          </rect>
+         </property>
+         <property name="title">
+          <string>Shadow</string>
+         </property>
+         <widget class="QWidget" name="layoutWidget">
+          <property name="geometry">
+           <rect>
+            <x>10</x>
+            <y>20</y>
+            <width>281</width>
+            <height>54</height>
+           </rect>
+          </property>
+          <layout class="QFormLayout" name="formLayout">
+           <item row="0" column="0">
+            <widget class="QCheckBox" name="ShadowCheckBox">
+             <property name="text">
+              <string>Use Shadow</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="ShadowColorLabel">
+             <property name="text">
+              <string>Shadow Color:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QPushButton" name="ShadowColorPushButton">
+             <property name="text">
+              <string/>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+        <widget class="QGroupBox" name="AlignmentGroupBox">
+         <property name="geometry">
+          <rect>
+           <x>10</x>
+           <y>200</y>
+           <width>321</width>
+           <height>161</height>
+          </rect>
+         </property>
+         <property name="title">
+          <string>Alignment</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="0" column="0">
+           <widget class="QLabel" name="HorizontalLabel">
+            <property name="text">
+             <string>Horizontal Align:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="HorizontalComboBox">
+            <item>
+             <property name="text">
+              <string>Left</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Right</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Center</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="VerticalLabel">
+            <property name="text">
+             <string>Vertical Align:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QComboBox" name="VerticalComboBox">
+            <item>
+             <property name="text">
+              <string>Top</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Middle</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Bottom</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QGroupBox" name="OutlineGroupBox">
+         <property name="geometry">
+          <rect>
+           <x>20</x>
+           <y>110</y>
+           <width>301</width>
+           <height>80</height>
+          </rect>
+         </property>
+         <property name="title">
+          <string>Outline</string>
+         </property>
+         <widget class="QWidget" name="layoutWidget_3">
+          <property name="geometry">
+           <rect>
+            <x>10</x>
+            <y>20</y>
+            <width>281</width>
+            <height>54</height>
+           </rect>
+          </property>
+          <layout class="QFormLayout" name="OutlineformLayout">
+           <item row="0" column="0">
+            <widget class="QCheckBox" name="OutlineCheckBox">
+             <property name="text">
+              <string>Use Outline</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0">
+            <widget class="QLabel" name="OutlineColorLabel">
+             <property name="text">
+              <string>Outline Color:</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="1">
+            <widget class="QPushButton" name="OutlineColorPushButton">
+             <property name="text">
+              <string/>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </widget>
+      </widget>
+     </widget>
+    </item>
+    <item>
+     <widget class="QWidget" name="RightSide" native="true">
+      <widget class="QGraphicsView" name="ThemePreView">
+       <property name="geometry">
+        <rect>
+         <x>0</x>
+         <y>30</y>
+         <width>341</width>
+         <height>341</height>
+        </rect>
+       </property>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>50</x>
+     <y>20</y>
+     <width>441</width>
+     <height>41</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="horizontalLayout">
+    <item>
+     <widget class="QLabel" name="ThemeNameLabel">
+      <property name="text">
+       <string>Theme Name</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLineEdit" name="ThemeNameEdit"/>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources>
+  <include location="../images/openlp-2.qrc"/>
+ </resources>
+ <connections/>
+</ui>


Follow ups