This commit is contained in:
rimach 2010-04-09 21:27:22 +02:00
commit 7a9d8c97aa
101 changed files with 2724 additions and 4351 deletions

View File

@ -172,7 +172,7 @@ from mediamanageritem import MediaManagerItem
from xmlrootclass import XmlRootClass
from serviceitem import ServiceItem
from serviceitem import ServiceItemType
from serviceitem import ServiceItem
from serviceitem import ItemCapabilities
from toolbar import OpenLPToolbar
from dockwidget import OpenLPDockWidget
from songxmlhandler import SongXMLBuilder, SongXMLParser

View File

@ -109,6 +109,12 @@ class EventReceiver(QtCore.QObject):
``presentation types``
Informs all components of the presentation types supported.
``blank_check``
Check to see if th eblank display message is required
``version_check``
Version has changed so pop up window.
"""
def __init__(self):
"""

View File

@ -419,7 +419,7 @@ class MediaManagerItem(QtGui.QWidget):
QtGui.QMessageBox.information(self,
self.trUtf8('No Service Item Selected'),
self.trUtf8('You must select a existing service item to add to.'))
elif self.title == service_item.name:
elif self.title.lower() == service_item.name.lower():
self.generateSlideData(service_item)
self.parent.service_manager.addServiceItem(service_item)
else:

View File

@ -49,7 +49,7 @@ class RenderManager(object):
"""
log.info(u'RenderManager Loaded')
def __init__(self, theme_manager, screens, screen_number=0):
def __init__(self, theme_manager, screens):
"""
Initialise the render manager.
"""
@ -57,7 +57,6 @@ class RenderManager(object):
self.screens = screens
self.theme_manager = theme_manager
self.renderer = Renderer()
self.screens.set_current_display(screen_number)
self.calculate_default(self.screens.current[u'size'])
self.theme = u''
self.service_theme = u''
@ -65,12 +64,9 @@ class RenderManager(object):
self.override_background = None
self.themedata = None
def update_display(self, screen_number):
def update_display(self):
"""
Updates the render manager's information about the current screen.
``screen_number``
The updated index of the output/display screen.
"""
log.debug(u'Update Display')
self.calculate_default(self.screens.current[u'size'])

View File

@ -42,6 +42,13 @@ class ServiceItemType(object):
Image = 2
Command = 3
class ItemCapabilities(object):
AllowsPreview = 1
AllowsEdit = 2
AllowsMaintain = 3
RequiresMedia = 4
class ServiceItem(object):
"""
The service item is a base class for the plugins to use to interact with
@ -67,14 +74,18 @@ class ServiceItem(object):
self.raw_footer = None
self.theme = None
self.service_item_type = None
self.edit_enabled = False
self.maintain_allowed = False
self._raw_frames = []
self._display_frames = []
self._uuid = unicode(uuid.uuid1())
self.auto_preview_allowed = False
self.notes = u''
self.from_plugin = False
self.capabilities = []
def add_capability(self, capability):
self.capabilities.append(capability)
def is_capable(self, capability):
return capability in self.capabilities
def addIcon(self, icon):
"""
@ -207,10 +218,8 @@ class ServiceItem(object):
u'type':self.service_item_type,
u'audit':self.audit,
u'notes':self.notes,
u'preview':self.auto_preview_allowed,
u'edit':self.edit_enabled,
u'maintain':self.maintain_allowed,
u'from_plugin':self.from_plugin
u'from_plugin':self.from_plugin,
u'capabilities':self.capabilities
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
@ -244,11 +253,9 @@ class ServiceItem(object):
self.addIcon(header[u'icon'])
self.raw_footer = header[u'footer']
self.audit = header[u'audit']
self.auto_preview_allowed = header[u'preview']
self.notes = header[u'notes']
self.edit_enabled = header[u'edit']
self.maintain_allowed = header[u'maintain']
self.from_plugin = header[u'from_plugin']
self.capabilities = header[u'capabilities']
if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']:
self._raw_frames.append(slide)
@ -284,11 +291,8 @@ class ServiceItem(object):
"""
return self._uuid != other._uuid
def is_song(self):
return self.name.lower() == u'songs'
def is_media(self):
return self.name.lower() == u'media'
return ItemCapabilities.RequiresMedia in self.capabilities
def is_command(self):
return self.service_item_type == ServiceItemType.Command

View File

@ -54,6 +54,7 @@ class SettingsTab(QtGui.QWidget):
self.config = PluginConfig(title)
else:
self.config = PluginConfig(section)
self.preLoad()
self.load()
def setupUi(self):
@ -62,6 +63,12 @@ class SettingsTab(QtGui.QWidget):
"""
pass
def preLoad(self):
"""
Setup the tab's interface.
"""
pass
def retranslateUi(self):
"""
Setup the interface translation strings.

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Theme>
<Name>openlp.org Packaged Theme</Name>
<BackgroundType>0</BackgroundType>
<BackgroundParameter1>clWhite</BackgroundParameter1>
<BackgroundParameter2/>
<BackgroundParameter3/>
<FontName>Tahoma</FontName>
<FontColor>$00007F</FontColor>
<FontProportion>53</FontProportion>
<FontUnits>pixels</FontUnits>
<Shadow>0</Shadow>
<ShadowColor>$000000</ShadowColor>
<Outline>0</Outline>
<OutlineColor>$000000</OutlineColor>
<HorizontalAlign>0</HorizontalAlign>
<VerticalAlign>0</VerticalAlign>
<WrapStyle>1</WrapStyle>
</Theme>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -1,110 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import sys
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-30s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename='plugins.log',
filemode='w')
console=logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)24s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'Logging started')
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..')))
class TestMediaManager:
def setup_class(self):
self.app = QtGui.QApplication([])
logging.info (u'App is ' + unicode(self.app))
self.main_window = QtGui.QMainWindow()
self.main_window.resize(200, 600)
self.MediaManagerDock = QtGui.QDockWidget(self.main_window)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(
self.MediaManagerDock.sizePolicy().hasHeightForWidth())
self.MediaManagerDock.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(u':/system/system_mediamanager.png'),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.MediaManagerDock.setWindowIcon(icon)
self.MediaManagerDock.setFloating(False)
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.MediaManagerLayout = QtGui.QHBoxLayout(self.MediaManagerContents)
self.MediaManagerLayout.setContentsMargins(0, 2, 0, 0)
self.MediaToolBox = QtGui.QToolBox(self.MediaManagerContents)
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(u'test1')
log.info(u'Start')
i1=MediaManagerItem(self.MediaToolBox)
i2=MediaManagerItem(self.MediaToolBox)
log.info(u'i1'+unicode(i1))
log.info(u'i2'+unicode(i2))
i1.addToolbar()
i1.addToolbarButton(u'Test1', u'Test1', None)
i2.addToolbar()
i2.addToolbarButton(u'Test2', u'Test2', None)
self.MediaToolBox.setItemText(
self.MediaToolBox.indexOf(i1), self.trUtf8('Item1'))
self.MediaToolBox.setItemText(
self.MediaToolBox.indexOf(i2), self.trUtf8('Item2'))
log.info(u'Show window')
self.main_window.show()
log.info(u'End')
return 1
if __name__ == "__main__":
t=TestMediaManager()
t.setup_class()
t.test1()
log.info(u'exec')
sys.exit(t.app.exec_())

View File

@ -1,74 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import 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',
filename='plugins.log',
filemode='w')
console=logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'Logging started')
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..')))
# test the plugin manager with some plugins in the test_plugins directory
class TestPluginManager:
def test_init(self):
self.p = PluginManager(u'./testplugins')
p = self.p
p.find_plugins(u'./testplugins', None, None)
assert(len(p.plugins) == 2)
# get list of the names of the plugins
names = [plugin.name for plugin in p.plugins]
# see which ones we've got
assert(u'testplugin1' in names)
assert(u'testplugin2' in names)
# and not got - it's too deep in the hierarchy!
assert(u'testplugin3' not in names)
# test that the weighting is done right
assert(p.plugins[0].name == "testplugin2")
assert(p.plugins[1].name == "testplugin1")
if __name__ == "__main__":
log.debug(u'Starting')
t = TestPluginManager()
t.test_init()
log.debug(u'List of plugins found:')
for plugin in t.p.plugins:
log.debug(u'Plugin %s, name=%s (version=%d)' %(unicode(plugin),
plugin.name, plugin.version))

View File

@ -1,241 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import sys
import os
import os.path
from PyQt4 import QtGui, QtCore
from openlp.core.theme import Theme
from openlp.core.lib import Renderer
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0, (os.path.join(mypath, '..', '..', '..')))
# from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66062
def whoami(depth=1):
return sys._getframe(depth).f_code.co_name
class TstFrame:
# {{{ init
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
# }}}
class TestRender_base:
def __init__(self):
if not os.path.exists(u'test_results'):
os.mkdir(u'test_results')
self.app = None
def write_to_file(self, pixmap, name):
im=pixmap.toImage()
testpathname = os.path.join(u'test_results', name+'.bmp')
if os.path.exists(testpathname):
os.unlink(testpathname)
im.save(testpathname, 'bmp')
return im
# xxx quitting the app still leaves it hanging aroudn so we die
# when trying to start another one. Not quitting doesn't help
# though This means that the py.test runs both test modules in
# sequence and the second one tries to create another application
# which gives us errors :(
def setup_class(self):
print "class setup", self
try:
if self.app is None:
pass
except AttributeError: # didn't have one
print "No app"
self.app = None
print "Test app (should be None)"
if self.app is None:
print "App is None"
self.app = QtGui.QApplication([])
else:
print "class setup, app is", app
# self.app = QtGui.QApplication([])
def teardown_class(self):
print "class quit", self, self.app
self.app.quit()
def setup_method(self, method):
print "SSsetup", method
if not hasattr(self, 'app'):
self.app = None
try: # see if we already have an app for some reason.
# have to try and so something, cant just test against None
print "app", self.app, ";;;"
print self.app.quit()
print "quitted"
except RuntimeError: # not valid app, create one
print "Runtime error"
except AttributeError: # didn't have one
print "Attribute error"
# print "App", self.app
# self.app = QtGui.QApplication([])
print "Application created and sorted"
self.size = QtCore.QSize(800,600)
frame = TstFrame(size = self.size)
self.frame = frame
self.paintdest = frame.GetPixmap()
self.renderer = Renderer()
self.renderer.set_paint_dest(self.paintdest)
self.expected_answer = "Don't know yet"
self.answer = None
print "--------------- Setup Done -------------"
def teardown_method(self, method):
self.write_to_file(self.frame.GetPixmap(), 'test_render')
class TestRender(TestRender_base):
def __init__(self):
TestRender_base.__init__(self)
def setup_method(self, method):
TestRender_base.setup_method(self, method)
self.renderer.set_debug(1)
themefile = os.path.abspath(u'data_for_tests/render_theme.xml')
self.renderer.set_theme(Theme(themefile)) # set default theme
self.renderer._render_background()
self.renderer.set_text_rectangle(QtCore.QRect(
0,0, self.size.width()-1, self.size.height()-1))
self.msg = None
def test_easy(self):
answer = self.renderer._render_single_line(
u'Test line', tlcorner = (0,100))
assert(answer == (219,163))
def test_longer(self):
answer = self.renderer._render_single_line(
u'Test line with more words than fit on one line',
tlcorner = (10,10))
assert(answer == (753,136))
def test_even_longer(self):
answer = self.renderer._render_single_line(
u'Test line with more words than fit on either one or two lines',
tlcorner = (10,10))
assert(answer == (753,199))
def test_lines(self):
lines = []
lines.append(u'Line One')
lines.append(u'Line Two')
lines.append(u'Line Three and should be long enough to wrap')
lines.append(u'Line Four and should be long enough to wrap also')
answer = self.renderer._render_lines(lines)
assert(answer == QtCore.QRect(0,0,741,378))
def test_set_words_openlp(self):
words="""
Verse 1: Line 1
Line 2
Verse 2: Line 1
Line 2
Verse 3: Line 1
Line 2
Line 3"""
expected_answer = ["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"]
answer = self.renderer.set_words_openlp(words)
assert(answer == expected_answer)
def test_render_screens(self):
words="""
Verse 1: Line 1
Line 2
Verse 2: Line 1
Line 2
Verse 3: Line 1
Line 2
Line 3"""
verses = self.renderer.set_words_openlp(words)
expected_answer = ["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"]
assert(verses == expected_answer)
expected_answer = [QtCore.QRect(0,0,397,126), QtCore.QRect(0,0,397,126),
QtCore.QRect(0,0,397,189)]
for v in range(len(verses)):
answer=self.renderer.render_screen(v)
# print v, answer.x(), answer.y(), answer.width(), answer.height()
assert(answer == expected_answer[v])
def split_test(self, number, answer, expected_answers):
lines=[]
print "Split test", number, answer
for i in range(number):
extra=""
if i == 51: # make an extra long line on line 51 to test wrapping
extra = "Some more words to make it wrap around don't you know until it wraps so many times we don't know what to do"
lines.append(u'Line %d %s' % (i, extra))
result = self.renderer.split_set_of_lines(lines)
print "results---------------__", result
for i in range(len(result)):
self.setup_method(None)
answer = self.renderer._render_lines(result[i])
print answer
self.write_to_file(self.frame.GetPixmap(), "split_test_%03d"% i)
print number, i, answer.x(), answer.y(), answer.width(), \
answer.height()
e = expected_answers[i]
assert(answer == QtCore.QRect(e[0],e[1],e[2],e[3]))
def test_splits(self):
print "Test splits"
self.split_test(100, 11, [(0,0,180,567), (0,0,214,567), (0,0,214,567),
(0,0,214,567), (0,0,214,567), (0,0,214,378), (0,0,759,567),
(0,0,214,567), (0,0,214,567), (0,0,214,567), (0,0,214,567),
(0,0,214,567), (0,0,214,567)])
self.split_test(30, 4, [ (0,0,180,441), (0,0,214,441), (0,0,214,441),
(0,0,214,441)])
self.split_test(20, 3, [(0,0,180,378), (0,0,214,378), (0,0,214,378)])
self.split_test(12, 2, [(0,0,180,378), (0,0,214,378)])
self.split_test(4, 1, [(0,0,180,252)])
self.split_test(6, 1, [(0,0,180,378)])
self.split_test(8, 1, [(0,0,180,504)])
if __name__ == "__main__":
t = TestRender()
t.setup_class()
t.setup_method(None)
t.test_easy()
t.test_splits()
t.teardown_method(None)

View File

