← Back to team overview

openlp-core team mailing list archive

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

 

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

Requested reviews:
    openlp.org Core (openlp-core)

Here is a big one.  

The code is not complete and needs a lot of polishing but we have some significant functions working.
To summerize the state of play:
Themes Import , Add , Edit (80%) and delete work.  (Don't delete last theme!)
Themes pushed to all components.

Service Controller has Theme drop down which pushes themes to the rendermanager.
RenderManager created to help plugins undertake rendering (30% complete)
Bibles and Custom plugins generate a rendered slide (Only one for now)
Rendered slide displayed On preview page and uses Theme set in slide controller.

Move 2 classes to correct place.




-- 
https://code.launchpad.net/~trb143/openlp/ThemeManager2/+merge/5894
Your team openlp.org Core is subscribed to branch lp:openlp.
=== modified file 'openlp.pyw'
--- openlp.pyw	2009-04-10 05:59:40 +0000
+++ openlp.pyw	2009-04-25 06:11:15 +0000
@@ -46,15 +46,15 @@
 
         self.setApplicationName(u'openlp.org')
         self.setApplicationVersion(u'1.9.0')
-        self.splash = SplashScreen()
+        self.splash = SplashScreen(self.applicationVersion())
         self.splash.show()
         # make sure Qt really display the splash screen
         self.processEvents()
         screens = []
         # Decide how many screens we have and their size
-        for i in range (0 ,  self.desktop().numScreens()):
-            screens.insert(i, (i+1, self.desktop().availableGeometry(i+1)))
-            log.info(u'Screen %d found with resolution %s', i+1, self.desktop().availableGeometry(i+1))
+        for screen in xrange (0 ,  self.desktop().numScreens()):
+            screens.insert(screen, (screen+1, self.desktop().availableGeometry(screen+1)))
+            log.info(u'Screen %d found with resolution %s', screen+1, self.desktop().availableGeometry(screen+1))
         # start the main app window
         self.main_window = MainWindow(screens)
         self.main_window.show()

=== modified file 'openlp/__init__.py'
--- openlp/__init__.py	2008-10-23 19:49:13 +0000
+++ openlp/__init__.py	2009-04-15 04:58:51 +0000
@@ -15,3 +15,10 @@
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place, Suite 330, Boston, MA 02111-1307 USA
 """
+__all__ = ['convertStringToBoolean']
+
+def convertStringToBoolean(stringvalue):
+    if stringvalue.lower() == 'true':
+        return True
+    else:
+        return False

=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2009-04-07 19:03:36 +0000
+++ openlp/core/__init__.py	2009-04-20 18:22:42 +0000
@@ -3,7 +3,7 @@
 """
 OpenLP - Open Source Lyrics Projection
 Copyright (c) 2008 Raoul Snyman
-Portions copyright (c) 2008 Martin Thompson, Tim Bentley
+Portions copyright (c) 2008-2009 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
@@ -19,15 +19,14 @@
 """
 from PyQt4 import QtCore, QtGui
 
-from render import Renderer
 from settingsmanager import SettingsManager
-from pluginmanager import PluginManager
+from openlp.core.lib.pluginmanager import PluginManager
 
-__all__ = ['Renderer', 'SettingsManager', 'PluginManager', 'translate', 'fileToXML']
+__all__ = ['SettingsManager', 'PluginManager', 'translate',
+            'fileToXML' ]
 
 def translate(context, text):
     return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8)
 
 def fileToXML(xmlfile):
     return open(xmlfile).read()
-

=== removed file 'openlp/core/interpolate.py'
--- openlp/core/interpolate.py	2008-12-01 13:15:31 +0000
+++ openlp/core/interpolate.py	1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
-# -*- 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
-"""
-
-# useful linear interpolation routines
-
-def interp1(val1, val2, fraction):
-    """return a linear 1d interpolation between val1 and val2 by fraction
-    if fraction=0.0, returns val1
-    if fraction=1.0, returns val2"""
-    return val1+((val2-val1)*fraction)
-def interpolate(val1, val2, fraction):
-    "vals can be list/tuples - if so, will return a tuple of interpolated values for each element."
-    assert (fraction >= 0.0)
-    assert (fraction <= 1.0)
-    assert (type(val1) == type(val2))
-    if (type(val1) == type(()) or
-        type (val1) == type([])):
-        assert(len(val1) == len(val2))
-        retval=[]
-        for i in range(len(val1)):
-            retval.append(interp1(val1[i], val2[i], fraction))
-        return tuple(retval)
-    else:
-        return interp1(val1, val2, fraction)

=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py	2009-04-07 19:45:21 +0000
+++ openlp/core/lib/__init__.py	2009-04-22 19:46:10 +0000
@@ -3,7 +3,7 @@
 """
 OpenLP - Open Source Lyrics Projection
 Copyright (c) 2008 Raoul Snyman
-Portions copyright (c) 2008 Martin Thompson, Tim Bentley,
+Portions copyright (c) 2008-2009 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
@@ -32,7 +32,9 @@
 from songxmlhandler import SongXMLBuilder
 from songxmlhandler import SongXMLParser
 from themexmlhandler import ThemeXML
+from renderer import Renderer
+from rendermanager import RenderManager
 
-__all__ = ['PluginConfig', 'Plugin', 'SettingsTab', 'MediaManagerItem', 'Event', 'EventType'
+__all__ = ['Renderer','PluginConfig', 'Plugin', 'SettingsTab', 'MediaManagerItem', 'Event', 'EventType'
            'XmlRootClass', 'ServiceItem', 'Receiver', 'OpenLPToolbar', 'SongXMLBuilder',
-           'SongXMLParser', 'EventManager', 'ThemeXML']
+           'SongXMLParser', 'EventManager', 'ThemeXML', 'RenderManager']

=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py	2009-03-23 20:18:06 +0000
+++ openlp/core/lib/plugin.py	2009-04-25 06:11:15 +0000
@@ -91,8 +91,9 @@
         self.preview_controller=plugin_helpers[u'preview']
         self.live_controller=plugin_helpers[u'live']
         self.theme_manager=plugin_helpers[u'theme']
-        self.event_manager=plugin_helpers[u'event']        
-        
+        self.event_manager=plugin_helpers[u'event']
+        self.render_manager=plugin_helpers[u'render']
+
     def check_pre_conditions(self):
         """
         Provides the Plugin with a handle to check if it can be loaded.
@@ -118,7 +119,7 @@
         Create a menu item and add it to the "Export" menu.
         """
         pass
-        
+
     def get_settings_tab(self):
         """
         Create a menu item and add it to the "Import" menu.

=== added file 'openlp/core/lib/pluginmanager.py'
--- openlp/core/lib/pluginmanager.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/pluginmanager.py	2009-04-20 18:22:42 +0000
@@ -0,0 +1,150 @@
+# -*- 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,
+
+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 os
+import sys
+import logging
+
+from openlp.core.lib import Plugin, EventManager
+
+class PluginManager(object):
+    """
+    This is the Plugin manager, which loads all the plugins,
+    and executes all the hooks, as and when necessary.
+    """
+    global log
+    log=logging.getLogger(u'PluginMgr')
+    log.info(u'Plugin manager loaded')
+
+    def __init__(self, dir):
+        """
+        The constructor for the plugin manager.
+        Passes the controllers on to the plugins for them to interact with via their ServiceItems
+        """
+        log.info(u'Plugin manager initing')
+        if not dir in sys.path:
+            log.debug("Inserting %s into sys.path", dir)
+            sys.path.insert(0, dir)
+        self.basepath = os.path.abspath(dir)
+        log.debug("Base path %s ", self.basepath)
+        self.plugins = []
+        # this has to happen after the UI is sorted self.find_plugins(dir)
+        log.info("Plugin manager done init")
+
+    def find_plugins(self, dir, plugin_helpers, eventmanager): # TODO shouldn't dir come from self.basepath
+        """
+        Scan the directory dir for objects inheriting from openlp.plugin
+        """
+        self.plugin_helpers = plugin_helpers
+        startdepth=len(os.path.abspath(dir).split(os.sep))
+        log.debug("find plugins %s at depth %d" %( str(dir), startdepth))
+
+        for root, dirs, files in os.walk(dir):
+            for name in files:
+                if name.endswith(".py") and not name.startswith("__"):
+                    path = os.path.abspath(os.path.join(root, name))
+                    thisdepth=len(path.split(os.sep))
+                    if thisdepth-startdepth > 2: # skip anything lower down
+                        continue
+                    modulename, pyext = os.path.splitext(path)
+                    prefix = os.path.commonprefix([self.basepath, path])
+                    # hack off the plugin base path
+                    modulename = modulename[len(prefix) + 1:]
+                    modulename = modulename.replace(os.path.sep, '.')
+                    # import the modules
+                    log.debug("Importing %s from %s. Depth %d" % (modulename, path, thisdepth))
+                    try:
+                        __import__(modulename, globals(), locals(), [])
+                    except ImportError, e:
+                        log.error("Failed to import module %s on path %s for reason %s", modulename, path, e.message)
+        self.plugin_classes = Plugin.__subclasses__()
+        self.plugins = []
+        plugin_objects = []
+        for p in self.plugin_classes:
+            try:
+                plugin = p(self.plugin_helpers)
+                log.debug(u'loaded plugin %s with helpers'%str(p))
+                log.debug("Plugin="+str(p))
+                if plugin.check_pre_conditions():
+                    log.debug("Appending "+str(p))
+                    plugin_objects.append(plugin)
+                    eventmanager.register(plugin)
+            except TypeError:
+                log.error(u'loaded plugin %s has no helpers'%str(p))
+        self.plugins = sorted(plugin_objects, self.order_by_weight)
+
+    def order_by_weight(self, x, y):
+        return cmp(x.weight, y.weight)
+
+    def hook_media_manager(self, mediatoolbox):
+        """
+        Loop through all the plugins. If a plugin has a valid media manager item,
+        add it to the media manager.
+        """
+        for plugin in self.plugins:
+            media_manager_item = plugin.get_media_manager_item()
+            if media_manager_item is not None:
+                log.debug('Inserting media manager item from %s' % plugin.name)
+                mediatoolbox.addItem(media_manager_item, plugin.icon, media_manager_item.title)
+
+    def hook_settings_tabs(self, settingsform=None):
+        """
+        Loop through all the plugins. If a plugin has a valid settings tab item,
+        add it to the settings tab.
+        """
+        for plugin in self.plugins:
+            settings_tab = plugin.get_settings_tab()
+            if settings_tab is not None:
+                log.debug('Inserting settings tab item from %s' % plugin.name)
+                settingsform.addTab(settings_tab)
+            else:
+                log.debug('No settings in %s' % plugin.name)
+
+    def hook_import_menu(self, import_menu):
+        """
+        Loop through all the plugins and give them an opportunity to add an item
+        to the import menu.
+        """
+        for plugin in self.plugins:
+            plugin.add_import_menu_item(import_menu)
+
+    def hook_export_menu(self, export_menu):
+        """
+        Loop through all the plugins and give them an opportunity to add an item
+        to the export menu.
+        """
+        for plugin in self.plugins:
+            plugin.add_export_menu_item(export_menu)
+
+    def hook_handle_event(self, eventmanager):
+        for plugin in self.plugins:
+            handle_event = plugin.handle_event(None)
+            print plugin, handle_event
+#            if settings_tab is not None:
+#                log.debug('Inserting settings tab item from %s' % plugin.name)
+#                settingsform.addTab(settings_tab)
+#            else:
+#                log.debug('No settings in %s' % plugin.name)
+    def initialise_plugins(self):
+        """
+        Loop through all the plugins and give them an opportunity to add an item
+        to the export menu.
+        """
+        for plugin in self.plugins:
+            plugin.initialise()

=== added file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/renderer.py	2009-04-25 06:11:15 +0000
@@ -0,0 +1,447 @@
+# -*- 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
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+import logging
+import os,  os.path
+
+import sys
+from PyQt4 import QtGui, QtCore, Qt
+
+from copy import copy
+
+class Renderer:
+
+    global log
+    log=logging.getLogger(u'Renderer')
+    log.info(u'Renderer Loaded')
+    """All the functions for rendering a set of words onto a Device Context
+
+    How to use:
+    set the words to be displayed with a call to set_words_openlp() - this returns an array of screenfuls of data
+    set a theme (if you need) with set_theme
+    tell it which DC to render to with set_DC()
+    set the borders of where you want the text (if not the whole DC) with set_text_rectangle()
+    tell it to render a particular screenfull with render_screen(n)
+
+    """
+    def __init__(self, path=None):
+        self._rect=None
+        self._debug=0
+        self.words=None
+        self._right_margin = 64 # the amount of right indent
+        self._shadow_offset=5
+        self._outline_offset=2
+        self._theme=None
+        self._bg_image_filename=None
+        self._paint=None
+        self._path = path
+
+    def set_debug(self, debug):
+        self._debug=debug
+
+    def set_theme(self, theme):
+        self._theme=theme
+        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)
+
+        self._bg_image_filename=os.path.join(self._path, self._theme.theme_name,  filename)
+        print self._bg_image_filename
+        if self._paint is not None:
+            self.scale_bg_image()
+
+    def scale_bg_image(self):
+        assert self._paint
+        i=QtGui.QImage(self._bg_image_filename)
+        # rescale and offset
+        imw=i.width()
+        imh=i.height()
+        print imw, imh
+        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)
+        if imratio > dcratio:
+            scale=dcw/float(imw)
+        elif imratio < dcratio:
+            scale=dch/float(imh)
+        else:
+            scale=dcw/float(imw) # either will do
+        neww=int(round(imw*scale))
+        newh=int(round(imh*scale))
+        self.background_offsetx=(dcw-neww)/2
+        self.background_offsety=(dch-newh)/2
+        self.img=QtGui.QPixmap.fromImage(i.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio))
+
+    def set_paint_dest(self, p):
+        self._paint=p
+        if self._bg_image_filename is not None:
+            self.scale_bg_image()
+
+    def format_slide(self, words, footer):
+        log.debug(u'format_slide %s', words)
+        verses=[]
+        words=words.replace(u'\r\n', u'\n')
+        verses_text = words.split(u'\n')
+        for v in verses_text:
+            lines=v.split(u'\n')
+            verses.append(self.split_set_of_lines(lines, footer)[0])
+        self.words = verses
+        verses_text=[]
+        for v in verses:
+            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])
+        import time
+        t=0.0
+        words=self.words[screennum]
+        retval=self._render_lines(words)
+        return retval
+
+    def set_text_rectangle(self, rect_main, rect_footer):
+        """ Sets the rectangle within which text should be rendered"""
+        self._rect=rect_main
+        self._rect_footer=rect_footer
+
+    def _render_background(self):
+        assert(self._theme)
+        assert(self._paint)
+        log.debug(u'render background %s ', self._theme.background_type)
+        p=QtGui.QPainter()
+        p.begin(self._paint)
+        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'horizontal':
+                w = int(self._paint.width())/2
+                gradient = QtGui.QLinearGradient(w, 0, w, self._paint.height()) # vertical
+            elif self._theme.background_direction == u'vertical':
+                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()
+            rectPath.moveTo(0, 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.background_type== u'image': # image
+            r=self._paint.rect()
+            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_color1)
+            #if self._theme.background_color1 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')
+
+    def split_set_of_lines(self, lines, footer):
+
+        """Given a list of lines, decide how to split them best if they don't all fit on the screen
+         - this is done by splitting at 1/2, 1/3 or 1/4 of the set
+         If it doesn't fit, even at this size, just split at each opportunity
+
+         We'll do this by getting the bounding box of each lline, and then summing them appropriately
+
+         Returns a list of [lists of lines], one set for each screenful
+         """
+        log.debug(u'Split set of lines')
+        # Probably ought to save the rendering results to a pseudoDC for redrawing efficiency.  But let's not optimse prematurely!
+
+        bboxes = []
+        for line in lines:
+            bboxes.append(self._render_single_line(line, footer))
+        numlines=len(lines)
+        bottom=self._rect.bottom()
+        for ratio in (numlines, numlines/2, numlines/3, numlines/4):
+            good=1
+            startline=0
+            endline=startline+ratio
+            while (endline<=numlines):
+                by=0
+                for (x, y) in bboxes[startline:endline]:
+                    by+=y
+                if by > bottom:
+                    good=0
+                    break
+                startline+=ratio
+                endline=startline+ratio
+            if good==1:
+                break
+
+        retval=[]
+        numlines_per_page=ratio
+        if good:
+            c=0
+            thislines=[]
+            while c < numlines:
+                thislines.append(lines[c])
+                c+=1
+                if len(thislines) == numlines_per_page:
+                    retval.append(thislines)
+                    thislines=[]
+        else:
+#             log.debug(u" "Just split where you can"
+            retval=[]
+            startline=0
+            endline=startline+1
+            while (endline<=numlines):
+                by=0
+                for (x, y) in bboxes[startline:endline]:
+                    by+=y
+                if by > bottom:
+                    retval.append(lines[startline:endline-1])
+                    startline=endline-1
+                    endline=startline # gets incremented below
+                    by=0
+                endline+=1
+
+        return retval
+
+    def _correctAlignment(self, rect, bbox):
+        x=rect.left()
+        if int(self._theme.display_verticalAlign) == 0: # top align
+            y = rect.top()
+        elif int(self._theme.display_verticalAlign) == 2: # bottom align
+            y=rect.bottom()-bbox.height()
+        elif int(self._theme.display_verticalAlign) == 1: # centre align
+            y=rect.top()+(rect.height()-bbox.height())/2
+        else:
+            assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
+        return x, y
+
+    def render_lines(self, lines, lines1=None):
+        """render a set of lines according to the theme, return bounding box"""
+        #log.debug(u'_render_lines %s', lines)
+
+        bbox=self._render_lines_unaligned(lines, False) # Main font
+        if lines1 is not None:
+            bbox1=self._render_lines_unaligned(lines1, True) # Footer Font
+
+        # put stuff on background so need to reset before doing the job properly.
+        self._render_background()
+        x, y = self._correctAlignment(self._rect, bbox)
+        bbox=self._render_lines_unaligned(lines, False,  (x, y))
+
+        if lines1 is not None:
+            #x, y = self._correctAlignment(self._rect_footer, bbox1)
+            bbox=self._render_lines_unaligned(lines1, True, (self._rect_footer.left(), self._rect_footer.top()) )
+
+        log.debug(u'render lines DONE')
+
+        return bbox
+
+    def _render_lines_unaligned(self, lines,  footer,  tlcorner=(0,0)):
+
+        """Given a list of lines to render, render each one in turn
+        (using the _render_single_line fn - which may result in going
+        off the bottom) They are expected to be pre-arranged to less
+        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)
+        x, y=tlcorner
+        brx=x
+        bry=y
+        for line in lines:
+            #if (line == ''):
+            #   continue
+            # render after current bottom, but at original left edge
+            # keep track of right edge to see which is biggest
+            (thisx, bry) = self._render_single_line(line, footer, (x,bry))
+            if (thisx > brx):
+                brx=thisx
+        retval=QtCore.QRect(x, y,brx-x, bry-y)
+        if self._debug:
+            p=QtGui.QPainter()
+            p.begin(self._paint)
+            p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
+            p.drawRect(retval)
+            p.end()
+        log.debug(u'render unaligned DONE')
+
+        return  retval
+
+    def _render_single_line(self, line, footer, tlcorner=(0,0)):
+
+        """render a single line of words onto the DC, top left corner
+        specified.
+
+        If the line is too wide for the context, it wraps, but
+        right-aligns the surplus words in the manner of song lyrics
+
+        Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
+        """
+        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
+        # right aligned with a "hanging indent"
+
+        # get the words
+#         log.debug(u" "Getting the words split right"
+        words=line.split(u' ')
+        thisline=u' '.join(words)
+        lastword=len(words)
+        lines=[]
+        maxx=self._rect.width(); maxy=self._rect.height();
+        while (len(words)>0):
+            w,h=self._get_extent_and_render(thisline, footer)
+            rhs=w+x
+            if rhs < maxx-self._right_margin:
+                lines.append(thisline)
+                words=words[lastword:]
+                thisline=' '.join(words)
+                lastword=len(words)
+            else:
+                lastword-=1
+                thisline=' '.join(words[:lastword])
+        startx=x
+        starty=y
+        rightextent=None
+        t=self._theme
+        if footer: # dont allow alignment messing with footers
+            align = 0
+        else:
+            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, footer,  tlcorner=(x, y), draw=False)
+
+            if t.display_shadow:
+                w+=self._shadow_offset
+                h+=self._shadow_offset
+            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
+                rightextent=x+w
+                if wrapstyle==1 and linenum != 0: # shift right from last line's rh edge
+                    rightextent=self._first_line_right_extent + self._right_margin
+                    if rightextent > maxx:
+                        rightextent = maxx
+                    x = rightextent-w
+
+            elif align==1: # right align
+                rightextent=maxx
+                x=maxx-w
+            elif align==2: # centre
+                x=(maxx-w)/2;
+                rightextent=x+w
+            # now draw the text, and any outlines/shadows
+            if t.display_shadow:
+                self._get_extent_and_render(line, footer,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, footer,(x+self._outline_offset,y), draw=True, color = t.display_outline_color)
+                self._get_extent_and_render(line, footer,(x, y+self._outline_offset), draw=True, color = t.display_outline_color)
+                self._get_extent_and_render(line, footer,(x, y-self._outline_offset), draw=True, color = t.display_outline_color)
+                self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True, color = t.display_outline_color)
+                if self._outline_offset > 1:
+                    self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
+                    self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
+                    self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
+                    self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
+
+            self._get_extent_and_render(line, footer,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
+        # draw a box around the text - debug only
+        if self._debug:
+            p=QtGui.QPainter()
+            p.begin(self._paint)
+            p.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
+            p.drawRect(startx,starty,rightextent-startx, y-starty)
+            p.end()
+
+        brcorner=(rightextent,y)
+        return brcorner
+
+    # xxx this is what to override for an SDL version
+    def _get_extent_and_render(self, line, footer,  tlcorner=(0,0), draw=False, color=None):
+        """Find bounding box of text  - as render_single_line.
+        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, 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.font_footer_name,
+                         int(self._theme.font_footer_proportion), # size
+                         QtGui.QFont.Normal, # weight
+                         0)# italic
+        else:
+            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 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:
+            if footer:
+                p.setPen(QtGui.QColor(self._theme.font_footer_color))
+            else:
+                p.setPen(QtGui.QColor(self._theme.font_main_color))
+        else:
+            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 draw:
+            p.drawText(x, y+metrics.height()-metrics.descent()-1, line)
+        p.end()
+        return (w, h)

