← 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)

443. By Tim Bentley 3 minutes ago
    Add Eventing after Themes loaded to tell plugins the themes have changed
442. By Tim Bentley 21 hours ago

    Store Theme name in list for correct display
441. By Tim Bentley on 2009-04-04

    Add ThemeManagerDialog
    More Rendering improvements
440. By Tim Bentley on 2009-04-04

    Add Themes to Bible Tab and default values
439. By Tim Bentley on 2009-04-04

    Add rendering for Circles and amend XML schema accordingly
438. By Tim Bentley on 2009-04-04

    Renderer now supports linear gradients correctly
    Update XML to include direction
    Add Booleans instead of 0/1 to XML schema
437. By Tim Bentley on 2009-04-03

    More ThemeManager changes
    Fix Rendering and theme handling
    Generate PNG theme on conversion
436. By Tim Bentley on 2009-04-01

    Fix up Theme XML code to work with strings and files.
    Fix Render.py to work with new XML schema
435. By Tim Bentley on 2009-04-01

    Import version 2 xml and build object.
434. By Tim Bentley on 2009-03-31

    Finish Import conversions take 1
    Add copyright information

433. By Tim Bentley on 2009-03-29
    Clean Up code style
    Add Theme migration code
    Fixes to Renderer
-- 
https://code.launchpad.net/~trb143/openlp/ThemeManager/+merge/5232
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/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