@ -1,319 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import sys
import os
from PyQt4 import QtGui, QtCore
from openlp.core.theme import Theme
from test_render import TestRender_base, whoami
pypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0, (os.path.join(mypath, '..', '..', '..')))
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
def __init__(self):
TestRender_base.__init__(self)
def setup_method(self, method):
TestRender_base.setup_method(self, method)
print "Theme setup", method
# print "setup theme"
self.renderer.set_theme(Theme(u'blank_theme.xml')) # set "blank" theme
self.renderer.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!
It soothes his sorrows, heals his wounds,
And drives away his fear.
"""
verses = self.renderer.set_words_openlp(words)
# usually the same
self.expected_answer = QtCore.QRect(0, 0, 559, 342)
self.msg = None
self.bmpname = "Not set a bitmap yet"
print "------------- setup done --------------"
def teardown_method(self, method):
print "============ teardown =============", method, self.bmpname
if self.bmpname is not None:
assert (self.compare_DC_to_file(self.bmpname))
if self.expected_answer is not None: # result=None => Nothing to check
assert self.expected_answer == self.answer
print "============ teardown done ========="
def compare_DC_to_file(self, name):
"""writes DC out to a bitmap file and then compares it with a golden
one returns True if OK, False if not (so you can assert on it)
"""
print "--- compare DC to file --- ", name
p = self.frame.GetPixmap()
im = self.write_to_file(p, name)
print "Compare"
goldenfilename=os.path.join(u'golden_bitmaps",name+".bmp')
if os.path.exists(goldenfilename):
goldenim = QtGui.QImage(goldenfilename)
else:
print "File", goldenfilename, "not found"
return False
if (compare_images(goldenim, im)):
print name, "Images match"
return True
else:
print name, goldenfilename, "Images don't match"
return False
def test_theme_basic(self):
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
print self.renderer._theme.FontProportion
print self.answer, self.expected_answer, \
self.answer == self.expected_answer
# self.msg=self.bmpname
# }}}
# {{{ Gradients
def test_gradient_h(self):
# normally we wouldn't hack with these directly!
self.renderer._theme.BackgroundType = 1
self.renderer._theme.BackgroundParameter1 = QtGui.QColor(255,0,0)
self.renderer._theme.BackgroundParameter2 = QtGui.QColor(255,255,0)
self.renderer._theme.BackgroundParameter3 = 1
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
def test_gradient_v(self):
# normally we wouldn't hack with these directly!
self.renderer._theme.BackgroundType = 1
self.renderer._theme.BackgroundParameter1 = QtGui.QColor(255,0,0)
self.renderer._theme.BackgroundParameter2 = QtGui.QColor(255,255,0)
self.renderer._theme.BackgroundParameter3 = 0
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
# }}}
# {{{ backgrounds
def test_bg_stretch_y(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join(u'data_for_tests',
'snowsmall.jpg')
t.BackgroundParameter2 = QtGui.QColor(0,0,64)
t.BackgroundParameter3 = 0
t.Name = "stretch y"
self.renderer.set_theme(t)
print "render"
self.answer = self.renderer.render_screen(0)
print "whoami"
self.bmpname = whoami()
print "fone"
def test_bg_shrink_y(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join(u'data_for_tests', 'snowbig.jpg')
t.BackgroundParameter2 = QtGui.QColor(0,0,64)
t.BackgroundParameter3 = 0
t.Name = "shrink y"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
def test_bg_stretch_x(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join(u'data_for_tests',
'treessmall.jpg')
t.BackgroundParameter2 = QtGui.QColor(0,0,64)
t.BackgroundParameter3 = 0
t.VerticalAlign = 2
t.Name = "stretch x"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 129, 559, 342)
self.bmpname = whoami()
def test_bg_shrink_x(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 2
t.BackgroundParameter1 = os.path.join(u'data_for_tests',
'treesbig.jpg')
t.BackgroundParameter2 = QtGui.QColor(0,0,64)
t.BackgroundParameter3 = 0
t.VerticalAlign = 2
t.Name = "shrink x"
self.renderer.set_theme(t)
self.expected_answer = QtCore.QRect(0, 129, 559, 342)
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
# }}}
# {{{ Vertical alignment
def test_theme_vertical_align_top(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 0
t.Name = "valign top"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
def test_theme_vertical_align_bot(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 1
t.Name = "valign bot"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 257, 559, 342)
self.bmpname = whoami()
def test_theme_vertical_align_cen(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 2
t.Name = "valign cen"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 129, 559, 342)
self.bmpname = whoami()
# }}}
# {{{ Horzontal alignment
def test_theme_horizontal_align_left(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 0
t.HorizontalAlign = 0
t.Name = "halign left"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
def test_theme_horizontal_align_right(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 0
t.HorizontalAlign = 1
t.Name = "halign right"
self.renderer.set_theme(t)
self.expected_answer = QtCore.QRect(0, 0, 800, 342)
self.answer = self.renderer.render_screen(0)
self.bmpname = whoami()
def test_theme_horizontal_align_centre(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 0
t.HorizontalAlign = 2
t.Name = "halign centre"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 0, 679, 342)
self.bmpname = whoami()
def test_theme_horizontal_align_left_lyric(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.VerticalAlign = 0
t.HorizontalAlign = 0
t.WrapStyle = 1
t.Name = "halign left lyric"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 0, 778, 342)
self.bmpname = whoami()
# }}}
# {{{ Shadows and outlines
def test_theme_shadow_outline(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,0);
t.Name="shadow/outline"
t.Shadow = 1
t.Outline = 1
t.ShadowColor = QtGui.QColor(64,128,0)
t.OutlineColor = QtGui.QColor(128,0,0)
self.renderer.set_debug(1)
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
hoffset = self.renderer._shadow_offset+2*(self.renderer._outline_offset)
voffset = hoffset * (len(self.renderer.words[0])+1)
self.expected_answer = QtCore.QRect(0, 0, 559+hoffset, 342+voffset)
self.bmpname = whoami()
# }}}
def test_theme_font(self):
t = Theme(u'blank_theme.xml')
t.BackgroundType = 0
t.BackgroundParameter1 = QtGui.QColor(0,0,64)
t.Name = "font"
t.FontName = "Times New Roman"
self.renderer.set_theme(t)
self.answer = self.renderer.render_screen(0)
self.expected_answer = QtCore.QRect(0, 0, 499, 336)
self.bmpname=whoami()
if __name__ == "__main__":
test_render_theme = TestRenderTheme()
test_render_theme.setup_class()
test_render_theme.setup_method(None)
test_render_theme.test_bg_stretch_y()
test_render_theme.teardown_method(None)

View File

@ -1,13 +0,0 @@
from openlp.core.lib import Plugin
import logging
class testplugin3toodeep(Plugin):
name="testplugin3"
version=0
global log
log=logging.getLogger(u'testplugin1')
log.info(u'Started')
weight=10
def __init__(self):
pass

View File

@ -1,13 +0,0 @@
from openlp.core.lib import Plugin
import logging
class testplugin1(Plugin):
name="testplugin1"
version=0
global log
log=logging.getLogger(u'testplugin1')
log.info(u'Started')
weight=10
def __init__(self):
pass

View File

@ -1,8 +0,0 @@
from openlp.core.lib import Plugin
class testplugin2(Plugin):
name="testplugin2"
version=1
weight=1
def __init__(self):
pass

View File

@ -1,82 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import os.path
import sys
from PyQt4 import QtGui
from openlp.core.theme import Theme
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0, (os.path.join(mypath, '..', '..', '..', '..')))
print sys.path
def test_read_theme():
dir = os.path.split(__file__)[0]
# test we can read a theme
theme = Theme(os.path.join(dir, 'test_theme.xml'))
print theme
assert(theme.BackgroundParameter1 == 'sunset1.jpg')
assert(theme.BackgroundParameter2 is None)
assert(theme.BackgroundParameter3 is None)
assert(theme.BackgroundType == 2)
assert(theme.FontColor == QtGui.QColor(255,255,255))
assert(theme.FontName == 'Tahoma')
assert(theme.FontProportion == 16)
assert(theme.FontUnits == 'pixels')
assert(theme.HorizontalAlign == 2)
assert(theme.Name == 'openlp.org Packaged Theme')
assert(theme.Outline == -1)
assert(theme.OutlineColor == QtGui.QColor(255,0,0))
assert(theme.Shadow == -1)
assert(theme.ShadowColor == QtGui.QColor(0,0,1))
assert(theme.VerticalAlign == 0)
def test_theme():
# test we create a "blank" theme correctly
theme = Theme()
print theme
assert(theme.BackgroundParameter1 == QtGui.QColor(0,0,0))
assert(theme.BackgroundParameter2 is None)
assert(theme.BackgroundParameter3 is None)
assert(theme.BackgroundType == 0)
assert(theme.FontColor == QtGui.QColor(255,255,255))
assert(theme.FontName == 'Arial')
assert(theme.FontProportion == 30)
assert(theme.HorizontalAlign == 0)
assert(theme.FontUnits == 'pixels')
assert(theme.Name == 'BlankStyle')
assert(theme.Outline == 0)
assert(theme.Shadow == 0)
assert(theme.VerticalAlign == 0)
print "Tests passed"
if __name__ == "__main__":
test_read_theme()
test_theme()

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Theme>
<Name>openlp.org Packaged Theme</Name>
<BackgroundType>2</BackgroundType>
<BackgroundParameter1>sunset1.jpg</BackgroundParameter1>
<BackgroundParameter2/>
<BackgroundParameter3/>
<FontName>Tahoma</FontName>
<FontColor>clWhite</FontColor>
<FontProportion>16</FontProportion>
<FontUnits>pixels</FontUnits>
<Shadow>-1</Shadow>
<ShadowColor>$00000001</ShadowColor>
<Outline>-1</Outline>
<OutlineColor>clRed</OutlineColor>
<HorizontalAlign>2</HorizontalAlign>
<VerticalAlign>0</VerticalAlign>
</Theme>

View File

@ -25,16 +25,29 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, str_to_bool
from openlp.core.lib import SettingsTab, str_to_bool, Receiver
class GeneralTab(SettingsTab):
"""
GeneralTab is the general settings tab in the settings dialog.
"""
def __init__(self, screen_list):
self.screen_list = screen_list
def __init__(self, screens):
self.screens = screens
SettingsTab.__init__(self, u'General')
def preLoad(self):
"""
Set up the display screen and set correct screen
values.
If not set before default to last screen.
"""
self.MonitorNumber = int(self.config.get_config(u'monitor',
self.screens.monitor_number))
self.screens.set_current_display(self.MonitorNumber)
self.screens.monitor_number = self.MonitorNumber
self.DisplayOnMonitor = str_to_bool(self.config.get_config(u'display on monitor', u'True'))
self.screens.display = self.DisplayOnMonitor
def setupUi(self):
self.setObjectName(u'GeneralTab')
self.tabTitleVisible = self.trUtf8('General')
@ -60,6 +73,10 @@ class GeneralTab(SettingsTab):
self.MonitorComboBox = QtGui.QComboBox(self.MonitorGroupBox)
self.MonitorComboBox.setObjectName(u'MonitorComboBox')
self.MonitorLayout.addWidget(self.MonitorComboBox)
self.MonitorLayout.addWidget(self.MonitorComboBox)
self.DisplayOnMonitorCheck = QtGui.QCheckBox(self.MonitorGroupBox)
self.DisplayOnMonitorCheck.setObjectName(u'MonitorComboBox')
self.MonitorLayout.addWidget(self.DisplayOnMonitorCheck)
self.GeneralLeftLayout.addWidget(self.MonitorGroupBox)
self.StartupGroupBox = QtGui.QGroupBox(self.GeneralLeftWidget)
self.StartupGroupBox.setObjectName(u'StartupGroupBox')
@ -133,6 +150,8 @@ class GeneralTab(SettingsTab):
self.GeneralLayout.addWidget(self.GeneralRightWidget)
QtCore.QObject.connect(self.MonitorComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onMonitorComboBoxChanged)
QtCore.QObject.connect(self.DisplayOnMonitorCheck,
QtCore.SIGNAL(u'stateChanged(int)'), self.onDisplayOnMonitorCheckChanged)
QtCore.QObject.connect(self.WarningCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onWarningCheckBoxChanged)
QtCore.QObject.connect(self.AutoOpenCheckBox,
@ -153,6 +172,7 @@ class GeneralTab(SettingsTab):
def retranslateUi(self):
self.MonitorGroupBox.setTitle(self.trUtf8('Monitors'))
self.MonitorLabel.setText(self.trUtf8('Select monitor for output display:'))
self.DisplayOnMonitorCheck.setText(self.trUtf8('Display if in single screen'))
self.StartupGroupBox.setTitle(self.trUtf8('Application Startup'))
self.WarningCheckBox.setText(self.trUtf8('Show blank screen warning'))
self.AutoOpenCheckBox.setText(self.trUtf8('Automatically open the last service'))
@ -168,6 +188,9 @@ class GeneralTab(SettingsTab):
def onMonitorComboBoxChanged(self):
self.MonitorNumber = self.MonitorComboBox.currentIndex()
def onDisplayOnMonitorCheckChanged(self, value):
self.DisplayOnMonitor = (value == QtCore.Qt.Checked)
def onAutoOpenCheckBoxChanged(self, value):
self.AutoOpen = (value == QtCore.Qt.Checked)
@ -193,13 +216,12 @@ class GeneralTab(SettingsTab):
self.Password = self.PasswordEdit.displayText()
def load(self):
for screen in self.screen_list.screen_list:
for screen in self.screens.screen_list:
screen_name = u'%s %d' % (self.trUtf8('Screen'), screen[u'number'] + 1)
if screen[u'primary']:
screen_name = u'%s (%s)' % (screen_name, self.trUtf8('primary'))
self.MonitorComboBox.addItem(screen_name)
# Get the configs
self.MonitorNumber = int(self.config.get_config(u'monitor', u'0'))
self.Warning = str_to_bool(self.config.get_config(u'blank warning', u'False'))
self.AutoOpen = str_to_bool(self.config.get_config(u'auto open', u'False'))
self.ShowSplash = str_to_bool(self.config.get_config(u'show splash', u'True'))
@ -211,6 +233,7 @@ class GeneralTab(SettingsTab):
self.SaveCheckServiceCheckBox.setChecked(self.PromptSaveService)
# Set a few things up
self.MonitorComboBox.setCurrentIndex(self.MonitorNumber)
self.DisplayOnMonitorCheck.setChecked(self.DisplayOnMonitor)
self.WarningCheckBox.setChecked(self.Warning)
self.AutoOpenCheckBox.setChecked(self.AutoOpen)
self.ShowSplashCheckBox.setChecked(self.ShowSplash)
@ -221,6 +244,7 @@ class GeneralTab(SettingsTab):
def save(self):
self.config.set_config(u'monitor', self.MonitorNumber)
self.config.set_config(u'display on monitor', self.DisplayOnMonitor)
self.config.set_config(u'blank warning', self.Warning)
self.config.set_config(u'auto open', self.AutoOpen)
self.config.set_config(u'show splash', self.ShowSplash)
@ -229,3 +253,9 @@ class GeneralTab(SettingsTab):
self.config.set_config(u'ccli number', self.CCLINumber)
self.config.set_config(u'songselect username', self.Username)
self.config.set_config(u'songselect password', self.Password)
self.screens.display = self.DisplayOnMonitor
#Monitor Number has changed.
if self.screens.monitor_number != self.MonitorNumber:
self.screens.monitor_number = self.MonitorNumber
self.screens.set_current_display(self.MonitorNumber)
Receiver.send_message(u'screen_changed')

View File

@ -130,13 +130,15 @@ class MainDisplay(DisplayWidget):
QtCore.SIGNAL(u'media_pause'), self.onMediaPause)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_stop'), self.onMediaStop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_config'), self.setup)
def setup(self, screenNumber):
def setup(self):
"""
Sets up the screen on a particular screen.
@param (integer) screen This is the screen number.
"""
log.debug(u'Setup %s for %s ' %(self.screens, screenNumber))
log.debug(u'Setup %s for %s ' %(self.screens,
self.screens.monitor_number))
self.setVisible(False)
self.screen = self.screens.current
#Sort out screen locations and sizes
@ -183,7 +185,6 @@ class MainDisplay(DisplayWidget):
else:
self.setVisible(False)
self.primary = True
Receiver.send_message(u'screen_changed')
def resetDisplay(self):
Receiver.send_message(u'stop_display_loop')
@ -247,7 +248,7 @@ class MainDisplay(DisplayWidget):
else:
self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame))
self.display_frame = frame
if not self.isVisible():
if not self.isVisible() and self.screens.display:
self.setVisible(True)
self.showFullScreen()
else:
@ -320,4 +321,4 @@ class MainDisplay(DisplayWidget):
self.video.setVisible(False)
self.display_text.show()
self.display_image.show()
self.blankDisplay(False, False)
self.blankDisplay(False, False)

View File

@ -190,19 +190,19 @@ class Ui_MainWindow(object):
self.ThemeManagerDock.setVisible(self.settingsmanager.showThemeManager)
# Create the menu items
self.FileNewItem = QtGui.QAction(MainWindow)
self.FileNewItem.setIcon(
self.ServiceManagerContents.Toolbar.getIconFromTitle(
u'New Service'))
#self.FileNewItem.setIcon(
# self.ServiceManagerContents.Toolbar.getIconFromTitle(
# u'New Service'))
self.FileNewItem.setObjectName(u'FileNewItem')
self.FileOpenItem = QtGui.QAction(MainWindow)
self.FileOpenItem.setIcon(
self.ServiceManagerContents.Toolbar.getIconFromTitle(
u'Open Service'))
#self.FileOpenItem.setIcon(
# self.ServiceManagerContents.Toolbar.getIconFromTitle(
# u'Open Service'))
self.FileOpenItem.setObjectName(u'FileOpenItem')
self.FileSaveItem = QtGui.QAction(MainWindow)
self.FileSaveItem.setIcon(
self.ServiceManagerContents.Toolbar.getIconFromTitle(
u'Save Service'))
#self.FileSaveItem.setIcon(
# self.ServiceManagerContents.Toolbar.getIconFromTitle(
# u'Save Service'))
self.FileSaveItem.setObjectName(u'FileSaveItem')
self.FileSaveAsItem = QtGui.QAction(MainWindow)
self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
@ -496,6 +496,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'version_check'), self.versionCheck)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'blank_check'), self.blankCheck)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'screen_changed'), self.screenChanged)
QtCore.QObject.connect(self.FileNewItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onNewService)
@ -512,7 +514,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
#RenderManager needs to call ThemeManager and
#ThemeManager needs to call RenderManager
self.RenderManager = RenderManager(self.ThemeManagerContents,
self.screens, self.getMonitorNumber())
self.screens)
#Define the media Dock Manager
self.mediaDockManager = MediaDockManager(self.MediaToolBox)
log.info(u'Load Plugins')
@ -563,24 +565,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok)
def getMonitorNumber(self):
"""
Set up the default behaviour of the monitor configuration in
here. Currently it is set to default to monitor 0 if the saved
monitor number does not exist.
"""
screen_number = int(self.generalConfig.get_config(u'monitor', 0))
if not self.screens.screen_exists(screen_number):
screen_number = 0
return screen_number
def show(self):
"""
Show the main form, as well as the display form
"""
self.showMaximized()
screen_number = self.getMonitorNumber()
self.mainDisplay.setup(screen_number)
#screen_number = self.getMonitorNumber()
self.mainDisplay.setup()
if self.mainDisplay.isVisible():
self.mainDisplay.setFocus()
self.activateWindow()
@ -598,7 +589,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtGui.QMessageBox.Ok)
def versionThread(self):
#app_version = self.applicationVersion[u'full']
vT = VersionThread(self, self.applicationVersion, self.generalConfig)
vT.start()
@ -621,13 +611,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Show the Settings dialog
"""
self.settingsForm.exec_()
updated_display = self.getMonitorNumber()
if updated_display != self.screens.current_display:
self.screens.set_current_display(updated_display)
self.RenderManager.update_display(updated_display)
self.mainDisplay.setup(updated_display)
#Trigger after changes have been made
Receiver.send_message(u'config_updated')
def screenChanged(self):
self.RenderManager.update_display()
self.mainDisplay.setup()
self.activateWindow()
def closeEvent(self, event):