=== added file 'openlp/core/lib/rendermanager.py'
--- openlp/core/lib/rendermanager.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/rendermanager.py	2009-04-25 06:38:21 +0000
@@ -0,0 +1,115 @@
+# -*- 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 - 2009Martin 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
+import os,  os.path
+import sys
+from PyQt4 import QtGui, QtCore, Qt
+from renderer import  Renderer
+
+class RenderManager:
+    """
+    Class to pull all Renderer interactions into one place.
+    The plugins will call helper methods to do the rendering but
+    this class will provide display defense code.
+    """
+    global log
+    log=logging.getLogger(u'RenderManager')
+    log.info(u'RenderManager Loaded')
+
+    def __init__(self, theme_manager, screen_list):
+        log.debug(u'Initilisation started')
+        self.screen_list = screen_list
+        self.theme_manager = theme_manager
+        self.displays = len(screen_list)
+        self.current_display = 1
+        self.renderer = Renderer(None)
+        self.calculate_default(self.screen_list[self.current_display-1][1])
+        self.frame = None
+
+    def set_default_theme(self, theme):
+        log.debug("default theme set to %s",  theme)
+        self.default_theme = self.theme_manager.getThemeData(theme)
+        self.renderer.set_theme(self.default_theme)
+
+        self.renderer.set_text_rectangle(QtCore.QRect(10,0, self.width-1, self.height-1),
+            QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start))
+
+
+    def set_theme(self, theme):
+        log.debug("theme set to %s",  theme)
+        self.theme = theme
+        self.renderer.set_theme(self.theme)
+
+        self.renderer.set_text_rectangle(QtCore.QRect(10,0, self.width-1, self.height-1),
+            QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start))
+        if theme.font_main_override == False:
+            pass
+        if theme.font_footer_override == False:
+            pass
+
+    def generate_preview(self):
+        self.calculate_default(QtCore.QSize(800,600))
+
+        self.renderer.set_text_rectangle(QtCore.QRect(10,0, self.width-1, self.height-1),
+            QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start))
+
+        frame = QtGui.QPixmap(self.width, self.height)
+        self.renderer.set_paint_dest(frame)
+
+        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.')
+        lines1=[]
+        lines1.append(u'Amazing Grace (John Newton)' )
+        lines1.append(u'CCLI xxx (c)Openlp.org')
+        answer=self.renderer.render_lines(lines, lines1)
+        return frame
+
+    def format_slide(self, words, footer):
+        self.calculate_default(QtCore.QSize(800,600))
+
+        self.renderer.set_text_rectangle(QtCore.QRect(10,0, self.width-1, self.height-1),
+            QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start))
+
+        return self.renderer.format_slide(words, footer)
+
+    def generate_slide(self,main_text, footer_text, preview=True):
+        if preview == True:
+            self.calculate_default(QtCore.QSize(800,600))
+
+        self.renderer.set_text_rectangle(QtCore.QRect(10,0, self.width-1, self.height-1),
+            QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start))
+
+        #frame = QtGui.QPixmap(self.width, self.height)
+        #self.renderer.set_paint_dest(frame)
+        #print main_text
+        answer=self.renderer.render_lines(main_text, footer_text)
+        return self.frame
+
+    def calculate_default(self, screen):
+        self.width = screen.width()
+        self.height = screen.height()
+        self.footer_start = int(self.height*0.95) # 95% is start of footer
+        #update the rederer frame
+        self.frame = QtGui.QPixmap(self.width, self.height)
+        self.renderer.set_paint_dest(self.frame)

=== modified file 'openlp/core/lib/settingstab.py'
--- openlp/core/lib/settingstab.py	2009-03-06 06:05:01 +0000
+++ openlp/core/lib/settingstab.py	2009-04-15 04:58:51 +0000
@@ -19,7 +19,6 @@
 """
 
 from PyQt4 import QtCore, QtGui
-from openlp.core.resources import *
 from openlp.core.lib import PluginConfig
 
 class SettingsTab(QtGui.QWidget):
@@ -39,7 +38,7 @@
         else:
             self.config = PluginConfig(str(title))
         self.load()
-                        
+
     def setTitle(self, title):
         self.tabTitle = title
 
@@ -51,15 +50,9 @@
 
     def retranslateUi(self):
         pass
-        
+
     def load(self):
         pass
-    
+
     def save(self):
         pass
-        
-    def convertStringToBoolean(self, stringvalue):
-        if stringvalue.lower() == 'true':
-            return True
-        else:
-            return False

=== modified file 'openlp/core/lib/themexmlhandler.py'
--- openlp/core/lib/themexmlhandler.py	2009-04-11 07:33:45 +0000
+++ openlp/core/lib/themexmlhandler.py	2009-04-21 19:45:50 +0000
@@ -21,9 +21,49 @@
 
 For XML Schema see wiki.openlp.org
 """
+
+from openlp import convertStringToBoolean
 from xml.dom.minidom import  Document
 from xml.etree.ElementTree import ElementTree, XML, dump
 
+blankthemexml=\
+'''<?xml version="1.0" encoding="iso-8859-1"?>
+ <theme version="1.0">
+   <name>BlankStyle</name>
+   <background mode="transparent"/>
+   <background type="solid" mode="opaque">
+      <color>#000000</color>
+   </background>
+   <background type="gradient" mode="opaque">
+      <startColor>#000000</startColor>
+      <endColor>#000000</endColor>
+      <direction>vertical</direction>
+   </background>
+   <background type="image" mode="opaque">
+      <filename>fred.bmp</filename>
+   </background>
+   <font type="main">
+      <name>Arial</name>
+      <color>#000000</color>
+      <proportion>30</proportion>
+      <location override="False" x="0" y="0" width="0" height="0"/>
+   </font>
+   <font type="footer">
+      <name>Arial</name>
+      <color>#000000</color>
+      <proportion>12</proportion>
+      <location override="False" x="0" y="0" width="0" height="0"/>
+   </font>
+   <display>
+      <shadow color="#000000">True</shadow>
+      <outline color="#000000">False</outline>
+       <horizontalAlign>0</horizontalAlign>
+       <verticalAlign>0</verticalAlign>
+       <wrapStyle>0</wrapStyle>
+   </display>
+ </theme>
+'''
+
 class ThemeXML():
     def __init__(self):
         # Create the minidom document
@@ -31,11 +71,11 @@
 
     def new_document(self, name):
         # Create the <song> base element
-        self.theme = self.theme_xml.createElement(u'Theme')
+        self.theme = self.theme_xml.createElement(u'theme')
         self.theme_xml.appendChild(self.theme)
         self.theme.setAttribute(u'version', u'1.0')
 
-        self.name = self.theme_xml.createElement(u'Name')
+        self.name = self.theme_xml.createElement(u'name')
         ctn = self.theme_xml.createTextNode(name)
         self.name.appendChild(ctn)
         self.theme.appendChild(self.name)
@@ -52,30 +92,23 @@
         background.setAttribute(u'type', u'solid')
         self.theme.appendChild(background)
 
-        color = self.theme_xml.createElement(u'color1')
+        color = self.theme_xml.createElement(u'color')
         bkc = self.theme_xml.createTextNode(bkcolor)
         color.appendChild(bkc)
         background.appendChild(color)
 
-        color = self.theme_xml.createElement(u'color2')
-        background.appendChild(color)
-
-        color = self.theme_xml.createElement(u'direction')
-        background.appendChild(color)
-
-
     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')
         self.theme.appendChild(background)
 
-        color = self.theme_xml.createElement(u'color1')
+        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'color2')
+        color = self.theme_xml.createElement(u'endColor')
         bkc = self.theme_xml.createTextNode(endcolor)
         color.appendChild(bkc)
         background.appendChild(color)
@@ -96,33 +129,34 @@
         color.appendChild(bkc)
         background.appendChild(color)
 
-    def add_font(self, fontname, fontcolor, fontproportion, override, fonttype=u'main', xpos=0, ypos=0 ,width=0, height=0):
+    def add_font(self, name, color, proportion, override, fonttype=u'main', xpos=0, ypos=0 ,width=0, height=0):
         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)
-
-        name = self.theme_xml.createElement(u'location')
-        name.setAttribute(u'override',override)
-        name.setAttribute(u'x',str(xpos))
-        name.setAttribute(u'y',str(ypos))
-        name.setAttribute(u'width',str(width))
-        name.setAttribute(u'height',str(height))
-        background.appendChild(name)
+        element = self.theme_xml.createElement(u'name')
+        fn = self.theme_xml.createTextNode(name)
+        element.appendChild(fn)
+        background.appendChild(element)
+
+        element = self.theme_xml.createElement(u'color')
+        fn = self.theme_xml.createTextNode(color)
+        element.appendChild(fn)
+        background.appendChild(element)
+
+        element = self.theme_xml.createElement(u'proportion')
+        fn = self.theme_xml.createTextNode(proportion)
+        element.appendChild(fn)
+        background.appendChild(element)
+
+        element = self.theme_xml.createElement(u'location')
+        element.setAttribute(u'override',override)
+        if override == True:
+            element.setAttribute(u'x',str(xpos))
+            element.setAttribute(u'y',str(ypos))
+            element.setAttribute(u'width',str(width))
+            element.setAttribute(u'height',str(height))
+        background.appendChild(element)
 
     def add_display(self, shadow, shadowColor, outline, outlineColor, horizontal, vertical, wrap):
         background = self.theme_xml.createElement(u'display')
@@ -170,6 +204,13 @@
         return self.theme_xml.toxml()
 
     def parse(self, xml):
+        self.baseParseXml()
+        self.parse_xml(xml)
+
+    def baseParseXml(self):
+        self.parse_xml(blankthemexml)
+
+    def parse_xml(self, xml):
         theme_xml = ElementTree(element=XML(xml))
         iter=theme_xml.getiterator()
         master = u''
@@ -185,13 +226,17 @@
                         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)
+                        et = convertStringToBoolean(element.text)
+                        setattr(self, master + element.tag , et)
                         setattr(self, master + element.tag +u'_'+ e[0], e[1])
                     else:
                         field = master + e[0]
-                        setattr(self, field, e[1])
+                        e1 = e[1]
+                        if e[1] == u'True' or e[1] == u'False':
+                            e1 = convertStringToBoolean(e[1])
+                        setattr(self, field, e1)
             else:
-                #print "c", element.tag
+                #print "c", element.tag, element.text
                 if element.tag is not None :
                     field = master + element.tag
                     setattr(self, field, element.text)

=== removed file 'openlp/core/pluginmanager.py'
--- openlp/core/pluginmanager.py	2009-03-25 20:30:48 +0000
+++ openlp/core/pluginmanager.py	1970-01-01 00:00:00 +0000
@@ -1,151 +0,0 @@
-# -*- 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,
-
-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 os
-import sys
-import logging
-
-from openlp.core.lib import Plugin, EventManager
-
-class PluginManager(object):
-    """
-    This is the Plugin manager, which loads all the plugins,
-    and executes all the hooks, as and when necessary.
-    """
-    global log
-    log=logging.getLogger(u'PluginMgr')
-    log.info(u'Plugin manager loaded')
-
-    def __init__(self, dir):
-        """
-        The constructor for the plugin manager.
-        Passes the controllers on to the plugins for them to interact with via their ServiceItems
-        """
-        log.info(u'Plugin manager initing')
-        if not dir in sys.path:
-            log.debug("Inserting %s into sys.path", dir)
-            sys.path.insert(0, dir)
-        self.basepath = os.path.abspath(dir)
-        log.debug("Base path %s ", self.basepath)
-        self.plugins = []
-        # this has to happen after the UI is sorted self.find_plugins(dir)
-        log.info("Plugin manager done init")
-
-    def find_plugins(self, dir, plugin_helpers, eventmanager): # TODO shouldn't dir come from self.basepath
-        """
-        Scan the directory dir for objects inheriting from openlp.plugin
-        """
-        self.plugin_helpers = plugin_helpers
-        startdepth=len(os.path.abspath(dir).split(os.sep))
-        log.debug("find plugins %s at depth %d" %( str(dir), startdepth))
-
-        for root, dirs, files in os.walk(dir):
-            for name in files:
-                if name.endswith(".py") and not name.startswith("__"):
-                    path = os.path.abspath(os.path.join(root, name))
-                    thisdepth=len(path.split(os.sep))
-                    if thisdepth-startdepth > 2: # skip anything lower down
-                        continue
-                    modulename, pyext = os.path.splitext(path)
-                    prefix = os.path.commonprefix([self.basepath, path])
-                    # hack off the plugin base path
-                    modulename = modulename[len(prefix) + 1:]
-                    modulename = modulename.replace(os.path.sep, '.')
-                    # import the modules
-                    log.debug("Importing %s from %s. Depth %d" % (modulename, path, thisdepth))
-                    try:
-                        __import__(modulename, globals(), locals(), [])
-                    except ImportError, e:
-                        log.error("Failed to import module %s on path %s for reason %s", modulename, path, e.message)
-        self.plugin_classes = Plugin.__subclasses__()
-        self.plugins = []
-        plugin_objects = []
-        for p in self.plugin_classes:
-            try:
-                plugin = p(self.plugin_helpers)
-                log.debug(u'loaded plugin %s with helpers'%str(p))
-                log.debug("Plugin="+str(p))
-                if plugin.check_pre_conditions():
-                    log.debug("Appending "+str(p))
-                    plugin_objects.append(plugin)
-                    eventmanager.register(plugin)
-            except TypeError:
-                log.error(u'loaded plugin %s has no helpers'%str(p))
-        self.plugins = sorted(plugin_objects, self.order_by_weight)
-
-    def order_by_weight(self, x, y):
-        return cmp(x.weight, y.weight)
-
-    def hook_media_manager(self, mediatoolbox):
-        """
-        Loop through all the plugins. If a plugin has a valid media manager item,
-        add it to the media manager.
-        """
-        for plugin in self.plugins:
-            media_manager_item = plugin.get_media_manager_item()
-            if media_manager_item is not None:
-                log.debug('Inserting media manager item from %s' % plugin.name)
-                mediatoolbox.addItem(media_manager_item, plugin.icon, media_manager_item.title)
-
-    def hook_settings_tabs(self, settingsform=None):
-        """
-        Loop through all the plugins. If a plugin has a valid settings tab item,
-        add it to the settings tab.
-        """
-        for plugin in self.plugins:
-            settings_tab = plugin.get_settings_tab()
-            if settings_tab is not None:
-                log.debug('Inserting settings tab item from %s' % plugin.name)
-                settingsform.addTab(settings_tab)
-            else:
-                log.debug('No settings in %s' % plugin.name)
-
-    def hook_import_menu(self, import_menu):
-        """
-        Loop through all the plugins and give them an opportunity to add an item
-        to the import menu.
-        """
-        for plugin in self.plugins:
-            plugin.add_import_menu_item(import_menu)
-
-    def hook_export_menu(self, export_menu):
-        """
-        Loop through all the plugins and give them an opportunity to add an item
-        to the export menu.
-        """
-        for plugin in self.plugins:
-            plugin.add_export_menu_item(export_menu)
-
-    def hook_handle_event(self, eventmanager):
-        for plugin in self.plugins:
-            handle_event = plugin.handle_event(None)
-            print plugin, handle_event
-#            if settings_tab is not None:
-#                log.debug('Inserting settings tab item from %s' % plugin.name)
-#                settingsform.addTab(settings_tab)
-#            else:
-#                log.debug('No settings in %s' % plugin.name)
-    def initialise_plugins(self):
-        """
-        Loop through all the plugins and give them an opportunity to add an item
-        to the export menu.
-        """
-        for plugin in self.plugins:
-            plugin.initialise()

=== removed file 'openlp/core/render.py'
--- openlp/core/render.py	2009-04-11 07:33:45 +0000
+++ openlp/core/render.py	1970-01-01 00:00:00 +0000
@@ -1,440 +0,0 @@
-# -*- 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
-
-import sys
-from PyQt4 import QtGui, QtCore, Qt
-
-from copy import copy
-#from interpolate import interpolate
-
-class Renderer:
-
-    global log
-    log=logging.getLogger(u'Renderer')
-    log.info(u'Renderer Loaded')
-    """All the functions for rendering a set of words onto a Device Context
-
-    How to use:
-    set the words to be displayed with a call to set_words_openlp() - this returns an array of screenfuls of data
-    set a theme (if you need) with set_theme
-    tell it which DC to render to with set_DC()
-    set the borders of where you want the text (if not the whole DC) with set_text_rectangle()
-    tell it to render a particular screenfull with render_screen(n)
-
-    """
-    def __init__(self):
-        self._rect=None
-        self._debug=0
-        self.words=None
-        self._right_margin = 64 # the amount of right indent
-        self._shadow_offset=5
-        self._outline_offset=2
-        self._theme=None
-        self._bg_image_filename=None
-        self._paint=None
-
-    def set_debug(self, debug):
-        self._debug=debug
-
-    def set_theme(self, theme):
-        self._theme=theme
-        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)
-        self._bg_image_filename=filename
-        if self._paint is not None:
-            self.scale_bg_image()
-
-    def scale_bg_image(self):
-        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()
-        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)
-        if imratio > dcratio:
-            scale=dcw/float(imw)
-        elif imratio < dcratio:
-            scale=dch/float(imh)
-        else:
-            scale=dcw/float(imw) # either will do
-        neww=int(round(imw*scale))
-        newh=int(round(imh*scale))
-        self.background_offsetx=(dcw-neww)/2
-        self.background_offsety=(dch-newh)/2
-        self.img=QtGui.QPixmap.fromImage(i.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio))
-
-    def set_paint_dest(self, p):
-        self._paint=p
-        if self._bg_image_filename is not None:
-            self.scale_bg_image()
-
-    def set_words_openlp(self, words):
-#         log.debug(u" "set words openlp", words
-        verses=[]
-        words=words.replace(u'\r\n', u'\n')
-        verses_text=words.split(u'\n\n')
-        for v in verses_text:
-            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(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])
-        import time
-        t=0.0
-        words=self.words[screennum]
-        retval=self._render_lines(words)
-        return retval
-
-    def set_text_rectangle(self, rect_main, rect_footer):
-        """ Sets the rectangle within which text should be rendered"""
-        self._rect=rect_main
-        self._rect_footer=rect_footer
-
-    def _render_background(self):
-        assert(self._theme)
-        assert(self._paint)
-        log.debug(u'render background %s ', self._theme.background_type)
-        p=QtGui.QPainter()
-        p.begin(self._paint)
-        if self._theme.background_type == u'solid':
-            p.fillRect(self._paint.rect(), QtGui.QColor(self._theme.background_color1))
-        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_color1))
-            gradient.setColorAt(1, QtGui.QColor(self._theme.background_color2))
-
-            p.setBrush(QtGui.QBrush(gradient))
-            rectPath = QtGui.QPainterPath()
-
-            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.closeSubpath()
-            p.drawPath(rectPath)
-
-        elif self._theme.background_type== u'image': # image
-            r=self._paint.rect()
-            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')
-
-    def split_set_of_lines(self, lines):
-
-        """Given a list of lines, decide how to split them best if they don't all fit on the screen
-         - this is done by splitting at 1/2, 1/3 or 1/4 of the set
-         If it doesn't fit, even at this size, just split at each opportunity
-
-         We'll do this by getting the bounding box of each line, and then summing them appropriately
-
-         Returns a list of [lists of lines], one set for each screenful
-         """
-#         log.debug(u" "Split set of lines"
-        # Probably ought to save the rendering results to a pseudoDC for redrawing efficiency.  But let's not optimse prematurely!
-
-        bboxes = []
-        for line in lines:
-            bboxes.append(self._render_single_line(line))
-        numlines=len(lines)
-        bottom=self._rect.bottom()
-        for ratio in (numlines, numlines/2, numlines/3, numlines/4):
-            good=1
-            startline=0
-            endline=startline+ratio
-            while (endline<=numlines):
-                by=0
-                for (x,y) in bboxes[startline:endline]:
-                    by+=y
-                if by > bottom:
-                    good=0
-                    break
-                startline+=ratio
-                endline=startline+ratio
-            if good==1:
-                break
-
-        retval=[]
-        numlines_per_page=ratio
-        if good:
-            c=0
-            thislines=[]
-            while c < numlines:
-                thislines.append(lines[c])
-                c+=1
-                if len(thislines) == numlines_per_page:
-                    retval.append(thislines)
-                    thislines=[]
-        else:
-#             log.debug(u" "Just split where you can"
-            retval=[]
-            startline=0
-            endline=startline+1
-            while (endline<=numlines):
-                by=0
-                for (x,y) in bboxes[startline:endline]:
-                    by+=y
-                if by > bottom:
-                    retval.append(lines[startline:endline-1])
-                    startline=endline-1
-                    endline=startline # gets incremented below
-                    by=0
-                endline+=1
-
-        return retval
-
-    def _correctAlignment(self, rect, bbox):
-        x=rect.left()
-        if int(self._theme.display_verticalAlign) == 0: # top align
-            y = rect.top()
-        elif int(self._theme.display_verticalAlign) == 1: # bottom align
-            y=rect.bottom()-bbox.height()
-        elif int(t.display_verticalAlign) == 2: # centre align
-            y=rect.top()+(rect.height()-bbox.height())/2
-        else:
-            assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
-        return x, y
-
-    def _render_lines(self, lines, lines1=None):
-        """render a set of lines according to the theme, return bounding box"""
-        #log.debug(u'_render_lines %s', lines)
-
-        bbox=self._render_lines_unaligned(lines, False) # Main font
-        if lines1 is not None:
-            bbox1=self._render_lines_unaligned(lines1, True) # Footer Font
-
-        # put stuff on background so need to reset before doing the job properly.
-        self._render_background()
-        x, y = self._correctAlignment(self._rect, bbox)
-        bbox=self._render_lines_unaligned(lines, False,  (x,y))
-
-        if lines1 is not None:
-            x, y = self._correctAlignment(self._rect_footer, bbox1)
-            bbox=self._render_lines_unaligned(lines1, True, (x,y) )
-
-        log.debug(u'render lines DONE')
-
-        return bbox
-
-    def _render_lines_unaligned(self, lines,  footer,  tlcorner=(0,0)):
-
-        """Given a list of lines to render, render each one in turn
-        (using the _render_single_line fn - which may result in going
-        off the bottom) They are expected to be pre-arranged to less
-        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)
-        x,y=tlcorner
-        brx=x
-        bry=y
-        for line in lines:
-            if (line == ''):
-                continue
-            # render after current bottom, but at original left edge
-            # keep track of right edge to see which is biggest
-            (thisx, bry) = self._render_single_line(line, footer, (x,bry))
-            if (thisx > brx):
-                brx=thisx
-        retval=QtCore.QRect(x,y,brx-x, bry-y)
-        if self._debug:
-            p=QtGui.QPainter()
-            p.begin(self._paint)
-            p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
-            p.drawRect(retval)
-            p.end()
-        log.debug(u'render unaligned DONE')
-
-        return  retval
-
-    def _render_single_line(self, line, footer, tlcorner=(0,0)):
-
-        """render a single line of words onto the DC, top left corner
-        specified.
-
-        If the line is too wide for the context, it wraps, but
-        right-aligns the surplus words in the manner of song lyrics
-
-        Returns the bottom-right corner (of what was rendered) as a tuple(x,y).
-        """
-        #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
-        # right aligned with a "hanging indent"
-
-        # get the words
-#         log.debug(u" "Getting the words split right"
-        words=line.split(u' ')
-        thisline=u' '.join(words)
-        lastword=len(words)
-        lines=[]
-        maxx=self._rect.width(); maxy=self._rect.height();
-        while (len(words)>0):
-            w,h=self._get_extent_and_render(thisline, footer)
-            rhs=w+x
-            if rhs < maxx-self._right_margin:
-                lines.append(thisline)
-                words=words[lastword:]
-                thisline=' '.join(words)
-                lastword=len(words)
-            else:
-                lastword-=1
-                thisline=' '.join(words[:lastword])
-        startx=x
-        starty=y
-        rightextent=None
-        t=self._theme
-        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, footer,  tlcorner=(x,y), draw=False)
-
-            if t.display_shadow:
-                w+=self._shadow_offset
-                h+=self._shadow_offset
-            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
-                rightextent=x+w
-                if wrapstyle==1 and linenum != 0: # shift right from last line's rh edge
-                    rightextent=self._first_line_right_extent + self._right_margin
-                    if rightextent > maxx:
-                        rightextent = maxx
-                    x = rightextent-w
-
-            elif align==1: # right align
-                rightextent=maxx
-                x=maxx-w
-            elif align==2: # centre
-                x=(maxx-w)/2;
-                rightextent=x+w
-            # now draw the text, and any outlines/shadows
-            if t.display_shadow:
-                self._get_extent_and_render(line, footer,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, footer,(x+self._outline_offset,y), draw=True, color = t.display_outline_color)
-                self._get_extent_and_render(line, footer,(x,y+self._outline_offset), draw=True, color = t.display_outline_color)
-                self._get_extent_and_render(line, footer,(x,y-self._outline_offset), draw=True, color = t.display_outline_color)
-                self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True, color = t.display_outline_color)
-                if self._outline_offset > 1:
-                    self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
-                    self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
-                    self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
-                    self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
-
-            self._get_extent_and_render(line, footer,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
-        # draw a box around the text - debug only
-        if self._debug:
-            p=QtGui.QPainter()
-            p.begin(self._paint)
-            p.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
-            p.drawRect(startx,starty,rightextent-startx,y-starty)
-            p.end()
-
-        brcorner=(rightextent,y)
-        return brcorner
-
-    # xxx this is what to override for an SDL version
-    def _get_extent_and_render(self, line, footer,  tlcorner=(0,0), draw=False, color=None):
-        """Find bounding box of text  - as render_single_line.
-        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, 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.font_footer_name,
-                         int(self._theme.font_footer_proportion), # size
-                         QtGui.QFont.Normal, # weight
-                         0)# italic
-        else:
-            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 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:
-            if footer:
-                p.setPen(QtGui.QColor(self._theme.font_footer_color))
-            else:
-                p.setPen(QtGui.QColor(self._theme.font_main_color))
-        else:
-            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 draw:
-            p.drawText(x,y+metrics.height()-metrics.descent()-1, line)
-        p.end()
-        return (w, h)

