Head
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
@ -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'])
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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>
|
Before Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 517 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.4 MiB |
@ -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_())
|
@ -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))
|
@ -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)
|
@ -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)
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,8 +0,0 @@
|
||||
from openlp.core.lib import Plugin
|
||||
|
||||
class testplugin2(Plugin):
|
||||
name="testplugin2"
|
||||
version=1
|
||||
weight=1
|
||||
def __init__(self):
|
||||
pass
|
@ -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()
|
@ -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>
|
@ -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')
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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' %
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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')
|
@ -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)
|
||||
|
@ -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 #
|
||||
###############################################################################
|
@ -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,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,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.
|
@ -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.
|
@ -1 +0,0 @@
|
||||
py.test --nocapture test_bibleManager.py
|
@ -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')
|
@ -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 )
|
@ -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)
|
@ -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)
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
Before Width: | Height: | Size: 716 B |
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -26,3 +26,5 @@
|
||||
from manager import SongManager
|
||||
from songstab import SongsTab
|
||||
from mediaitem import SongMediaItem
|
||||
from sofimport import SofImport
|
||||
from songimport import SongImport
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
530
openlp/plugins/songs/lib/sofimport.py
Normal 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
|
||||
|
273
openlp/plugins/songs/lib/songimport.py
Normal 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
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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
|
@ -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
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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()
|
@ -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()
|
@ -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()
|
@ -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)
|
BIN
resources/images/general_add.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
resources/images/general_delete.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
resources/images/general_edit.png
Normal file
After Width: | Height: | Size: 726 B |
BIN
resources/images/general_export.png
Normal file
After Width: | Height: | Size: 638 B |
BIN
resources/images/general_import.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
resources/images/general_live.png
Normal file
After Width: | Height: | Size: 720 B |
BIN
resources/images/general_new.png
Normal file
After Width: | Height: | Size: 579 B |
BIN
resources/images/general_open.png
Normal file
After Width: | Height: | Size: 531 B |
BIN
resources/images/general_preview.png
Normal file
After Width: | Height: | Size: 815 B |