View File

@ -37,14 +37,17 @@ class ScreenList(object):
self.preview = None
self.current = None
self.screen_list = []
self.count = 0
self.display_count = 0
#actual display number
self.current_display = 0
#save config display number
self.monitor_number = 0
def add_screen(self, screen):
if screen[u'primary']:
self.current = screen
self.screen_list.append(screen)
self.count += 1
self.display_count += 1
def screen_exists(self, number):
for screen in self.screen_list:
@ -53,21 +56,15 @@ class ScreenList(object):
return False
def set_current_display(self, number):
if number + 1 > self.count:
"""
Set up the current screen dimensions
"""
if number + 1 > self.display_count:
self.current = self.screen_list[0]
self.current_display = 0
else:
self.current = self.screen_list[number]
self.preview = self.current
self.current_display = number
if self.count == 1:
if self.display_count == 1:
self.preview = self.screen_list[0]
# if self.screen[u'number'] != screenNumber:
# # We will most probably never actually hit this bit, but just in
# # case the index in the list doesn't match the screen number, we
# # search for it.
# for scrn in self.screens:
# if scrn[u'number'] == screenNumber:
# self.screen = scrn
# break

View File

@ -33,7 +33,7 @@ log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui
from openlp.core.lib import PluginConfig, OpenLPToolbar, ServiceItem, \
contextMenuAction, Receiver, str_to_bool, build_icon
contextMenuAction, Receiver, str_to_bool, build_icon, ItemCapabilities
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm
class ServiceManagerList(QtGui.QTreeWidget):
@ -233,9 +233,9 @@ class ServiceManager(QtGui.QWidget):
self.editAction.setVisible(False)
self.maintainAction.setVisible(False)
self.notesAction.setVisible(False)
if serviceItem[u'service_item'].edit_enabled:
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit):
self.editAction.setVisible(True)
if serviceItem[u'service_item'].maintain_allowed:
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsMaintain):
self.maintainAction.setVisible(True)
if item.parent() is None:
self.notesAction.setVisible(True)
@ -713,7 +713,7 @@ class ServiceManager(QtGui.QWidget):
get_config(u'auto preview', u'False')):
item += 1
if self.serviceItems and item < len(self.serviceItems) and \
self.serviceItems[item][u'service_item'].auto_preview_allowed:
serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsPreview):
self.parent.PreviewController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], 0)
@ -722,7 +722,8 @@ class ServiceManager(QtGui.QWidget):
Posts a remote edit message to a plugin to allow item to be edited.
"""
item, count = self.findServiceItem()
if self.serviceItems[item][u'service_item'].edit_enabled:
if self.serviceItems[item][u'service_item'].\
is_capable(ItemCapabilities.AllowsEdit):
self.remoteEditTriggered = True
Receiver.send_message(u'%s_edit' %
self.serviceItems[item][u'service_item'].name, u'L:%s' %

View File

@ -34,11 +34,11 @@ log = logging.getLogger(__name__)
class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
def __init__(self, screen_list, mainWindow, parent=None):
def __init__(self, screens, mainWindow, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
# General tab
self.GeneralTab = GeneralTab(screen_list)
self.GeneralTab = GeneralTab(screens)
self.addTab(u'General', self.GeneralTab)
# Themes tab
self.ThemesTab = ThemesTab(mainWindow)

View File

@ -30,6 +30,8 @@ import os
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
from openlp.core.lib import ItemCapabilities
class HideMode(object):
"""
This is basically an enumeration class which specifies the mode of a Bible.
@ -375,8 +377,7 @@ class SlideController(QtGui.QWidget):
self.Toolbar.makeWidgetsInvisible(self.image_list)
if item.is_text():
self.Toolbar.makeWidgetsInvisible(self.image_list)
if item.is_song() and \
str_to_bool(self.songsconfig.get_config(u'show songbar', True)) \
if str_to_bool(self.songsconfig.get_config(u'show songbar', True)) \
and len(self.slideList) > 0:
self.Toolbar.makeWidgetsVisible([u'Song Menu'])
elif item.is_image():
@ -395,7 +396,7 @@ class SlideController(QtGui.QWidget):
self.Toolbar.setVisible(True)
self.Mediabar.setVisible(False)
self.Toolbar.makeWidgetsInvisible(self.song_edit_list)
if item.edit_enabled and item.from_plugin:
if item.is_capable(ItemCapabilities.AllowsEdit) and item.from_plugin:
self.Toolbar.makeWidgetsVisible(self.song_edit_list)
elif item.is_media():
self.Toolbar.setVisible(False)
@ -494,15 +495,18 @@ class SlideController(QtGui.QWidget):
bits = frame[u'verseTag'].split(u':')
tag = None
#If verse handle verse number else tag only
if bits[0] == self.trUtf8('Verse'):
tag = u'%s%s' % (bits[0][0], bits[1][0:] )
row = bits[1][0:]
if bits[0] == self.trUtf8('Verse') or \
bits[0] == self.trUtf8('Chorus'):
tag = u'%s\n%s' % (bits[0][0], bits[1][0:] )
tag1 = u'%s%s' % (bits[0][0], bits[1][0:] )
row = tag
else:
tag = bits[0]
tag1 = tag
row = bits[0][0:1]
if tag not in self.slideList:
self.slideList[tag] = framenumber
self.SongMenu.menu().addAction(self.trUtf8(u'%s'%tag),
if tag1 not in self.slideList:
self.slideList[tag1] = framenumber
self.SongMenu.menu().addAction(self.trUtf8(u'%s'%tag1),
self.onSongBarHandler)
else:
row += 1
@ -519,6 +523,7 @@ class SlideController(QtGui.QWidget):
slide_height = width * self.parent.RenderManager.screen_ratio
row += 1
rowitem.setText(unicode(row))
rowitem.setTextAlignment(QtCore.Qt.AlignVCenter)
self.PreviewListWidget.setItem(framenumber, 0, rowitem)
self.PreviewListWidget.setItem(framenumber, 1, item)
if slide_height != 0:
@ -759,7 +764,7 @@ class SlideController(QtGui.QWidget):
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
file = os.path.join(item.service_item_path, item.get_frame_title())
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
self.onMediaPlay()

View File

@ -1,160 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import sys
import os
import os.path
import logging
from PyQt4 import QtGui
from openlp.core.ui import ServiceManager
from openlp.plugins.images.lib import ImageServiceItem
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0, (os.path.join(mypath, '..', '..', '..', '..')))
logging.basicConfig(filename='test_service_manager.log', level=logging.INFO,
filemode='w')
# # from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66062
# def whoami(depth=1):
# return sys._getframe(depth).f_code.co_name
global app
global log
log = logging.getLogger(u'TestServiceManager')
class TestServiceManager_base:
def __init__(self):
pass
def setup_class(self):
log.info( "class setup" + unicode(self))
try:
if app is None:
app = QtGui.QApplication([])
except UnboundLocalError:
app = QtGui.QApplication([])
def teardown_class(self):
pass
def setup_method(self, method):
log.info(u'Setup method:' + unicode(method))
self.expected_answer = "Don't know yet"
self.answer = None
self.s = ServiceManager(None)
log.info(u'--------------- Setup Done -------------')
def teardown_method(self, method):
self.s = None
def select_row(self, row):
# now select the line we just added
# first get the index
i = QModelIndex(self.s.service_data.index(0,0))
# make a selection of it
self.sm = QItemSelectionModel(self.s.service_data)
self.sm.select(i, QItemSelectionModel.ClearAndSelect)
log.info(unicode(self.sm.selectedIndexes()))
self.s.TreeView.setSelectionModel(self.sm)
log.info(u'Selected indexes = ' + unicode(
self.s.TreeView.selectedIndexes()))
def test_easy(self):
log.info(u'test_easy')
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
log.info(u'done')
def test_2items_as_separate_items(self):
# If nothing is selected when item is added, a new base service item
# is added
log.info(u'test_2items_as_separate_items')
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
item = ImageServiceItem(None)
item.add(u'test2.gif')
item.add(u'test3.gif')
self.s.addServiceItem(item)
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
assert lines[2].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[3] == "test2.gif"
assert lines[4] == "test3.gif"
log.info(u'done')
def test_2items_merged(self):
# If the first object is selected when item is added it should be
# extended
log.info(u'test_2items_merged')
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
self.select_row(0)
log.info(u'Selected indexes = ' + unicode(
self.s.TreeView.selectedIndexes()))
item = ImageServiceItem(None)
item.add(u'test2.gif')
item.add(u'test3.gif')
self.s.addServiceItem(item)
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
assert lines[2] == "test2.gif"
assert lines[3] == "test3.gif"
log.info(u'done')
# more tests to do:
# add different types of service item
# move up, down
# move to top, bottom
# new and save as
# deleting items
if __name__ == "__main__":
t=TestServiceManager_base()
t.setup_class()
t.setup_method(None)
t.test_easy()
t.teardown_method(None)
print "Pass"
log.info(u'Pass')

View File

@ -29,7 +29,7 @@ import time
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, str_to_bool, \
BaseListWithDnD
BaseListWithDnD, ItemCapabilities
from openlp.plugins.bibles.forms import ImportWizardForm
log = logging.getLogger(__name__)
@ -449,7 +449,7 @@ class BibleMediaItem(MediaManagerItem):
raw_slides = []
raw_footer = []
bible_text = u''
service_item.auto_preview_allowed = True
service_item.add_capability(ItemCapabilities.AllowsPreview)
#If we want to use a 2nd translation / version
bible2 = u''
if self.SearchTabWidget.currentIndex() == 0:
@ -608,4 +608,4 @@ class BibleMediaItem(MediaManagerItem):
def searchByReference(self, bible, search):
log.debug(u'searchByReference %s, %s', bible, search)
self.search_results = self.parent.manager.get_verses(bible, search)
self.search_results = self.parent.manager.get_verses(bible, search)

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################