=== modified file 'openlp/core/test/test_plugin_manager.py'
--- openlp/core/test/test_plugin_manager.py	2009-03-12 20:19:24 +0000
+++ openlp/core/test/test_plugin_manager.py	2009-04-20 18:22:42 +0000
@@ -1,4 +1,7 @@
 import logging
+import os, sys
+from openlp.core.lib.pluginmanager import PluginManager
+
 logging.basicConfig(level=logging.DEBUG,
                 format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                 datefmt='%m-%d %H:%M',
@@ -14,11 +17,9 @@
 log=logging.getLogger('')
 
 logging.info("Logging started")
-import os, sys
 mypath=os.path.split(os.path.abspath(__file__))[0]
 
 sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..')))
-from openlp.core.pluginmanager import PluginManager
 
 # test the plugin manager with some plugins in the test_plugins directory
 class TestPluginManager:

=== modified file 'openlp/core/ui/amendthemedialog.py'
--- openlp/core/ui/amendthemedialog.py	2009-04-11 05:43:52 +0000
+++ openlp/core/ui/amendthemedialog.py	2009-04-21 19:45:50 +0000
@@ -2,7 +2,7 @@
 
 # Form implementation generated from reading ui file 'amendthemedialog.ui'
 #
-# Created: Fri Apr 10 20:38:33 2009
+# Created: Tue Apr 21 06:06:56 2009
 #      by: PyQt4 UI code generator 4.4.4
 #
 # WARNING! All changes made in this file will be lost!
@@ -12,272 +12,416 @@
 class Ui_AmendThemeDialog(object):
     def setupUi(self, AmendThemeDialog):
         AmendThemeDialog.setObjectName("AmendThemeDialog")
-        AmendThemeDialog.resize(752, 533)
+        AmendThemeDialog.setWindowModality(QtCore.Qt.ApplicationModal)
+        AmendThemeDialog.resize(586, 651)
         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(50, 20, 441, 41))
-        self.layoutWidget.setObjectName("layoutWidget")
-        self.horizontalLayout = QtGui.QHBoxLayout(self.layoutWidget)
-        self.horizontalLayout.setObjectName("horizontalLayout")
-        self.ThemeNameLabel = QtGui.QLabel(self.layoutWidget)
+        AmendThemeDialog.setModal(True)
+        self.AmendThemeLayout = QtGui.QVBoxLayout(AmendThemeDialog)
+        self.AmendThemeLayout.setSpacing(8)
+        self.AmendThemeLayout.setMargin(8)
+        self.AmendThemeLayout.setObjectName("AmendThemeLayout")
+        self.ThemeNameWidget = QtGui.QWidget(AmendThemeDialog)
+        self.ThemeNameWidget.setObjectName("ThemeNameWidget")
+        self.ThemeNameLayout = QtGui.QHBoxLayout(self.ThemeNameWidget)
+        self.ThemeNameLayout.setSpacing(8)
+        self.ThemeNameLayout.setMargin(0)
+        self.ThemeNameLayout.setObjectName("ThemeNameLayout")
+        self.ThemeNameLabel = QtGui.QLabel(self.ThemeNameWidget)
         self.ThemeNameLabel.setObjectName("ThemeNameLabel")
-        self.horizontalLayout.addWidget(self.ThemeNameLabel)
-        self.ThemeNameEdit = QtGui.QLineEdit(self.layoutWidget)
+        self.ThemeNameLayout.addWidget(self.ThemeNameLabel)
+        self.ThemeNameEdit = QtGui.QLineEdit(self.ThemeNameWidget)
         self.ThemeNameEdit.setObjectName("ThemeNameEdit")
-        self.horizontalLayout.addWidget(self.ThemeNameEdit)
-        self.widget = QtGui.QWidget(AmendThemeDialog)
-        self.widget.setGeometry(QtCore.QRect(31, 71, 721, 411))
-        self.widget.setObjectName("widget")
-        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.widget)
-        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
-        self.LeftSide = QtGui.QWidget(self.widget)
-        self.LeftSide.setObjectName("LeftSide")
-        self.tabWidget = QtGui.QTabWidget(self.LeftSide)
-        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 341, 401))
-        self.tabWidget.setObjectName("tabWidget")
+        self.ThemeNameLayout.addWidget(self.ThemeNameEdit)
+        self.AmendThemeLayout.addWidget(self.ThemeNameWidget)
+        self.ContentWidget = QtGui.QWidget(AmendThemeDialog)
+        self.ContentWidget.setObjectName("ContentWidget")
+        self.ContentLayout = QtGui.QHBoxLayout(self.ContentWidget)
+        self.ContentLayout.setSpacing(8)
+        self.ContentLayout.setMargin(0)
+        self.ContentLayout.setObjectName("ContentLayout")
+        self.ThemeTabWidget = QtGui.QTabWidget(self.ContentWidget)
+        self.ThemeTabWidget.setObjectName("ThemeTabWidget")
         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.BackgroundLayout = QtGui.QFormLayout(self.BackgroundTab)
+        self.BackgroundLayout.setMargin(8)
+        self.BackgroundLayout.setSpacing(8)
+        self.BackgroundLayout.setObjectName("BackgroundLayout")
+        self.BackgroundLabel = QtGui.QLabel(self.BackgroundTab)
         self.BackgroundLabel.setObjectName("BackgroundLabel")
-        self.gridLayout.addWidget(self.BackgroundLabel, 0, 0, 1, 2)
-        self.BackgroundComboBox = QtGui.QComboBox(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.BackgroundLabel)
+        self.BackgroundComboBox = QtGui.QComboBox(self.BackgroundTab)
         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.BackgroundLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.BackgroundComboBox)
+        self.BackgroundTypeLabel = QtGui.QLabel(self.BackgroundTab)
         self.BackgroundTypeLabel.setObjectName("BackgroundTypeLabel")
-        self.gridLayout.addWidget(self.BackgroundTypeLabel, 1, 0, 1, 2)
-        self.BackgroundTypeComboBox = QtGui.QComboBox(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.BackgroundTypeLabel)
+        self.BackgroundTypeComboBox = QtGui.QComboBox(self.BackgroundTab)
         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.BackgroundLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.BackgroundTypeComboBox)
+        self.Color1Label = QtGui.QLabel(self.BackgroundTab)
         self.Color1Label.setObjectName("Color1Label")
-        self.gridLayout.addWidget(self.Color1Label, 2, 0, 1, 1)
-        self.Color1PushButton = QtGui.QPushButton(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.Color1Label)
+        self.Color1PushButton = QtGui.QPushButton(self.BackgroundTab)
         self.Color1PushButton.setObjectName("Color1PushButton")
-        self.gridLayout.addWidget(self.Color1PushButton, 2, 2, 1, 2)
-        self.Color2Label = QtGui.QLabel(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.Color1PushButton)
+        self.Color2Label = QtGui.QLabel(self.BackgroundTab)
         self.Color2Label.setObjectName("Color2Label")
-        self.gridLayout.addWidget(self.Color2Label, 3, 0, 1, 1)
-        self.Color2PushButton = QtGui.QPushButton(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.Color2Label)
+        self.Color2PushButton = QtGui.QPushButton(self.BackgroundTab)
         self.Color2PushButton.setObjectName("Color2PushButton")
-        self.gridLayout.addWidget(self.Color2PushButton, 3, 2, 1, 2)
-        self.ImageLabel = QtGui.QLabel(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.Color2PushButton)
+        self.ImageLabel = QtGui.QLabel(self.BackgroundTab)
         self.ImageLabel.setObjectName("ImageLabel")
-        self.gridLayout.addWidget(self.ImageLabel, 4, 0, 1, 1)
-        self.ImageLineEdit = QtGui.QLineEdit(self.layoutWidget1)
+        self.BackgroundLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.ImageLabel)
+        self.GradientLabel = QtGui.QLabel(self.BackgroundTab)
+        self.GradientLabel.setObjectName("GradientLabel")
+        self.BackgroundLayout.setWidget(6, QtGui.QFormLayout.LabelRole, self.GradientLabel)
+        self.GradientComboBox = QtGui.QComboBox(self.BackgroundTab)
+        self.GradientComboBox.setObjectName("GradientComboBox")
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.GradientComboBox.addItem(QtCore.QString())
+        self.BackgroundLayout.setWidget(6, QtGui.QFormLayout.FieldRole, self.GradientComboBox)
+        self.ImageFilenameWidget = QtGui.QWidget(self.BackgroundTab)
+        self.ImageFilenameWidget.setObjectName("ImageFilenameWidget")
+        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.ImageFilenameWidget)
+        self.horizontalLayout_2.setSpacing(0)
+        self.horizontalLayout_2.setMargin(0)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.ImageLineEdit = QtGui.QLineEdit(self.ImageFilenameWidget)
         self.ImageLineEdit.setObjectName("ImageLineEdit")
-        self.gridLayout.addWidget(self.ImageLineEdit, 4, 1, 1, 2)
-        self.ImagePushButton = QtGui.QPushButton(self.layoutWidget1)
+        self.horizontalLayout_2.addWidget(self.ImageLineEdit)
+        self.ImageToolButton = QtGui.QToolButton(self.ImageFilenameWidget)
         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, "")
+        icon1.addPixmap(QtGui.QPixmap(":/images/image_load.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.ImageToolButton.setIcon(icon1)
+        self.ImageToolButton.setObjectName("ImageToolButton")
+        self.horizontalLayout_2.addWidget(self.ImageToolButton)
+        self.BackgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.ImageFilenameWidget)
+        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        #self.BackgroundLayout.addItem(spacerItem, 7, 1, 1, 1)
+        self.ThemeTabWidget.addTab(self.BackgroundTab, "")
         self.FontMainTab = QtGui.QWidget()
         self.FontMainTab.setObjectName("FontMainTab")
-        self.MainFontGroupBox = QtGui.QGroupBox(self.FontMainTab)
-        self.MainFontGroupBox.setGeometry(QtCore.QRect(20, 10, 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.FontMainTab)
-        self.FooterFontGroupBox.setGeometry(QtCore.QRect(20, 160, 301, 190))
-        self.FooterFontGroupBox.setObjectName("FooterFontGroupBox")
-        self.verticalLayout = QtGui.QVBoxLayout(self.FooterFontGroupBox)
-        self.verticalLayout.setObjectName("verticalLayout")
-        self.FontMainUseDefault = QtGui.QCheckBox(self.FooterFontGroupBox)
-        self.FontMainUseDefault.setTristate(False)
-        self.FontMainUseDefault.setObjectName("FontMainUseDefault")
-        self.verticalLayout.addWidget(self.FontMainUseDefault)
-        self.horizontalLayout_3 = QtGui.QHBoxLayout()
-        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
-        self.FontMainXLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FontMainLayout = QtGui.QHBoxLayout(self.FontMainTab)
+        self.FontMainLayout.setSpacing(8)
+        self.FontMainLayout.setMargin(8)
+        self.FontMainLayout.setObjectName("FontMainLayout")
+        self.MainLeftWidget = QtGui.QWidget(self.FontMainTab)
+        self.MainLeftWidget.setObjectName("MainLeftWidget")
+        self.MainLeftLayout = QtGui.QVBoxLayout(self.MainLeftWidget)
+        self.MainLeftLayout.setSpacing(8)
+        self.MainLeftLayout.setMargin(0)
+        self.MainLeftLayout.setObjectName("MainLeftLayout")
+        self.FontMainGroupBox = QtGui.QGroupBox(self.MainLeftWidget)
+        self.FontMainGroupBox.setObjectName("FontMainGroupBox")
+        self.MainFontLayout = QtGui.QFormLayout(self.FontMainGroupBox)
+        self.MainFontLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
+        self.MainFontLayout.setMargin(8)
+        self.MainFontLayout.setSpacing(8)
+        self.MainFontLayout.setObjectName("MainFontLayout")
+        self.FontMainlabel = QtGui.QLabel(self.FontMainGroupBox)
+        self.FontMainlabel.setObjectName("FontMainlabel")
+        self.MainFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.FontMainlabel)
+        self.FontMainComboBox = QtGui.QFontComboBox(self.FontMainGroupBox)
+        self.FontMainComboBox.setObjectName("FontMainComboBox")
+        self.MainFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.FontMainComboBox)
+        self.FontMainColorLabel = QtGui.QLabel(self.FontMainGroupBox)
+        self.FontMainColorLabel.setObjectName("FontMainColorLabel")
+        self.MainFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.FontMainColorLabel)
+        self.FontMainColorPushButton = QtGui.QPushButton(self.FontMainGroupBox)
+        self.FontMainColorPushButton.setObjectName("FontMainColorPushButton")
+        self.MainFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontMainColorPushButton)
+        self.FontMainSize = QtGui.QLabel(self.FontMainGroupBox)
+        self.FontMainSize.setObjectName("FontMainSize")
+        self.MainFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontMainSize)
+        self.FontMainSizeSpinBox = QtGui.QSpinBox(self.FontMainGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontMainSizeSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontMainSizeSpinBox.setSizePolicy(sizePolicy)
+        self.FontMainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0))
+        self.FontMainSizeSpinBox.setProperty("value", QtCore.QVariant(16))
+        self.FontMainSizeSpinBox.setMaximum(999)
+        self.FontMainSizeSpinBox.setObjectName("FontMainSizeSpinBox")
+        self.MainFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.FontMainSizeSpinBox)
+        self.MainLeftLayout.addWidget(self.FontMainGroupBox)
+        spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.MainLeftLayout.addItem(spacerItem1)
+        self.FontMainLayout.addWidget(self.MainLeftWidget)
+        self.MainRightWidget = QtGui.QWidget(self.FontMainTab)
+        self.MainRightWidget.setObjectName("MainRightWidget")
+        self.MainRightLayout = QtGui.QVBoxLayout(self.MainRightWidget)
+        self.MainRightLayout.setSpacing(8)
+        self.MainRightLayout.setMargin(0)
+        self.MainRightLayout.setObjectName("MainRightLayout")
+        self.MainLocationGroupBox = QtGui.QGroupBox(self.MainRightWidget)
+        self.MainLocationGroupBox.setObjectName("MainLocationGroupBox")
+        self.MainLocationLayout = QtGui.QFormLayout(self.MainLocationGroupBox)
+        self.MainLocationLayout.setMargin(8)
+        self.MainLocationLayout.setSpacing(8)
+        self.MainLocationLayout.setObjectName("MainLocationLayout")
+        self.DefaultLocationLabel = QtGui.QLabel(self.MainLocationGroupBox)
+        self.DefaultLocationLabel.setObjectName("DefaultLocationLabel")
+        self.MainLocationLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.DefaultLocationLabel)
+        self.FontMainDefaultCheckBox = QtGui.QCheckBox(self.MainLocationGroupBox)
+        self.FontMainDefaultCheckBox.setTristate(False)
+        self.FontMainDefaultCheckBox.setObjectName("FontMainDefaultCheckBox")
+        self.MainLocationLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.FontMainDefaultCheckBox)
+        self.FontMainXLabel = QtGui.QLabel(self.MainLocationGroupBox)
         self.FontMainXLabel.setObjectName("FontMainXLabel")
-        self.horizontalLayout_3.addWidget(self.FontMainXLabel)
-        self.FontMainXEdit = QtGui.QLineEdit(self.FooterFontGroupBox)
-        self.FontMainXEdit.setObjectName("FontMainXEdit")
-        self.horizontalLayout_3.addWidget(self.FontMainXEdit)
-        self.verticalLayout.addLayout(self.horizontalLayout_3)
-        self.horizontalLayout_4 = QtGui.QHBoxLayout()
-        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
-        self.FontMainYLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.MainLocationLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.FontMainXLabel)
+        self.FontMainYLabel = QtGui.QLabel(self.MainLocationGroupBox)
         self.FontMainYLabel.setObjectName("FontMainYLabel")
-        self.horizontalLayout_4.addWidget(self.FontMainYLabel)
-        self.FontMainYEdit = QtGui.QLineEdit(self.FooterFontGroupBox)
-        self.FontMainYEdit.setObjectName("FontMainYEdit")
-        self.horizontalLayout_4.addWidget(self.FontMainYEdit)
-        self.verticalLayout.addLayout(self.horizontalLayout_4)
-        self.horizontalLayout_5 = QtGui.QHBoxLayout()
-        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
-        self.FontMainWidthLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.MainLocationLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontMainYLabel)
+        self.FontMainWidthLabel = QtGui.QLabel(self.MainLocationGroupBox)
         self.FontMainWidthLabel.setObjectName("FontMainWidthLabel")
-        self.horizontalLayout_5.addWidget(self.FontMainWidthLabel)
-        self.FontMainWidthEdit = QtGui.QLineEdit(self.FooterFontGroupBox)
-        self.FontMainWidthEdit.setObjectName("FontMainWidthEdit")
-        self.horizontalLayout_5.addWidget(self.FontMainWidthEdit)
-        self.verticalLayout.addLayout(self.horizontalLayout_5)
-        self.horizontalLayout_6 = QtGui.QHBoxLayout()
-        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
-        self.FontMainHeightLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.MainLocationLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.FontMainWidthLabel)
+        self.FontMainHeightLabel = QtGui.QLabel(self.MainLocationGroupBox)
         self.FontMainHeightLabel.setObjectName("FontMainHeightLabel")
-        self.horizontalLayout_6.addWidget(self.FontMainHeightLabel)
-        self.FontMainHeightEdit = QtGui.QLineEdit(self.FooterFontGroupBox)
-        self.FontMainHeightEdit.setObjectName("FontMainHeightEdit")
-        self.horizontalLayout_6.addWidget(self.FontMainHeightEdit)
-        self.verticalLayout.addLayout(self.horizontalLayout_6)
-        self.tabWidget.addTab(self.FontMainTab, "")
+        self.MainLocationLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.FontMainHeightLabel)
+        self.FontMainXSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontMainXSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontMainXSpinBox.setSizePolicy(sizePolicy)
+        self.FontMainXSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontMainXSpinBox.setProperty("value", QtCore.QVariant(0))
+        self.FontMainXSpinBox.setMaximum(9999)
+        self.FontMainXSpinBox.setObjectName("FontMainXSpinBox")
+        self.MainLocationLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontMainXSpinBox)
+        self.FontMainYSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontMainYSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontMainYSpinBox.setSizePolicy(sizePolicy)
+        self.FontMainYSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontMainYSpinBox.setMaximum(9999)
+        self.FontMainYSpinBox.setObjectName("FontMainYSpinBox")
+        self.MainLocationLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.FontMainYSpinBox)
+        self.FontMainWidthSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontMainWidthSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontMainWidthSpinBox.setSizePolicy(sizePolicy)
+        self.FontMainWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontMainWidthSpinBox.setMaximum(9999)
+        self.FontMainWidthSpinBox.setObjectName("FontMainWidthSpinBox")
+        self.MainLocationLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.FontMainWidthSpinBox)
+        self.FontMainHeightSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontMainHeightSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontMainHeightSpinBox.setSizePolicy(sizePolicy)
+        self.FontMainHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontMainHeightSpinBox.setMaximum(9999)
+        self.FontMainHeightSpinBox.setObjectName("FontMainHeightSpinBox")
+        self.MainLocationLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.FontMainHeightSpinBox)
+        self.MainRightLayout.addWidget(self.MainLocationGroupBox)
+        spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.MainRightLayout.addItem(spacerItem2)
+        self.FontMainLayout.addWidget(self.MainRightWidget)
+        self.ThemeTabWidget.addTab(self.FontMainTab, "")
         self.FontFooterTab = QtGui.QWidget()
         self.FontFooterTab.setObjectName("FontFooterTab")
