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)