View File

@ -1,8 +0,0 @@
1,1,"Genesis","GEN"
2,1,"Exodus","EXOD"
3,1,"Leviticus","LEV"
4,1,"Numbers","NUM"
47,2,"Matthew","MATT"
48,2,"Mark","MARK"
49,2,"Luke","LUKE"
50,2,"John","JOHN"
1 1 1 Genesis GEN
2 2 1 Exodus EXOD
3 3 1 Leviticus LEV
4 4 1 Numbers NUM
5 47 2 Matthew MATT
6 48 2 Mark MARK
7 49 2 Luke LUKE
8 50 2 John JOHN

View File

@ -1,9 +0,0 @@
1,1,"Genesis","GEN"
2,1,"Exodus","EXOD"
3,1,"Leviticus","LEV"
4,1,"Numbers","NUM"
46,1,"Malachi","MAL"
47,2,"Matthew","MATT"
48,2,"Mark","MARK"
49,2,"Luke","LUKE"
50,2,"John","JOHN"
1 1 1 Genesis GEN
2 2 1 Exodus EXOD
3 3 1 Leviticus LEV
4 4 1 Numbers NUM
5 46 1 Malachi MAL
6 47 2 Matthew MATT
7 48 2 Mark MARK
8 49 2 Luke LUKE
9 50 2 John JOHN

View File

@ -1,35 +0,0 @@
"Genesis",1,1,"First this: God created the Heavens and Earth - all you see, all you don't see."
"Genesis",1,2,"Earth was a soup of nothingness, a bottomless emptiness, an inky blackness. God's Spirit brooded like a bird above the watery abyss."
"Exodus",1,1,"These are the names of the Israelites who went to Egypt with Jacob, each bringing his family members:"
"Exodus",1,2,"Reuben, Simeon, Levi, and Judah,"
"Exodus",2,1,"A man from the family of Levi married a Levite woman."
"Exodus",2,2,"The woman became pregnant and had a son. She saw there was something special about him and hid him. She hid him for three months."
"Leviticus",1,1,"God called Moses and spoke to him from the Tent of Meeting:"
"Leviticus",1,2,"""Speak to the People of Israel. Tell them, When anyone presents an offering to God, present an animal from either the herd or the flock."
"Leviticus",1,3,"""If the offering is a Whole-Burnt-Offering from the herd, present a male without a defect at the entrance to the Tent of Meeting that it may be accepted by God."
"Numbers",1,1,"God spoke to Moses in the Wilderness of Sinai at the Tent of Meeting on the first day of the second month in the second year after they had left Egypt. He said,"
"Numbers",1,2,"""Number the congregation of the People of Israel by clans and families, writing down the names of every male."
"Matthew",1,1,"The family tree of Jesus Christ, David's son, Abraham's son:"
"Matthew",1,2,"Abraham had Isaac, Isaac had Jacob, Jacob had Judah and his brothers,"
"Matthew",1,3,"Judah had Perez and Zerah (the mother was Tamar), Perez had Hezron, Hezron had Aram,"
"Matthew",1,4,"Aram had Amminadab, Amminadab had Nahshon, Nahshon had Salmon,"
"Matthew",1,5,"Salmon had Boaz (his mother was Rahab), Boaz had Obed (Ruth was the mother), Obed had Jesse,"
"Matthew",1,6,"Jesse had David, and David became king. David had Solomon (Uriah's wife was the mother),"
"Matthew",1,7,"Solomon had Rehoboam, Rehoboam had Abijah, Abijah had Asa,"
"Matthew",1,8,"Asa had Jehoshaphat, Jehoshaphat had Joram, Joram had Uzziah,"
"Matthew",2,1,"After Jesus was born in Bethlehem village, Judah territory - this was during Herod's kingship - a band of scholars arrived in Jerusalem from the East."
"Matthew",2,2,"They asked around, ""Where can we find and pay homage to the newborn King of the Jews? We observed a star in the eastern sky that "Matthew",3,1,"While Jesus was living in the Galilean hills, John, called ""the Baptizer,"" was preaching in the desert country of Judea."
"Matthew",3,2,"His message was simple and austere, like his desert surroundings: ""Change your life. God's kingdom is here."""
"Matthew",3,3,"John and his message were authorized by Isaiah's prophecy: Thunder in the desert! Prepare for God's arrival! Make the road smooth and straight!"
"Mark",1,1,"The good news of Jesus Christ - the Message! - begins here,"
"Mark",1,2,"following to the letter the scroll of the prophet Isaiah. Watch closely: I'm sending my preacher ahead of you; He'll make the road smooth for you."
"Mark",1,3,"Thunder in the desert! Prepare for God's arrival! Make the road smooth and straight!"
"Luke",1,1,"So many others have tried their hand at putting together a story of the wonderful harvest of Scripture and history that took place among us,"
"Luke",1,2,"using reports handed down by the original eyewitnesses who served this Word with their very lives."
"Luke",1,3,"Since I have investigated all the reports in close detail, starting from the story's beginning, I decided to write it all out for you, most honorable Theophilus,"
"John",1,1,"The Word was first, the Word present to God, God present to the Word. The Word was God,"
"John",1,2,"in readiness for God from day one."
"John",1,3,"Everything was created through him; nothing - not one thing! - came into being without him."
"John",2,1,"Three days later there was a wedding in the village of Cana in Galilee. Jesus' mother was there."
"John",2,2,"Jesus and his disciples were guests also."
"John",2,3,"When they started running low on wine at the wedding banquet, Jesus' mother told him, ""They're just about out of wine."""
Can't render this file because it contains an unexpected character in line 21 and column 146.

View File

@ -1,35 +0,0 @@
"Genesis",1,1,"In the beginning God created the heavens and the earth."
"Genesis",1,2,"Now the earth was formless and empty, darkness was over the surface of the deep, and the Spirit of God was hovering over the waters."
"Exodus",1,1,"These are the names of the sons of Israel who went to Egypt with Jacob, each with his family:"
"Exodus",1,2,"Reuben, Simeon, Levi and Judah;"
"Exodus",2,1,"Now a man of the house of Levi married a Levite woman,"
"Exodus",2,2,"and she became pregnant and gave birth to a son. When she saw that he was a fine child, she hid him for three months."
"Leviticus",1,1,"The Lord called to Moses and spoke to him from the Tent of Meeting. He said,"
"Leviticus",1,2,"""Speak to the Israelites and say to them: 'When any of you brings an offering to the Lord, bring as your offering an animal from either the herd or the flock."
"Leviticus",1,3,"""'If the offering is a burnt offering from the herd, he is to offer a male without defect. He must present it at the entrance to the Tent of Meeting so that it will be acceptable to the Lord."
"Numbers",1,1,"The Lord spoke to Moses in the Tent of Meeting in the Desert of Sinai on the first day of the second month of the second year after the Israelites came out of Egypt. He said:"
"Numbers",1,2,"""Take a census of the whole Israelite community by their clans and families, listing every man by name, one by one."
"Matthew",1,1,"A record of the genealogy of Jesus Christ the son of David, the son of Abraham:"
"Matthew",1,2,"Abraham was the father of Isaac,"
"Matthew",1,3,"Judah the father of Perez and Zerah, whose mother was Tamar,"
"Matthew",1,4,"Ram the father of Amminadab,"
"Matthew",1,5,"Salmon the father of Boaz, whose mother was Rahab,"
"Matthew",1,6,"and Jesse the father of King David."
"Matthew",1,7,"Solomon the father of Rehoboam,"
"Matthew",1,8,"Asa the father of Jehoshaphat,"
"Matthew",2,1,"After Jesus was born in Bethlehem in Judea, during the time of King Herod, Magi from the east came to Jerusalem"
"Matthew",2,2,"and asked, ""Where is the one who has been born king of the Jews? We saw his star in the east and have come to worship "Matthew",3,1,"In those days John the Baptist came, preaching in the Desert of Judea"
"Matthew",3,2,"and saying, ""Repent, for the kingdom of heaven is near."""
"Matthew",3,3,"This is he who was spoken of through the prophet Isaiah: ""A voice of one calling in the desert, 'Prepare the way for the Lord, make straight paths for him.'"""
"Mark",1,1,"The beginning of the gospel about Jesus Christ, the Son of God."
"Mark",1,2,"It is written in Isaiah the prophet: ""I will send my messenger ahead of you, who will prepare your way""--"
"Mark",1,3,"""a voice of one calling in the desert, 'Prepare the way for the Lord, make straight paths for him.'"""
"Luke",1,1,"Many have undertaken to draw up an account of the things that have been fulfilled among us,"
"Luke",1,2,"just as they were handed down to us by those who from the first were eyewitnesses and servants of the word."
"Luke",1,3,"Therefore, since I myself have carefully investigated everything from the beginning, it seemed good also to me to write an orderly account for you, most excellent Theophilus,"
"John",1,1,"In the beginning was the Word, and the Word was with God, and the Word was God."
"John",1,2,"He was with God in the beginning."
"John",1,3,"Through him all things were made; without him nothing was made that has been made."
"John",2,1,"On the third day a wedding took place at Cana in Galilee. Jesus' mother was there,"
"John",2,2,"and Jesus and his disciples had also been invited to the wedding."
"John",2,3,"When the wine was gone, Jesus' mother said to him, ""They have no more wine."""
Can't render this file because it contains an unexpected character in line 21 and column 135.

View File

@ -1 +0,0 @@
py.test --nocapture test_bibleManager.py

View File

@ -1,124 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import os.path
import sys
from openlp.plugins.bibles.lib.biblemanager import BibleManager
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..')))
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename='plugins.log',
filemode='w')
console = logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'\nLogging started')
class TestBibleManager:
log = logging.getLogger(u'testBibleMgr')
def setup_class(self):
log.debug(u'\n.......Register BM')
self.bm = BibleManager()
def testRegisterCSVBibleFiles(self):
# Register a bible from files
log.debug(u'\n.......testRegisterBibleFiles')
self.bm.registerFileBible(u'TheMessage','biblebooks_msg_short.csv','bibleverses_msg_short.csv')
self.bm.registerFileBible(u'NIV','biblebooks_niv_short.csv','bibleverses_niv_short.csv')
b = self.bm.get_bibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)
def testRegisterHTTPBible(self):
# Register a bible from files
log.debug( '\n.......testRegisterBibleHTTP')
self.bm.registerHTTPBible(u'asv', u'Crosswalk', u'', u'', u'')
self.bm.registerHTTPBible(u'nasb', u'Biblegateway', u'', u'', u'')
self.bm.registerHTTPBible(u'nkj', u'Biblegateway',
u'http://tigger2:3128/', u'', u'')
b = self.bm.get_bibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)
def testGetBibles(self):
log.debug(u'\n.......testGetBibles')
# make sure the shuffled sequence does not lose any elements
b = self.bm.get_bibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)
def testGetBibleBooks(self):
log.debug(u'\n.......testGetBibleBooks')
c = self.bm.get_bible_books(u'NIV')
for c1 in c:
log.debug( c1)
assert(c1 in c)
def testGetBookChapterCount(self):
log.debug(u'\n.......testGetBookChapterCount')
assert(self.bm.get_book_chapter_count(u'Matthew') == '28')
def testGetBookVerseCount(self):
log.debug(u'\n.......testGetBookVerseCount')
assert(self.bm.get_book_verse_count(u'Genesis', 1) == '31')
assert(self.bm.get_book_verse_count(u'Genesis', 2) == '25')
assert(self.bm.get_book_verse_count(u'Matthew', 1) == '25')
assert(self.bm.get_book_verse_count(u'Revelation', 1) == '20')
def testGetVerseText(self):
log.debug(u'\n.......testGetVerseText')
#c = self.bm.get_verse_text(u'TheMessage",'Genesis',1,2,1)
#log.debug( c )
#c = self.bm.get_verse_text(u'NIV','Genesis',1,1,2)
#log.debug( c )
c = self.bm.get_verse_text(u'asv','Genesis',10,1,20)
log.debug( c )
c = self.bm.get_verse_text(u'nasb','Genesis',10,1,20)
log.debug( c )
c = self.bm.get_verse_text(u'nkj','Revelation',10,1,20)
log.debug( c )
def testLoadBible(self):
log.debug(u'\n.......testLoadBible')
#self.bm.loadBible(u'asv')
#self.bm.loadBible(u'nasb')
#self.bm.loadBible(u'nkj')

View File

@ -1,100 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import os.path
import sys
from openlp.plugins.biblemanager.bibleManager import BibleManager
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..')))
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename='plugins.log',
filemode='w')
console = logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'\nLogging started')
class TestBibleManager:
log = logging.getLogger(u'testBibleMgr')
def setup_class(self):
log.debug(u'\n.......Register BM')
self.bm = BibleManager()
def testGetBibles(self):
log.debug(u'\n.......testGetBibles')
# make sure the shuffled sequence does not lose any elements
b = self.bm.getBibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)
def testGetBibleBooks(self):
log.debug(u'\n.......testGetBibleBooks')
c = self.bm.getBibleBooks(u'asv')
for c1 in c:
log.debug( c1)
assert(c1 in c)
def testGetBookChapterCount(self):
log.debug(u'\n.......testGetBookChapterCount')
assert(self.bm.getBookChapterCount(u'asv', u'Matthew')[0] == 28)
def testGetBookVerseCount(self):
log.debug(u'\n.......testGetBookVerseCount')
assert(self.bm.getBookVerseCount(u'asv', u'Genesis', 1)[0] == 31)
assert(self.bm.getBookVerseCount(u'TheMessage', u'Genesis', 2)[0] == 25)
assert(self.bm.getBookVerseCount(u'asv', u'Matthew', 1)[0] == 25)
assert(self.bm.getBookVerseCount(u'TheMessage', u'Revelation',
1)[0] == 20)
def testGetVerseText(self):
log.debug(u'\n.......testGetVerseText')
#c = self.bm.getVerseText(u'TheMessage",'Genesis',1,2,1)
#log.debug( c )
#c = self.bm.getVerseText(u'NIV','Genesis',1,1,2)
#log.debug( c )
c = self.bm.getVerseText(u'asv', u'Genesis', 10, 1, 20)
log.debug( c )
c = self.bm.getVerseText(u'TheMessage', u'Genesis', 10, 1, 20)
log.debug( c )
c = self.bm.getVerseText(u'asv', u'Revelation', 10, 1, 20)
log.debug( c )
c = self.bm.getVersesFromText(u'asv', u'Jesus wept')
log.debug( c )
c = self.bm.getVersesFromText(u'TheMessage', u'Jesus wept')
log.debug( c )

View File