-        self.FooterFontGroupBox_2 = QtGui.QGroupBox(self.FontFooterTab)
-        self.FooterFontGroupBox_2.setGeometry(QtCore.QRect(20, 160, 301, 190))
-        self.FooterFontGroupBox_2.setObjectName("FooterFontGroupBox_2")
-        self.verticalLayout_2 = QtGui.QVBoxLayout(self.FooterFontGroupBox_2)
-        self.verticalLayout_2.setObjectName("verticalLayout_2")
-        self.FontMainUseDefault_2 = QtGui.QCheckBox(self.FooterFontGroupBox_2)
-        self.FontMainUseDefault_2.setTristate(False)
-        self.FontMainUseDefault_2.setObjectName("FontMainUseDefault_2")
-        self.verticalLayout_2.addWidget(self.FontMainUseDefault_2)
-        self.horizontalLayout_7 = QtGui.QHBoxLayout()
-        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
-        self.FontFooterXLabel = QtGui.QLabel(self.FooterFontGroupBox_2)
+        self.FontFooterLayout = QtGui.QHBoxLayout(self.FontFooterTab)
+        self.FontFooterLayout.setSpacing(8)
+        self.FontFooterLayout.setMargin(8)
+        self.FontFooterLayout.setObjectName("FontFooterLayout")
+        self.FooterLeftWidget = QtGui.QWidget(self.FontFooterTab)
+        self.FooterLeftWidget.setObjectName("FooterLeftWidget")
+        self.FooterLeftLayout = QtGui.QVBoxLayout(self.FooterLeftWidget)
+        self.FooterLeftLayout.setSpacing(8)
+        self.FooterLeftLayout.setMargin(0)
+        self.FooterLeftLayout.setObjectName("FooterLeftLayout")
+        self.FooterFontGroupBox = QtGui.QGroupBox(self.FooterLeftWidget)
+        self.FooterFontGroupBox.setObjectName("FooterFontGroupBox")
+        self.FooterFontLayout = QtGui.QFormLayout(self.FooterFontGroupBox)
+        self.FooterFontLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
+        self.FooterFontLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
+        self.FooterFontLayout.setMargin(8)
+        self.FooterFontLayout.setSpacing(8)
+        self.FooterFontLayout.setObjectName("FooterFontLayout")
+        self.FontFooterLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FontFooterLabel.setObjectName("FontFooterLabel")
+        self.FooterFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.FontFooterLabel)
+        self.FontFooterComboBox = QtGui.QFontComboBox(self.FooterFontGroupBox)
+        self.FontFooterComboBox.setObjectName("FontFooterComboBox")
+        self.FooterFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.FontFooterComboBox)
+        self.FontFooterColorLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FontFooterColorLabel.setObjectName("FontFooterColorLabel")
+        self.FooterFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.FontFooterColorLabel)
+        self.FontFooterColorPushButton = QtGui.QPushButton(self.FooterFontGroupBox)
+        self.FontFooterColorPushButton.setObjectName("FontFooterColorPushButton")
+        self.FooterFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontFooterColorPushButton)
+        self.FontFooterSizeLabel = QtGui.QLabel(self.FooterFontGroupBox)
+        self.FontFooterSizeLabel.setObjectName("FontFooterSizeLabel")
+        self.FooterFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontFooterSizeLabel)
+        self.FontFooterSizeSpinBox = QtGui.QSpinBox(self.FooterFontGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontFooterSizeSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontFooterSizeSpinBox.setSizePolicy(sizePolicy)
+        self.FontFooterSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0))
+        self.FontFooterSizeSpinBox.setProperty("value", QtCore.QVariant(10))
+        self.FontFooterSizeSpinBox.setMaximum(999)
+        self.FontFooterSizeSpinBox.setObjectName("FontFooterSizeSpinBox")
+        self.FooterFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.FontFooterSizeSpinBox)
+        self.FooterLeftLayout.addWidget(self.FooterFontGroupBox)
+        spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.FooterLeftLayout.addItem(spacerItem3)
+        self.FontFooterLayout.addWidget(self.FooterLeftWidget)
+        self.FooterRightWidget = QtGui.QWidget(self.FontFooterTab)
+        self.FooterRightWidget.setObjectName("FooterRightWidget")
+        self.FooterRightLayout = QtGui.QVBoxLayout(self.FooterRightWidget)
+        self.FooterRightLayout.setSpacing(8)
+        self.FooterRightLayout.setMargin(0)
+        self.FooterRightLayout.setObjectName("FooterRightLayout")
+        self.LocationFooterGroupBox = QtGui.QGroupBox(self.FooterRightWidget)
+        self.LocationFooterGroupBox.setObjectName("LocationFooterGroupBox")
+        self.LocationFooterLayout = QtGui.QFormLayout(self.LocationFooterGroupBox)
+        self.LocationFooterLayout.setFieldGrowthPolicy(QtGui.QFormLayout.ExpandingFieldsGrow)
+        self.LocationFooterLayout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
+        self.LocationFooterLayout.setMargin(8)
+        self.LocationFooterLayout.setSpacing(8)
+        self.LocationFooterLayout.setObjectName("LocationFooterLayout")
+        self.FontFooterDefaultLabel = QtGui.QLabel(self.LocationFooterGroupBox)
+        self.FontFooterDefaultLabel.setObjectName("FontFooterDefaultLabel")
+        self.LocationFooterLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.FontFooterDefaultLabel)
+        self.FontFooterDefaultCheckBox = QtGui.QCheckBox(self.LocationFooterGroupBox)
+        self.FontFooterDefaultCheckBox.setTristate(False)
+        self.FontFooterDefaultCheckBox.setObjectName("FontFooterDefaultCheckBox")
+        self.LocationFooterLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.FontFooterDefaultCheckBox)
+        self.FontFooterXLabel = QtGui.QLabel(self.LocationFooterGroupBox)
         self.FontFooterXLabel.setObjectName("FontFooterXLabel")
-        self.horizontalLayout_7.addWidget(self.FontFooterXLabel)
-        self.FontFooterXEdit = QtGui.QLineEdit(self.FooterFontGroupBox_2)
-        self.FontFooterXEdit.setObjectName("FontFooterXEdit")
-        self.horizontalLayout_7.addWidget(self.FontFooterXEdit)
-        self.verticalLayout_2.addLayout(self.horizontalLayout_7)
-        self.horizontalLayout_8 = QtGui.QHBoxLayout()
-        self.horizontalLayout_8.setObjectName("horizontalLayout_8")
-        self.FontFooterYLabel = QtGui.QLabel(self.FooterFontGroupBox_2)
+        self.LocationFooterLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.FontFooterXLabel)
+        self.FontFooterYLabel = QtGui.QLabel(self.LocationFooterGroupBox)
         self.FontFooterYLabel.setObjectName("FontFooterYLabel")
-        self.horizontalLayout_8.addWidget(self.FontFooterYLabel)
-        self.FontFooterYEdit = QtGui.QLineEdit(self.FooterFontGroupBox_2)
-        self.FontFooterYEdit.setObjectName("FontFooterYEdit")
-        self.horizontalLayout_8.addWidget(self.FontFooterYEdit)
-        self.verticalLayout_2.addLayout(self.horizontalLayout_8)
-        self.horizontalLayout_9 = QtGui.QHBoxLayout()
-        self.horizontalLayout_9.setObjectName("horizontalLayout_9")
-        self.FontFooterWidthLabel = QtGui.QLabel(self.FooterFontGroupBox_2)
+        self.LocationFooterLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontFooterYLabel)
+        self.FontFooterWidthLabel = QtGui.QLabel(self.LocationFooterGroupBox)
         self.FontFooterWidthLabel.setObjectName("FontFooterWidthLabel")
-        self.horizontalLayout_9.addWidget(self.FontFooterWidthLabel)
-        self.FontFooterWidthEdit = QtGui.QLineEdit(self.FooterFontGroupBox_2)
-        self.FontFooterWidthEdit.setObjectName("FontFooterWidthEdit")
-        self.horizontalLayout_9.addWidget(self.FontFooterWidthEdit)
-        self.verticalLayout_2.addLayout(self.horizontalLayout_9)
-        self.horizontalLayout_10 = QtGui.QHBoxLayout()
-        self.horizontalLayout_10.setObjectName("horizontalLayout_10")
-        self.FontFooterHeightLabel = QtGui.QLabel(self.FooterFontGroupBox_2)
+        self.LocationFooterLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.FontFooterWidthLabel)
+        self.FontFooterHeightLabel = QtGui.QLabel(self.LocationFooterGroupBox)
         self.FontFooterHeightLabel.setObjectName("FontFooterHeightLabel")
-        self.horizontalLayout_10.addWidget(self.FontFooterHeightLabel)
-        self.FontFooterHeightEdit = QtGui.QLineEdit(self.FooterFontGroupBox_2)
-        self.FontFooterHeightEdit.setObjectName("FontFooterHeightEdit")
-        self.horizontalLayout_10.addWidget(self.FontFooterHeightEdit)
-        self.verticalLayout_2.addLayout(self.horizontalLayout_10)
-        self.FooterFontGroupBox_3 = QtGui.QGroupBox(self.FontFooterTab)
-        self.FooterFontGroupBox_3.setGeometry(QtCore.QRect(20, 10, 307, 119))
-        self.FooterFontGroupBox_3.setObjectName("FooterFontGroupBox_3")
-        self.gridLayout_3 = QtGui.QGridLayout(self.FooterFontGroupBox_3)
-        self.gridLayout_3.setObjectName("gridLayout_3")
-        self.FontFooterlabel = QtGui.QLabel(self.FooterFontGroupBox_3)
-        self.FontFooterlabel.setObjectName("FontFooterlabel")
-        self.gridLayout_3.addWidget(self.FontFooterlabel, 0, 0, 1, 1)
-        self.FontFooterComboBox = QtGui.QFontComboBox(self.FooterFontGroupBox_3)
-        self.FontFooterComboBox.setObjectName("FontFooterComboBox")
-        self.gridLayout_3.addWidget(self.FontFooterComboBox, 0, 1, 1, 2)
-        self.FontFooterColorLabel = QtGui.QLabel(self.FooterFontGroupBox_3)
-        self.FontFooterColorLabel.setObjectName("FontFooterColorLabel")
-        self.gridLayout_3.addWidget(self.FontFooterColorLabel, 1, 0, 1, 1)
-        self.FontFooterColorPushButton = QtGui.QPushButton(self.FooterFontGroupBox_3)
-        self.FontFooterColorPushButton.setObjectName("FontFooterColorPushButton")
-        self.gridLayout_3.addWidget(self.FontFooterColorPushButton, 1, 2, 1, 1)
-        self.FontFooterSizeLabel = QtGui.QLabel(self.FooterFontGroupBox_3)
-        self.FontFooterSizeLabel.setObjectName("FontFooterSizeLabel")
-        self.gridLayout_3.addWidget(self.FontFooterSizeLabel, 2, 0, 1, 1)
-        self.FontFooterSizeLineEdit = QtGui.QLineEdit(self.FooterFontGroupBox_3)
-        self.FontFooterSizeLineEdit.setObjectName("FontFooterSizeLineEdit")
-        self.gridLayout_3.addWidget(self.FontFooterSizeLineEdit, 2, 1, 1, 1)
-        self.FontFooterSlider = QtGui.QSlider(self.FooterFontGroupBox_3)
-        self.FontFooterSlider.setProperty("value", QtCore.QVariant(15))
-        self.FontFooterSlider.setMaximum(40)
-        self.FontFooterSlider.setOrientation(QtCore.Qt.Horizontal)
-        self.FontFooterSlider.setTickPosition(QtGui.QSlider.TicksBelow)
-        self.FontFooterSlider.setTickInterval(5)
-        self.FontFooterSlider.setObjectName("FontFooterSlider")
-        self.gridLayout_3.addWidget(self.FontFooterSlider, 2, 2, 1, 1)
-        self.tabWidget.addTab(self.FontFooterTab, "")
-        self.OptionsTab = QtGui.QWidget()
-        self.OptionsTab.setObjectName("OptionsTab")
-        self.ShadowGroupBox = QtGui.QGroupBox(self.OptionsTab)
-        self.ShadowGroupBox.setGeometry(QtCore.QRect(20, 10, 301, 80))
+        self.LocationFooterLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.FontFooterHeightLabel)
+        self.FontFooterXSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontFooterXSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontFooterXSpinBox.setSizePolicy(sizePolicy)
+        self.FontFooterXSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontFooterXSpinBox.setProperty("value", QtCore.QVariant(0))
+        self.FontFooterXSpinBox.setMaximum(9999)
+        self.FontFooterXSpinBox.setObjectName("FontFooterXSpinBox")
+        self.LocationFooterLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontFooterXSpinBox)
+        self.FontFooterYSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.FontFooterYSpinBox.sizePolicy().hasHeightForWidth())
+        self.FontFooterYSpinBox.setSizePolicy(sizePolicy)
+        self.FontFooterYSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontFooterYSpinBox.setProperty("value", QtCore.QVariant(0))
+        self.FontFooterYSpinBox.setMaximum(9999)
+        self.FontFooterYSpinBox.setObjectName("FontFooterYSpinBox")
+        self.LocationFooterLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.FontFooterYSpinBox)
+        self.FontFooterWidthSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox)
+        self.FontFooterWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontFooterWidthSpinBox.setMaximum(9999)
+        self.FontFooterWidthSpinBox.setObjectName("FontFooterWidthSpinBox")
+        self.LocationFooterLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.FontFooterWidthSpinBox)
+        self.FontFooterHeightSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox)
+        self.FontFooterHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0))
+        self.FontFooterHeightSpinBox.setMaximum(9999)
+        self.FontFooterHeightSpinBox.setObjectName("FontFooterHeightSpinBox")
+        self.LocationFooterLayout.setWidget(4, QtGui.QFormLayout.FieldRole, self.FontFooterHeightSpinBox)
+        self.FooterRightLayout.addWidget(self.LocationFooterGroupBox)
+        spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.FooterRightLayout.addItem(spacerItem4)
+        self.FontFooterLayout.addWidget(self.FooterRightWidget)
+        self.ThemeTabWidget.addTab(self.FontFooterTab, "")
+        self.OtherOptionsTab = QtGui.QWidget()
+        self.OtherOptionsTab.setObjectName("OtherOptionsTab")
+        self.OtherOptionsLayout = QtGui.QHBoxLayout(self.OtherOptionsTab)
+        self.OtherOptionsLayout.setSpacing(8)
+        self.OtherOptionsLayout.setMargin(8)
+        self.OtherOptionsLayout.setObjectName("OtherOptionsLayout")
+        self.OptionsLeftWidget = QtGui.QWidget(self.OtherOptionsTab)
+        self.OptionsLeftWidget.setObjectName("OptionsLeftWidget")
+        self.OptionsLeftLayout = QtGui.QVBoxLayout(self.OptionsLeftWidget)
+        self.OptionsLeftLayout.setSpacing(8)
+        self.OptionsLeftLayout.setMargin(0)
+        self.OptionsLeftLayout.setObjectName("OptionsLeftLayout")
+        self.ShadowGroupBox = QtGui.QGroupBox(self.OptionsLeftWidget)
         self.ShadowGroupBox.setObjectName("ShadowGroupBox")
-        self.layoutWidget2 = QtGui.QWidget(self.ShadowGroupBox)
-        self.layoutWidget2.setGeometry(QtCore.QRect(10, 20, 281, 58))
-        self.layoutWidget2.setObjectName("layoutWidget2")
-        self.formLayout = QtGui.QFormLayout(self.layoutWidget2)
-        self.formLayout.setObjectName("formLayout")
-        self.ShadowCheckBox = QtGui.QCheckBox(self.layoutWidget2)
+        self.verticalLayout = QtGui.QVBoxLayout(self.ShadowGroupBox)
+        self.verticalLayout.setSpacing(8)
+        self.verticalLayout.setMargin(8)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.OutlineWidget = QtGui.QWidget(self.ShadowGroupBox)
+        self.OutlineWidget.setObjectName("OutlineWidget")
+        self.OutlineLayout = QtGui.QFormLayout(self.OutlineWidget)
+        self.OutlineLayout.setMargin(0)
+        self.OutlineLayout.setSpacing(8)
+        self.OutlineLayout.setObjectName("OutlineLayout")
+        self.OutlineCheckBox = QtGui.QCheckBox(self.OutlineWidget)
+        self.OutlineCheckBox.setObjectName("OutlineCheckBox")
+        self.OutlineLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.OutlineCheckBox)
+        self.OutlineColorLabel = QtGui.QLabel(self.OutlineWidget)
+        self.OutlineColorLabel.setObjectName("OutlineColorLabel")
+        self.OutlineLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.OutlineColorLabel)
+        self.OutlineColorPushButton = QtGui.QPushButton(self.OutlineWidget)
+        self.OutlineColorPushButton.setObjectName("OutlineColorPushButton")
+        self.OutlineLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.OutlineColorPushButton)
+        self.OutlineEnabledLabel = QtGui.QLabel(self.OutlineWidget)
+        self.OutlineEnabledLabel.setObjectName("OutlineEnabledLabel")
+        self.OutlineLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.OutlineEnabledLabel)
+        self.verticalLayout.addWidget(self.OutlineWidget)
+        self.ShadowWidget = QtGui.QWidget(self.ShadowGroupBox)
+        self.ShadowWidget.setObjectName("ShadowWidget")
+        self.ShadowLayout = QtGui.QFormLayout(self.ShadowWidget)
+        self.ShadowLayout.setMargin(0)
+        self.ShadowLayout.setSpacing(8)
+        self.ShadowLayout.setObjectName("ShadowLayout")
+        self.ShadowCheckBox = QtGui.QCheckBox(self.ShadowWidget)
         self.ShadowCheckBox.setObjectName("ShadowCheckBox")
-        self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.ShadowCheckBox)
-        self.ShadowColorLabel = QtGui.QLabel(self.layoutWidget2)
+        self.ShadowLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.ShadowCheckBox)
+        self.ShadowColorLabel = QtGui.QLabel(self.ShadowWidget)
         self.ShadowColorLabel.setObjectName("ShadowColorLabel")
-        self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.ShadowColorLabel)
-        self.ShadowColorPushButton = QtGui.QPushButton(self.layoutWidget2)
+        self.ShadowLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.ShadowColorLabel)
+        self.ShadowColorPushButton = QtGui.QPushButton(self.ShadowWidget)
         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.ShadowLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.ShadowColorPushButton)
+        self.ShadowEnabledLabel = QtGui.QLabel(self.ShadowWidget)
+        self.ShadowEnabledLabel.setObjectName("ShadowEnabledLabel")
+        self.ShadowLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.ShadowEnabledLabel)
+        self.verticalLayout.addWidget(self.ShadowWidget)
+        self.OptionsLeftLayout.addWidget(self.ShadowGroupBox)
+        spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.OptionsLeftLayout.addItem(spacerItem5)
+        self.OtherOptionsLayout.addWidget(self.OptionsLeftWidget)
+        self.OptionsRightWidget = QtGui.QWidget(self.OtherOptionsTab)
+        self.OptionsRightWidget.setObjectName("OptionsRightWidget")
+        self.OptionsRightLayout = QtGui.QVBoxLayout(self.OptionsRightWidget)
+        self.OptionsRightLayout.setSpacing(8)
+        self.OptionsRightLayout.setMargin(0)
+        self.OptionsRightLayout.setObjectName("OptionsRightLayout")
+        self.AlignmentGroupBox = QtGui.QGroupBox(self.OptionsRightWidget)
         self.AlignmentGroupBox.setObjectName("AlignmentGroupBox")
         self.gridLayout_4 = QtGui.QGridLayout(self.AlignmentGroupBox)
         self.gridLayout_4.setObjectName("gridLayout_4")
@@ -299,43 +443,82 @@
         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, 58))
-        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.widget)
-        self.RightSide.setObjectName("RightSide")
-        self.ThemePreview = QtGui.QLabel(self.RightSide)
-        self.ThemePreview.setGeometry(QtCore.QRect(20, 60, 311, 271))
-        self.ThemePreview.setFrameShape(QtGui.QFrame.Box)
-        self.ThemePreview.setFrameShadow(QtGui.QFrame.Raised)
-        self.ThemePreview.setLineWidth(2)
+        self.OptionsRightLayout.addWidget(self.AlignmentGroupBox)
+        spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
+        self.OptionsRightLayout.addItem(spacerItem6)
+        self.OtherOptionsLayout.addWidget(self.OptionsRightWidget)
+        self.ThemeTabWidget.addTab(self.OtherOptionsTab, "")
+        self.ContentLayout.addWidget(self.ThemeTabWidget)
+        self.AmendThemeLayout.addWidget(self.ContentWidget)
+        self.PreviewGroupBox = QtGui.QGroupBox(AmendThemeDialog)
+        self.PreviewGroupBox.setObjectName("PreviewGroupBox")
+        self.ThemePreviewLayout = QtGui.QHBoxLayout(self.PreviewGroupBox)
+        self.ThemePreviewLayout.setSpacing(8)
+        self.ThemePreviewLayout.setMargin(8)
+        self.ThemePreviewLayout.setObjectName("ThemePreviewLayout")
+        spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+        self.ThemePreviewLayout.addItem(spacerItem7)
+        self.ThemePreview = QtGui.QLabel(self.PreviewGroupBox)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.ThemePreview.sizePolicy().hasHeightForWidth())
+        self.ThemePreview.setSizePolicy(sizePolicy)
+        self.ThemePreview.setMinimumSize(QtCore.QSize(300, 225))
+        self.ThemePreview.setFrameShape(QtGui.QFrame.WinPanel)
+        self.ThemePreview.setFrameShadow(QtGui.QFrame.Sunken)
+        self.ThemePreview.setLineWidth(1)
         self.ThemePreview.setScaledContents(True)
         self.ThemePreview.setObjectName("ThemePreview")
-        self.horizontalLayout_2.addWidget(self.RightSide)
+        self.ThemePreviewLayout.addWidget(self.ThemePreview)
+        spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+        self.ThemePreviewLayout.addItem(spacerItem8)
+        self.AmendThemeLayout.addWidget(self.PreviewGroupBox)
+        self.ThemeButtonBox = QtGui.QDialogButtonBox(AmendThemeDialog)
+        self.ThemeButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
+        self.ThemeButtonBox.setObjectName("ThemeButtonBox")
+        self.AmendThemeLayout.addWidget(self.ThemeButtonBox)
 
         self.retranslateUi(AmendThemeDialog)
-        self.tabWidget.setCurrentIndex(0)
+        self.ThemeTabWidget.setCurrentIndex(0)
+        QtCore.QObject.connect(self.ThemeButtonBox, QtCore.SIGNAL("accepted()"), AmendThemeDialog.accept)
+        QtCore.QObject.connect(self.ThemeButtonBox, QtCore.SIGNAL("rejected()"), AmendThemeDialog.reject)
         QtCore.QMetaObject.connectSlotsByName(AmendThemeDialog)
