diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py
index 78d469e73..95be246f3 100644
--- a/openlp/core/lib/toolbar.py
+++ b/openlp/core/lib/toolbar.py
@@ -36,6 +36,7 @@ class OpenLPToolbar(QtGui.QToolBar):
"""
A method to help developers easily add a button to the toolbar.
"""
+ ButtonIcon = None
if type(icon) is QtGui.QIcon:
ButtonIcon = icon
elif type(icon) is types.StringType:
@@ -46,9 +47,10 @@ class OpenLPToolbar(QtGui.QToolBar):
else:
ButtonIcon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(icon)),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
- ToolbarButton = self.addAction(ButtonIcon, title)
- if tooltip is not None:
- ToolbarButton.setToolTip(tooltip)
+ if ButtonIcon is not None:
+ ToolbarButton = self.addAction(ButtonIcon, title)
+ if tooltip is not None:
+ ToolbarButton.setToolTip(tooltip)
if slot is not None:
QtCore.QObject.connect(ToolbarButton, QtCore.SIGNAL('triggered()'), slot)
self.icons[title]=ButtonIcon
diff --git a/openlp/core/pluginmanager.py b/openlp/core/pluginmanager.py
index c6d7c1542..fa3c33442 100644
--- a/openlp/core/pluginmanager.py
+++ b/openlp/core/pluginmanager.py
@@ -45,7 +45,7 @@ class PluginManager(object):
self.basepath = os.path.abspath(dir)
log.debug("Base path %s ", self.basepath)
self.plugins = []
- # this has to happen after the UI is sroted self.find_plugins(dir)
+ # this has to happen after the UI is sorted self.find_plugins(dir)
log.info("Plugin manager done init")
def find_plugins(self, dir, preview_controller, live_controller): # xxx shouldn't dir come from self.basepath
diff --git a/openlp/core/render.py b/openlp/core/render.py
index 22b944752..41a1643ab 100644
--- a/openlp/core/render.py
+++ b/openlp/core/render.py
@@ -375,14 +375,19 @@ class Renderer:
print "_get_extent_and_render", [line], tlcorner, dodraw
p=QtGui.QPainter()
p.begin(self._paint)
- # use this to scale for rendering in "operators view" xxx
-# p.SetUserScale(0.5,0.5)
# 'twould be more efficient to set this once when theme changes
# or p changes
font=QtGui.QFont(self._theme.FontName,
self._theme.FontProportion, # size
QtGui.QFont.Normal, # weight
0)# italic
+ # to make the unit tests monitor independent, we have to be able to
+ # specify whether a font proportion is in pixels or points
+ if self._theme.FontUnits.lower() == "pixels":
+ print "pixels"
+ font.setPixelSize(self._theme.FontProportion)
+ print self._theme.FontName, self._theme.FontProportion
+ print font.family(), font.pointSize()
p.setFont(font)
if color == None:
p.setPen(self._theme.FontColor)
diff --git a/openlp/core/test/data_for_tests/render_theme.xml b/openlp/core/test/data_for_tests/render_theme.xml
index 445a7eba1..0958cc5c6 100644
--- a/openlp/core/test/data_for_tests/render_theme.xml
+++ b/openlp/core/test/data_for_tests/render_theme.xml
@@ -7,7 +7,8 @@
Tahoma
$00007F
- 32
+ 53
+ pixels
0
$000000
0
diff --git a/openlp/core/test/test_mediamanageritem.py b/openlp/core/test/test_mediamanageritem.py
index 22113707b..96d0fd460 100644
--- a/openlp/core/test/test_mediamanageritem.py
+++ b/openlp/core/test/test_mediamanageritem.py
@@ -19,16 +19,13 @@ import os, sys
mypath=os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..')))
-from openlp.plugins import MediaManagerItem
+from openlp.core.lib import MediaManagerItem
class TestMediaManager:
def setup_class(self):
self.app = QtGui.QApplication([])
logging.info ("App is " + str(self.app))
self.main_window = QtGui.QMainWindow()
self.main_window.resize(200, 600)
-# self.StatusBar = QtGui.QStatusBar(self.main_window)
-# self.StatusBar.setObjectName("StatusBar")
-# self.main_window.setStatusBar(self.StatusBar)
self.MediaManagerDock = QtGui.QDockWidget(self.main_window)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
@@ -39,34 +36,29 @@ class TestMediaManager:
icon.addPixmap(QtGui.QPixmap(":/system/system_mediamanager.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.MediaManagerDock.setWindowIcon(icon)
self.MediaManagerDock.setFloating(False)
-# self.MediaManagerDock.setObjectName("MediaManagerDock")
self.MediaManagerContents = QtGui.QWidget()
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.MediaManagerContents.sizePolicy().hasHeightForWidth())
self.MediaManagerContents.setSizePolicy(sizePolicy)
-# self.MediaManagerContents.setObjectName("MediaManagerContents")
self.MediaManagerLayout = QtGui.QHBoxLayout(self.MediaManagerContents)
self.MediaManagerLayout.setContentsMargins(0, 2, 0, 0)
-# self.MediaManagerLayout.setObjectName("MediaManagerLayout")
self.MediaToolBox = QtGui.QToolBox(self.MediaManagerContents)
-# self.MediaToolBox.setObjectName("MediaToolBox")
self.MediaManagerDock.setWidget(self.MediaManagerContents)
self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.MediaManagerDock)
self.MediaManagerLayout.addWidget(self.MediaToolBox)
def test1(self):
log=logging.getLogger("test1")
log.info("Start")
-# i1=MediaManagerItem()
-# i2=MediaManagerItem()
i1=MediaManagerItem(self.MediaToolBox)
i2=MediaManagerItem(self.MediaToolBox)
- i2.choose_area.text="More Stuff"
log.info("i1"+str(i1))
log.info("i2"+str(i2))
- self.MediaToolBox.addItem(i1, i1.icon, "Test1")
- self.MediaToolBox.addItem(i2, i2.icon, "Test2")
+ i1.addToolbar()
+ i1.addToolbarButton("Test1", "Test1", None)
+ i2.addToolbar()
+ i2.addToolbarButton("Test2", "Test2", None)
self.MediaToolBox.setItemText(self.MediaToolBox.indexOf(i1), QtGui.QApplication.translate("main_window", "Item1", None, QtGui.QApplication.UnicodeUTF8))
self.MediaToolBox.setItemText(self.MediaToolBox.indexOf(i2), QtGui.QApplication.translate("main_window", "Item2", None, QtGui.QApplication.UnicodeUTF8))
log.info("Show window")
diff --git a/openlp/core/test/test_plugin_manager.py b/openlp/core/test/test_plugin_manager.py
index bf04ec269..1736d67fb 100644
--- a/openlp/core/test/test_plugin_manager.py
+++ b/openlp/core/test/test_plugin_manager.py
@@ -23,7 +23,9 @@ from openlp.core.pluginmanager import PluginManager
# test the plugin manager with some plugins in the test_plugins directory
class TestPluginManager:
def test_init(self):
- p=PluginManager("./testplugins")
+ self.p=PluginManager("./testplugins")
+ p=self.p
+ p.find_plugins('./testplugins', None, None)
assert (len(p.plugins)==2);
# get list of the names of the plugins
names=[plugin.name for plugin in p.plugins]
@@ -37,6 +39,8 @@ class TestPluginManager:
assert p.plugins[1].name=="testplugin1"
if __name__=="__main__":
log.debug("Starting")
- p=PluginManager("./testplugins")
- for plugin in p.plugins:
+ t=TestPluginManager()
+ t.test_init()
+ log.debug("List of plugins found:")
+ for plugin in t.p.plugins:
log.debug("Plugin %s, name=%s (version=%d)"%(str(plugin), plugin.name, plugin.version))
diff --git a/openlp/core/test/test_render.py b/openlp/core/test/test_render.py
index f843b113b..18a480de0 100644
--- a/openlp/core/test/test_render.py
+++ b/openlp/core/test/test_render.py
@@ -213,6 +213,7 @@ if __name__=="__main__":
t=TestRender()
t.setup_class()
t.setup_method(None)
+ t.test_easy()
t.test_splits()
t.teardown_method(None)
diff --git a/openlp/core/test/test_render_theme.py b/openlp/core/test/test_render_theme.py
index c4828ab68..9bd66a1ae 100644
--- a/openlp/core/test/test_render_theme.py
+++ b/openlp/core/test/test_render_theme.py
@@ -21,10 +21,33 @@ import sys
import os
mypath=os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..', '..','..')))
-from openlp.theme import Theme
+from openlp.core.theme import Theme
from openlp.core import Renderer
from PyQt4 import QtGui, QtCore
+
+def compare_images(goldenim, testim, threshold=0.01):
+ # easy test first
+ if goldenim == testim:
+ return 1
+ # how close are they? Calculated the sum of absolute differences in
+ # each channel of each pixel and divide by the number of pixels in the image
+ # if this sum is < threshold, the images are deemed to be "close enough"
+ sad=0;
+ for x in range(goldenim.width()):
+ for y in range(goldenim.height()):
+ p1=goldenim.pixel(x,y)
+ p2=testim.pixel(x,y)
+ sad += abs((p1&0xFF)-(p2&0xFF))
+ sad += abs((p1>>8&0xFF)-(p2>>8&0xFF))
+ sad += abs((p1>>16&0xFF)-(p2>>16&0xFF))
+ sad /= float(goldenim.width()*goldenim.height())
+ if (sad < threshold):
+ return 1
+
+ return 0
+
+
class TestRenderTheme(TestRender_base):
# {{{ Basics
@@ -34,7 +57,7 @@ class TestRenderTheme(TestRender_base):
TestRender_base.setup_method(self, method)
print "Theme setup", method
# print "setup theme"
- self.r.set_theme(Theme()) # set "blank" theme
+ self.r.set_theme(Theme('blank_theme.xml')) # set "blank" theme
self.r.set_text_rectangle(QtCore.QRect(0,0, self.size.width(), self.size.height()))
words="""How sweet the name of Jesus sounds
In a believer's ear!
@@ -70,7 +93,7 @@ And drives away his fear.
else:
print "File", goldenfilename, "not found"
return False
- if (goldenim == im):
+ if (compare_images(goldenim, im)):
print name, "Images match"
return True
else:
@@ -80,6 +103,7 @@ And drives away his fear.
def test_theme_basic(self):
self.answer=self.r.render_screen(0)
self.bmpname=whoami()
+ print self.r._theme.FontProportion
print self.answer, self.expected_answer, self.answer==self.expected_answer
# self.msg=self.bmpname
@@ -105,14 +129,12 @@ And drives away his fear.
# }}}
# {{{ backgrounds
def test_bg_stretch_y(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join('data_for_tests', "snowsmall.jpg");
t.BackgroundParameter2 = QtGui.QColor(0,0,64);
t.BackgroundParameter3 = 0
t.Name="stretch y"
- print t
- print "set theme"
self.r.set_theme(t)
print "render"
self.answer=self.r.render_screen(0)
@@ -120,7 +142,7 @@ And drives away his fear.
self.bmpname=whoami()
print "fone"
def test_bg_shrink_y(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join('data_for_tests', "snowbig.jpg");
t.BackgroundParameter2 = QtGui.QColor(0,0,64);
@@ -131,7 +153,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_bg_stretch_x(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join('data_for_tests', "treessmall.jpg");
t.BackgroundParameter2 = QtGui.QColor(0,0,64);
@@ -144,7 +166,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_bg_shrink_x(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join('data_for_tests', "treesbig.jpg");
t.BackgroundParameter2 = QtGui.QColor(0,0,64);
@@ -158,7 +180,7 @@ And drives away his fear.
# }}}
# {{{ Vertical alignment
def test_theme_vertical_align_top(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 0
@@ -168,7 +190,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_theme_vertical_align_bot(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 1
@@ -179,7 +201,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_theme_vertical_align_cen(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 2
@@ -191,7 +213,7 @@ And drives away his fear.
# }}}
# {{{ Horzontal alignment
def test_theme_horizontal_align_left(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 0
@@ -202,7 +224,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_theme_horizontal_align_right(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 0
@@ -214,7 +236,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_theme_horizontal_align_centre(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 0
@@ -226,7 +248,7 @@ And drives away his fear.
self.bmpname=whoami()
def test_theme_horizontal_align_left_lyric(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.VerticalAlign = 0
@@ -241,7 +263,8 @@ And drives away his fear.
# }}}
# {{{ Shadows and outlines
def test_theme_shadow_outline(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
+
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,0);
t.Name="shadow/outline"
@@ -259,7 +282,7 @@ And drives away his fear.
self.bmpname=whoami()
# }}}
def test_theme_font(self):
- t=Theme()
+ t=Theme('blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64);
t.Name="font"
@@ -274,5 +297,5 @@ if __name__=="__main__":
t=TestRenderTheme()
t.setup_class()
t.setup_method(None)
- t.test_theme_font()
+ t.test_bg_stretch_y()
t.teardown_method(None)
diff --git a/openlp/core/theme/test/test_theme.py b/openlp/core/theme/test/test_theme.py
index 5ab7791ec..f4b760d4e 100644
--- a/openlp/core/theme/test/test_theme.py
+++ b/openlp/core/theme/test/test_theme.py
@@ -1,26 +1,8 @@
-"""
-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 os
import sys
mypath=os.path.split(os.path.abspath(__file__))[0]
-sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..','..')))
+sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..', '..')))
print sys.path
from openlp.core.theme import Theme
@@ -38,6 +20,7 @@ def test_read_theme():
assert(t.FontColor == QtGui.QColor(255,255,255))
assert(t.FontName == "Tahoma")
assert(t.FontProportion == 16)
+ assert(t.FontUnits == "pixels")
assert(t.HorizontalAlign == 2)
assert(t.Name == "openlp.org Packaged Theme")
assert(t.Outline == -1)
@@ -45,6 +28,7 @@ def test_read_theme():
assert(t.Shadow == -1)
assert(t.ShadowColor == QtGui.QColor(0,0,1))
assert(t.VerticalAlign == 0)
+def test_theme():
# test we create a "blank" theme correctly
t=Theme()
print t
@@ -56,16 +40,16 @@ def test_read_theme():
assert(t.FontName == "Arial")
assert(t.FontProportion == 30)
assert(t.HorizontalAlign == 0)
+ assert(t.FontUnits == "pixels")
assert(t.Name == "BlankStyle")
assert(t.Outline == 0)
assert(t.Shadow == 0)
assert(t.VerticalAlign == 0)
-
+
print "Tests passed"
-def test_theme():
- test_read_theme()
-
+
if __name__=="__main__":
test_read_theme()
+ test_theme()
diff --git a/openlp/core/theme/test/test_theme.xml b/openlp/core/theme/test/test_theme.xml
index 63dfc1519..0e2e98284 100644
--- a/openlp/core/theme/test/test_theme.xml
+++ b/openlp/core/theme/test/test_theme.xml
@@ -8,6 +8,7 @@
Tahoma
clWhite
16
+ pixels
-1
$00000001
-1
diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py
index a56e67e3b..81f94a9ce 100644
--- a/openlp/core/theme/theme.py
+++ b/openlp/core/theme/theme.py
@@ -1,30 +1,15 @@
-# -*- 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
+import platform
+ver = platform.python_version()
+if ver >= '2.5':
+ from xml.etree.ElementTree import ElementTree, XML
+else:
+ from elementtree import ElementTree, XML
-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 sys
-import os
from PyQt4 import QtGui
-sys.path.append(os.path.abspath("./../.."))
-from openlp.core.lib import XmlRootClass
+DelphiColors={"clRed":0xFF0000,
+ "clBlack":0x000000,
+ "clWhite":0xFFFFFF}
blankstylexml=\
'''
@@ -37,6 +22,7 @@ blankstylexml=\
Arial
clWhite
30
+ pixels
0
0
0
@@ -45,16 +31,12 @@ blankstylexml=\
'''
-DelphiColors={"clRed":0xFF0000,
- "clBlack":0x000000,
- "clWhite":0xFFFFFF}
-
-class Theme(XmlRootClass):
+class Theme:
def __init__(self, xmlfile=None):
""" stores the info about a theme
attributes:
name : theme name
-
+
BackgroundType : 0 - solid color
1 - gradient color
2 - image
@@ -67,10 +49,11 @@ class Theme(XmlRootClass):
for solid - N/A
BackgroundParameter3 : for image - N/A
for gradient - 0 -> vertical, 1 -> horizontal
-
+
FontName : name of font to use
FontColor : color for main font
- FontProportion : point size of font
+ FontProportion : size of font
+ FontUnits : whether size of font is in or
Shadow : 0 - no shadow, non-zero use shadow
ShadowColor : color for drop shadow
@@ -87,19 +70,59 @@ class Theme(XmlRootClass):
1 - lyrics
"""
# init to defaults
- self._setFromXml(blankstylexml, 'Theme')
+ self._set_from_XML(blankstylexml)
if xmlfile != None:
# init from xmlfile
file=open(xmlfile)
t=''.join(file.readlines()) # read the file and change list to a string
- self._setFromXml(t, 'Theme')
+ self._set_from_XML(t)
- def post_tag_hook(self, tag, val):
- if DelphiColors.has_key(val):
- val=DelphiColors[val]
- if (tag.find("Color") > 0 or
- (tag.find("BackgroundParameter") == 0 and type(val) == type(0))):
- # convert to a QtGui.Color
- val= QtGui.QColor((val>>16) & 0xFF, (val>>8)&0xFF, val&0xFF)
+ def _get_as_string(self):
+ s=""
+ keys=dir(self)
+ keys.sort()
+ for k in keys:
+ if k[0:1] != "_":
+ s+= "_%s_" %(getattr(self,k))
+ return s
+ def _set_from_XML(self, xml):
+ root=ElementTree(element=XML(xml))
+ iter=root.getiterator()
+ for element in iter:
+ if element.tag != "Theme":
+ t=element.text
+# print element.tag, t, type(t)
+ if type(t) == type(None): # easy!
+ val=t
+ if type(t) == type(" "): # strings need special handling to sort the colours out
+# print "str",
+ if t[0] == "$": # might be a hex number
+# print "hex",
+ try:
+ val=int(t[1:], 16)
+ except ValueError: # nope
+# print "nope",
+ pass
+ elif DelphiColors.has_key(t):
+# print "colour",
+ val=DelphiColors[t]
+ else:
+ try:
+ val=int(t)
+ except ValueError:
+ val=t
+ if (element.tag.find("Color") > 0 or
+ (element.tag.find("BackgroundParameter") == 0 and type(val) == type(0))):
+ # convert to a wx.Colour
+ val= QtGui.QColor((val>>16) & 0xFF, (val>>8)&0xFF, val&0xFF)
+ # print [val]
+ setattr(self,element.tag, val)
+
+
+ def __str__(self):
+ s=""
+ for k in dir(self):
+ if k[0:1] != "_":
+ s+= "%30s : %s\n" %(k,getattr(self,k))
+ return s
- return (tag, val)