@ -1,68 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import os.path
import sys
from openlp.plugins.bibles.lib.biblemanager import BibleManager
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..')))
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename='plugins.log',
filemode='w')
console = logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'\nLogging started')
class TestBibleManager:
log = logging.getLogger(u'testBibleMgr')
def setup_class(self):
log.debug(u'\n.......Register BM')
self.bm = BibleManager()
def testRegisterCSVBibleFiles(self):
# Register a bible from files
log.debug(u'\n.......testRegisterBibleFiles')
self.bm.registerCSVFileBible(u'TheMessage',
u'biblebooks_msg_short.csv', u'bibleverses_msg_short.csv')
self.bm.registerCSVFileBible(u'NIV', u'biblebooks_niv_short.csv',
u'bibleverses_niv_short.csv')
b = self.bm.get_bibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)

View File

@ -1,65 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import os.path
import sys
from openlp.plugins.bibles.lib.biblemanager import BibleManager
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..')))
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M',
filename='plugins.log',
filemode='w')
console = logging.StreamHandler()
# set a format which is simpler for console use
formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
logging.getLogger(u'').addHandler(console)
log = logging.getLogger(u'')
logging.info(u'\nLogging started')
class TestBibleManager:
log = logging.getLogger(u'testBibleMgr')
def setup_class(self):
log.debug(u'\n.......Register BM')
self.bm = BibleManager()
def testRegisterOSISBibleFiles(self):
# Register a bible from files
log.debug(u'\n.......testRegisterOSISBibleFiles')
self.bm.register_osis_file_bible(u'asv', u'asv.osis')
b = self.bm.get_bibles()
for b1 in b:
log.debug( b1)
assert(b1 in b)

View File

@ -28,7 +28,7 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD,\
Receiver, str_to_bool
Receiver, str_to_bool, ItemCapabilities
log = logging.getLogger(__name__)
@ -144,11 +144,11 @@ class CustomMediaItem(MediaManagerItem):
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else:
item_id = self.remoteCustom
service_item.auto_preview_allowed = True
service_item.add_capability(ItemCapabilities.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview)
customSlide = self.parent.custommanager.get_custom(item_id)
title = customSlide.title
credit = customSlide.credits
service_item.edit_enabled = True
service_item.editId = item_id
theme = customSlide.theme_name
if theme:
@ -166,4 +166,4 @@ class CustomMediaItem(MediaManagerItem):
else:
raw_footer.append(u'')
service_item.raw_footer = raw_footer
return True
return True

View File

@ -28,7 +28,7 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
contextMenuAction
contextMenuAction, ItemCapabilities
log = logging.getLogger(__name__)
@ -140,8 +140,8 @@ class ImageMediaItem(MediaManagerItem):
items = self.ListView.selectedIndexes()
if items:
service_item.title = self.trUtf8('Image(s)')
service_item.auto_preview_allowed = True
service_item.maintain_allowed = True
service_item.add_capability(ItemCapabilities.AllowsMaintain)
service_item.add_capability(ItemCapabilities.AllowsPreview)
for item in items:
bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())

View File

@ -28,7 +28,8 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
ItemCapabilities
log = logging.getLogger(__name__)
@ -82,6 +83,7 @@ class MediaMediaItem(MediaManagerItem):
if len(items) > 1:
return False
service_item.title = unicode(self.trUtf8('Media'))
service_item.add_capability(ItemCapabilities.RequiresMedia)
for item in items:
bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())

View File

@ -152,7 +152,6 @@ class PresentationMediaItem(MediaManagerItem):
service_item.title = unicode(self.DisplayTypeComboBox.currentText())
service_item.shortname = unicode(self.DisplayTypeComboBox.currentText())
shortname = service_item.shortname
for item in items:
bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())

Binary file not shown.

Before

Width:  |  Height:  |  Size: 716 B

View File

@ -411,16 +411,18 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.SongTabWidget.setCurrentIndex(2)
self.AuthorsListView.setFocus()
#split the verse list by space and mark lower case for testing
taglist = unicode(self.trUtf8(' bcitped'))
taglist = unicode(self.trUtf8(' bitped'))
for verse in unicode(self.VerseOrderEdit.text()).lower().split(u' '):
if len(verse) > 1:
if verse[0:1] == u'%s' % self.trUtf8('v') and verse[1:].isdigit():
if (verse[0:1] == u'%s' % self.trUtf8('v') or
verse[0:1] == u'%s' % self.trUtf8('c')) \
and verse[1:].isdigit():
pass
else:
self.SongTabWidget.setCurrentIndex(0)
self.VerseOrderEdit.setFocus()
return False, \
self.trUtf8('Invalid verse entry - vX')
self.trUtf8('Invalid verse entry - Vx or Cx')
else:
if taglist.find(verse) > -1:
pass
@ -429,7 +431,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.VerseOrderEdit.setFocus()
return False, \
self.trUtf8(\
'Invalid verse entry - values must be Numeric, I,B,C,T,P,E,O')
'Invalid verse entry, values must be I,B,T,P,E,O,Vx,Cx')
return True, u''
def onTitleEditItemLostFocus(self):

View File