+        AmendThemeDialog.setTabOrder(self.ThemeButtonBox, self.ThemeNameEdit)
+        AmendThemeDialog.setTabOrder(self.ThemeNameEdit, self.ThemeTabWidget)
+        AmendThemeDialog.setTabOrder(self.ThemeTabWidget, self.BackgroundComboBox)
+        AmendThemeDialog.setTabOrder(self.BackgroundComboBox, self.BackgroundTypeComboBox)
+        AmendThemeDialog.setTabOrder(self.BackgroundTypeComboBox, self.Color1PushButton)
+        AmendThemeDialog.setTabOrder(self.Color1PushButton, self.Color2PushButton)
+        AmendThemeDialog.setTabOrder(self.Color2PushButton, self.ImageLineEdit)
+        AmendThemeDialog.setTabOrder(self.ImageLineEdit, self.ImageToolButton)
+        AmendThemeDialog.setTabOrder(self.ImageToolButton, self.GradientComboBox)
+        AmendThemeDialog.setTabOrder(self.GradientComboBox, self.FontMainComboBox)
+        AmendThemeDialog.setTabOrder(self.FontMainComboBox, self.FontMainColorPushButton)
+        AmendThemeDialog.setTabOrder(self.FontMainColorPushButton, self.FontMainSizeSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontMainSizeSpinBox, self.FontMainDefaultCheckBox)
+        AmendThemeDialog.setTabOrder(self.FontMainDefaultCheckBox, self.FontMainXSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontMainXSpinBox, self.FontMainYSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontMainYSpinBox, self.FontMainWidthSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontMainWidthSpinBox, self.FontMainHeightSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontMainHeightSpinBox, self.FontFooterComboBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterComboBox, self.FontFooterColorPushButton)
+        AmendThemeDialog.setTabOrder(self.FontFooterColorPushButton, self.FontFooterSizeSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterSizeSpinBox, self.FontFooterDefaultCheckBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterDefaultCheckBox, self.FontFooterXSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterXSpinBox, self.FontFooterYSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterYSpinBox, self.FontFooterWidthSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterWidthSpinBox, self.FontFooterHeightSpinBox)
+        AmendThemeDialog.setTabOrder(self.FontFooterHeightSpinBox, self.OutlineCheckBox)
+        AmendThemeDialog.setTabOrder(self.OutlineCheckBox, self.OutlineColorPushButton)
+        AmendThemeDialog.setTabOrder(self.OutlineColorPushButton, self.ShadowCheckBox)
+        AmendThemeDialog.setTabOrder(self.ShadowCheckBox, self.ShadowColorPushButton)
+        AmendThemeDialog.setTabOrder(self.ShadowColorPushButton, self.HorizontalComboBox)
+        AmendThemeDialog.setTabOrder(self.HorizontalComboBox, self.VerticalComboBox)
 
     def retranslateUi(self, AmendThemeDialog):
         AmendThemeDialog.setWindowTitle(QtGui.QApplication.translate("AmendThemeDialog", "Theme Maintance", None, QtGui.QApplication.UnicodeUTF8))
-        self.ThemeNameLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Theme Name", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeNameLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Theme Name:", 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))
@@ -350,32 +533,44 @@
         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", "Display Location", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontMainUseDefault.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use default location", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeTabWidget.setTabText(self.ThemeTabWidget.indexOf(self.BackgroundTab), QtGui.QApplication.translate("AmendThemeDialog", "Background", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Main Font", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainlabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainSize.setText(QtGui.QApplication.translate("AmendThemeDialog", "Size:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainSizeSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "pt", None, QtGui.QApplication.UnicodeUTF8))
+        self.MainLocationGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Display Location", None, QtGui.QApplication.UnicodeUTF8))
+        self.DefaultLocationLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use Default Location:", None, QtGui.QApplication.UnicodeUTF8))
         self.FontMainXLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "X Position:", None, QtGui.QApplication.UnicodeUTF8))
         self.FontMainYLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Y Position:", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontMainWidthLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Width", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontMainHeightLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Height", None, QtGui.QApplication.UnicodeUTF8))
-        self.tabWidget.setTabText(self.tabWidget.indexOf(self.FontMainTab), QtGui.QApplication.translate("AmendThemeDialog", "Font Main", None, QtGui.QApplication.UnicodeUTF8))
-        self.FooterFontGroupBox_2.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Display Location", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontMainUseDefault_2.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use default location", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainWidthLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Width:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainHeightLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Height:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainXSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainYSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainWidthSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontMainHeightSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeTabWidget.setTabText(self.ThemeTabWidget.indexOf(self.FontMainTab), QtGui.QApplication.translate("AmendThemeDialog", "Font Main", None, QtGui.QApplication.UnicodeUTF8))
+        self.FooterFontGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Footer Font", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterSizeLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Size:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterSizeSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "pt", None, QtGui.QApplication.UnicodeUTF8))
+        self.LocationFooterGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Display Location", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterDefaultLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Use Default Location:", None, QtGui.QApplication.UnicodeUTF8))
         self.FontFooterXLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "X Position:", None, QtGui.QApplication.UnicodeUTF8))
         self.FontFooterYLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Y Position:", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontFooterWidthLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Width", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontFooterHeightLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Height", None, QtGui.QApplication.UnicodeUTF8))
-        self.FooterFontGroupBox_3.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Footer Font", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontFooterlabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font:", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontFooterColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Font Color", None, QtGui.QApplication.UnicodeUTF8))
-        self.FontFooterSizeLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Size:", None, QtGui.QApplication.UnicodeUTF8))
-        self.tabWidget.setTabText(self.tabWidget.indexOf(self.FontFooterTab), QtGui.QApplication.translate("AmendThemeDialog", "Font Footer", 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.FontFooterWidthLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Width:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterHeightLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Height:", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterXSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterYSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterWidthSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.FontFooterHeightSpinBox.setSuffix(QtGui.QApplication.translate("AmendThemeDialog", "px", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeTabWidget.setTabText(self.ThemeTabWidget.indexOf(self.FontFooterTab), QtGui.QApplication.translate("AmendThemeDialog", "Font Footer", None, QtGui.QApplication.UnicodeUTF8))
+        self.ShadowGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Shadow && Outline", None, QtGui.QApplication.UnicodeUTF8))
+        self.OutlineColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Outline Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.OutlineEnabledLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Show Outline:", None, QtGui.QApplication.UnicodeUTF8))
         self.ShadowColorLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Shadow Color:", None, QtGui.QApplication.UnicodeUTF8))
+        self.ShadowEnabledLabel.setText(QtGui.QApplication.translate("AmendThemeDialog", "Show Shadow:", 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))
@@ -385,8 +580,6 @@
         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", "Alignment", None, QtGui.QApplication.UnicodeUTF8))
+        self.ThemeTabWidget.setTabText(self.ThemeTabWidget.indexOf(self.OtherOptionsTab), QtGui.QApplication.translate("AmendThemeDialog", "Other Options", None, QtGui.QApplication.UnicodeUTF8))
+        self.PreviewGroupBox.setTitle(QtGui.QApplication.translate("AmendThemeDialog", "Preview", None, QtGui.QApplication.UnicodeUTF8))
 

=== modified file 'openlp/core/ui/amendthemeform.py'
--- openlp/core/ui/amendthemeform.py	2009-04-11 15:16:02 +0000
+++ openlp/core/ui/amendthemeform.py	2009-04-23 18:12:36 +0000
@@ -23,8 +23,8 @@
 from PyQt4 import QtCore, QtGui
 from PyQt4.QtGui import QColor, QFont
 from openlp.core.lib import ThemeXML
+from openlp.core.lib import Renderer
 from openlp.core import fileToXML
-from openlp.core import Renderer
 from openlp.core import translate
 
 from amendthemedialog import Ui_AmendThemeDialog
@@ -33,23 +33,27 @@
 
 class AmendThemeForm(QtGui.QDialog,  Ui_AmendThemeDialog):
 
-    def __init__(self, parent=None):
+    def __init__(self, thememanager, parent=None):
         QtGui.QDialog.__init__(self, parent)
+        self.thememanager = thememanager
+        self.theme = ThemeXML() # Needed here as UI setup generates Events
         self.setupUi(self)
 
         #define signals
-        #Exits
-        QtCore.QObject.connect(self.ThemeButtonBox, QtCore.SIGNAL("accepted()"), self.accept)
-        QtCore.QObject.connect(self.ThemeButtonBox, QtCore.SIGNAL("rejected()"), self.close)
         #Buttons
         QtCore.QObject.connect(self.Color1PushButton ,
             QtCore.SIGNAL("pressed()"), self.onColor1PushButtonClicked)
         QtCore.QObject.connect(self.Color2PushButton ,
             QtCore.SIGNAL("pressed()"), self.onColor2PushButtonClicked)
-        QtCore.QObject.connect(self.MainFontColorPushButton,
-            QtCore.SIGNAL("pressed()"), self.onMainFontColorPushButtonClicked)
+        QtCore.QObject.connect(self.FontMainColorPushButton,
+            QtCore.SIGNAL("pressed()"), self.onFontMainColorPushButtonClicked)
         QtCore.QObject.connect(self.FontFooterColorPushButton,
             QtCore.SIGNAL("pressed()"), self.onFontFooterColorPushButtonClicked)
+        QtCore.QObject.connect(self.OutlineColorPushButton,
+            QtCore.SIGNAL("pressed()"), self.onOutlineColorPushButtonClicked)
+        QtCore.QObject.connect(self.ShadowColorPushButton,
+            QtCore.SIGNAL("pressed()"), self.onShadowColorPushButtonClicked)
+
         #Combo boxes
         QtCore.QObject.connect(self.BackgroundComboBox,
             QtCore.SIGNAL("activated(int)"), self.onBackgroundComboBoxSelected)
@@ -57,16 +61,69 @@
             QtCore.SIGNAL("activated(int)"), self.onBackgroundTypeComboBoxSelected)
         QtCore.QObject.connect(self.GradientComboBox,
             QtCore.SIGNAL("activated(int)"), self.onGradientComboBoxSelected)
+        QtCore.QObject.connect(self.FontMainComboBox,
+            QtCore.SIGNAL("activated(int)"), self.onFontMainComboBoxSelected)
+        QtCore.QObject.connect(self.FontFooterComboBox,
+            QtCore.SIGNAL("activated(int)"), self.onFontFooterComboBoxSelected)
+        QtCore.QObject.connect(self.HorizontalComboBox,
+            QtCore.SIGNAL("activated(int)"), self.onHorizontalComboBoxSelected)
+        QtCore.QObject.connect(self.VerticalComboBox,
+            QtCore.SIGNAL("activated(int)"), self.onVerticalComboBoxSelected)
+
+        QtCore.QObject.connect(self.FontMainSizeSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontMainSizeSpinBoxChanged)
+        QtCore.QObject.connect(self.FontFooterSizeSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontFooterSizeSpinBoxChanged)
+        QtCore.QObject.connect(self.FontMainDefaultCheckBox,
+            QtCore.SIGNAL("stateChanged(int)"), self.onFontMainDefaultCheckBoxChanged)
+        QtCore.QObject.connect(self.FontMainXSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontMainXSpinBoxChanged)
+        QtCore.QObject.connect(self.FontMainYSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontMainYSpinBoxChanged)
+        QtCore.QObject.connect(self.FontMainWidthSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontMainWidthSpinBoxChanged)
+        QtCore.QObject.connect(self.FontMainHeightSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontMainHeightSpinBoxChanged)
+        QtCore.QObject.connect(self.FontFooterDefaultCheckBox,
+            QtCore.SIGNAL("stateChanged(int)"), self.onFontFooterDefaultCheckBoxChanged)
+        QtCore.QObject.connect(self.FontFooterXSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontFooterXSpinBoxChanged)
+        QtCore.QObject.connect(self.FontFooterYSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontFooterYSpinBoxChanged)
+        QtCore.QObject.connect(self.FontFooterWidthSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontFooterWidthSpinBoxChanged)
+        QtCore.QObject.connect(self.FontFooterHeightSpinBox,
+            QtCore.SIGNAL("valueChanged(int)"), self.onFontFooterHeightSpinBoxChanged)
+        QtCore.QObject.connect(self.OutlineCheckBox,
+            QtCore.SIGNAL("stateChanged(int)"), self.onOutlineCheckBoxChanged)
+        QtCore.QObject.connect(self.ShadowCheckBox,
+            QtCore.SIGNAL("stateChanged(int)"), self.onShadowCheckBoxChanged)
 
 
     def accept(self):
+        new_theme = ThemeXML()
+        theme_name = str(self.ThemeNameEdit.displayText())
+        new_theme.new_document(theme_name)
+        if self.theme.background_type == u'solid':
+            new_theme.add_background_solid(str(self.theme.background_color))
+        elif self.theme.theme.background_type == u'gradient':
+            new_theme.add_background_gradient(str(self.theme.background_startColor), str(self.theme.background_endColor), self.theme.background_direction)
+        #else:
+            #newtheme.add_background_image(str(self.theme.))
+
+        new_theme.add_font(str(self.theme.font_main_name), str(self.theme.font_main_color), str(self.theme.font_main_proportion), u'False')
+        new_theme.add_font(str(self.theme.font_footer_name), str(self.theme.font_footer_color), str(self.theme.font_footer_proportion), u'False', u'footer')
+        new_theme.add_display(str(self.theme.display_shadow), str(self.theme.display_shadow_color), str(self.theme.display_outline), str(self.theme.display_outline_color),
+            str(self.theme.display_horizontalAlign), str(self.theme.display_verticalAlign), str(self.theme.display_wrapStyle))
+
+        theme = new_theme.extract_xml()
+        self.thememanager.saveTheme(theme_name, theme)
         return QtGui.QDialog.accept(self)
 
     def themePath(self, path):
         self.path = path
 
     def loadTheme(self, theme):
-        self.theme = ThemeXML()
         if theme == None:
             self.theme.parse(self.baseTheme())
         else:
@@ -74,78 +131,235 @@
             xml = fileToXML(xml_file)
             self.theme.parse(xml)
         self.paintUi(self.theme)
-        self.generateImage(self.theme)
-
-    def onGradientComboBoxSelected(self):
-        if self.GradientComboBox.currentIndex() == 0: # Horizontal
-            self.theme.background_direction = u'horizontal'
-        elif self.GradientComboBox.currentIndex() == 1: # vertical
-            self.theme.background_direction = u'vertical'
-        else:
-            self.theme.background_direction = u'circular'
-        self.stateChanging(self.theme)
-        self.generateImage(self.theme)
-
-    def onBackgroundComboBoxSelected(self):
-        if self.BackgroundComboBox.currentIndex() == 0: # Opaque
+        self.previewTheme(self.theme)
+
+    #
+    #Main Font Tab
+    #
+    def onFontMainComboBoxSelected(self):
+        self.theme.font_main_name = self.FontMainComboBox.currentFont().family()
+        self.previewTheme(self.theme)
+
+    def onFontMainColorPushButtonClicked(self):
+        self.theme.font_main_color = QtGui.QColorDialog.getColor(
+            QColor(self.theme.font_main_color), self).name()
+
+        self.FontMainColorPushButton.setStyleSheet(
+            'background-color: %s' % str(self.theme.font_main_color))
+        self.previewTheme(self.theme)
+
+    def onFontMainSizeSpinBoxChanged(self, value):
+        self.theme.font_main_proportion = value
+        self.previewTheme(self.theme)
+
+    def onFontMainDefaultCheckBoxChanged(self, value):
+        if value == 2:  # checked
+            self.theme.font_main_override = False
+        else:
+            self.theme.font_main_override = True
+
+        if int(self.theme.font_main_x) == 0 and int(self.theme.font_main_y) == 0 and \
+                int(self.theme.font_main_width) == 0 and int(self.theme.font_main_height) == 0:
+            self.theme.font_main_x = u'10'
+            self.theme.font_main_y = u'10'
+            self.theme.font_main_width = u'1024'
+            self.theme.font_main_height = u'730'
+            self.FontMainXSpinBox.setValue(int(self.theme.font_main_x))
+            self.FontMainYSpinBox.setValue(int(self.theme.font_main_y))
+            self.FontMainWidthSpinBox.setValue(int(self.theme.font_main_width))
+            self.FontMainHeightSpinBox.setValue(int(self.theme.font_main_height))
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onFontMainXSpinBoxChanged(self, value):
+        self.theme.font_main_x = value
+        self.previewTheme(self.theme)
+
+    def onFontMainYSpinBoxChanged(self, value):
+        self.theme.font_main_y = value
+        self.previewTheme(self.theme)
+
+    def onFontMainWidthSpinBoxChanged(self, value):
+        self.theme.font_main_width = value
+        self.previewTheme(self.theme)
+
+    def onFontMainHeightSpinBoxChanged(self, value):
+        self.theme.font_main_height = value
+        self.previewTheme(self.theme)
+
+
+    #
+    #Footer Font Tab
+    #
+    def onFontFooterComboBoxSelected(self):
+        self.theme.font_footer_name = self.FontFooterComboBox.currentFont().family()
+        self.previewTheme(self.theme)
+
+    def onFontFooterColorPushButtonClicked(self):
+        self.theme.font_footer_color = QtGui.QColorDialog.getColor(
+            QColor(self.theme.font_footer_color), self).name()
+
+        self.FontFooterColorPushButton.setStyleSheet(
+            'background-color: %s' % str(self.theme.font_footer_color))
+        self.previewTheme(self.theme)
+
+    def onFontFooterSizeSpinBoxChanged(self, value):
+        self.theme.font_footer_proportion = value
+        self.previewTheme(self.theme)
+
+    def onFontFooterDefaultCheckBoxChanged(self):
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onFontFooterDefaultCheckBoxChanged(self, value):
+        if value == 2:  # checked
+            self.theme.font_footer_override = False
+        else:
+            self.theme.font_footer_override = True
+            if int(self.theme.font_footer_x) == 0 and int(self.theme.font_footer_y) == 0 and \
+                    int(self.theme.font_footer_width) == 0 and int(self.theme.font_footer_height) == 0:
+                self.theme.font_footer_x = u'10'
+                self.theme.font_footer_y = u'730'
+                self.theme.font_footer_width = u'1024'
+                self.theme.font_footer_height = u'38'
+
+                self.FontFooterXSpinBox.setValue(int(self.theme.font_footer_x))
+                self.FontFooterYSpinBox.setValue(int(self.theme.font_footer_y))
+                self.FontFooterWidthSpinBox.setValue(int(self.theme.font_footer_width))
+                self.FontFooterHeightSpinBox.setValue(int(self.theme.font_footer_height))
+
+
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onFontFooterXSpinBoxChanged(self, value):
+        self.theme.font_footer_x = value
+        self.previewTheme(self.theme)
+
+    def onFontFooterYSpinBoxChanged(self, value):
+        self.theme.font_footer_y = value
+        self.previewTheme(self.theme)
+
+    def onFontFooterWidthSpinBoxChanged(self, value):
+        self.theme.font_footer_width = value
+        self.previewTheme(self.theme)
+
+    def onFontFooterHeightSpinBoxChanged(self, value):
+        self.theme.font_footer_height = value
+        self.previewTheme(self.theme)
+
+    #
+    #Background Tab
+    #
+    def onGradientComboBoxSelected(self, currentIndex):
+        self.setBackground(self.BackgroundTypeComboBox.currentIndex(), currentIndex)
+
+    def onBackgroundComboBoxSelected(self, currentIndex):
+        if currentIndex == 0: # Opaque
             self.theme.background_mode = u'opaque'
         else:
             self.theme.background_mode = u'transparent'
         self.stateChanging(self.theme)
-        self.generateImage(self.theme)
-
-    def onBackgroundTypeComboBoxSelected(self):
-        if self.BackgroundTypeComboBox.currentIndex() == 0: # Solid
+        self.previewTheme(self.theme)
+
+    def onBackgroundTypeComboBoxSelected(self, currentIndex):
+        self.setBackground(currentIndex, self.GradientComboBox.currentIndex())
+
+    def setBackground(self, background, gradient):
+        if background == 0: # Solid
             self.theme.background_type = u'solid'
-        elif self.BackgroundTypeComboBox.currentIndex() == 1: # Gradient
+            if self.theme.background_color is None :
+                self.theme.background_color = u'#000000'
+        elif background == 1: # Gradient
             self.theme.background_type = u'gradient'
-            if self.theme.background_direction == None: # never defined
+            if gradient == 0: # Horizontal
                 self.theme.background_direction = u'horizontal'
-                self.theme.background_color2 = u'#000000'
+            elif gradient == 1: # vertical
+                self.theme.background_direction = u'vertical'
+            else:
+                self.theme.background_direction = u'circular'
+            if self.theme.background_startColor is None :
+                self.theme.background_startColor = u'#000000'
+            if self.theme.background_endColor is None :
+                self.theme.background_endColor = u'#ff0000'
         else:
             self.theme.background_type = u'image'
         self.stateChanging(self.theme)
-        self.generateImage(self.theme)
+        self.previewTheme(self.theme)
 
     def onColor1PushButtonClicked(self):
-        self.theme.background_color1 = QtGui.QColorDialog.getColor(
-            QColor(self.theme.background_color1), self).name()
-        self.Color1PushButton.setStyleSheet(
-            'background-color: %s' % str(self.theme.background_color1))
+        if self.theme.background_type == u'solid':
+            self.theme.background_color = QtGui.QColorDialog.getColor(
+                QColor(self.theme.background_color), self).name()
+            self.Color1PushButton.setStyleSheet(
+                'background-color: %s' % str(self.theme.background_color))
+        else:
+            self.theme.background_startColor = QtGui.QColorDialog.getColor(
+                QColor(self.theme.background_startColor), self).name()
+            self.Color1PushButton.setStyleSheet(
+                'background-color: %s' % str(self.theme.background_startColor))
 
-        self.generateImage(self.theme)
+        self.previewTheme(self.theme)
 
     def onColor2PushButtonClicked(self):
-        self.theme.background_color2 = QtGui.QColorDialog.getColor(
-            QColor(self.theme.background_color2), self).name()
+        self.theme.background_endColor = QtGui.QColorDialog.getColor(
+            QColor(self.theme.background_endColor), self).name()
         self.Color2PushButton.setStyleSheet(
-            'background-color: %s' % str(self.theme.background_color2))
-
-        self.generateImage(self.theme)
-
-    def onMainFontColorPushButtonClicked(self):
-        self.theme.font_main_color = QtGui.QColorDialog.getColor(
-            QColor(self.theme.font_main_color), self).name()
-
-        self.MainFontColorPushButton.setStyleSheet(
-            'background-color: %s' % str(self.theme.font_main_color))
-        self.generateImage(self.theme)
-
-    def onFontFooterColorPushButtonClicked(self):
-        self.theme.font_footer_color = QtGui.QColorDialog.getColor(
-            QColor(self.theme.font_footer_color), self).name()
-
-        self.FontFooterColorPushButton.setStyleSheet(
-            'background-color: %s' % str(self.theme.font_footer_color))
-        self.generateImage(self.theme)
-
+            'background-color: %s' % str(self.theme.background_endColor))
+
+        self.previewTheme(self.theme)
+    #
+    #Other Tab
+    #
+    def onOutlineCheckBoxChanged(self, value):
+        if value == 2:  # checked
+            self.theme.display_outline = True
+        else:
+            self.theme.display_outline = False
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onOutlineColorPushButtonClicked(self):
+        self.theme.display_outline_color = QtGui.QColorDialog.getColor(
+            QColor(self.theme.display_outline_color), self).name()
+        self.OutlineColorPushButton.setStyleSheet(
+            'background-color: %s' % str(self.theme.display_outline_color))
+        self.previewTheme(self.theme)
+
+    def onShadowCheckBoxChanged(self, value):
+        if value == 2:  # checked
+            self.theme.display_shadow = True
+        else:
+            self.theme.display_shadow = False
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onShadowColorPushButtonClicked(self):
+        self.theme.display_shadow_color = QtGui.QColorDialog.getColor(
+            QColor(self.theme.display_shadow_color), self).name()
+        self.ShadowColorPushButton.setStyleSheet(
+            'background-color: %s' % str(self.theme.display_shadow_color))
+        self.previewTheme(self.theme)
+
+    def onHorizontalComboBoxSelected(self, currentIndex):
+        self.theme.display_horizontalAlign = currentIndex
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+
+    def onVerticalComboBoxSelected(self, currentIndex):
+        self.theme.display_verticalAlign = currentIndex
+        self.stateChanging(self.theme)
+        self.previewTheme(self.theme)
+    #
+    #Local Methods
+    #
     def baseTheme(self):
         log.debug(u'base Theme')
         newtheme = ThemeXML()
         newtheme.new_document(u'New Theme')
         newtheme.add_background_solid(str(u'#000000'))
-        newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(30), u'False')
-        newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(12), u'False', u'footer')
+        newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(30), False)
+        newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(12), False, u'footer')
         newtheme.add_display(str(False), str(u'#FFFFFF'), str(False), str(u'#FFFFFF'),
             str(0), str(0), str(0))
 
@@ -154,76 +368,147 @@
     def paintUi(self, theme):
         print theme  # leave as helpful for initial development
         self.stateChanging(theme)
-        self.BackgroundTypeComboBox.setCurrentIndex(0)
-        self.BackgroundComboBox.setCurrentIndex(0)
-        self.GradientComboBox.setCurrentIndex(0)
-        self.MainFontColorPushButton.setStyleSheet(
+        self.ThemeNameEdit.setText(self.theme.theme_name)
+        if self.theme.background_mode == u'opaque':
+            self.BackgroundComboBox.setCurrentIndex(0)
+        else:
+            self.BackgroundComboBox.setCurrentIndex(1)
+
+        if theme.background_type == u'solid':
+            self.BackgroundTypeComboBox.setCurrentIndex(0)
+        elif theme.background_type == u'gradient':
+            self.BackgroundTypeComboBox.setCurrentIndex(1)
+        else:
+            self.BackgroundTypeComboBox.setCurrentIndex(2)
+
+        if self.theme.background_direction == u'horizontal':
+            self.GradientComboBox.setCurrentIndex(0)
+        elif self.theme.background_direction == u'vertical':
+            self.GradientComboBox.setCurrentIndex(1)
+        else:
+            self.GradientComboBox.setCurrentIndex(2)
+
+        self.FontMainSizeSpinBox.setValue(int(self.theme.font_main_proportion))
+        self.FontMainXSpinBox.setValue(int(self.theme.font_main_x))
+        self.FontMainYSpinBox.setValue(int(self.theme.font_main_y))
+        self.FontMainWidthSpinBox.setValue(int(self.theme.font_main_width))
+        self.FontMainHeightSpinBox.setValue(int(self.theme.font_main_height))
+        self.FontFooterSizeSpinBox.setValue(int(self.theme.font_footer_proportion))
+        self.FontFooterXSpinBox.setValue(int(self.theme.font_footer_x))
+        self.FontFooterYSpinBox.setValue(int(self.theme.font_footer_y))
+        self.FontFooterWidthSpinBox.setValue(int(self.theme.font_footer_width))
+        self.FontFooterHeightSpinBox.setValue(int(self.theme.font_footer_height))
+        self.FontMainColorPushButton.setStyleSheet(
             'background-color: %s' % str(theme.font_main_color))
         self.FontFooterColorPushButton.setStyleSheet(
             'background-color: %s' % str(theme.font_footer_color))
 
+        if self.theme.font_main_override == False:
+            self.FontMainDefaultCheckBox.setChecked(True)
+        else:
+            self.FontMainDefaultCheckBox.setChecked(False)
+
+        if self.theme.font_footer_override == False:
+            self.FontFooterDefaultCheckBox.setChecked(True)
+        else:
+            self.FontFooterDefaultCheckBox.setChecked(False)
+
+        self.OutlineColorPushButton.setStyleSheet(
+            'background-color: %s' % str(theme.display_outline_color))
+        self.ShadowColorPushButton.setStyleSheet(
+            'background-color: %s' % str(theme.display_shadow_color))
+
+        if self.theme.display_outline:
+            self.OutlineCheckBox.setChecked(True)
+            self.OutlineColorPushButton.setEnabled(True)
+        else:
+            self.OutlineCheckBox.setChecked(False)
+            self.OutlineColorPushButton.setEnabled(False)
+
+        if self.theme.display_shadow:
+            self.ShadowCheckBox.setChecked(True)
+            self.ShadowColorPushButton.setEnabled(True)
+        else:
+            self.ShadowCheckBox.setChecked(False)
+            self.ShadowColorPushButton.setEnabled(False)
+
+        self.HorizontalComboBox.setCurrentIndex(int(self.theme.display_horizontalAlign))
+        self.VerticalComboBox.setCurrentIndex(int(self.theme.display_verticalAlign))
+
     def stateChanging(self, theme):
         if theme.background_type == u'solid':
             self.Color1PushButton.setStyleSheet(
-                'background-color: %s' % str(theme.background_color1))
-            self.Color1Label.setText(translate(u'ThemeManager', u'Background Font:'))
+                'background-color: %s' % str(theme.background_color))
+            self.Color1Label.setText(translate(u'ThemeManager', u'Background Color:'))
             self.Color1Label.setVisible(True)
             self.Color1PushButton.setVisible(True)
             self.Color2Label.setVisible(False)
             self.Color2PushButton.setVisible(False)
+            self.ImageLabel.setVisible(False)
+            self.ImageLineEdit.setVisible(False)
+            self.ImageFilenameWidget.setVisible(False)
+            self.GradientLabel.setVisible(False)
+            self.GradientComboBox.setVisible(False)
         elif theme.background_type == u'gradient':
             self.Color1PushButton.setStyleSheet(
-                'background-color: %s' % str(theme.background_color1))
+                'background-color: %s' % str(theme.background_startColor))
             self.Color2PushButton.setStyleSheet(
-                'background-color: %s' % str(theme.background_color2))
+                'background-color: %s' % str(theme.background_endColor))
             self.Color1Label.setText(translate(u'ThemeManager', u'First  Color:'))
             self.Color2Label.setText(translate(u'ThemeManager', u'Second Color:'))
             self.Color1Label.setVisible(True)
             self.Color1PushButton.setVisible(True)
             self.Color2Label.setVisible(True)
             self.Color2PushButton.setVisible(True)
+            self.ImageLabel.setVisible(False)
+            self.ImageLineEdit.setVisible(False)
+            self.ImageFilenameWidget.setVisible(False)
+            self.GradientLabel.setVisible(True)
+            self.GradientComboBox.setVisible(True)
         else: # must be image
             self.Color1Label.setVisible(False)
             self.Color1PushButton.setVisible(False)
             self.Color2Label.setVisible(False)
             self.Color2PushButton.setVisible(False)
-
-    def generateImage(self, theme):
-        log.debug(u'generateImage %s ',  theme)
-        #theme = ThemeXML()
-        #theme.parse(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), QtCore.QRect(10,560, 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.')
-        lines1=[]
-        lines1.append(u'Amazing Grace (John Newton)' )
-        lines1.append(u'CCLI xxx (c)Openlp.org')
-
-        answer=r._render_lines(lines, lines1)
-
-        self.ThemePreview.setPixmap(frame.GetPixmap())
-
-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
+            self.ImageLabel.setVisible(True)
+            self.ImageLineEdit.setVisible(True)
+            self.ImageFilenameWidget.setVisible(True)
+            self.GradientLabel.setVisible(False)
+            self.GradientComboBox.setVisible(False)
+
+        if theme.font_main_override == False:
+            self.FontMainXSpinBox.setEnabled(False)
+            self.FontMainYSpinBox.setEnabled(False)
+            self.FontMainWidthSpinBox.setEnabled(False)
+            self.FontMainHeightSpinBox.setEnabled(False)
+        else:
+            self.FontMainXSpinBox.setEnabled(True)
+            self.FontMainYSpinBox.setEnabled(True)
+            self.FontMainWidthSpinBox.setEnabled(True)
+            self.FontMainHeightSpinBox.setEnabled(True)
+
+        if theme.font_footer_override == False:
+            self.FontFooterXSpinBox.setEnabled(False)
+            self.FontFooterYSpinBox.setEnabled(False)
+            self.FontFooterWidthSpinBox.setEnabled(False)
+            self.FontFooterHeightSpinBox.setEnabled(False)
+        else:
+            self.FontFooterXSpinBox.setEnabled(True)
+            self.FontFooterYSpinBox.setEnabled(True)
+            self.FontFooterWidthSpinBox.setEnabled(True)
+            self.FontFooterHeightSpinBox.setEnabled(True)
+
+        if self.theme.display_outline:
+            self.OutlineColorPushButton.setEnabled(True)
+        else:
+            self.OutlineColorPushButton.setEnabled(False)
+
+        if self.theme.display_shadow:
+            self.ShadowColorPushButton.setEnabled(True)
+        else:
+            self.ShadowColorPushButton.setEnabled(False)
+
+
+    def previewTheme(self, theme):
+        frame = self.thememanager.generateImage(theme)
+        self.ThemePreview.setPixmap(frame)

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2009-04-09 18:50:20 +0000
+++ openlp/core/ui/mainwindow.py	2009-04-25 06:11:15 +0000
@@ -28,7 +28,7 @@
 
 from openlp.core.ui import AboutForm, SettingsForm, AlertForm, \
                            SlideController, ServiceManager, ThemeManager
-from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab, EventManager
+from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab, EventManager, RenderManager
 
 from openlp.core import PluginManager
 
@@ -52,11 +52,17 @@
 
         self.setupUi()
 
+        #warning cyclic dependency
+        #RenderManager needs to call ThemeManager and
+        #ThemeManager needs to call RenderManager
+        self.RenderManager = RenderManager(self.ThemeManagerContents, self.screen_list)
+
         log.info(u'Load Plugins')
         self.plugin_helpers[u'preview'] = self.PreviewController
         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_helpers[u'render'] = self.RenderManager
 
         self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers, self.EventManager)
         # hook methods have to happen after find_plugins.  Find plugins needs the controllers
@@ -84,6 +90,9 @@
         # Once all components are initialised load the Themes
         log.info(u'Load Themes')
         self.ThemeManagerContents.setEventManager(self.EventManager)
+        self.ThemeManagerContents.setRenderManager(self.RenderManager)
+        self.ServiceManagerContents.setRenderManager(self.RenderManager)
+        self.ThemeManagerContents.setServiceManager(self.ServiceManagerContents)
         self.ThemeManagerContents.loadThemes()
 
     def setupUi(self):

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2009-03-23 19:17:07 +0000
+++ openlp/core/ui/servicemanager.py	2009-04-25 06:11:15 +0000
@@ -29,6 +29,7 @@
 # from openlp.core.ui import AboutForm, AlertForm, SettingsForm, SlideController
 from openlp.core.lib import OpenLPToolbar
 from openlp.core.lib import ServiceItem
+from openlp.core.lib import RenderManager
 
 # from openlp.core import PluginManager
 import logging
@@ -61,7 +62,7 @@
         self.endRemoveRows()
     def addRow(self, item):
         self.insertRow(len(self.items), item)
-        
+
     def index(self, row, col, parent = QModelIndex()):
         return self.createIndex(row,col)
 
@@ -90,7 +91,7 @@
             return QVariant(retval)
         else:
             return retval
-        
+
     def __iter__(self):
         for i in self.items:
             yield i
@@ -99,7 +100,7 @@
         log.info("Get Item:%d -> %s" %(row, str(self.items)))
         return self.items[row]
 
-    
+
 class ServiceManager(QWidget):
 
     """Manages the orders of service.  Currently this involves taking
@@ -109,7 +110,7 @@
     Also handles the UI tasks of moving things up and down etc.
     """
     global log
-    log=logging.getLogger(u'ServiceManager')    
+    log=logging.getLogger(u'ServiceManager')
 
     def __init__(self, parent):
         QWidget.__init__(self)
@@ -128,9 +129,6 @@
         self.Toolbar.addSeparator()
         self.ThemeComboBox = QtGui.QComboBox(self.Toolbar)
         self.ThemeComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
-        self.ThemeComboBox.addItem(QtCore.QString())
-        self.ThemeComboBox.addItem(QtCore.QString())
-        self.ThemeComboBox.addItem(QtCore.QString())
         self.ThemeWidget = QtGui.QWidgetAction(self.Toolbar)
         self.ThemeWidget.setDefaultWidget(self.ThemeComboBox)
         self.Toolbar.addAction(self.ThemeWidget)
@@ -141,7 +139,15 @@
         self.service_data=ServiceData()
         self.TreeView.setModel(self.service_data)
         self.Layout.addWidget(self.TreeView)
-        
+        QtCore.QObject.connect(self.ThemeComboBox,
+            QtCore.SIGNAL("activated(int)"), self.onThemeComboBoxSelected)
+
+    def setRenderManager(self, renderManager):
+        self.renderManager = renderManager
+
+    def onThemeComboBoxSelected(self, currentIndex):
+        self.renderManager.set_default_theme(self.ThemeComboBox.currentText())
+
     def addServiceItem(self, item):
         """Adds service item"""
         log.info("addServiceItem")
@@ -165,7 +171,7 @@
                 self.service_data.addRow(item)
             else:
                 self.service_data.insertRow(row+1, item)
-                
+
     def removeServiceItem(self):
         """Remove currently selected item"""
         pass
@@ -189,3 +195,10 @@
         oosfile.write(self.oos_as_text)
         oosfile.write("# END OOS\n")
         oosfile.close()
+
+    def updateThemeList(self, theme_list):
+        self.ThemeComboBox.clear()
+        for theme in theme_list:
+            self.ThemeComboBox.addItem(theme)
+            self.renderManager.set_default_theme(self.ThemeComboBox.currentText())
+

=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py	2009-02-20 21:13:04 +0000
+++ openlp/core/ui/slidecontroller.py	2009-04-25 06:11:15 +0000
@@ -3,7 +3,7 @@
 """
 OpenLP - Open Source Lyrics Projection
 Copyright (c) 2008 Raoul Snyman
-Portions copyright (c) 2008 Martin Thompson, Tim Bentley,
+Portions copyright (c) 2008-2009 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
@@ -27,7 +27,7 @@
         self.Pane = QtGui.QWidget(control_splitter)
         self.Splitter = QtGui.QSplitter(self.Pane)
         self.Splitter.setOrientation(QtCore.Qt.Vertical)
-        
+
         self.PaneLayout = QtGui.QVBoxLayout(self.Pane)
         self.PaneLayout.addWidget(self.Splitter)
         self.PaneLayout.setSpacing(50)
@@ -41,6 +41,23 @@
         self.Controller.setGeometry(QtCore.QRect(0, 0, 828, 536))
         self.Controller.setWidget(self.ControllerContents)
 
-        self.Screen = QtGui.QGraphicsView(self.Splitter)
-        self.Screen.setMaximumSize(QtCore.QSize(16777215, 250))
-
+        #self.Screen = QtGui.QGraphicsView(self.Splitter)
+        #self.Screen.setMaximumSize(QtCore.QSize(16777215, 250))
+
+
+        self.ThemePreview = QtGui.QLabel(self.Splitter)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.ThemePreview.sizePolicy().hasHeightForWidth())
+        self.ThemePreview.setSizePolicy(sizePolicy)
+        self.ThemePreview.setMinimumSize(QtCore.QSize(250, 190))
+        self.ThemePreview.setFrameShape(QtGui.QFrame.WinPanel)
+        self.ThemePreview.setFrameShadow(QtGui.QFrame.Sunken)
+        self.ThemePreview.setLineWidth(1)
+        self.ThemePreview.setScaledContents(True)
+        self.ThemePreview.setObjectName("ThemePreview")
+
+
+    def previewFrame(self, frame):
+        self.ThemePreview.setPixmap(frame)

=== modified file 'openlp/core/ui/splashscreen.py'
--- openlp/core/ui/splashscreen.py	2008-11-28 14:05:41 +0000
+++ openlp/core/ui/splashscreen.py	2009-04-25 06:11:15 +0000
@@ -20,12 +20,15 @@
 
 from PyQt4 import QtCore, QtGui
 
-from openlp.core.resources import *
+#from openlp.core.resources import *
+from openlp.core import translate
 
 class SplashScreen(object):
-    def __init__(self):
+    def __init__(self, version):
         self.splash_screen = QtGui.QSplashScreen()
         self.setupUi()
+        starting = translate('SplashScreen',u'Starting')
+        self.message=starting+u'..... '+version
 
     def setupUi(self):
         self.splash_screen.setObjectName("splash_screen")
@@ -60,7 +63,7 @@
 
     def show(self):
         self.splash_screen.show()
-        self.splash_screen.showMessage(u'Starting...', QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom,  QtCore.Qt.black)
+        self.splash_screen.showMessage(self.message, QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom,  QtCore.Qt.black)
         self.splash_screen.repaint()
 
     def finish(self, widget):

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2009-04-11 15:16:02 +0000
+++ openlp/core/ui/thememanager.py	2009-04-25 06:38:21 +0000
@@ -20,6 +20,7 @@
 import os,os.path
 import sys
 import zipfile
+import shutil
 
 from time import sleep
 from copy import deepcopy
@@ -30,17 +31,18 @@
 from PyQt4.QtGui import *
 
 from openlp.core.ui import AmendThemeForm
+from openlp.core.ui import ServiceManager
 from openlp.core import translate
-from openlp.core import Renderer
+from openlp.core import fileToXML
 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 ThemeXML
+from openlp.core.lib import Renderer
 from openlp.core.utils import ConfigHelper
 
-
 import logging
 
 class ThemeData(QAbstractItemModel):
@@ -153,7 +155,7 @@
         self.Layout = QtGui.QVBoxLayout(self)
         self.Layout.setSpacing(0)
         self.Layout.setMargin(0)
-        self.amendThemeForm = AmendThemeForm()
+        self.amendThemeForm = AmendThemeForm(self)
         self.Toolbar = OpenLPToolbar(self)
         self.Toolbar.addToolbarButton(translate('ThemeManager',u'New Theme'), ":/themes/theme_new.png",
             translate('ThemeManager',u'Allows a Theme to be created'), self.onAddTheme)
@@ -186,6 +188,12 @@
     def setEventManager(self, eventManager):
         self.eventManager = eventManager
 
+    def setRenderManager(self, renderManager):
+        self.renderManager = renderManager
+
+    def setServiceManager(self, serviceManager):
+        self.serviceManager = serviceManager
+
     def onAddTheme(self):
         self.amendThemeForm.loadTheme(None)
         self.amendThemeForm.exec_()
@@ -198,7 +206,19 @@
         self.amendThemeForm.exec_()
 
     def onDeleteTheme(self):
-        pass
+        items = self.ThemeListView.selectedIndexes()
+        theme = ''
+        for item in items:
+            data = self.Theme_data.getValue(item)
+            theme = data[3]
+        th = theme +  u'.png'
+        try:
+            os.remove(os.path.join(self.path, th))
+        except:
+            pass #if not present do not worry
+        shutil.rmtree(os.path.join(self.path, theme))
+        self.Theme_data.clearItems()
+        self.loadThemes()
 
     def onExportTheme(self):
         pass
@@ -224,18 +244,33 @@
                     self.Theme_data.addRow(os.path.join(self.path, name))
 
         self.eventManager.post_event(Event(EventType.ThemeListChanged))
+        self.serviceManager.updateThemeList(self.getThemes())
 
     def getThemes(self):
         return self.Theme_data.getList()
 
+    def getThemeData(self, themename):
+        xml_file = os.path.join(self.path, str(themename), str(themename)+u'.xml')
+        xml = fileToXML(xml_file)
+        theme = ThemeXML()
+        theme.parse(xml)
+        return theme
+
     def checkThemesExists(self, dir):
         log.debug(u'check themes')
         if os.path.exists(dir) == False:
             os.mkdir(dir)
 
     def unzipTheme(self, filename, dir):
+        """
+        Unzip the theme , remove the preview file if stored
+        Generate a new preview fileCheck the XML theme version and upgrade if
+        necessary.
+        """
         log.debug(u'Unzipping theme %s', filename)
         zip = zipfile.ZipFile(str(filename))
+        filexml = None
+        themename = None
         for file in zip.namelist():
             if file.endswith('/'):
                 theme_dir = os.path.join(dir, file)
@@ -244,20 +279,23 @@
             else:
                 fullpath = os.path.join(dir, file)
                 names = file.split(u'/')
-                xml_data = zip.read(file)
-                if os.path.splitext (file) [1].lower ()  in [u'.xml']:
-                    if self.checkVersion1(xml_data):
-                        filexml = self.migrateVersion122(filename, fullpath, xml_data)
+                if len(names) > 1: # not preview file
+                    if themename is None:
+                        themename = names[0]
+                    xml_data = zip.read(file)
+                    if os.path.splitext (file) [1].lower ()  in [u'.xml']:
+                        if self.checkVersion1(xml_data):
+                            filexml = self.migrateVersion122(filename, fullpath, xml_data) # upgrade theme xml
+                        else:
+                            filexml = xml_data
                         outfile = open(fullpath, 'w')
                         outfile.write(filexml)
                         outfile.close()
-                        self.generateImage(dir,names[0], filexml)
-                else:
-                    if os.path.splitext (file) [1].lower ()  in [u'.bmp']:
-                        if fullpath is not os.path.join(dir, file):
-                            outfile = open(fullpath, 'w')
-                            outfile.write(zip.read(file))
-                            outfile.close()
+                    else:
+                        outfile = open(fullpath, 'w')
+                        outfile.write(zip.read(file))
+                        outfile.close()
+        self.generateAndSaveImage(dir,themename, filexml)
 
     def checkVersion1(self, xmlfile):
         log.debug(u'checkVersion1 ')
@@ -278,7 +316,7 @@
             newtheme.add_background_solid(str(t.BackgroundParameter1.name()))
         elif t.BackgroundType == 1:
             direction = "vertical"
-            if t.BackgroundParameter1.name() == 1:
+            if t.BackgroundParameter3.name() == 1:
                 direction = "horizontal"
             newtheme.add_background_gradient(str(t.BackgroundParameter1.name()), str(t.BackgroundParameter2.name()), direction)
         else:
@@ -296,48 +334,37 @@
             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)
+    def saveTheme(self, name, theme_xml) :
+        log.debug(u'saveTheme %s %s', name, theme_xml)
+        self.generateAndSaveImage(self.path, name, theme_xml)
+        theme_dir = os.path.join(self.path, name)
+        if os.path.exists(theme_dir) == False:
+            os.mkdir(os.path.join(self.path, name))
+
+        theme_file = os.path.join(theme_dir, name+u'.xml')
+        outfile = open(theme_file, 'w')
+        outfile.write(theme_xml)
+        outfile.close()
+        self.Theme_data.clearItems()
+        self.loadThemes()
+
+    def generateAndSaveImage(self, dir, name, theme_xml):
+        log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
         theme = ThemeXML()
         theme.parse(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), QtCore.QRect(10,560, 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.')
-        lines1=[]
-        lines1.append(u'Amazing Grace (John Newton)' )
-        lines1.append(u'CCLI xxx (c)Openlp.org')
-
-        answer=r._render_lines(lines, lines1)
-
-        im=frame.GetPixmap().toImage()
-        samplepathname=os.path.join(dir, name+u'.png')
+
+        frame = self.generateImage(theme)
+
+        im=frame.toImage()
+        samplepathname=os.path.join(self.path, name+u'.png')
         if os.path.exists(samplepathname):
             os.unlink(samplepathname)
         im.save(samplepathname, u'png')
         log.debug(u'Theme image written to %s',samplepathname)
 
+    def generateImage(self, theme):
+        log.debug(u'generateImage %s ',  theme)
+        self.renderManager.set_theme(theme)
+        frame = self.renderManager.generate_preview()
+        return frame
 
-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-04-06 18:45:45 +0000
+++ openlp/plugins/bibles/lib/biblestab.py	2009-04-15 04:58:51 +0000
@@ -21,8 +21,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core import translate
+from openlp import  convertStringToBoolean
 from openlp.core.lib import SettingsTab
-from openlp.core.resources import *
 
 class BiblesTab(SettingsTab):
     """