@ -59,46 +59,43 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
def onAddIntro(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Intro'))
self.VerseTextEdit.insertPlainText(u'---[Intro:1]---\n')
self.VerseTextEdit.setFocus()
def onAddEnding(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Ending'))
self.VerseTextEdit.insertPlainText(u'---[Ending:1]---\n')
self.VerseTextEdit.setFocus()
def onAddOther(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Other'))
self.VerseTextEdit.insertPlainText(u'---[Other:1]---\n')
self.VerseTextEdit.setFocus()
def onAddPreChorus(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Pre-Chorus'))
self.VerseTextEdit.insertPlainText(u'---[Pre-Chorus:1]---\n')
self.VerseTextEdit.setFocus()
def onAddBridge(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Bridge'))
self.VerseTextEdit.insertPlainText(u'---[Bridge:1]---\n')
self.VerseTextEdit.setFocus()
def onAddChorus(self):
self.startNewLine()
self.VerseTextEdit.insertPlainText(u'---[%s:1]---\n'
% self.trUtf8('Chorus'))
count = self.VerseTextEdit.toPlainText().\
count(u'---[Chorus')
self.VerseTextEdit.insertPlainText(u'---[Chorus:%s]---\n'
% unicode(count + 1))
self.VerseTextEdit.setFocus()
def onAddVerse(self):
self.startNewLine()
count = self.VerseTextEdit.toPlainText().\
count(u'---[%s' % self.trUtf8('Verse'))
self.VerseTextEdit.insertPlainText(u'---[%s:%s]---\n'
% (self.trUtf8('Verse'), count + 1))
count(u'---[Verse')
self.VerseTextEdit.insertPlainText(u'---[Verse:%s]---\n'
% unicode(count + 1))
self.VerseTextEdit.setFocus()
def setVerse(self, text, verseCount=0, single=False, tag=u'Verse:1'):
@ -155,7 +152,8 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
return text
def onVerseComboChanged(self, id):
if unicode(self.VerseListComboBox.currentText()) == self.trUtf8('Verse'):
if unicode(self.VerseListComboBox.currentText()) == self.trUtf8('Verse') or \
unicode(self.VerseListComboBox.currentText()) == self.trUtf8('Chrous'):
self.SubVerseListComboBox.setEnabled(True)
else:
self.SubVerseListComboBox.setEnabled(False)

View File

@ -26,3 +26,5 @@
from manager import SongManager
from songstab import SongsTab
from mediaitem import SongMediaItem
from sofimport import SofImport
from songimport import SongImport

View File

@ -133,6 +133,12 @@ class SongManager():
"""
return self.session.query(Author).get(id)
def get_author_by_name(self, name):
"""
Get author by display name
"""
return self.session.query(Author).filter_by(display_name=name).first()
def save_author(self, author):
"""
Save the Author and refresh the cache
@ -172,6 +178,12 @@ class SongManager():
"""
return self.session.query(Topic).get(id)
def get_topic_by_name(self, name):
"""
Get topic by name
"""
return self.session.query(Topic).filter_by(name=name).first()
def save_topic(self, topic):
"""
Save the Topic
@ -211,6 +223,12 @@ class SongManager():
"""
return self.session.query(Book).get(id)
def get_book_by_name(self, name):
"""
Get book by name
"""
return self.session.query(Book).filter_by(name=name).first()
def save_book(self, book):
"""
Save the Book

View File

@ -28,7 +28,7 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, SongXMLParser, \
BaseListWithDnD, Receiver, str_to_bool
BaseListWithDnD, Receiver, str_to_bool, ItemCapabilities
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm
log = logging.getLogger(__name__)
@ -271,12 +271,23 @@ class SongMediaItem(MediaManagerItem):
self.edit_song_form.exec_()
def onDeleteClick(self):
item = self.ListView.currentItem()
if item:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.parent.songmanager.delete_song(item_id)
row = self.ListView.row(item)
self.ListView.takeItem(row)
items = self.ListView.selectedIndexes()
if items:
if len(items) == 1:
del_message = self.trUtf8('Delete song?')
else:
del_message = unicode(self.trUtf8('Delete %d song?')) % len(items)
ans = QtGui.QMessageBox.question(self,
self.trUtf8('Delete Confirmation'), del_message,
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok|
QtGui.QMessageBox.Cancel),
QtGui.QMessageBox.Ok)
if ans == QtGui.QMessageBox.Cancel:
return
for item in items:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.parent.songmanager.delete_song(item_id)
self.onSearchTextButtonClick()
def generateSlideData(self, service_item):
raw_footer = []
@ -290,10 +301,10 @@ class SongMediaItem(MediaManagerItem):
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else:
item_id = self.remoteSong
service_item.auto_preview_allowed = True
service_item.add_capability(ItemCapabilities.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview)
song = self.parent.songmanager.get_song(item_id)
service_item.theme = song.theme_name
service_item.edit_enabled = True
service_item.editId = item_id
if song.lyrics.startswith(u'<?xml version='):
songXML = SongXMLParser(song.lyrics)
@ -310,8 +321,10 @@ class SongMediaItem(MediaManagerItem):
break
for verse in verseList:
if verse[1]:
if verse[0][u'type'] == "Verse":
if verse[0][u'label'] == order[1:]:
if verse[0][u'type'] == "Verse" \
or verse[0][u'type'] == "Chorus":
if verse[0][u'label'] == order[1:] and \
verse[0][u'type'][0] == order[0]:
verseTag = u'%s:%s' % \
(verse[0][u'type'], verse[0][u'label'])
service_item.add_from_text\
@ -345,4 +358,4 @@ class SongMediaItem(MediaManagerItem):
service_item.audit = [
song.title, author_audit, song.copyright, song.ccli_number
]
return True
return True

View File

@ -0,0 +1,530 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
# OOo API documentation:
# http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Structure_of_Text_Documents
# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Text/Iterating_over_Text
# http://www.oooforum.org/forum/viewtopic.phtml?t=14409
# http://wiki.services.openoffice.org/wiki/Python
import re
import os
import time
from PyQt4 import QtCore
from songimport import SongImport
if os.name == u'nt':
from win32com.client import Dispatch
BOLD = 150.0
ITALIC = 2
PAGE_BEFORE = 4
PAGE_AFTER = 5
PAGE_BOTH = 6
else:
import uno
from com.sun.star.awt.FontWeight import BOLD
from com.sun.star.awt.FontSlant import ITALIC
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
class SofImport(object):
"""
Import songs provided on disks with the Songs of Fellowship music books
VOLS1_2.RTF, sof3words.rtf and sof4words.rtf
Use OpenOffice.org Writer for processing the rtf file
The three books are not only inconsistant with each other, they are
inconsistant in themselves too with their formatting. Not only this, but
the 1+2 book does not space out verses correctly. This script attempts
to sort it out, but doesn't get it 100% right. But better than having to
type them all out!
It attempts to detect italiced verses, and treats these as choruses in
the verse ordering. Again not perfect, but a start.
"""
def __init__(self, songmanager):
"""
Initialise the class. Requires a songmanager class which is passed
to SongImport for writing song to disk
"""
self.song = None
self.manager = songmanager
self.process_started = False
def import_sof(self, filename):
self.start_ooo()
self.open_ooo_file(filename)
self.process_doc()
self.close_ooo()
def start_ooo(self):
"""
Start OpenOffice.org process
TODO: The presentation/Impress plugin may already have it running
"""
if os.name == u'nt':
self.start_ooo_process()
self.desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
else:
context = uno.getComponentContext()
resolver = context.ServiceManager.createInstanceWithContext(
u'com.sun.star.bridge.UnoUrlResolver', context)
ctx = None
loop = 0
while ctx is None and loop < 5:
try:
ctx = resolver.resolve(u'uno:socket,host=localhost,' \
+ 'port=2002;urp;StarOffice.ComponentContext')
except:
pass
self.start_ooo_process()
loop += 1
manager = ctx.ServiceManager
self.desktop = manager.createInstanceWithContext(
"com.sun.star.frame.Desktop", ctx )
def start_ooo_process(self):
try:
if os.name == u'nt':
self.manager = Dispatch(u'com.sun.star.ServiceManager')
self.manager._FlagAsMethod(u'Bridge_GetStruct')
self.manager._FlagAsMethod(u'Bridge_GetValueObject')
else:
cmd = u'openoffice.org -nologo -norestore -minimized -invisible ' \
+ u'-nofirststartwizard ' \
+ '-accept="socket,host=localhost,port=2002;urp;"'
process = QtCore.QProcess()
process.startDetached(cmd)
process.waitForStarted()
self.process_started = True
except:
pass
def open_ooo_file(self, filepath):
"""
Open the passed file in OpenOffice.org Writer
"""
if os.name == u'nt':
url = u'file:///' + filepath.replace(u'\\', u'/')
url = url.replace(u':', u'|').replace(u' ', u'%20')
else:
url = uno.systemPathToFileUrl(filepath)
properties = []
properties = tuple(properties)
self.document = self.desktop.loadComponentFromURL(url, u'_blank',
0, properties)
def close_ooo(self):
"""
Close RTF file. Note, on Windows we'll leave OOo running
Leave running on Windows
"""
self.document.close(True)
if self.process_started:
self.desktop.terminate()
def process_doc(self):
"""
Process the RTF file, a paragraph at a time
"""
self.blanklines = 0
self.new_song()
paragraphs = self.document.getText().createEnumeration()
while paragraphs.hasMoreElements():
paragraph = paragraphs.nextElement()
if paragraph.supportsService("com.sun.star.text.Paragraph"):
self.process_paragraph(paragraph)
if self.song:
self.song.finish()
self.song = None
def process_paragraph(self, paragraph):
"""
Process a paragraph.
In the first book, a paragraph is a single line. In the latter ones
they may contain multiple lines.
Each paragraph contains textportions. Each textportion has it's own
styling, e.g. italics, bold etc.
Also check for page breaks, which indicates a new song in books 1+2.
In later books, there may not be line breaks, so check for 3 or more
newlines
"""
text = u''
textportions = paragraph.createEnumeration()
while textportions.hasMoreElements():
textportion = textportions.nextElement()
if textportion.BreakType in (PAGE_BEFORE, PAGE_BOTH):
self.process_paragraph_text(text)
self.new_song()
text = u''
text += self.process_textportion(textportion)
if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH):
self.process_paragraph_text(text)
self.new_song()
text = u''
self.process_paragraph_text(text)
def process_paragraph_text(self, text):
"""
Split the paragraph text into multiple lines and process
"""
for line in text.split(u'\n'):
self.process_paragraph_line(line)
if self.blanklines > 2:
self.new_song()
def process_paragraph_line(self, text):
"""
Process a single line. Throw away that text which isn't relevant, i.e.
stuff that appears at the end of the song.
Anything that is OK, append to the current verse
"""
text = text.strip()
if text == u'':
self.blanklines += 1
if self.blanklines > 1:
return
if self.song.get_title() != u'':
self.finish_verse()
return
self.blanklines = 0
if self.skip_to_close_bracket:
if text.endswith(u')'):
self.skip_to_close_bracket = False
return
if text.startswith(u'CCL Licence'):
self.italics = False
return
if text == u'A Songs of Fellowship Worship Resource':
return
if text.startswith(u'(NB.') or text.startswith(u'(Regrettably') \
or text.startswith(u'(From'):
self.skip_to_close_bracket = True
return
if text.startswith(u'Copyright'):
self.song.add_copyright(text)
return
if text == u'(Repeat)':
self.finish_verse()
self.song.repeat_verse()
return
if self.song.get_title() == u'':
if self.song.get_copyright() == u'':
self.add_author(text)
else:
self.song.add_copyright(text)
return
self.add_verse_line(text)
def process_textportion(self, textportion):
"""
Process a text portion. Here we just get the text and detect if
it's bold or italics. If it's bold then its a song number or song title.
Song titles are in all capitals, so we must bring the capitalization
into line
"""
text = textportion.getString()
text = self.tidy_text(text)
if text.strip() == u'':
return text
if textportion.CharWeight == BOLD:
boldtext = text.strip()
if boldtext.isdigit() and self.song.get_song_number() == '':
self.add_songnumber(boldtext)
return u''
if self.song.get_title() == u'':
text = self.uncap_text(text)
self.add_title(text)
return text
if text.strip().startswith(u'('):
return text
self.italics = (textportion.CharPosture == ITALIC)
return text
def new_song(self):
"""
A change of song. Store the old, create a new
... but only if the last song was complete. If not, stick with it
"""
if self.song:
self.finish_verse()
if not self.song.check_complete():
return
self.song.finish()
self.song = SongImport(self.manager)
self.skip_to_close_bracket = False
self.is_chorus = False
self.italics = False
self.currentverse = u''
def add_songnumber(self, song_no):
"""
Add a song number, store as alternate title. Also use the song
number to work out which songbook we're in
"""
self.song.set_song_number(song_no)
self.song.set_alternate_title(song_no + u'.')
if int(song_no) <= 640:
self.song.set_song_book(u'Songs of Fellowship 1',
u'Kingsway Publications')
elif int(song_no) <= 1150:
self.song.set_song_book(u'Songs of Fellowship 2',
u'Kingsway Publications')
elif int(song_no) <= 1690:
self.song.set_song_book(u'Songs of Fellowship 3',
u'Kingsway Publications')
else:
self.song.set_song_book(u'Songs of Fellowship 4',
u'Kingsway Publications')
def add_title(self, text):
"""
Add the title to the song. Strip some leading/trailing punctuation that
we don't want in a title
"""
title = text.strip()
if title.startswith(u'\''):
title = title[1:]
if title.endswith(u','):
title = title[:-1]
self.song.set_title(title)
def add_author(self, text):
"""
Add the author. OpenLP stores them individually so split by 'and', '&'
and comma.
However need to check for "Mr and Mrs Smith" and turn it to
"Mr Smith" and "Mrs Smith".
"""
text = text.replace(u' and ', u' & ')
for author in text.split(u','):
authors = author.split(u'&')
for i in range(len(authors)):
author2 = authors[i].strip()
if author2.find(u' ') == -1 and i < len(authors) - 1:
author2 = author2 + u' ' \
+ authors[i + 1].strip().split(u' ')[-1]
if author2.endswith(u'.'):
author2 = author2[:-1]
if author2:
self.song.add_author(author2)
def add_verse_line(self, text):
"""
Add a line to the current verse. If the formatting has changed and
we're beyond the second line of first verse, then this indicates
a change of verse. Italics are a chorus
"""
if self.italics != self.is_chorus and ((len(self.song.verses) > 0) or
(self.currentverse.count(u'\n') > 1)):
self.finish_verse()
if self.italics:
self.is_chorus = True
self.currentverse += text + u'\n'
def finish_verse(self):
"""
Verse is finished, store it. Note in book 1+2, some songs are formatted
incorrectly. Here we try and split songs with missing line breaks into
the correct number of verses.
"""
if self.currentverse.strip() == u'':
return
if self.is_chorus:
versetag = u'C'
splitat = None
else:
versetag = u'V'
splitat = self.verse_splits(self.song.get_song_number())
if splitat:
ln = 0
verse = u''
for line in self.currentverse.split(u'\n'):
ln += 1
if line == u'' or ln > splitat:
self.song.add_verse(verse, versetag)
ln = 0
if line:
verse = line + u'\n'
else:
verse = u''
else:
verse += line + u'\n'
if verse:
self.song.add_verse(verse, versetag)
else:
self.song.add_verse(self.currentverse, versetag)
self.currentverse = u''
self.is_chorus = False
def tidy_text(self, text):
"""
Get rid of some dodgy unicode and formatting characters we're not
interested in. Some can be converted to ascii.
"""
text = text.replace(u'\t', u' ')
text = text.replace(u'\r', u'\n')
text = text.replace(u'\u2018', u'\'')
text = text.replace(u'\u2019', u'\'')
text = text.replace(u'\u201c', u'"')
text = text.replace(u'\u201d', u'"')
text = text.replace(u'\u2026', u'...')
text = text.replace(u'\u2013', u'-')
text = text.replace(u'\u2014', u'-')
return text
def uncap_text(self, text):
"""
Words in the title are in all capitals, so we lowercase them.
However some of these words, e.g. referring to God need a leading
capital letter.
There is a complicated word "One", which is sometimes lower and
sometimes upper depending on context. Never mind, keep it lower.
"""
textarr = re.split(u'(\W+)', text)
textarr[0] = textarr[0].capitalize()
for i in range(1, len(textarr)):
# Do not translate these. Fixed strings in SOF song file
if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY',
u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER',
u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE',
u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS',
u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH',
u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S',
u'FATHER\'S', u'ELIJAH'):
textarr[i] = textarr[i].capitalize()
else:
textarr[i] = textarr[i].lower()
text = u''.join(textarr)
return text
def verse_splits(self, song_number):
"""
Because someone at Kingsway forgot to check the 1+2 RTF file,
some verses were not formatted correctly.
"""
if song_number == 11: return 8
if song_number == 18: return 5
if song_number == 21: return 6
if song_number == 23: return 4
if song_number == 24: return 7
if song_number == 27: return 4
if song_number == 31: return 6
if song_number == 49: return 4
if song_number == 50: return 8
if song_number == 70: return 4
if song_number == 75: return 8
if song_number == 79: return 6
if song_number == 97: return 7
if song_number == 107: return 4
if song_number == 109: return 4
if song_number == 133: return 4
if song_number == 155: return 10
if song_number == 156: return 8
if song_number == 171: return 4
if song_number == 188: return 7
if song_number == 192: return 4
if song_number == 208: return 8
if song_number == 215: return 8
if song_number == 220: return 4
if song_number == 247: return 6
if song_number == 248: return 6
if song_number == 251: return 8
if song_number == 295: return 8
if song_number == 307: return 5
if song_number == 314: return 6
if song_number == 325: return 8
if song_number == 386: return 6
if song_number == 415: return 4
if song_number == 426: return 4
if song_number == 434: return 5
if song_number == 437: return 4
if song_number == 438: return 6
if song_number == 456: return 8
if song_number == 461: return 4
if song_number == 469: return 4
if song_number == 470: return 5
if song_number == 476: return 6
if song_number == 477: return 7
if song_number == 480: return 8
if song_number == 482: return 4
if song_number == 512: return 4
if song_number == 513: return 8
if song_number == 518: return 5
if song_number == 520: return 4
if song_number == 523: return 6
if song_number == 526: return 8
if song_number == 527: return 4
if song_number == 529: return 4
if song_number == 537: return 4
if song_number == 555: return 6
if song_number == 581: return 4
if song_number == 589: return 6
if song_number == 590: return 4
if song_number == 593: return 8
if song_number == 596: return 4
if song_number == 610: return 6
if song_number == 611: return 6
if song_number == 619: return 8
if song_number == 645: return 5
if song_number == 653: return 6
if song_number == 683: return 7
if song_number == 686: return 4
if song_number == 697: return 8
if song_number == 698: return 4
if song_number == 704: return 6
if song_number == 716: return 4
if song_number == 717: return 6
if song_number == 730: return 4
if song_number == 731: return 8
if song_number == 732: return 8
if song_number == 738: return 4
if song_number == 756: return 9
if song_number == 815: return 6
if song_number == 830: return 8
if song_number == 831: return 4
if song_number == 876: return 6
if song_number == 877: return 6
if song_number == 892: return 4
if song_number == 894: return 6
if song_number == 902: return 8
if song_number == 905: return 8
if song_number == 921: return 6
if song_number == 940: return 7
if song_number == 955: return 9
if song_number == 968: return 8
if song_number == 972: return 7
if song_number == 974: return 4
if song_number == 988: return 6
if song_number == 991: return 5
if song_number == 1002: return 8
if song_number == 1024: return 8
if song_number == 1044: return 9
if song_number == 1088: return 6
if song_number == 1117: return 6
if song_number == 1119: return 7
return None

View File

@ -0,0 +1,273 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import string
from openlp.core.lib import SongXMLBuilder
from openlp.plugins.songs.lib.models import Song, Author, Topic, Book
class SongImport(object):
"""
Helper class for import a song from a third party source into OpenLP
This class just takes the raw strings, and will work out for itself
whether the authors etc already exist and add them or refer to them
as necessary
"""
def __init__(self, song_manager):
"""
Initialise and create defaults for properties
song_manager is an instance of a SongManager, through which all
database access is performed
"""
self.manager = song_manager
self.title = u''
self.song_number = u''
self.alternate_title = u''
self.copyright = u''
self.comment = u''
self.theme_name = u''
self.ccli_number = u''
self.authors = []
self.topics = []
self.song_book_name = u''
self.song_book_pub = u''
self.verse_order_list = []
self.verses = []
self.versecount = 0
self.choruscount = 0
def get_title(self):
"""
Return the title
"""
return self.title
def get_copyright(self):
"""
Return the copyright
"""
return self.copyright
def get_song_number(self):
"""
Return the song number
"""
return self.song_number
def set_title(self, title):
"""
Set the title
"""
self.title = title
def set_alternate_title(self, title):
"""
Set the alternate title
"""
self.alternate_title = title
def set_song_number(self, song_number):
"""
Set the song number
"""
self.song_number = song_number
def set_song_book(self, song_book, publisher):
"""
Set the song book name and publisher
"""
self.song_book_name = song_book
self.song_book_pub = publisher
def add_copyright(self, copyright):
"""
Build the copyright field
"""
if self.copyright != u'':
self.copyright += ' '
self.copyright += copyright
def add_author(self, text):
"""
Add an author to the list
"""
self.authors.append(text)
def add_verse(self, verse, versetag):
"""
Add a verse. This is the whole verse, lines split by \n
Verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the verses/
choruses itself) or None, where it will assume verse
It will also attempt to detect duplicates. In this case it will just
add to the verse order
"""
for (oldversetag, oldverse) in self.verses:
if oldverse.strip() == verse.strip():
self.verse_order_list.append(oldversetag)
return
if versetag.startswith(u'C'):
self.choruscount += 1
if versetag == u'C':
versetag += unicode(self.choruscount)
if versetag == u'V' or not versetag:
self.versecount += 1
versetag = u'V' + unicode(self.versecount)
self.verses.append([versetag, verse.rstrip()])
self.verse_order_list.append(versetag)
if versetag.startswith(u'V') and self.contains_verse(u'C1'):
self.verse_order_list.append(u'C1')
def repeat_verse(self):
"""
Repeat the previous verse in the verse order
"""
self.verse_order_list.append(self.verse_order_list[-1])
def contains_verse(self, versetag):
return versetag in self.verse_order_list
def check_complete(self):
"""
Check the mandatory fields are entered (i.e. title and a verse)
Author not checked here, if no author then "Author unknown" is
automatically added
"""
if self.title == u'' or len(self.verses) == 0:
return False
else:
return True
def remove_punctuation(self, text):
"""
Remove punctuation from the string for searchable fields
"""
for c in string.punctuation:
text = text.replace(c, u'')
return text
def finish(self):
"""
All fields have been set to this song. Write it away
"""
if len(self.authors) == 0:
self.authors.append(u'Author unknown')
self.commit_song()
#self.print_song()
def commit_song(self):
"""
Write the song and it's fields to disk
"""
song = Song()
song.title = self.title
song.search_title = self.remove_punctuation(self.title) \
+ '@' + self.alternate_title
song.song_number = self.song_number
song.search_lyrics = u''
sxml = SongXMLBuilder()
sxml.new_document()
sxml.add_lyrics_to_song()
for (versetag, versetext) in self.verses:
if versetag[0] == u'C':
versetype = u'Chorus'
elif versetag[0] == u'V':
versetype = u'Verse'
elif versetag[0] == u'B':
versetype = u'Bridge'
elif versetag[0] == u'I':
versetype = u'Intro'
elif versetag[0] == u'P':
versetype = u'Prechorus'
elif versetag[0] == u'E':
versetype = u'Ending'
else:
versetype = u'Other'
sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext)
song.search_lyrics += u' ' + self.remove_punctuation(versetext)
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
song.verse_order = u' '.join(self.verse_order_list)
song.copyright = self.copyright
song.comment = self.comment
song.theme_name = self.theme_name
song.ccli_number = self.ccli_number
for authortext in self.authors:
author = self.manager.get_author_by_name(authortext)
if author is None:
author = Author()
author.display_name = authortext
author.last_name = authortext.split(u' ')[-1]
author.first_name = u' '.join(authortext.split(u' ')[:-1])
self.manager.save_author(author)
song.authors.append(author)
if self.song_book_name:
song_book = self.manager.get_book_by_name(self.song_book_name)
if song_book is None:
song_book = Book()
song_book.name = self.song_book_name
song_book.publisher = self.song_book_pub
self.manager.save_book(song_book)
song.song_book_id = song_book.id
for topictext in self.topics:
topic = self.manager.get_topic_by_name(topictext)
if topic is None:
topic = Topic()
topic.name = topictext
self.manager.save_topic(topic)
song.topics.append(topictext)
self.manager.save_song(song)
def print_song(self):
"""
For debugging
"""
print u'========================================' \
+ u'========================================'
print u'TITLE: ' + self.title
print u'ALT TITLE: ' + self.alternate_title
for (versetag, versetext) in self.verses:
print u'VERSE ' + versetag + u': ' + versetext
print u'ORDER: ' + u' '.join(self.verse_order_list)
for author in self.authors:
print u'AUTHOR: ' + author
if self.copyright:
print u'COPYRIGHT: ' + self.copyright
if self.song_book_name:
print u'BOOK: ' + self.song_book_name
if self.song_book_pub:
print u'BOOK PUBLISHER: ' + self.song_book_pub
if self.song_number:
print u'NUMBER: ' + self.song_number
for topictext in self.topics:
print u'TOPIC: ' + topictext
if self.comment:
print u'COMMENT: ' + self.comment
if self.theme_name:
print u'THEME: ' + self.theme_name
if self.ccli_number:
print u'CCLI: ' + self.ccli_number

View File

@ -27,8 +27,9 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, build_icon, PluginStatus
from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab
from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver
from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \
SofImport
from openlp.plugins.songs.forms import OpenLPImportForm, OpenSongExportForm, \
OpenSongImportForm, OpenLPExportForm
@ -102,24 +103,35 @@ class SongsPlugin(Plugin):
self.ImportOpenlp1Item.setObjectName(u'ImportOpenlp1Item')
self.ImportOpenlp2Item = QtGui.QAction(import_menu)
self.ImportOpenlp2Item.setObjectName(u'ImportOpenlp2Item')
self.ImportSofItem = QtGui.QAction(import_menu)
self.ImportSofItem.setObjectName(u'ImportSofItem')
# Add to menus
self.ImportSongMenu.addAction(self.ImportOpenlp1Item)
self.ImportSongMenu.addAction(self.ImportOpenlp2Item)
self.ImportSongMenu.addAction(self.ImportOpenSongItem)
self.ImportSongMenu.addAction(self.ImportSofItem)
import_menu.addAction(self.ImportSongMenu.menuAction())
# Translations...
self.ImportSongMenu.setTitle(import_menu.trUtf8('&Song'))
self.ImportOpenSongItem.setText(import_menu.trUtf8('OpenSong'))
self.ImportOpenlp1Item.setText(import_menu.trUtf8('openlp.org 1.0'))
self.ImportOpenlp1Item.setToolTip(
import_menu.trUtf8('Export songs in openlp.org 1.0 format'))
import_menu.trUtf8('Import songs in openlp.org 1.0 format'))
self.ImportOpenlp1Item.setStatusTip(
import_menu.trUtf8('Export songs in openlp.org 1.0 format'))
import_menu.trUtf8('Import songs in openlp.org 1.0 format'))
self.ImportOpenlp2Item.setText(import_menu.trUtf8('OpenLP 2.0'))
self.ImportOpenlp2Item.setToolTip(
import_menu.trUtf8('Export songs in OpenLP 2.0 format'))
import_menu.trUtf8('Import songs in OpenLP 2.0 format'))
self.ImportOpenlp2Item.setStatusTip(
import_menu.trUtf8('Export songs in OpenLP 2.0 format'))
import_menu.trUtf8('Import songs in OpenLP 2.0 format'))
self.ImportSofItem.setText(
import_menu.trUtf8('Songs of Fellowship'))
self.ImportSofItem.setToolTip(
import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \
+ '.rtf and sof4words.rtf supplied with the music books'))
self.ImportSofItem.setStatusTip(
import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \
+ '.rtf and sof4words.rtf supplied with the music books'))
# Signals and slots
QtCore.QObject.connect(self.ImportOpenlp1Item,
QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick)
@ -127,6 +139,8 @@ class SongsPlugin(Plugin):
QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick)
QtCore.QObject.connect(self.ImportOpenSongItem,
QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick)
QtCore.QObject.connect(self.ImportSofItem,
QtCore.SIGNAL(u'triggered()'), self.onImportSofItemClick)
self.ImportSongMenu.menuAction().setVisible(False)
def add_export_menu_item(self, export_menu):
@ -169,6 +183,25 @@ class SongsPlugin(Plugin):
def onImportOpenSongItemClick(self):
self.opensong_import_form.show()
def onImportSofItemClick(self):
filename = QtGui.QFileDialog.getOpenFileName(
None, self.trUtf8('Open Songs of Fellowship file'),
u'', u'Songs of Fellowship file (*.rtf *.RTF)')
try:
sofimport = SofImport(self.songmanager)
sofimport.import_sof(unicode(filename))
except:
log.exception('Could not import SoF file')
QtGui.QMessageBox.critical(None,
self.ImportSongMenu.trUtf8('Import Error'),
self.ImportSongMenu.trUtf8('Error importing Songs of '
+ 'Fellowship file.\nOpenOffice.org must be installed'
+ ' and you must be using an unedited copy of the RTF'
+ ' included with the Songs of Fellowship Music Editions'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok)
Receiver.send_message(u'load_song_list')
def onExportOpenlp1ItemClicked(self):
self.openlp_export_form.show()

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<song>
<title>Amazing Grace</title>
<author>John Newton</author>
<copyright>1982 Jubilate Hymns Limited</copyright>
<presentation></presentation>
<capo print=""></capo>
<tempo></tempo>
<timesig></timesig>
<ccli>1037882</ccli>
<theme>God: Attributes</theme>
<alttheme></alttheme>
<user1></user1>
<user2></user2>
<user3></user3>
<lyrics>[V1]
. D D7 G D Bm E A A7
Amazing grace how sweet the sound that saved a wretch like me;
. D D7 G D Bm A G D
I once was lost but now I'm found, was blind but now I see.
[V2]
. D D7 G D Bm E A A7
Twas grace that taught my heart to fear, and grace my fears relieved;
. D D7 G D Bm A G D
How precious did that grace appear the hour I first believed!
[V3]
. D D7 G D Bm E A A7
Through many dangers, toils, and snares I have already come;
. D D7 G D Bm A G D
'Tis grace that brought me safe thus far and grace will lead me home.
[V4]
. D D7 G D Bm E A A7
When we've been there ten thousand years bright shining as the sun;
. D D7 G D Bm A G D
We've no less days to sing God's praise than when we'd first begun!</lyrics></song>

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><song><title>På en fjern ensom høj</title><author></author><copyright></copyright><ccli></ccli><lyrics>[V1]
På en fjern ensom høj,
Jesu kors dyrest stod,
symbolet på smerte og skam.
O, jeg elsker det kors,
hvor Guds søn gjorde bod,
da forbandelsen blev lagt på ham.
[C1]
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
[V2]
O, det urgamle kors,
med sin hvile og fred,
tilhyllet i verdens foragt.
Se, det hellige lam,
som på Golgatha stred,
og til jorden Guds nåde har bragt.
[C2]
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
[V3]
I det urgamle kors,
i hans blod farvet rødt,
en underfuld skønhed jeg ser.
Ja, det var på det kors,
at han selv blev forstødt,
nu skal aldrig for dommen jeg mer.
[C3]
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
[V4]
For det urgamle kors,
står mit hjerte i brand,
min plads jeg nu har ved dets fod.
Til han kalder en dag,
mig til himmelens land,
og til hvilen hos Faderen god.
[C4]
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</lyrics><presentation>V1 C1 V2 C2 V3 C3 V4 C4</presentation></song>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<song>
<title>The Solid Rock</title>
<author>Edward Mote and John B. Dykes</author>
<copyright>Public Domain</copyright>
<presentation>V1 C V2 C V3 C V4 C</presentation>
<ccli>101740</ccli>
<theme>Christ: Victory</theme>
<alttheme>Fruit: Peace/Comfort</alttheme>
<lyrics>[V]
. E B A B E
1My hope is built on nothing less than Jesus' blood and righteousness;
2When darkness veils His lovely face, I rest on His un___changing grace.
3His oath, His cove_____nant, His blood|support me in the whelming flood;
4When He shall come with trumpet sound, O may I then in Him be found;
. E B A B E
1I dare not trust the sweetest frame, but wholly lean on Jesus' name.
2In every high and stormy gale, my anchor holds within the veil.
3When all around my soul gives way, He then is all my hope and stay.
4Dressed in His righteous___ness alone, fault___less to stand be_fore the throne.
[C]
. E A
On Christ, the solid rock I stand;
. E B
All other ground is sinking sand,
. A B E
All other ground is sinking sand.</lyrics></song>

View File

@ -1,36 +0,0 @@
Song Title Here
Chorus 1
Lyrics
Lyrics
Lyrics
Lyrics
Verse 1
Lyrics
Lyrics
Lyrics
Verse 2
Lyrics
Lyrics
Lyrics
Misc 1
(BRIDGE)
Lyrics
Lyrics
Lyrics
Lyrics
CCLI Song No. 1234567
© 1996 Publisher Info
Author/artist name
For use solely in accordance with the SongSelect Advanced Terms of Agreement. All rights Reserved.
CCLI License No. 1234567

View File

@ -1,61 +0,0 @@
På en fjern ensom høj
Verse 1
På en fjern ensom høj,
Jesu kors dyrest stod,
symbolet på smerte og skam.
O, jeg elsker det kors,
hvor Guds søn gjorde bod,
da forbandelsen blev lagt på ham.
Chorus 1
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
Verse 2
O, det urgamle kors,
med sin hvile og fred,
tilhyllet i verdens foragt.
Se, det hellige lam,
som på Golgatha stred,
og til jorden Guds nåde har bragt.
Chorus 2
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
Verse 3
I det urgamle kors,
i hans blod farvet rødt,
en underfuld skønhed jeg ser.
Ja, det var på det kors,
at han selv blev forstødt,
nu skal aldrig for dommen jeg mer.
Chorus 3
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
Verse 4
For det urgamle kors,
står mit hjerte i brand,
min plads jeg nu har ved dets fod.
Til han kalder en dag,
mig til himmelens land,
og til hvilen hos Faderen god.
Chorus 4
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
CCLI Song No.
©
Georg Bennard

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Song>
<title>Amazing Grace</title>
<lyrics>
<verse name="v1">
Amazing grace how sweet the sound that saved a wretch like me;
I once was lost but now I'm found, was blind but now I see.
</verse>
<verse name="v2">
Twas grace that taught my heart to fear, and grace my fears relieved;
How precious did that grace appear the hour I first believed!
</verse>
<verse name="v3">
Through many dangers, toils, and snares I have already come;
'Tis grace that brought me safe thus far and grace will lead me home.
</verse>
<verse name="v4">
When we've been there ten thousand years bright shining as the sun;
We've no less days to sing God's praise than when we'd first begun!
</verse>
</lyrics>
</Song>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Song>
<title>Amazing Grace</title>
<lyrics lang="en_US">
<verse name="v1">
Amazing grace how sweet the sound that saved a wretch like me;
I once was lost but now I'm found, was blind but now I see.
</verse>
<verse name="v2">
Twas grace that taught my heart to fear, and grace my fears relieved;
How precious did that grace appear the hour I first believed!
</verse>
<verse name="v3">
Through many dangers, toils, and snares I have already come;
'Tis grace that brought me safe thus far and grace will lead me home.
</verse>
<verse name="v4">
When we've been there ten thousand years bright shining as the sun;
We've no less days to sing God's praise than when we'd first begun!
</verse>
</lyrics>
</Song>

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Song>
<title>På en fjern ensom høj</title>
<lyrics lang="dk_DK">
<verse name="v1">
På en fjern ensom høj,
Jesu kors dyrest stod,
symbolet på smerte og skam.
O, jeg elsker det kors,
hvor Guds søn gjorde bod,
da forbandelsen blev lagt på ham.
</verse>
<verse name="c1">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v2">
O, det urgamle kors,
med sin hvile og fred,
tilhyllet i verdens foragt.
Se, det hellige lam,
som på Golgatha stred,
og til jorden Guds nåde har bragt.
</verse>
<verse name="c2">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v3">
I det urgamle kors,
i hans blod farvet rødt,
en underfuld skønhed jeg ser.
Ja, det var på det kors,
at han selv blev forstødt,
nu skal aldrig for dommen jeg mer.
</verse>
<verse name="c3">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v4">
For det urgamle kors,
står mit hjerte i brand,
min plads jeg nu har ved dets fod.
Til han kalder en dag,
mig til himmelens land,
og til hvilen hos Faderen god.
</verse>
<verse name="c4">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
</lyrics>
</Song>

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Song>
<title>På en fjern ensom høj</title>
<lyrics lang="dk_DK">
<verse name="v1">
På en fjern ensom høj,
Jesu kors dyrest stod,
symbolet på smerte og skam.
O, jeg elsker det kors,
hvor Guds søn gjorde bod,
da forbandelsen blev lagt på ham.
</verse>
<verse name="c1">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v2">
O, det urgamle kors,
med sin hvile og fred,
tilhyllet i verdens foragt.
Se, det hellige lam,
som på Golgatha stred,
og til jorden Guds nåde har bragt.
</verse>
<verse name="c2">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v3">
I det urgamle kors,
i hans blod farvet rødt,
en underfuld skønhed jeg ser.
Ja, det var på det kors,
at han selv blev forstødt,
nu skal aldrig for dommen jeg mer.
</verse>
<verse name="c3">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
<verse name="v4">
For det urgamle kors,
står mit hjerte i brand,
min plads jeg nu har ved dets fod.
Til han kalder en dag,
mig til himmelens land,
og til hvilen hos Faderen god.
</verse>
<verse name="c4">
Jeg vil elske det urgamle kors,
i det kraft er der sejer og sang.
Lad mig favne det hellige kors,
det med kronen ombyttes engang.
</verse>
</lyrics>
</Song>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Song>
<title>Amazing Grace</title>
<lyrics>
<verse name="v1">
<b>Amazing grace</b> how sweet the sound that saved a wretch like me;
I once was lost but now I'm found, was blind but now I see.
</verse>
<verse name="v2">
<u>Twas grace that taught my <i>heart</i> to fear, and grace my fears relieved;</u>
How precious did that <i>grace</i> appear the hour I first believed!
</verse>
<verse name="v3">
Through many dangers, toils, and snares I have already come;
'Tis grace that brought me safe thus far and grace will lead me home.
</verse>
<verse name="v4">
When we've been there ten thousand years bright shining as the sun;
We've no less days to sing <b><i>God's praise</i></b> than when we'd first begun!
</verse>
</lyrics>
</Song>

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Song>
<lyrics lang="en_US">
<title>Amazing Grace</title>
<verse name="v1">
<theme>name of verse specific theme</theme>
<comment>any text</comment>
<part name="men">
Amazing grace, how ...
</part>
<part name="women">
A b c
D e f
</part>
...
</verse>
<verse name="c">
<comment>any text</comment>
...
</verse>
</lyrics>
<lyrics lang="de_DE">
<title>Erstaunliche Anmut</title>
<verse name="v1">
Erstaunliche Anmut, wie
...
</verse>
<verse name="c">
...
</verse>
</lyrics>
</Song>

View File

@ -1,182 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import py.test
import os
import sys
__ThisDir__ = os.path.dirname(__file__)
if "" == __ThisDir__ :
__ThisDir__ = os.path.abspath(u'.')
sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__))
from openlp.plugins.songs.lib.songxml import *
class Test_Basic(object):
"""Class for first initialization check
set-get functions
"""
def test_Creation(self):
"""Init: Create as empty"""
s = Song()
assert(True)
def test_Title1(self):
"""Set an empty title - raises an exception"""
s = Song()
py.test.raises(SongTitleError, s.set_title, '')
def test_Title2(self):
"""Set a normal title"""
s = Song()
t = "A normal title"
s.set_title(t)
assert(s.get_title() == t)
assert(s.get_search_title() == t)
def test_Title3(self):
"""Set a titel with punctuation 1"""
s = Song()
t1 = "Hey! Come on, ya programmers*"
t2 = "Hey Come on ya programmers"
s.set_title(t1)
assert(s.get_title() == t1)
assert(s.get_search_title() == t2)
def test_Title4(self):
"""Set a titel with punctuation 2"""
s = Song()
t1 = "??#Hey! Come on, ya programmers*"
t2 = "Hey Come on ya programmers"
s.set_title(t1)
assert(s.get_title() == t1)
assert(s.get_search_title() == t2)
def test_Title5(self):
"""
Set a title
Where searchable title becomes empty raises an exception
"""
s = Song()
py.test.raises(SongTitleError, s.set_title, ',*')
def test_Copyright(self):
"""Set a copyright string"""
s = Song()
assert(s.get_copyright() == '')
s.set_copyright(u'A B Car')
assert(s.get_copyright() == 'A B Car')
def test_SongCclino(self):
"""Set a SongCcliNo"""
s = Song()
assert(s.get_song_cclino() == '')
s.set_song_cclino(12345)
assert(s.get_song_cclino() == '12345')
def test_SongBook(self):
"""Set a songbook value"""
s = Song()
assert(s.get_song_book() == '')
s.set_song_book(u'Hymns')
assert(s.get_song_book() == u'Hymns')
def test_SongNumber(self):
"""Set a song number"""
s = Song()
assert(s.get_song_number() == '')
s.set_song_number(278)
assert(s.get_song_number() == '278')
def test_Theme(self):
"""Set a theme name"""
s = Song()
assert(s.get_theme() == '')
s.set_theme(u'Red')
assert(s.get_theme() == 'Red')
def test_VerseOrder(self):
"""Set a verse order"""
s = Song()
assert(s.get_verse_order() == '')
s.set_verse_order(u'V1 C V2')
assert(s.get_verse_order() == 'V1 C V2')
def test_Comments(self):
"""Set a comment"""
s = Song()
assert(s.get_comments() == '')
s.set_comments(u'a comment')
assert(s.get_comments() == 'a comment')
def test_AuthorList(self):
"""Set author lists"""
s = Song()
assert(s.get_author_list(True) == '')
assert(s.get_author_list(False) == [])
t1 = "John Newton"
s.set_author_list(t1)
assert(s.get_author_list(True) == t1)
assert(s.get_author_list(False) == [t1])
s.set_author_list(u' Peter Done , John Newton')
assert(s.get_author_list(True)== 'Peter Done, John Newton')
assert(s.get_author_list(False) == ["Peter Done", u'John Newton'])
s.set_author_list(None)
assert(s.get_author_list(True) == '')
assert(s.get_author_list(False) == [])
s.set_author_list(u'')
assert(s.get_author_list(True) == '')
assert(s.get_author_list(False) == [""])
s.set_author_list([])
assert(s.get_author_list(True) == '')
assert(s.get_author_list(False) == [""])
def test_CategoryArray(self):
"""Set categories"""
s = Song()
assert(s.get_category_array(True) == '')
assert(s.get_category_array(False) == [])
t1 = "Gospel"
s.set_category_array(t1)
assert(s.get_category_array(True) == t1)
assert(s.get_category_array(False) == [t1])
s.set_category_array(u' Gospel, Hymns ')
assert(s.get_category_array(True) == 'Gospel, Hymns')
assert(s.get_category_array(False) == ["Gospel", u'Hymns'])
s.set_category_array(None)
assert(s.get_category_array(True) == '')
assert(s.get_category_array(False) == [])
s.set_category_array(u'')
assert(s.get_category_array(True) == '')
assert(s.get_category_array(False) == [""])
s.set_category_array([])
assert(s.get_category_array(True) == '')
assert(s.get_category_array(False) == [""])
if '__main__' == __name__:
r = Test_Basic()
r.test_asString()