@@ -182,11 +182,11 @@
             self.bible_search = True
 
     def load(self):
-        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.paragraph_style = convertStringToBoolean(self.config.get_config('paragraph style', u'True'))
+        self.show_new_chapters = 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'))
+        self.bible_search = convertStringToBoolean(self.config.get_config('search as type', u'True'))
         if self.paragraph_style:
             self.ParagraphRadioButton.setChecked(True)
         else:

=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py	2009-02-24 20:24:01 +0000
+++ openlp/plugins/bibles/lib/manager.py	2009-04-25 06:09:47 +0000
@@ -52,16 +52,16 @@
         self.proxyname = self.config.get_config("proxy name") #get proxy name for screen
         self.bibleSuffix = "sqlite"
         self.dialogobject = None
-     
+
         self.reload_bibles()
-    
+
     def reload_bibles(self):
         log.debug("Reload bibles")
-        
+
         files = self.config.get_files(self.bibleSuffix)
         log.debug("Bible Files %s",  files )
-        
-        self.bible_db_cache = {}   
+
+        self.bible_db_cache = {}
         self.bible_http_cache  = {}
 
         self.book_testaments = {} # books of the bible with testaments
@@ -88,17 +88,17 @@
                 nhttp.set_bibleid(bibleid)  # tell The Server where to get the verses from.
             else:
                 self.bible_http_cache [bname] = None # makes the Full / partial code easier.
-                
+
             if self.web_bibles_present:
                 self.book_testaments = {} # books of the bible linked to bibleid  {osis , name}
                 self.book_abbreviations = {} # books of the bible linked to bibleid  {osis ,Abbrev }
-        
+
                 filepath = os.path.split(os.path.abspath(__file__))[0]
-                filepath = os.path.abspath(os.path.join(filepath, '..', 'resources','httpbooks.csv')) 
+                filepath = os.path.abspath(os.path.join(filepath, '..', 'resources','httpbooks.csv'))
                 fbibles=open(filepath, 'r')
                 for line in fbibles:
                     p = line.split(",")
-                    self.book_abbreviations[p[0]] = p[1].replace('\n', '')             
+                    self.book_abbreviations[p[0]] = p[1].replace('\n', '')
                     self.book_testaments[p[0]] = p[2].replace('\n', '')
         log.debug( "Bible Initialised")
 
@@ -136,7 +136,7 @@
         If the database exists it is deleted and the database is reloaded
         from scratch.
         """
-        log.debug( "register_CSV_file_bible %s,%s,%s", biblename, booksfile, versefile)          
+        log.debug( "register_CSV_file_bible %s,%s,%s", biblename, booksfile, versefile)
         if self._is_new_bible(biblename):
             nbible = BibleDBImpl(self.biblePath, biblename, self.config) # Create new Bible
             nbible.create_tables() # Create Database
@@ -150,7 +150,7 @@
         If the database exists it is deleted and the database is reloaded
         from scratch.
         """
-        log.debug( "register_OSIS_file_bible %s , %s", biblename, osisfile)        
+        log.debug( "register_OSIS_file_bible %s , %s", biblename, osisfile)
         if self._is_new_bible(biblename):
             nbible = BibleDBImpl(self.biblePath, biblename, self.config) # Create new Bible
             nbible.create_tables() # Create Database
@@ -170,7 +170,7 @@
             if mode == "full":
                 r.append(b)
             else:
-                if self.bible_http_cache [b] == None:  # we do not have an http bible 
+                if self.bible_http_cache [b] == None:  # we do not have an http bible
                     r.append(b)
         return r
 
@@ -250,16 +250,16 @@
                             log.debug("New http book %s , %s, %s",  book, book.id, book.name)
                             self.bible_db_cache[bible].create_chapter(book.id, \
                                                                       search_results.get_chapter(),\
-                                                                      search_results.get_verselist())                            
+                                                                      search_results.get_verselist())
                         else:
                             ## Book exists check chapter and texts only.
                             v = self.bible_db_cache[bible].get_bible_chapter(book.id, chapter)
                             if v == None:
                                 self.bible_db_cache[bible].create_chapter(book.id, \
-                                                                          book_chapter, \
+                                                                          chapter, \
                                                                           search_results.get_verselist())
             else:
-                log.debug("get_verse_text : old book")                
+                log.debug("get_verse_text : old book")
                 for chapter in range(schapter, echapter+1):
                     v = self.bible_db_cache[bible].get_bible_chapter(book.id, chapter)
                     if v == None:
@@ -267,9 +267,9 @@
                             search_results = self.bible_http_cache [bible].get_bible_chapter(bible, book.id, bookname, chapter)
                             self.bible_db_cache[bible].create_chapter(book.id, \
                                                                       search_results.get_chapter(),\
-                                                                      search_results.get_verselist())     
+                                                                      search_results.get_verselist())
                         except :
-                            log.error("Errow thrown %s", sys.exc_info()[1])                        
+                            log.error("Errow thrown %s", sys.exc_info()[1])
 
         if schapter == echapter:
             text = self.bible_db_cache[bible].get_bible_text(bookname, schapter, sverse, everse)

=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py	2009-03-19 17:31:33 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py	2009-04-25 06:11:15 +0000
@@ -48,19 +48,19 @@
         # Create buttons for the toolbar
         ## New Bible Button ##
         self.addToolbarButton(
-            translate(u'BibleMediaItem','New Bible'), 
+            translate(u'BibleMediaItem','New Bible'),
             translate(u'BibleMediaItem','Register a new Bible'),
             ':/themes/theme_import.png', self.onBibleNewClick, 'BibleNewItem')
         ## Separator Line ##
         self.addToolbarSeparator()
         ## Preview Bible Button ##
         self.addToolbarButton(
-            translate(u'BibleMediaItem','Preview Bible'), 
+            translate(u'BibleMediaItem','Preview Bible'),
             translate(u'BibleMediaItem','Preview the selected Bible Verse'),
             ':/system/system_preview.png', self.onBiblePreviewClick, 'BiblePreviewItem')
         ## Live Bible Button ##
         self.addToolbarButton(
-            translate(u'BibleMediaItem','Go Live'), 
+            translate(u'BibleMediaItem','Go Live'),
             translate(u'BibleMediaItem','Send the selected Bible Verse(s) live'),
             ':/system/system_live.png', self.onBibleLiveClick, 'BibleLiveItem')
         ## Add Bible Button ##
@@ -183,9 +183,10 @@
         self.BibleListView.setAlternatingRowColors(True)
         self.BibleListData = TextListData()
         self.BibleListView.setModel(self.BibleListData)
-        
+        self.BibleListView.setSelectionMode(2)
+
         self.PageLayout.addWidget(self.BibleListView)
-        
+
         # Combo Boxes
         QtCore.QObject.connect(self.AdvancedVersionComboBox,
             QtCore.SIGNAL("activated(int)"), self.onAdvancedVersionComboBox)
@@ -215,7 +216,7 @@
             translate(u'BibleMediaItem',u'&Add to Service'), self.onBibleAddClick))
 
     def retranslateUi(self):
-        log.debug(u'retranslateUi')        
+        log.debug(u'retranslateUi')
         self.QuickVersionLabel.setText(translate(u'BibleMediaItem', u'Version:'))
         self.QuickSearchLabel.setText(translate(u'BibleMediaItem', u'Search Type:'))
         self.QuickSearchLabel.setText(translate(u'BibleMediaItem', u'Find:'))
@@ -241,15 +242,15 @@
         self.loadBibles()
 
     def loadBibles(self):
-        log.debug(u'Loading Bibles')  
+        log.debug(u'Loading Bibles')
         self.QuickVersionComboBox.clear()
         self.AdvancedVersionComboBox.clear()
-        
+
         bibles = self.parent.biblemanager.get_bibles(u'full')
-        
+
         for bible in bibles:  # load bibles into the combo boxes
             self.QuickVersionComboBox.addItem(bible)
-            
+
         bibles = self.parent.biblemanager.get_bibles(u'partial') # Without HTTP
         first = True
         for bible in bibles:  # load bibles into the combo boxes
@@ -328,6 +329,8 @@
         log.debug(u'Bible Preview Button pressed')
         items = self.BibleListView.selectedIndexes()
         old_chapter = ''
+        main_lines=[]
+        footer_lines = []
         for item in items:
             text = self.BibleListData.getValue(item)
             verse = text[:text.find("(")]
@@ -348,16 +351,19 @@
             else:
                 loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
             old_chapter = chapter
-            print book
-            print loc
-            print text
+            main_lines.append(loc + u' '+text)
+            if len(footer_lines) <= 1:
+                footer_lines.append(book)
+
+        frame=self.parent.render_manager.generate_slide(main_lines, footer_lines)
+        self.parent.preview_controller.previewFrame(frame)
 
     def formatVerse(self, old_chapter, chapter, verse, opening, closing):
         loc = opening
         if old_chapter != chapter:
             loc += chapter + u':'
-        elif not self.parent.bibles_tab.new_chapter_check:
-            loc += chapter + u':'            
+        elif not self.parent.bibles_tab.show_new_chapters:
+            loc += chapter + u':'
         loc += verse
         loc += closing
         return loc

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2009-03-15 19:31:33 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2009-04-25 06:11:15 +0000
@@ -23,7 +23,7 @@
 
 from openlp.core import translate
 from openlp.core.lib import MediaManagerItem
-from openlp.core.resources import *
+from openlp.core.lib import SongXMLParser
 
 from openlp.plugins.custom.lib import TextListData
 
@@ -44,7 +44,7 @@
         # Create buttons for the toolbar
         ## New Custom Button ##
         self.addToolbarButton(
-            translate('CustomMediaItem',u'New Custom Item'), 
+            translate('CustomMediaItem',u'New Custom Item'),
             translate('CustomMediaItem',u'Add a new Custom Item'),
             ':/custom/custom_new.png', self.onCustomNewClick, 'CustomNewItem')
         ## Edit Custom Button ##
@@ -72,7 +72,7 @@
         ## Add Custom Button ##
         self.addToolbarButton(
             translate('CustomMediaItem',u'Add Custom To Service'),
-            translate('CustomMediaItem',u'Add the selected Custom(s) to the service'), 
+            translate('CustomMediaItem',u'Add the selected Custom(s) to the service'),
             ':/system/system_add.png', self.onCustomAddClick, 'CustomAddItem')
         # Add the Customlist widget
         self.CustomWidget = QtGui.QWidget(self)
@@ -82,7 +82,7 @@
         sizePolicy.setHeightForWidth(self.CustomWidget.sizePolicy().hasHeightForWidth())
         self.CustomWidget.setSizePolicy(sizePolicy)
         self.CustomWidget.setObjectName(u'CustomWidget')
-        
+
 #        self.SearchLayout = QtGui.QGridLayout(self.CustomWidget)
 #        self.SearchLayout.setObjectName('SearchLayout')
 #        self.SearchTextLabel = QtGui.QLabel(self.CustomWidget)
@@ -92,7 +92,7 @@
 #        self.SearchTextEdit = QtGui.QLineEdit(self.CustomWidget)
 #        self.SearchTextEdit.setObjectName('SearchTextEdit')
 #        self.SearchLayout.addWidget(self.SearchTextEdit, 2, 1, 1, 2)
-#        
+#
 #        self.ClearTextButton = QtGui.QPushButton(self.CustomWidget)
 #        self.ClearTextButton.setObjectName('ClearTextButton')
 #
@@ -102,22 +102,22 @@
 #        self.SearchLayout.addWidget(self.SearchTextButton, 3, 2, 1, 1)
         # Add the Custom widget to the page layout
         self.PageLayout.addWidget(self.CustomWidget)
-        
+
         self.CustomListView = QtGui.QListView()
         self.CustomListView.setAlternatingRowColors(True)
         self.CustomListData = TextListData()
         self.CustomListView.setModel(self.CustomListData)
-        
+
         self.PageLayout.addWidget(self.CustomListView)
 
         # Signals
-#        QtCore.QObject.connect(self.SearchTextButton, 
+#        QtCore.QObject.connect(self.SearchTextButton,
 #            QtCore.SIGNAL("pressed()"), self.onSearchTextButtonClick)
-#        QtCore.QObject.connect(self.ClearTextButton, 
+#        QtCore.QObject.connect(self.ClearTextButton,
 #            QtCore.SIGNAL("pressed()"), self.onClearTextButtonClick)
-#        QtCore.QObject.connect(self.SearchTextEdit, 
+#        QtCore.QObject.connect(self.SearchTextEdit,
 #            QtCore.SIGNAL("textChanged(const QString&)"), self.onSearchTextEditChanged)
-#        QtCore.QObject.connect(self.CustomListView, 
+#        QtCore.QObject.connect(self.CustomListView,
 #            QtCore.SIGNAL("itemPressed(QTableWidgetItem * item)"), self.onCustomSelected)
 
         #define and add the context menu
@@ -135,14 +135,14 @@
         self.CustomListView.addAction(self.contextMenuAction(
             self.CustomListView, ':/system/system_add.png',
             translate('CustomMediaItem',u'&Add to Service'), self.onCustomEditClick))
-            
+
 #    def retranslateUi(self):
 #        self.ClearTextButton.setText(translate('CustomMediaItem', u'Clear'))
-#        self.SearchTextButton.setText(translate('CustomMediaItem', u'Search'))        
-        
+#        self.SearchTextButton.setText(translate('CustomMediaItem', u'Search'))
+
     def initialise(self):
         self.loadCustomList(self.parent.custommanager.get_all_slides())
-        
+
     def loadCustomList(self, list):
         self.CustomListData.resetStore()
         for CustomSlide in list:
@@ -166,9 +166,9 @@
         self._display_results(search_results)
 
     def onCustomNewClick(self):
-        self.parent.edit_custom_form.loadCustom(0)        
+        self.parent.edit_custom_form.loadCustom(0)
         self.parent.edit_custom_form.exec_()
-        self.initialise()        
+        self.initialise()
 
     def onCustomEditClick(self):
         indexes = self.CustomListView.selectedIndexes()
@@ -185,7 +185,25 @@
             self.CustomListData.deleteRow(index)
 
     def onCustomPreviewClick(self):
-        pass
+        indexes = self.CustomListView.selectedIndexes()
+        main_lines=[]
+        footer_lines = []
+        slide = None
+        for index in indexes:
+            id = self.CustomListData.getId(index)
+            customSlide = self.parent.custommanager.get_custom(id)
+            title = customSlide.title
+            credit = customSlide.title
+
+            songXML=SongXMLParser(customSlide.text)
+            verseList = songXML.get_verses()
+            for verse in verseList:
+                slide = self.parent.render_manager.format_slide(verse[1], False)
+
+            footer_lines.append(title + u' '+ credit)
+
+        frame=self.parent.render_manager.generate_slide(slide, footer_lines)
+        self.parent.preview_controller.previewFrame(frame)
 
     def onCustomLiveClick(self):
         pass

=== modified file 'openlp/plugins/videos/lib/filelistdata.py'
--- openlp/plugins/videos/lib/filelistdata.py	2009-03-15 19:31:33 +0000
+++ openlp/plugins/videos/lib/filelistdata.py	2009-04-25 06:11:15 +0000
@@ -80,3 +80,7 @@
     def getFilename(self, index):
         row = index.row()
         return self.items[row][0]
+
+    def getValue(self, index):
+        row = index.row()
+        return self.items[row][0]

=== modified file 'openlp/plugins/videos/lib/mediaitem.py'
--- openlp/plugins/videos/lib/mediaitem.py	2009-03-19 17:31:33 +0000
+++ openlp/plugins/videos/lib/mediaitem.py	2009-04-25 06:11:15 +0000
@@ -24,7 +24,6 @@
 
 from openlp.core import translate
 from openlp.core.lib import MediaManagerItem
-from openlp.core.resources import *
 
 from openlp.plugins.videos.lib import VideoTab
 from openlp.plugins.videos.lib import FileListData
@@ -40,93 +39,97 @@
     def __init__(self, parent, icon, title):
         MediaManagerItem.__init__(self, parent, icon, title)
 
-    def setupUi(self):        
+    def setupUi(self):
                 # Add a toolbar
         self.addToolbar()
         # Create buttons for the toolbar
         ## New Video Button ##
         self.addToolbarButton(
-            translate('VideoMediaItem',u'New Video'), 
+            translate('VideoMediaItem',u'New Video'),
             translate('VideoMediaItem',u'Load videos into openlp.org'),
             ':/videos/video_load.png', self.onVideoNewClick, 'VideoNewItem')
         ## Delete Video Button ##
         self.addToolbarButton(
-            translate('VideoMediaItem',u'Delete Video'), 
+            translate('VideoMediaItem',u'Delete Video'),
             translate('VideoMediaItem',u'Delete the selected video'),
             ':/videos/video_delete.png', self.onVideoDeleteClick, 'VideoDeleteItem')
         ## Separator Line ##
         self.addToolbarSeparator()
         ## Preview Video Button ##
         self.addToolbarButton(
-            translate('VideoMediaItem',u'Preview Video'), 
+            translate('VideoMediaItem',u'Preview Video'),
             translate('VideoMediaItem',u'Preview the selected video'),
             ':/system/system_preview.png', self.onVideoPreviewClick, 'VideoPreviewItem')
         ## Live Video Button ##
         self.addToolbarButton(
-            translate('VideoMediaItem',u'Go Live'), 
+            translate('VideoMediaItem',u'Go Live'),
             translate('VideoMediaItem',u'Send the selected video live'),
             ':/system/system_live.png', self.onVideoLiveClick, 'VideoLiveItem')
         ## Add Video Button ##
         self.addToolbarButton(
             translate('VideoMediaItem',u'Add Video To Service'),
-            translate('VideoMediaItem',u'Add the selected video(s) to the service'), 
+            translate('VideoMediaItem',u'Add the selected video(s) to the service'),
             ':/system/system_add.png',self.onVideoAddClick, 'VideoAddItem')
         ## Add the videolist widget ##
-        
+
         self.VideoListView = QtGui.QListView()
         self.VideoListView.setAlternatingRowColors(True)
         self.VideoListData = FileListData()
         self.VideoListView.setModel(self.VideoListData)
-        
+
         self.PageLayout.addWidget(self.VideoListView)
-        
+
         #define and add the context menu
         self.VideoListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
 
         self.VideoListView.addAction(self.contextMenuAction(
-            self.VideoListView, ':/system/system_preview.png', 
+            self.VideoListView, ':/system/system_preview.png',
             translate('VideoMediaItem',u'&Preview Video'), self.onVideoPreviewClick))
         self.VideoListView.addAction(self.contextMenuAction(
-            self.VideoListView, ':/system/system_live.png', 
+            self.VideoListView, ':/system/system_live.png',
             translate('VideoMediaItem',u'&Show Live'), self.onVideoLiveClick))
         self.VideoListView.addAction(self.contextMenuAction(
-            self.VideoListView, ':/system/system_add.png', 
+            self.VideoListView, ':/system/system_add.png',
             translate('VideoMediaItem',u'&Add to Service'), self.onVideoAddClick))
-        
+
     def initialise(self):
         list = self.parent.config.load_list(u'videos')
         self.loadVideoList(list)
 
     def onVideoNewClick(self):