View File

@ -1,192 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import sys
__ThisDir__ = os.path.dirname(__file__)
if "" == __ThisDir__ :
__ThisDir__ = os.path.abspath(u'.')
sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__))
from openlp.plugins.songs.lib.songxml import *
_sample1 = \
'''<?xml version="1.0" encoding="UTF-8"?>
<song>
<title></title>
<author></author>
<copyright></copyright>
<presentation></presentation>
<ccli></ccli>
<theme></theme>
<lyrics>[V1]
. chord line 1
verse 1 line 1
. chord line 2
verse 1 line 2
[V2]
verse 2 line 1
verse 2 line 2
[V3]
verse 3 line 1
verse 3 line 2
[C]
. chorus chord line 1
chorus line 1
. chorus chord line 2
chorus line 2</lyrics>
</song>
'''
_sample2 = \
'''<?xml version="1.0" encoding="UTF-8"?>
<song>
<title></title>
<author></author>
<copyright></copyright>
<presentation></presentation>
<ccli></ccli>
<theme></theme>
<lyrics>[V]
1verse 1 line 1
2verse 2 line 1
3verse 3 line 1
1verse 1 line 2
2verse 2 line 2
3verse 3 line 2
[C]
chorus line 1
chorus line 2</lyrics>
</song>
'''
_sample3 = \
'''<?xml version="1.0" encoding="UTF-8"?>
<song>
<title></title>
<author></author>
<copyright></copyright>
<presentation></presentation>
<ccli></ccli>
<theme></theme>
<lyrics>[V]
1verse 1 line 1
2verse 2 line 1
3verse 3 line 1
1verse 1 line 2
2verse 2 line 2
3verse 3 line 2
[C]
chorus line 1
chorus line 2
[P]
pre-chorus line 1
pre-chorus line 2
pre-chorus line 3
[B]
bridge line 1
bridge line 2
</lyrics>
</song>
'''
class Test_OpenSong(object):
"""Test cases for converting from OpenSong xml format to Song"""
def test_sample1(self):
"""OpenSong: handwritten sample1"""
s = Song()
s.from_opensong_buffer(_sample1)
l = s.get_lyrics()
assert(len(l) == (4*3+3))
assert(s.get_number_of_slides() == 4)
def test_sample2(self):
"""OpenSong: handwritten sample2 - with verses and chorus"""
s = Song()
s.from_opensong_buffer(_sample2)
l = s.get_lyrics()
assert(len(l) == (4*3+3))
assert(s.get_number_of_slides() == 4)
def test_sample3(self):
"""OpenSong: handwritten sample3 - with verses, chorus, bridge and pre-chorus"""
s = Song()
s.from_opensong_buffer(_sample3)
l = s.get_lyrics()
assert(len(l) == (4*3+4+5+4))
assert(s.get_number_of_slides() == 6)
def test_file1(self):
"""OpenSong: parse Amazing Grace"""
global __ThisDir__
s = Song()
s.from_opensong_file(u'%s/data_opensong/Amazing Grace'%(__ThisDir__))
assert(s.get_title() == 'Amazing Grace')
assert(s.get_copyright() == '1982 Jubilate Hymns Limited')
assert(s.get_song_cclino() == '1037882')
assert(s.get_category_array(True) == 'God: Attributes')
assert(s.get_author_list(True) == 'John Newton')
assert(s.get_verse_order() == '')
assert(s.get_number_of_slides() == 4)
def test_file2(self):
"""OpenSong: parse The Solid Rock"""
s = Song()
s.from_opensong_file(u'%s/data_opensong/The Solid Rock'%(__ThisDir__))
assert(s.get_title() == 'The Solid Rock')
assert(s.get_copyright() == 'Public Domain')
assert(s.get_song_cclino() == '101740')
assert(s.get_category_array(True) == 'Christ: Victory, Fruit: Peace/Comfort')
assert(s.get_author_list(True) == 'Edward Mote, John B. Dykes')
assert(s.get_verse_order() == 'V1 C V2 C V3 C V4 C')
assert(s.get_number_of_slides() == 5)
def test_file3(self):
"""OpenSong: parse 'På en fjern ensom høj' (danish)"""
#FIXME: problem with XML convert and danish characters
s = Song()
s.from_opensong_file(u'%s/data_opensong/På en fjern ensom høj'%(__ThisDir__))
assert(s.get_title() == u'På en fjern ensom høj')
assert(s.get_copyright() == '')
assert(s.get_song_cclino() == '')
assert(s.get_category_array(True) == '')
assert(s.get_author_list(True) == '')
assert(s.get_verse_order() == 'V1 C1 V2 C2 V3 C3 V4 C4')
assert(s.get_number_of_slides() == 8)
if '__main__' == __name__:
r = Test_OpenSong()
r.test_file3()