-        files = QtGui.QFileDialog.getOpenFileNames(None, 
-            translate('VideoMediaItem', u'Select Video(s)'), 
+        files = QtGui.QFileDialog.getOpenFileNames(None,
+            translate('VideoMediaItem', u'Select Video(s)'),
             self.parent.config.get_last_dir(), u'Images (*.avi *.mpeg)')
         if len(files) > 0:
             self.loadVideoList(files)
             dir, filename = os.path.split(str(files[0]))
             self.parent.config.set_last_dir(dir)
             self.parent.config.set_list(u'videos', self.VideoListData.getFileList())
-            
+
     def getFileList(self):
         filelist = [item[0] for item in self.VideoListView];
-        return filelist            
+        return filelist
 
     def loadVideoList(self, list):
         for files in list:
             self.VideoListData.addRow(files)
-            
+
     def onVideoDeleteClick(self):
         indexes = self.VideoListView.selectedIndexes()
         for index in indexes:
             current_row = int(index.row())
             self.VideoListData.removeRow(current_row)
-        self.parent.config.set_list(u'videos', self.VideoListData.getFileList())            
+        self.parent.config.set_list(u'videos', self.VideoListData.getFileList())
 
     def onVideoPreviewClick(self):
-        pass
+        log.debug(u'Video Preview Button pressed')
+        items = self.VideoListView.selectedIndexes()
+        for item in items:
+            text = self.VideoListData.getValue(item)
+            print text
 
     def onVideoLiveClick(self):
         pass
 
     def onVideoAddClick(self):
-        pass        
+        pass

=== modified file 'openlp/plugins/videos/lib/videotab.py'
--- openlp/plugins/videos/lib/videotab.py	2009-03-15 19:31:33 +0000
+++ openlp/plugins/videos/lib/videotab.py	2009-04-15 04:58:51 +0000
@@ -21,8 +21,8 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core import translate
+from openlp import convertStringToBoolean
 from openlp.core.lib import SettingsTab
-from openlp.core.resources import *
 
 class VideoTab(SettingsTab):
     """
@@ -49,12 +49,12 @@
         self.UseVMRLabel = QtGui.QLabel(self.VideoModeGroupBox)
         self.UseVMRLabel.setObjectName("UseVMRLabel")
         self.VideoModeLayout.addWidget(self.UseVMRLabel)
-        
+
         self.VideoLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.VideoModeGroupBox)
-        # Signals and slots        
+        # Signals and slots
         QtCore.QObject.connect(self.UseVMRCheckBox,
-            QtCore.SIGNAL("stateChanged(int)"), self.onVMRCheckBoxChanged)             
-        
+            QtCore.SIGNAL("stateChanged(int)"), self.onVMRCheckBoxChanged)
+
     def retranslateUi(self):
         self.VideoModeGroupBox.setTitle(translate("SettingsForm", "Video Mode"))
         self.UseVMRCheckBox.setText(translate("SettingsForm", "Use Video Mode Rendering"))
@@ -69,11 +69,11 @@
         self.use_vmr_mode = False
         if use_vmr_mode == 2: # we have a set value convert to True/False
             self.use_vmr_mode = True
-    
+
     def load(self):
-        self.use_vmr_mode = self.convertStringToBoolean(self.config.get_config(u'use mode layout', u'False'))
+        self.use_vmr_mode = convertStringToBoolean(self.config.get_config(u'use mode layout', u'False'))
         if self.use_vmr_mode :
             self.UseVMRCheckBox.setChecked(True)
-        
+
     def save(self):
-        self.config.set_config(u'use mode layout', str(self.use_vmr_mode))        
+        self.config.set_config(u'use mode layout', str(self.use_vmr_mode))

=== modified file 'resources/forms/amendthemedialog.ui'
--- resources/forms/amendthemedialog.ui	2009-04-11 05:43:52 +0000
+++ resources/forms/amendthemedialog.ui	2009-04-21 19:45:50 +0000
@@ -1,13 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
  <class>AmendThemeDialog</class>
- <widget class="QWidget" name="AmendThemeDialog">
+ <widget class="QDialog" name="AmendThemeDialog">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>752</width>
-    <height>533</height>
+    <width>586</width>
+    <height>651</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -17,87 +20,74 @@
    <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>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 class="QWidget" name="">
-   <property name="geometry">
-    <rect>
-     <x>31</x>
-     <y>71</y>
-     <width>721</width>
-     <height>411</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>0</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">
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="AmendThemeLayout">
+   <property name="spacing">
+    <number>8</number>
+   </property>
+   <property name="margin">
+    <number>8</number>
+   </property>
+   <item>
+    <widget class="QWidget" name="ThemeNameWidget" native="true">
+     <layout class="QHBoxLayout" name="ThemeNameLayout">
+      <property name="spacing">
+       <number>8</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <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>
+   </item>
+   <item>
+    <widget class="QWidget" name="ContentWidget" native="true">
+     <layout class="QHBoxLayout" name="ContentLayout">
+      <property name="spacing">
+       <number>8</number>
+      </property>
+      <property name="margin">
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QTabWidget" name="ThemeTabWidget">
+        <property name="currentIndex">
+         <number>0</number>
+        </property>
+        <widget class="QWidget" name="BackgroundTab">
+         <attribute name="title">
+          <string>Background</string>
+         </attribute>
+         <layout class="QFormLayout" name="BackgroundLayout">
+          <property name="horizontalSpacing">
+           <number>8</number>
+          </property>
+          <property name="verticalSpacing">
+           <number>8</number>
+          </property>
+          <property name="margin">
+           <number>8</number>
+          </property>
+          <item row="0" column="0">
            <widget class="QLabel" name="BackgroundLabel">
             <property name="text">
              <string>Background:</string>
             </property>
            </widget>
           </item>
-          <item row="0" column="2" colspan="2">
+          <item row="0" column="1">
            <widget class="QComboBox" name="BackgroundComboBox">
             <item>
              <property name="text">
@@ -111,14 +101,14 @@
             </item>
            </widget>
           </item>
-          <item row="1" column="0" colspan="2">
+          <item row="1" column="0">
            <widget class="QLabel" name="BackgroundTypeLabel">
             <property name="text">
              <string>Background Type:</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="2" colspan="2">
+          <item row="1" column="1">
            <widget class="QComboBox" name="BackgroundTypeComboBox">
             <item>
              <property name="text">
@@ -144,7 +134,7 @@
             </property>
            </widget>
           </item>
-          <item row="2" column="2" colspan="2">
+          <item row="2" column="1">
            <widget class="QPushButton" name="Color1PushButton">
             <property name="text">
              <string/>
@@ -158,7 +148,7 @@
             </property>
            </widget>
           </item>
-          <item row="3" column="2" colspan="2">
+          <item row="3" column="1">
            <widget class="QPushButton" name="Color2PushButton">
             <property name="text">
              <string/>
@@ -172,28 +162,14 @@
             </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">
+          <item row="6" column="0">
            <widget class="QLabel" name="GradientLabel">
             <property name="text">
              <string>Gradient :</string>
             </property>
            </widget>
           </item>
-          <item row="5" column="2" colspan="2">
+          <item row="6" column="1">
            <widget class="QComboBox" name="GradientComboBox">
             <item>
              <property name="text">
@@ -212,518 +188,1015 @@
             </item>
            </widget>
           </item>
-         </layout>
-        </widget>
-       </widget>
-       <widget class="QWidget" name="FontMainTab">
-        <attribute name="title">
-         <string>Font Main</string>
-        </attribute>
-        <widget class="QGroupBox" name="MainFontGroupBox">
-         <property name="geometry">
-          <rect>
-           <x>20</x>
-           <y>10</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>160</y>
-           <width>301</width>
-           <height>190</height>
-          </rect>
-         </property>
-         <property name="title">
-          <string>Display Location</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout">
-          <item>
-           <widget class="QCheckBox" name="FontMainUseDefault">
-            <property name="text">
-             <string>Use default location</string>
-            </property>
-            <property name="tristate">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_3">
-            <item>
-             <widget class="QLabel" name="FontMainXLabel">
-              <property name="text">
-               <string>X Position:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontMainXEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_4">
-            <item>
-             <widget class="QLabel" name="FontMainYLabel">
-              <property name="text">
-               <string>Y Position:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontMainYEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_5">
-            <item>
-             <widget class="QLabel" name="FontMainWidthLabel">
-              <property name="text">
-               <string>Width</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontMainWidthEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_6">
-            <item>
-             <widget class="QLabel" name="FontMainHeightLabel">
-              <property name="text">
-               <string>Height</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontMainHeightEdit"/>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </widget>
-       <widget class="QWidget" name="FontFooterTab">
-        <attribute name="title">
-         <string>Font Footer</string>
-        </attribute>
-        <widget class="QGroupBox" name="FooterFontGroupBox_2">
-         <property name="geometry">
-          <rect>
-           <x>20</x>
-           <y>160</y>
-           <width>301</width>
-           <height>190</height>
-          </rect>
-         </property>
-         <property name="title">
-          <string>Display Location</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout_2">
-          <item>
-           <widget class="QCheckBox" name="FontMainUseDefault_2">
-            <property name="text">
-             <string>Use default location</string>
-            </property>
-            <property name="tristate">
-             <bool>false</bool>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_7">
-            <item>
-             <widget class="QLabel" name="FontFooterXLabel">
-              <property name="text">
-               <string>X Position:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontFooterXEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_8">
-            <item>
-             <widget class="QLabel" name="FontFooterYLabel">
-              <property name="text">
-               <string>Y Position:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontFooterYEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_9">
-            <item>
-             <widget class="QLabel" name="FontFooterWidthLabel">
-              <property name="text">
-               <string>Width</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontFooterWidthEdit"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_10">
-            <item>
-             <widget class="QLabel" name="FontFooterHeightLabel">
-              <property name="text">
-               <string>Height</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLineEdit" name="FontFooterHeightEdit"/>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-        <widget class="QGroupBox" name="FooterFontGroupBox_3">
-         <property name="geometry">
-          <rect>
-           <x>20</x>
-           <y>10</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="FontFooterlabel">
-            <property name="text">
-             <string>Font:</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1" colspan="2">
-           <widget class="QFontComboBox" name="FontFooterComboBox"/>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="FontFooterColorLabel">
-            <property name="text">
-             <string>Font Color</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="2">
-           <widget class="QPushButton" name="FontFooterColorPushButton">
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="FontFooterSizeLabel">
-            <property name="text">
-             <string>Size:</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <widget class="QLineEdit" name="FontFooterSizeLineEdit"/>
-          </item>
-          <item row="2" column="2">
-           <widget class="QSlider" name="FontFooterSlider">
-            <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>Alignment</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>58</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>58</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="QLabel" name="ThemePreview">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>60</y>
-         <width>311</width>
-         <height>271</height>
-        </rect>
-       </property>
-       <property name="frameShape">
-        <enum>QFrame::Box</enum>
-       </property>
-       <property name="frameShadow">
-        <enum>QFrame::Raised</enum>
-       </property>
-       <property name="lineWidth">
-        <number>2</number>
-       </property>
-       <property name="text">
-        <string/>
-       </property>
-       <property name="scaledContents">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </widget>
-    </item>
-   </layout>
-  </widget>
+          <item row="4" column="1">
+           <widget class="QWidget" name="ImageFilenameWidget" native="true">
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <property name="spacing">
+              <number>0</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QLineEdit" name="ImageLineEdit"/>
+             </item>
+             <item>
+              <widget class="QToolButton" name="ImageToolButton">
+               <property name="text">
+                <string/>
+               </property>
+               <property name="icon">
+                <iconset resource="../images/openlp-2.qrc">
+                 <normaloff>:/images/image_load.png</normaloff>:/images/image_load.png</iconset>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item row="7" column="1">
+           <spacer name="BackgroundSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>40</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="FontMainTab">
+         <attribute name="title">
+          <string>Font Main</string>
+         </attribute>
+         <layout class="QHBoxLayout" name="FontMainLayout">
+          <property name="spacing">
+           <number>8</number>
+          </property>
+          <property name="margin">
+           <number>8</number>
+          </property>
+          <item>
+           <widget class="QWidget" name="MainLeftWidget" native="true">
+            <layout class="QVBoxLayout" name="MainLeftLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="FontMainGroupBox">
+               <property name="title">
+                <string>Main Font</string>
+               </property>
+               <layout class="QFormLayout" name="MainFontLayout">
+                <property name="formAlignment">
+                 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+                </property>
+                <property name="horizontalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="verticalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="margin">
+                 <number>8</number>
+                </property>
+                <item row="0" column="0">
+                 <widget class="QLabel" name="FontMainlabel">
+                  <property name="text">
+                   <string>Font:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QFontComboBox" name="FontMainComboBox"/>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QLabel" name="FontMainColorLabel">
+                  <property name="text">
+                   <string>Font Color:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QPushButton" name="FontMainColorPushButton">
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="0">
+                 <widget class="QLabel" name="FontMainSize">
+                  <property name="text">
+                   <string>Size:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="1">
+                 <widget class="QSpinBox" name="FontMainSizeSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>70</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="value">
+                   <number>16</number>
+                  </property>
+                  <property name="suffix">
+                   <string>pt</string>
+                  </property>
+                  <property name="maximum">
+                   <number>999</number>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <spacer name="FontMainSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QWidget" name="MainRightWidget" native="true">
+            <layout class="QVBoxLayout" name="MainRightLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="MainLocationGroupBox">
+               <property name="title">
+                <string>Display Location</string>
+               </property>
+               <layout class="QFormLayout" name="MainLocationLayout">
+                <property name="horizontalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="verticalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="margin">
+                 <number>8</number>
+                </property>
+                <item row="0" column="0">
+                 <widget class="QLabel" name="DefaultLocationLabel">
+                  <property name="text">
+                   <string>Use Default Location:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QCheckBox" name="FontMainDefaultCheckBox">
+                  <property name="text">
+                   <string/>
+                  </property>
+                  <property name="tristate">
+                   <bool>false</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QLabel" name="FontMainXLabel">
+                  <property name="text">
+                   <string>X Position:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="0">
+                 <widget class="QLabel" name="FontMainYLabel">
+                  <property name="text">
+                   <string>Y Position:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="3" column="0">
+                 <widget class="QLabel" name="FontMainWidthLabel">
+                  <property name="text">
+                   <string>Width:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="4" column="0">
+                 <widget class="QLabel" name="FontMainHeightLabel">
+                  <property name="text">
+                   <string>Height:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QSpinBox" name="FontMainXSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="value">
+                   <number>0</number>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="1">
+                 <widget class="QSpinBox" name="FontMainYSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="3" column="1">
+                 <widget class="QSpinBox" name="FontMainWidthSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="4" column="1">
+                 <widget class="QSpinBox" name="FontMainHeightSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <spacer name="MainLocationSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="FontFooterTab">
+         <attribute name="title">
+          <string>Font Footer</string>
+         </attribute>
+         <layout class="QHBoxLayout" name="FontFooterLayout">
+          <property name="spacing">
+           <number>8</number>
+          </property>
+          <property name="margin">
+           <number>8</number>
+          </property>
+          <item>
+           <widget class="QWidget" name="FooterLeftWidget" native="true">
+            <layout class="QVBoxLayout" name="FooterLeftLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="FooterFontGroupBox">
+               <property name="title">
+                <string>Footer Font</string>
+               </property>
+               <layout class="QFormLayout" name="FooterFontLayout">
+                <property name="fieldGrowthPolicy">
+                 <enum>QFormLayout::ExpandingFieldsGrow</enum>
+                </property>
+                <property name="formAlignment">
+                 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+                </property>
+                <property name="horizontalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="verticalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="margin">
+                 <number>8</number>
+                </property>
+                <item row="0" column="0">
+                 <widget class="QLabel" name="FontFooterLabel">
+                  <property name="text">
+                   <string>Font:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QFontComboBox" name="FontFooterComboBox"/>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QLabel" name="FontFooterColorLabel">
+                  <property name="text">
+                   <string>Font Color:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QPushButton" name="FontFooterColorPushButton">
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="0">
+                 <widget class="QLabel" name="FontFooterSizeLabel">
+                  <property name="text">
+                   <string>Size:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="1">
+                 <widget class="QSpinBox" name="FontFooterSizeSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>70</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="value">
+                   <number>10</number>
+                  </property>
+                  <property name="suffix">
+                   <string>pt</string>
+                  </property>
+                  <property name="maximum">
+                   <number>999</number>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <spacer name="FontFooterSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QWidget" name="FooterRightWidget" native="true">
+            <layout class="QVBoxLayout" name="FooterRightLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="LocationFooterGroupBox">
+               <property name="title">
+                <string>Display Location</string>
+               </property>
+               <layout class="QFormLayout" name="LocationFooterLayout">
+                <property name="fieldGrowthPolicy">
+                 <enum>QFormLayout::ExpandingFieldsGrow</enum>
+                </property>
+                <property name="formAlignment">
+                 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+                </property>
+                <property name="horizontalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="verticalSpacing">
+                 <number>8</number>
+                </property>
+                <property name="margin">
+                 <number>8</number>
+                </property>
+                <item row="0" column="0">
+                 <widget class="QLabel" name="FontFooterDefaultLabel">
+                  <property name="text">
+                   <string>Use Default Location:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QCheckBox" name="FontFooterDefaultCheckBox">
+                  <property name="text">
+                   <string/>
+                  </property>
+                  <property name="tristate">
+                   <bool>false</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QLabel" name="FontFooterXLabel">
+                  <property name="text">
+                   <string>X Position:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="0">
+                 <widget class="QLabel" name="FontFooterYLabel">
+                  <property name="text">
+                   <string>Y Position:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="3" column="0">
+                 <widget class="QLabel" name="FontFooterWidthLabel">
+                  <property name="text">
+                   <string>Width:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="4" column="0">
+                 <widget class="QLabel" name="FontFooterHeightLabel">
+                  <property name="text">
+                   <string>Height:</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QSpinBox" name="FontFooterXSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="value">
+                   <number>0</number>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="2" column="1">
+                 <widget class="QSpinBox" name="FontFooterYSpinBox">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="value">
+                   <number>0</number>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="3" column="1">
+                 <widget class="QSpinBox" name="FontFooterWidthSpinBox">
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+                <item row="4" column="1">
+                 <widget class="QSpinBox" name="FontFooterHeightSpinBox">
+                  <property name="minimumSize">
+                   <size>
+                    <width>78</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="suffix">
+                   <string>px</string>
+                  </property>
+                  <property name="maximum">
+                   <number>9999</number>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <spacer name="FontFooterLocationSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="OtherOptionsTab">
+         <attribute name="title">
+          <string>Other Options</string>
+         </attribute>
+         <layout class="QHBoxLayout" name="OtherOptionsLayout">
+          <property name="spacing">
+           <number>8</number>
+          </property>
+          <property name="margin">
+           <number>8</number>
+          </property>
+          <item>
+           <widget class="QWidget" name="OptionsLeftWidget" native="true">
+            <layout class="QVBoxLayout" name="OptionsLeftLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="ShadowGroupBox">
+               <property name="title">
+                <string>Shadow &amp;&amp; Outline</string>
+               </property>
+               <layout class="QVBoxLayout" name="verticalLayout">
+                <property name="spacing">
+                 <number>8</number>
+                </property>
+                <property name="margin">
+                 <number>8</number>
+                </property>
+                <item>
+                 <widget class="QWidget" name="OutlineWidget" native="true">
+                  <layout class="QFormLayout" name="OutlineLayout">
+                   <property name="horizontalSpacing">
+                    <number>8</number>
+                   </property>
+                   <property name="verticalSpacing">
+                    <number>8</number>
+                   </property>
+                   <property name="margin">
+                    <number>0</number>
+                   </property>
+                   <item row="0" column="1">
+                    <widget class="QCheckBox" name="OutlineCheckBox">
+                     <property name="text">
+                      <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>
+                   <item row="0" column="0">
+                    <widget class="QLabel" name="OutlineEnabledLabel">
+                     <property name="text">
+                      <string>Show Outline:</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QWidget" name="ShadowWidget" native="true">
+                  <layout class="QFormLayout" name="ShadowLayout">
+                   <property name="horizontalSpacing">
+                    <number>8</number>
+                   </property>
+                   <property name="verticalSpacing">
+                    <number>8</number>
+                   </property>
+                   <property name="margin">
+                    <number>0</number>
+                   </property>
+                   <item row="0" column="1">
+                    <widget class="QCheckBox" name="ShadowCheckBox">
+                     <property name="text">
+                      <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>
+                   <item row="0" column="0">
+                    <widget class="QLabel" name="ShadowEnabledLabel">
+                     <property name="text">
+                      <string>Show Shadow:</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item>
+              <spacer name="ShadowSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QWidget" name="OptionsRightWidget" native="true">
+            <layout class="QVBoxLayout" name="OptionsRightLayout">
+             <property name="spacing">
+              <number>8</number>
+             </property>
+             <property name="margin">
+              <number>0</number>
+             </property>
+             <item>
+              <widget class="QGroupBox" name="AlignmentGroupBox">
+               <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>
+             </item>
+             <item>
+              <spacer name="AlignmentSpacer">
+               <property name="orientation">
+                <enum>Qt::Vertical</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>20</width>
+                 <height>40</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="PreviewGroupBox">
+     <property name="title">
+      <string>Preview</string>
+     </property>
+     <layout class="QHBoxLayout" name="ThemePreviewLayout">
+      <property name="spacing">
+       <number>8</number>
+      </property>
+      <property name="margin">
+       <number>8</number>
+      </property>
+      <item>
+       <spacer name="PreviewLeftSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QLabel" name="ThemePreview">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>300</width>
+          <height>225</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::WinPanel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="lineWidth">
+         <number>1</number>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="scaledContents">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="PreviewRightSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="ThemeButtonBox">
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
  </widget>
+ <tabstops>
+  <tabstop>ThemeButtonBox</tabstop>
+  <tabstop>ThemeNameEdit</tabstop>
+  <tabstop>ThemeTabWidget</tabstop>
+  <tabstop>BackgroundComboBox</tabstop>
+  <tabstop>BackgroundTypeComboBox</tabstop>
+  <tabstop>Color1PushButton</tabstop>
+  <tabstop>Color2PushButton</tabstop>
+  <tabstop>ImageLineEdit</tabstop>
+  <tabstop>ImageToolButton</tabstop>
+  <tabstop>GradientComboBox</tabstop>
+  <tabstop>FontMainComboBox</tabstop>
+  <tabstop>FontMainColorPushButton</tabstop>
+  <tabstop>FontMainSizeSpinBox</tabstop>
+  <tabstop>FontMainDefaultCheckBox</tabstop>
+  <tabstop>FontMainXSpinBox</tabstop>
+  <tabstop>FontMainYSpinBox</tabstop>
+  <tabstop>FontMainWidthSpinBox</tabstop>
+  <tabstop>FontMainHeightSpinBox</tabstop>
+  <tabstop>FontFooterComboBox</tabstop>
+  <tabstop>FontFooterColorPushButton</tabstop>
+  <tabstop>FontFooterSizeSpinBox</tabstop>
+  <tabstop>FontFooterDefaultCheckBox</tabstop>
+  <tabstop>FontFooterXSpinBox</tabstop>
+  <tabstop>FontFooterYSpinBox</tabstop>
+  <tabstop>FontFooterWidthSpinBox</tabstop>
+  <tabstop>FontFooterHeightSpinBox</tabstop>
+  <tabstop>OutlineCheckBox</tabstop>
+  <tabstop>OutlineColorPushButton</tabstop>
+  <tabstop>ShadowCheckBox</tabstop>
+  <tabstop>ShadowColorPushButton</tabstop>
+  <tabstop>HorizontalComboBox</tabstop>
+  <tabstop>VerticalComboBox</tabstop>
+ </tabstops>
  <resources>
   <include location="../images/openlp-2.qrc"/>
  </resources>
- <connections/>
+ <connections>
+  <connection>
+   <sender>ThemeButtonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>AmendThemeDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>375</x>
+     <y>466</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>375</x>
+     <y>241</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>ThemeButtonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>AmendThemeDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>375</x>
+     <y>466</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>375</x>
+     <y>241</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
 </ui>


Follow ups