View File

@ -1,66 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import sys
__ThisDir__ = os.path.dirname(__file__)
if "" == __ThisDir__ :
__ThisDir__ = os.path.abspath(u'.')
sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__))
from openlp.plugins.songs.lib.songxml import *
class Test_Text(object):
"""Test cases for converting from text format to Song"""
def test_file1(self):
"""OpenSong: parse CCLI example"""
global __ThisDir__
s = Song()
s.from_ccli_text_file(u'%s/data_text/CCLI example.txt'%(__ThisDir__))
assert(s.get_title() == 'Song Title Here')
assert(s.get_author_list(True) == 'Author, artist name')
assert(s.get_copyright() == '1996 Publisher Info')
assert(s.get_song_cclino() == '1234567')
assert(s.get_number_of_slides() == 4)
def test_file2(self):
"""OpenSong: parse PåEnFjern (danish)"""
global __ThisDir__
s = Song()
s.from_ccli_text_file(u'%s/data_text/PåEnFjern.txt'%(__ThisDir__))
assert(s.get_title() == 'På en fjern ensom høj')
assert(s.get_author_list(True) == 'Georg Bennard')
assert(s.get_copyright() == '')
assert(s.get_song_cclino() == '')
assert(s.get_number_of_slides() == 8)
if '__main__' == __name__:
# for local debugging
r = Test_Text()
r.test_file1()
r.test_file2()

View File

@ -1,156 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import sys
__ThisDir__ = os.path.dirname(__file__)
if "" == __ThisDir__ :
__ThisDir__ = os.path.abspath(u'.')
sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__))
from openlp.plugins.songs.lib.songxml import *
class Test_Verse(object):
"""Class for testing verses for preview and review"""
def stdSong(self):
"""Definition of a standard song"""
s = Song()
self.title = "A song"
self.author = "John Newton"
self.copyright = "Peter Hamil"
self.ccli = "123456"
s.set_lyrics(["# verse","a single line"])
s.set_title(self.title)
s.set_copyright(self.copyright)
s.set_author_list(self.author)
s.set_song_cclino(self.ccli)
return s
def check_allfields(self, r, isblank = 0):
#[theme, title, author, cpright, ccli, lyrics]
if isblank == 1 :
assert(r[1] == '')
else :
assert(r[1] == self.title)
if isblank == 2 :
assert(r[2] == '')
else :
assert(r[2] == self.author)
if isblank == 3 :
assert(r[3] == '')
else :
assert(r[3] == self.copyright)
if isblank == 4 :
assert(r[4] == '')
else :
assert(r[4] == self.ccli)
def test_title_show_noshow(self):
"""Test the show title flag"""
s = self.stdSong()
r = s.get_render_slide(1)
self.check_allfields(r)
s.set_show_title(False)
r = s.get_render_slide(1)
self.check_allfields(r, 1)
s.set_show_title(True)
r = s.get_render_slide(1)
self.check_allfields(r)
def test_author_show_noshow(self):
"""Test the show author flag"""
s = self.stdSong()
r = s.get_render_slide(1)
self.check_allfields(r)
s.set_show_author_list(False)
r = s.get_render_slide(1)
self.check_allfields(r, 2)
s.set_show_author_list(True)
r = s.get_render_slide(1)
self.check_allfields(r)
def test_copyright_show_noshow(self):
"""Test the show copyright flag"""
s = self.stdSong()
r = s.get_render_slide(1)
self.check_allfields(r)
s.set_show_copyright(False)
r = s.get_render_slide(1)
self.check_allfields(r, 3)
s.set_show_copyright(True)
r = s.get_render_slide(1)
self.check_allfields(r)
def test_ccli_show_noshow(self):
"""Test the show copyright flag"""
s = self.stdSong()
r = s.get_render_slide(1)
self.check_allfields(r)
s.set_show_song_cclino(False)
r = s.get_render_slide(1)
self.check_allfields(r, 4)
s.set_show_song_cclino(True)
r = s.get_render_slide(1)
self.check_allfields(r)
def test_verse1(self):
"""Test an empty verse list"""
s = Song()
s.set_lyrics([])
assert(s.get_number_of_slides() == 0)
def test_verse2(self):
"""Test a list with an empty string"""
s = Song()
s.set_lyrics([""])
assert(s.get_number_of_slides() == 0)
def test_verse3a(self):
"""Test a one liner song"""
s = Song()
s.set_lyrics(["Single verse"])
assert(s.get_number_of_slides() == 1)
def test_verse3b(self):
"""Test a one liner song"""
s = Song()
s.set_lyrics(["", u'Single verse'])
assert(s.get_number_of_slides() == 1)
def test_verse3c(self):
"""Test a one liner song"""
s = Song()
s.set_lyrics(["", u'Single verse', u'', u''])
assert(s.get_number_of_slides() == 1)
def test_verse3d(self):
"""Test a one liner song"""
s = Song()
s.set_lyrics(["", u'# Verse', u'', u''])
assert(s.get_number_of_slides() == 1)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Some files were not shown because too many files have changed in this diff Show More