Merge from trunk.

This commit is contained in:
Michael Gorven 2009-11-27 13:00:01 +02:00
commit 662962abef
64 changed files with 1092 additions and 773 deletions

View File

@ -74,15 +74,21 @@ class OpenLP(QtGui.QApplication):
#Load and store current Application Version #Load and store current Application Version
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(filepath, u'version.txt')) filepath = os.path.abspath(os.path.join(filepath, u'version.txt'))
fversion = None
try: try:
fversion = open(filepath, 'r') fversion = open(filepath, 'r')
for line in fversion: for line in fversion:
bits = unicode(line).split(u'-') bits = unicode(line).split(u'-')
applicationVersion = {u'Full':unicode(line).rstrip(), applicationVersion = {u'Full':unicode(line).rstrip(),
u'version':bits[0], u'build':bits[1]} u'version':bits[0], u'build':bits[1]}
log.info(u'Openlp version %s build %s' %
(applicationVersion[u'version'],applicationVersion[u'build'] ))
except: except:
applicationVersion = {u'Full':u'1.9.0-000', applicationVersion = {u'Full':u'1.9.0-000',
u'version':u'1.9.0', u'build':u'000'} u'version':u'1.9.0', u'build':u'000'}
finally:
if fversion:
fversion.close()
#set the default string encoding #set the default string encoding
try: try:
sys.setappdefaultencoding(u'utf-8') sys.setappdefaultencoding(u'utf-8')
@ -127,24 +133,40 @@ def main():
# Set up command line options. # Set up command line options.
usage = u'Usage: %prog [options] [qt-options]' usage = u'Usage: %prog [options] [qt-options]'
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
parser.add_option("-d", "--debug", dest="debug", parser.add_option("-l", "--log-level", dest="loglevel",
action="store_true", help="set logging to DEBUG level") default="info", metavar="LEVEL",
help="Set logging to LEVEL level. Valid values are "
"\"debug\", \"info\", \"warning\".")
parser.add_option("-p", "--portable", dest="portable",
action="store_true",
help="Specify if this should be run as a portable app, "
"off a USB flash drive.")
parser.add_option("-s", "--style", dest="style",
help="Set the Qt4 style (passed directly to Qt4).")
# Set up logging # Set up logging
filename = u'openlp.log' filename = u'openlp.log'
logfile = RotatingFileHandler(filename, maxBytes=200000, backupCount=5) logfile = RotatingFileHandler(filename, maxBytes=200000, backupCount=5)
logfile.setFormatter(logging.Formatter( logfile.setFormatter(logging.Formatter(
u'%(asctime)s %(name)-15s %(levelname)-8s %(message)s')) u'%(asctime)s %(name)-15s %(levelname)-8s %(message)s'))
log.addHandler(logfile) log.addHandler(logfile)
logging.addLevelName(15, u'Timer')
# Parse command line options and deal with them. # Parse command line options and deal with them.
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
if options.debug: qt_args = []
if options.loglevel.lower() in ['d', 'debug']:
log.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG)
elif options.loglevel.lower() in ['w', 'warning']:
log.setLevel(logging.WARNING)
else: else:
log.setLevel(logging.INFO) log.setLevel(logging.INFO)
if options.style:
qt_args.extend(['-style', options.style])
# Throw the rest of the arguments at Qt, just in case.
qt_args.extend(args)
# Initialise the resources # Initialise the resources
qInitResources() qInitResources()
# Now create and actually run the application. # Now create and actually run the application.
app = OpenLP(sys.argv) app = OpenLP(qt_args)
sys.exit(app.run()) sys.exit(app.run())
if __name__ == u'__main__': if __name__ == u'__main__':

View File

@ -26,11 +26,14 @@
The :mod:`lib` module contains most of the components and libraries that make The :mod:`lib` module contains most of the components and libraries that make
OpenLP work. OpenLP work.
""" """
import logging
import os.path
import types import types
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
log = logging.getLogger(__name__)
def translate(context, text): def translate(context, text):
""" """
A special shortcut method to wrap around the Qt4 translation functions. A special shortcut method to wrap around the Qt4 translation functions.
@ -47,24 +50,28 @@ def translate(context, text):
return QtGui.QApplication.translate( return QtGui.QApplication.translate(
context, text, None, QtGui.QApplication.UnicodeUTF8) context, text, None, QtGui.QApplication.UnicodeUTF8)
def file_to_xml(xmlfile): def get_text_file_string(text_file):
""" """
Open a file and return the contents of the file. Open a file and return the contents of the file. If the supplied file name
is not a file then the function returns False. If there is an error
loading the file then the function will return None.
``xmlfile`` ``textfile``
The name of the file. The name of the file.
""" """
file = None if not os.path.isfile(text_file):
xml = None return False
file_handle = None
content_string = None
try: try:
file = open(xmlfile, u'r') file_handle = open(text_file, u'r')
xml = file.read() content_string = file_handle.read()
except IOError: except IOError:
log.exception(u'Failed to open XML file') log.error(u'Failed to open text file %s' % text_file)
finally: finally:
if file: if file_handle:
file.close() file_handle.close()
return xml return content_string
def str_to_bool(stringvalue): def str_to_bool(stringvalue):
""" """
@ -148,5 +155,5 @@ from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem from mediamanageritem import MediaManagerItem
from baselistwithdnd import BaseListWithDnD from baselistwithdnd import BaseListWithDnD
__all__ = [ 'translate', 'file_to_xml', 'str_to_bool', __all__ = [ 'translate', 'get_text_file_string', 'str_to_bool',
'contextMenuAction', 'contextMenuSeparator','ServiceItem'] 'contextMenuAction', 'contextMenuSeparator', 'ServiceItem']

View File

@ -129,16 +129,16 @@ class EventReceiver(QtCore.QObject):
class Receiver(): class Receiver():
""" """
Class to allow events to be passed from different parts of the Class to allow events to be passed from different parts of the system. This
system. This is a static wrapper around the ``EventReceiver`` is a static wrapper around the ``EventReceiver`` class. As there is only
class. As there is only one instance of it in the system the QT one instance of it in the system the Qt4 signal/slot architecture can send
signal/slot architecture can send messages across the system. messages across the system.
To send a message: To send a message:
``Receiver().send_message(u'<<Message ID>>', data)`` ``Receiver.send_message(u'<<Message ID>>', data)``
To receive a Message To receive a Message
``QtCore.QObject.connect(Receiver().get_receiver(), QtCore.SIGNAL(u'<<Message ID>>'), <<ACTION>>)`` ``QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'<<Message ID>>'), <<ACTION>>)``
""" """
eventreceiver = EventReceiver() eventreceiver = EventReceiver()

View File

@ -139,14 +139,6 @@ class Plugin(QtCore.QObject):
""" """
return True return True
def can_be_disabled(self):
"""
Indicates whether the plugin can be disabled by the plugin list.
Returns True or False.
"""
return False
def set_status(self): def set_status(self):
""" """
Sets the status of the plugin Sets the status of the plugin

View File

@ -105,10 +105,7 @@ class PluginManager(object):
for plugin in plugins_list: for plugin in plugins_list:
if plugin.check_pre_conditions(): if plugin.check_pre_conditions():
log.debug(u'Plugin %s active', unicode(plugin.name)) log.debug(u'Plugin %s active', unicode(plugin.name))
if plugin.can_be_disabled(): plugin.set_status()
plugin.set_status()
else:
plugin.status = PluginStatus.Active
else: else:
plugin.status = PluginStatus.Disabled plugin.status = PluginStatus.Disabled
self.plugins.append(plugin) self.plugins.append(plugin)

View File

@ -168,35 +168,45 @@ class Renderer(object):
line_width = self._rect.width() - self._right_margin line_width = self._rect.width() - self._right_margin
#number of lines on a page - adjust for rounding up. #number of lines on a page - adjust for rounding up.
page_length = int(self._rect.height() / metrics.height() - 2 ) - 1 page_length = int(self._rect.height() / metrics.height() - 2 ) - 1
#Average number of characters in line
ave_line_width = line_width / metrics.averageCharWidth() ave_line_width = line_width / metrics.averageCharWidth()
ave_line_width = int(ave_line_width + (ave_line_width * 1)) #Maximum size of a character
max_char_width = metrics.maxWidth()
#Min size of a character
min_char_width = metrics.width(u'i')
char_per_line = line_width / min_char_width
log.debug(u'Page Length area height %s , metrics %s , lines %s' % log.debug(u'Page Length area height %s , metrics %s , lines %s' %
(int(self._rect.height()), metrics.height(), page_length )) (int(self._rect.height()), metrics.height(), page_length ))
split_pages = [] split_pages = []
page = [] page = []
split_lines = [] split_lines = []
count = 0
for line in text: for line in text:
#Must be a blank line so keep it. #Must be a blank line so keep it.
if len(line) == 0: if len(line) == 0:
line = u' ' line = u' '
while len(line) > 0: while len(line) > 0:
if len(line) > ave_line_width: pos = char_per_line
pos = line.find(u' ', ave_line_width) split_text = line[:pos]
split_text = line[:pos] #line needs splitting
else: if metrics.width(split_text, -1) > line_width:
pos = len(line) #We have no spaces
split_text = line if split_text.find(u' ') == -1:
while metrics.width(split_text, -1) > line_width: #Move back 1 char at a time till it fits
#Find the next space to the left
pos = line[:pos].rfind(u' ')
#no more spaces found
if pos == 0:
split_text = line
while metrics.width(split_text, -1) > line_width: while metrics.width(split_text, -1) > line_width:
split_text = split_text[:-1] split_text = split_text[:-1]
pos = len(split_text) pos = len(split_text)
else: else:
split_text = line[:pos] #We have spaces so split at previous one
while metrics.width(split_text, -1) > line_width:
pos = split_text.rfind(u' ')
#no more spaces and we are still too long
if pos == -1:
while metrics.width(split_text, -1) > line_width:
split_text = split_text[:-1]
pos = len(split_text)
else:
split_text = line[:pos]
split_lines.append(split_text) split_lines.append(split_text)
line = line[pos:].lstrip() line = line[pos:].lstrip()
#if we have more text add up to 10 spaces on the front. #if we have more text add up to 10 spaces on the front.
@ -450,32 +460,32 @@ class Renderer(object):
draw=True, color = self._theme.display_shadow_color) draw=True, color = self._theme.display_shadow_color)
if self._theme.display_outline: if self._theme.display_outline:
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x+self._outline_offset, y), draw=True, (x + self._outline_offset, y), draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x, y+self._outline_offset), draw=True, (x, y + self._outline_offset), draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x, y-self._outline_offset), draw=True, (x, y - self._outline_offset), draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x-self._outline_offset, y), draw=True, (x - self._outline_offset, y), draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
if self._outline_offset > 1: if self._outline_offset > 1:
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x+self._outline_offset, y+self._outline_offset), (x + self._outline_offset, y + self._outline_offset),
draw=True, draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x-self._outline_offset, y+self._outline_offset), (x - self._outline_offset, y + self._outline_offset),
draw=True, draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x+self._outline_offset, y-self._outline_offset), (x + self._outline_offset, y - self._outline_offset),
draw=True, draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, self._get_extent_and_render(line, footer,
(x-self._outline_offset, y-self._outline_offset), (x - self._outline_offset, y - self._outline_offset),
draw=True, draw=True,
color = self._theme.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,tlcorner=(x, y), self._get_extent_and_render(line, footer,tlcorner=(x, y),

View File

@ -193,17 +193,17 @@ class RenderManager(object):
self.renderer.set_theme(themedata) self.renderer.set_theme(themedata)
self.build_text_rectangle(themedata) self.build_text_rectangle(themedata)
self.renderer.set_frame_dest(self.width, self.height, True) self.renderer.set_frame_dest(self.width, self.height, True)
verse = [] verse = u'Amazing Grace!\n'\
verse.append(u'Amazing Grace!') 'How sweet the sound\n'\
verse.append(u'How sweet the sound') 'To save a wretch like me;\n'\
verse.append(u'To save a wretch like me;') 'I once was lost but now am found,\n'\
verse.append(u'I once was lost but now am found,') 'Was blind, but now I see.'
verse.append(u'Was blind, but now I see.')
footer = [] footer = []
footer.append(u'Amazing Grace (John Newton)' ) footer.append(u'Amazing Grace (John Newton)' )
footer.append(u'Public Domain') footer.append(u'Public Domain')
footer.append(u'CCLI xxx') footer.append(u'CCLI xxx')
return self.renderer.generate_frame_from_lines(verse, footer) formatted = self.renderer.format_slide(verse, False)
return self.renderer.generate_frame_from_lines(formatted[0], footer)
def format_slide(self, words): def format_slide(self, words):
""" """
@ -253,7 +253,7 @@ class RenderManager(object):
newImage = QtGui.QImage(w, h, QtGui.QImage.Format_ARGB32_Premultiplied) newImage = QtGui.QImage(w, h, QtGui.QImage.Format_ARGB32_Premultiplied)
newImage.fill(QtCore.Qt.black) newImage.fill(QtCore.Qt.black)
painter = QtGui.QPainter(newImage) painter = QtGui.QPainter(newImage)
painter.drawImage((w-realw) / 2, (h-realh) / 2, preview) painter.drawImage((w - realw) / 2, (h - realh) / 2, preview)
return newImage return newImage
def calculate_default(self, screen): def calculate_default(self, screen):

View File

@ -29,7 +29,7 @@ import uuid
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import buildIcon from openlp.core.lib import buildIcon, Receiver
class ServiceItemType(object): class ServiceItemType(object):
""" """
@ -38,7 +38,6 @@ class ServiceItemType(object):
Text = 1 Text = 1
Image = 2 Image = 2
Command = 3 Command = 3
Video = 4
class ServiceItem(object): class ServiceItem(object):
""" """
@ -50,31 +49,28 @@ class ServiceItem(object):
log = logging.getLogger(u'ServiceItem') log = logging.getLogger(u'ServiceItem')
log.info(u'Service Item created') log.info(u'Service Item created')
def __init__(self, hostplugin=None): def __init__(self, plugin=None):
""" """
Set up the service item. Set up the service item.
``hostplugin`` ``plugin``
The plugin that this service item belongs to. The plugin that this service item belongs to.
""" """
self.plugin = hostplugin if plugin:
if hostplugin: self.RenderManager = plugin.render_manager
self.RenderManager = self.plugin.render_manager self.name = plugin.name
self.shortname = hostplugin.name
self.name = self.plugin.name
self.title = u'' self.title = u''
self.audit = u'' self.audit = u''
self.items = [] self.items = []
self.iconic_representation = None self.iconic_representation = None
self.raw_slides = None
self.frames = []
self.raw_footer = None self.raw_footer = None
self.theme = None self.theme = None
self.service_item_path = None self.service_item_path = None
self.service_item_type = None self.service_item_type = None
self.editEnabled = False self.edit_enabled = False
self.service_frames = [] self._raw_frames = []
self.uuid = unicode(uuid.uuid1()) self._display_frames = []
self._uuid = unicode(uuid.uuid1())
def addIcon(self, icon): def addIcon(self, icon):
""" """
@ -93,32 +89,27 @@ class ServiceItem(object):
The render method is what generates the frames for the screen. The render method is what generates the frames for the screen.
""" """
log.debug(u'Render called') log.debug(u'Render called')
self.frames = [] self._display_frames = []
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides') log.debug(u'Formatting slides')
if self.theme is None: if self.theme is None:
self.RenderManager.set_override_theme(None) self.RenderManager.set_override_theme(None)
else: else:
self.RenderManager.set_override_theme(self.theme) self.RenderManager.set_override_theme(self.theme)
for slide in self.service_frames: for slide in self._raw_frames:
before = time.time() before = time.time()
formated = self.RenderManager.format_slide(slide[u'raw_slide']) formated = self.RenderManager.format_slide(slide[u'raw_slide'])
for format in formated: for format in formated:
frame = None
lines = u'' lines = u''
for line in format: for line in format:
lines += line + u'\n' lines += line + u'\n'
title = lines.split(u'\n')[0] title = lines.split(u'\n')[0]
self.frames.append({u'title': title, u'text': lines, self._display_frames.append({u'title': title, u'text': lines})
u'image': frame}) log.log(15, u'Formatting took %4s' % (time.time() - before))
log.info(u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Command:
self.frames = self.service_frames
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for slide in self.service_frames: for slide in self._raw_frames:
slide[u'image'] = \ slide[u'image'] = \
self.RenderManager.resize_image(slide[u'image']) self.RenderManager.resize_image(slide[u'image'])
self.frames = self.service_frames
else: else:
log.error(u'Invalid value renderer :%s' % self.service_item_type) log.error(u'Invalid value renderer :%s' % self.service_item_type)
@ -133,19 +124,19 @@ class ServiceItem(object):
self.RenderManager.set_override_theme(None) self.RenderManager.set_override_theme(None)
else: else:
self.RenderManager.set_override_theme(self.theme) self.RenderManager.set_override_theme(self.theme)
format = self.frames[row][u'text'].split(u'\n') format = self._display_frames[row][u'text'].split(u'\n')
frame = self.RenderManager.generate_slide(format, frame = self.RenderManager.generate_slide(format,
self.raw_footer) self.raw_footer)
return frame return frame
def add_from_image(self, path, frame_title, image): def add_from_image(self, path, title, image):
""" """
Add an image slide to the service item. Add an image slide to the service item.
``path`` ``path``
The directory in which the image file is located. The directory in which the image file is located.
``frame_title`` ``title``
A title for the slide in the service item. A title for the slide in the service item.
``image`` ``image``
@ -153,16 +144,10 @@ class ServiceItem(object):
""" """
self.service_item_type = ServiceItemType.Image self.service_item_type = ServiceItemType.Image
self.service_item_path = path self.service_item_path = path
self.service_frames.append( self._raw_frames.append(
{u'title': frame_title, u'text': None, u'image': image}) {u'title': title, u'image': image})
def add_from_media(self, path, frame_title, image): def add_from_text(self, title, raw_slide):
self.service_item_type = ServiceItemType.Video
self.service_item_path = path
self.service_frames.append(
{u'title': frame_title, u'text': None, u'image': image})
def add_from_text(self, frame_title, raw_slide):
""" """
Add a text slide to the service item. Add a text slide to the service item.
@ -173,24 +158,27 @@ class ServiceItem(object):
The raw text of the slide. The raw text of the slide.
""" """
self.service_item_type = ServiceItemType.Text self.service_item_type = ServiceItemType.Text
frame_title = frame_title.split(u'\n')[0] title = title.split(u'\n')[0]
self.service_frames.append( self._raw_frames.append(
{u'title': frame_title, u'raw_slide': raw_slide}) {u'title': title, u'raw_slide': raw_slide})
def add_from_command(self, path, frame_title, image): def add_from_command(self, path, file_name, image):
""" """
Add a slide from a command. Add a slide from a command.
``frame_title`` ``path``
The title of the slide in the service item. The title of the slide in the service item.
``command`` ``file_name``
The title of the slide in the service item.
``image``
The command of/for the slide. The command of/for the slide.
""" """
self.service_item_type = ServiceItemType.Command self.service_item_type = ServiceItemType.Command
self.service_item_path = path self.service_item_path = path
self.service_frames.append( self._raw_frames.append(
{u'title': frame_title, u'command': None, u'text':None, u'image': image}) {u'title': file_name, u'image': image})
def get_service_repr(self): def get_service_repr(self):
""" """
@ -199,7 +187,7 @@ class ServiceItem(object):
""" """
service_header = { service_header = {
u'name': self.name.lower(), u'name': self.name.lower(),
u'plugin': self.shortname, u'plugin': self.name,
u'theme':self.theme, u'theme':self.theme,
u'title':self.title, u'title':self.title,
u'icon':self.icon, u'icon':self.icon,
@ -209,17 +197,14 @@ class ServiceItem(object):
} }
service_data = [] service_data = []
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
for slide in self.service_frames: for slide in self._raw_frames:
service_data.append(slide) service_data.append(slide)
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for slide in self.service_frames: for slide in self._raw_frames:
service_data.append(slide[u'title']) service_data.append(slide[u'title'])
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for slide in self.service_frames: for slide in self._raw_frames:
service_data.append(slide[u'title']) service_data.append({u'title':slide[u'title'], u'image':slide[u'image']})
elif self.service_item_type == ServiceItemType.Video:
for slide in self.service_frames:
service_data.append(slide[u'title'])
return {u'header': service_header, u'data': service_data} return {u'header': service_header, u'data': service_data}
def set_from_service(self, serviceitem, path=None): def set_from_service(self, serviceitem, path=None):
@ -244,7 +229,7 @@ class ServiceItem(object):
self.audit = header[u'audit'] self.audit = header[u'audit']
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']: for slide in serviceitem[u'serviceitem'][u'data']:
self.service_frames.append(slide) self._raw_frames.append(slide)
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image) filename = os.path.join(path, text_image)
@ -252,7 +237,68 @@ class ServiceItem(object):
self.add_from_image(path, text_image, real_image) self.add_from_image(path, text_image, real_image)
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image) filename = os.path.join(path, text_image[u'title'])
self.add_from_command(path, text_image) self.add_from_command(path, text_image[u'title'], text_image[u'image'] )
elif self.service_item_type == ServiceItemType.Video:
pass def merge(self, other):
"""
Updates the _uuid with the value from the original one
The _uuid is unique for a give service item but this allows one to
replace an original version.
"""
self._uuid = other._uuid
def __eq__(self, other):
"""
Confirms the service items are for the same instance
"""
if not other:
return False
return self._uuid == other._uuid
def __ne__(self, other):
"""
Confirms the service items are not for the same instance
"""
return self._uuid != other._uuid
def is_song(self):
return self.name == u'Songs'
def is_media(self):
return self.name.lower() == u'media'
def is_command(self):
return self.service_item_type == ServiceItemType.Command
def is_image(self):
return self.service_item_type == ServiceItemType.Image
def is_text(self):
return self.service_item_type == ServiceItemType.Text
def get_frames(self):
if self.service_item_type == ServiceItemType.Text:
return self._display_frames
else:
return self._raw_frames
def get_rendered_frame(self, row):
"""
Returns the correct frame for a given list and
renders it if required.
"""
if self.service_item_type == ServiceItemType.Text:
return self.render_individual(row)
else:
return self._raw_frames[row][u'image']
def get_frame_title(self, row=0):
"""
Returns the title of the raw frame
"""
return self._raw_frames[row][u'title']
def request_audit(self):
if self.audit:
Receiver.send_message(u'songusage_live', self.audit)

View File

@ -45,7 +45,6 @@ class SettingsManager(object):
else: else:
self.mainwindow_left = mainwindow_docbars self.mainwindow_left = mainwindow_docbars
self.mainwindow_right = mainwindow_docbars self.mainwindow_right = mainwindow_docbars
self.slidecontroller = (self.width - ( self.slidecontroller = (self.width - (
self.mainwindow_left + self.mainwindow_right) - 100 ) / 2 self.mainwindow_left + self.mainwindow_right) - 100 ) / 2
self.slidecontroller_image = self.slidecontroller - 50 self.slidecontroller_image = self.slidecontroller - 50
@ -60,7 +59,7 @@ class SettingsManager(object):
u'user interface', u'display previewpanel', True)) u'user interface', u'display previewpanel', True))
def setUIItemVisibility(self, item=u'', isVisible=True): def setUIItemVisibility(self, item=u'', isVisible=True):
if item != u'': if item:
if item == u'ThemeManagerDock': if item == u'ThemeManagerDock':
ConfigHelper.set_config(u'user interface', ConfigHelper.set_config(u'user interface',
u'display thememanager', isVisible) u'display thememanager', isVisible)

View File

@ -134,7 +134,8 @@ class SongXMLParser(object):
The XML of the song to be parsed. The XML of the song to be parsed.
""" """
try: try:
self.song_xml = ElementTree(element=XML(xml)) self.song_xml = ElementTree(
element=XML(unicode(xml).encode('unicode-escape')))
except: except:
log.exception(u'Invalid xml %s', xml) log.exception(u'Invalid xml %s', xml)
@ -147,7 +148,8 @@ class SongXMLParser(object):
verse_list = [] verse_list = []
for element in iter: for element in iter:
if element.tag == u'verse': if element.tag == u'verse':
verse_list.append([element.attrib, element.text]) verse_list.append([element.attrib,
unicode(element.text).decode('unicode-escape')])
return verse_list return verse_list
def dump_xml(self): def dump_xml(self):

View File

@ -30,7 +30,7 @@ from xml.etree.ElementTree import ElementTree, XML
from openlp.core.lib import str_to_bool from openlp.core.lib import str_to_bool
blankthemexml=\ blankthemexml=\
'''<?xml version="1.0" encoding="iso-8859-1"?> '''<?xml version="1.0" encoding="utf-8"?>
<theme version="1.0"> <theme version="1.0">
<name>BlankStyle</name> <name>BlankStyle</name>
<background mode="transparent"/> <background mode="transparent"/>
@ -348,6 +348,7 @@ class ThemeXML(object):
iter = theme_xml.getiterator() iter = theme_xml.getiterator()
master = u'' master = u''
for element in iter: for element in iter:
element.text = unicode(element.text).decode('unicode-escape')
if len(element.getchildren()) > 0: if len(element.getchildren()) > 0:
master = element.tag + u'_' master = element.tag + u'_'
else: else:

View File

@ -46,7 +46,7 @@ class OpenLPToolbar(QtGui.QToolBar):
self.log.debug(u'Init done') self.log.debug(u'Init done')
def addToolbarButton(self, title, icon, tooltip=None, slot=None, def addToolbarButton(self, title, icon, tooltip=None, slot=None,
objectname=None): checkable=False):
""" """
A method to help developers easily add a button to the toolbar. A method to help developers easily add a button to the toolbar.
@ -69,14 +69,19 @@ class OpenLPToolbar(QtGui.QToolBar):
""" """
ButtonIcon = buildIcon(icon) ButtonIcon = buildIcon(icon)
if ButtonIcon: if ButtonIcon:
if slot: if slot and not checkable:
ToolbarButton = self.addAction(ButtonIcon, title, slot) ToolbarButton = self.addAction(ButtonIcon, title, slot)
else: else:
ToolbarButton = self.addAction(ButtonIcon, title) ToolbarButton = self.addAction(ButtonIcon, title)
if tooltip: if tooltip:
ToolbarButton.setToolTip(tooltip) ToolbarButton.setToolTip(tooltip)
if checkable:
ToolbarButton.setCheckable(True)
QtCore.QObject.connect(ToolbarButton,
QtCore.SIGNAL(u'toggled(bool)'), slot)
self.icons[title] = ButtonIcon self.icons[title] = ButtonIcon
self.actions[title] = ToolbarButton self.actions[title] = ToolbarButton
return ToolbarButton
def addToolbarSeparator(self, handle): def addToolbarSeparator(self, handle):
""" """

View File

@ -28,7 +28,7 @@ import os.path
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import ThemeXML, file_to_xml from openlp.core.lib import ThemeXML
from amendthemedialog import Ui_AmendThemeDialog from amendthemedialog import Ui_AmendThemeDialog
log = logging.getLogger(u'AmendThemeForm') log = logging.getLogger(u'AmendThemeForm')
@ -126,7 +126,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
def accept(self): def accept(self):
new_theme = ThemeXML() new_theme = ThemeXML()
theme_name = unicode(self.ThemeNameEdit.displayText()) theme_name = unicode(self.ThemeNameEdit.displayText())
new_theme.new_document(theme_name) new_theme.new_document(theme_name.encode('unicode-escape'))
save_from = None save_from = None
save_to = None save_to = None
if self.theme.background_mode == u'transparent': if self.theme.background_mode == u'transparent':
@ -144,7 +144,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
(path, filename) = \ (path, filename) = \
os.path.split(unicode(self.theme.background_filename)) os.path.split(unicode(self.theme.background_filename))
new_theme.add_background_image(filename) new_theme.add_background_image(filename)
save_to= os.path.join(self.path, theme_name, filename ) save_to = os.path.join(self.path, theme_name, filename)
save_from = self.theme.background_filename save_from = self.theme.background_filename
new_theme.add_font(unicode(self.theme.font_main_name), new_theme.add_font(unicode(self.theme.font_main_name),
@ -184,33 +184,26 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
def loadTheme(self, theme): def loadTheme(self, theme):
log.debug(u'LoadTheme %s', theme) log.debug(u'LoadTheme %s', theme)
if theme is None: self.theme = theme
self.theme.parse(self.thememanager.baseTheme())
else:
xml_file = os.path.join(self.path, theme, theme + u'.xml')
xml = file_to_xml(xml_file)
self.theme.parse(xml)
self.theme.extend_image_filename(self.path)
self.thememanager.cleanTheme(self.theme)
# Stop the initial screen setup generating 1 preview per field! # Stop the initial screen setup generating 1 preview per field!
self.allowPreview = False self.allowPreview = False
self.paintUi(self.theme) self.paintUi(self.theme)
self.allowPreview = True self.allowPreview = True
self.previewTheme(self.theme) self.previewTheme()
def onImageToolButtonClicked(self): def onImageToolButtonClicked(self):
filename = QtGui.QFileDialog.getOpenFileName( filename = QtGui.QFileDialog.getOpenFileName(
self, self.trUtf8(u'Open file')) self, self.trUtf8(u'Open file'))
if filename != u'': if filename:
self.ImageLineEdit.setText(filename) self.ImageLineEdit.setText(filename)
self.theme.background_filename = filename self.theme.background_filename = filename
self.previewTheme(self.theme) self.previewTheme()
# #
#Main Font Tab #Main Font Tab
# #
def onFontMainComboBoxSelected(self): def onFontMainComboBoxSelected(self):
self.theme.font_main_name = self.FontMainComboBox.currentFont().family() self.theme.font_main_name = self.FontMainComboBox.currentFont().family()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainWeightComboBoxSelected(self, value): def onFontMainWeightComboBoxSelected(self, value):
if value == 0: if value == 0:
@ -225,7 +218,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.font_main_weight = u'Bold' self.theme.font_main_weight = u'Bold'
self.theme.font_main_italics = True self.theme.font_main_italics = True
self.previewTheme(self.theme) self.previewTheme()
def onFontMainColorPushButtonClicked(self): def onFontMainColorPushButtonClicked(self):
self.theme.font_main_color = QtGui.QColorDialog.getColor( self.theme.font_main_color = QtGui.QColorDialog.getColor(
@ -233,12 +226,12 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
self.FontMainColorPushButton.setStyleSheet( self.FontMainColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.font_main_color)) u'background-color: %s' % unicode(self.theme.font_main_color))
self.previewTheme(self.theme) self.previewTheme()
def onFontMainSizeSpinBoxChanged(self): def onFontMainSizeSpinBoxChanged(self):
if self.theme.font_main_proportion != self.FontMainSizeSpinBox.value(): if self.theme.font_main_proportion != self.FontMainSizeSpinBox.value():
self.theme.font_main_proportion = self.FontMainSizeSpinBox.value() self.theme.font_main_proportion = self.FontMainSizeSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainDefaultCheckBoxChanged(self, value): def onFontMainDefaultCheckBoxChanged(self, value):
if value == 2: # checked if value == 2: # checked
@ -259,41 +252,41 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
self.FontMainLineSpacingSpinBox.setValue( self.FontMainLineSpacingSpinBox.setValue(
self.theme.font_main_indentation) self.theme.font_main_indentation)
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onFontMainXSpinBoxChanged(self): def onFontMainXSpinBoxChanged(self):
if self.theme.font_main_x != self.FontMainXSpinBox.value(): if self.theme.font_main_x != self.FontMainXSpinBox.value():
self.theme.font_main_x = self.FontMainXSpinBox.value() self.theme.font_main_x = self.FontMainXSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainYSpinBoxChanged(self): def onFontMainYSpinBoxChanged(self):
if self.theme.font_main_y != self.FontMainYSpinBox.value(): if self.theme.font_main_y != self.FontMainYSpinBox.value():
self.theme.font_main_y = self.FontMainYSpinBox.value() self.theme.font_main_y = self.FontMainYSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainWidthSpinBoxChanged(self): def onFontMainWidthSpinBoxChanged(self):
if self.theme.font_main_width != self.FontMainWidthSpinBox.value(): if self.theme.font_main_width != self.FontMainWidthSpinBox.value():
self.theme.font_main_width = self.FontMainWidthSpinBox.value() self.theme.font_main_width = self.FontMainWidthSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainLineSpacingSpinBoxChanged(self): def onFontMainLineSpacingSpinBoxChanged(self):
if self.theme.font_main_indentation != \ if self.theme.font_main_indentation != \
self.FontMainLineSpacingSpinBox.value(): self.FontMainLineSpacingSpinBox.value():
self.theme.font_main_indentation = \ self.theme.font_main_indentation = \
self.FontMainLineSpacingSpinBox.value() self.FontMainLineSpacingSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontMainHeightSpinBoxChanged(self): def onFontMainHeightSpinBoxChanged(self):
if self.theme.font_main_height != self.FontMainHeightSpinBox.value(): if self.theme.font_main_height != self.FontMainHeightSpinBox.value():
self.theme.font_main_height = self.FontMainHeightSpinBox.value() self.theme.font_main_height = self.FontMainHeightSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
# #
#Footer Font Tab #Footer Font Tab
# #
def onFontFooterComboBoxSelected(self): def onFontFooterComboBoxSelected(self):
self.theme.font_footer_name = \ self.theme.font_footer_name = \
self.FontFooterComboBox.currentFont().family() self.FontFooterComboBox.currentFont().family()
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterWeightComboBoxSelected(self, value): def onFontFooterWeightComboBoxSelected(self, value):
if value == 0: if value == 0:
@ -308,22 +301,21 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.font_footer_weight = u'Bold' self.theme.font_footer_weight = u'Bold'
self.theme.font_footer_italics = True self.theme.font_footer_italics = True
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterColorPushButtonClicked(self): def onFontFooterColorPushButtonClicked(self):
self.theme.font_footer_color = QtGui.QColorDialog.getColor( self.theme.font_footer_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.font_footer_color), self).name() QtGui.QColor(self.theme.font_footer_color), self).name()
self.FontFooterColorPushButton.setStyleSheet( self.FontFooterColorPushButton.setStyleSheet(
'background-color: %s' % unicode(self.theme.font_footer_color)) 'background-color: %s' % unicode(self.theme.font_footer_color))
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterSizeSpinBoxChanged(self): def onFontFooterSizeSpinBoxChanged(self):
if self.theme.font_footer_proportion != \ if self.theme.font_footer_proportion != \
self.FontFooterSizeSpinBox.value(): self.FontFooterSizeSpinBox.value():
self.theme.font_footer_proportion = \ self.theme.font_footer_proportion = \
self.FontFooterSizeSpinBox.value() self.FontFooterSizeSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterDefaultCheckBoxChanged(self, value): def onFontFooterDefaultCheckBoxChanged(self, value):
if value == 2: # checked if value == 2: # checked
@ -343,29 +335,29 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
self.FontFooterHeightSpinBox.setValue( self.FontFooterHeightSpinBox.setValue(
self.theme.font_footer_height) self.theme.font_footer_height)
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterXSpinBoxChanged(self): def onFontFooterXSpinBoxChanged(self):
if self.theme.font_footer_x != self.FontFooterXSpinBox.value(): if self.theme.font_footer_x != self.FontFooterXSpinBox.value():
self.theme.font_footer_x = self.FontFooterXSpinBox.value() self.theme.font_footer_x = self.FontFooterXSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterYSpinBoxChanged(self): def onFontFooterYSpinBoxChanged(self):
if self.theme.font_footer_y != self.FontFooterYSpinBox.value(): if self.theme.font_footer_y != self.FontFooterYSpinBox.value():
self.theme.font_footer_y = self.FontFooterYSpinBox.value() self.theme.font_footer_y = self.FontFooterYSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterWidthSpinBoxChanged(self): def onFontFooterWidthSpinBoxChanged(self):
if self.theme.font_footer_width != self.FontFooterWidthSpinBox.value(): if self.theme.font_footer_width != self.FontFooterWidthSpinBox.value():
self.theme.font_footer_width = self.FontFooterWidthSpinBox.value() self.theme.font_footer_width = self.FontFooterWidthSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
def onFontFooterHeightSpinBoxChanged(self): def onFontFooterHeightSpinBoxChanged(self):
if self.theme.font_footer_height != \ if self.theme.font_footer_height != \
self.FontFooterHeightSpinBox.value(): self.FontFooterHeightSpinBox.value():
self.theme.font_footer_height = \ self.theme.font_footer_height = \
self.FontFooterHeightSpinBox.value() self.FontFooterHeightSpinBox.value()
self.previewTheme(self.theme) self.previewTheme()
# #
#Background Tab #Background Tab
# #
@ -379,7 +371,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.background_mode = u'transparent' self.theme.background_mode = u'transparent'
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onBackgroundTypeComboBoxSelected(self, currentIndex): def onBackgroundTypeComboBoxSelected(self, currentIndex):
self.setBackground(currentIndex, self.GradientComboBox.currentIndex()) self.setBackground(currentIndex, self.GradientComboBox.currentIndex())
@ -404,7 +396,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.background_type = u'image' self.theme.background_type = u'image'
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onColor1PushButtonClicked(self): def onColor1PushButtonClicked(self):
if self.theme.background_type == u'solid': if self.theme.background_type == u'solid':
@ -419,14 +411,14 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
u'background-color: %s' % \ u'background-color: %s' % \
unicode(self.theme.background_startColor)) unicode(self.theme.background_startColor))
self.previewTheme(self.theme) self.previewTheme()
def onColor2PushButtonClicked(self): def onColor2PushButtonClicked(self):
self.theme.background_endColor = QtGui.QColorDialog.getColor( self.theme.background_endColor = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.background_endColor), self).name() QtGui.QColor(self.theme.background_endColor), self).name()
self.Color2PushButton.setStyleSheet( self.Color2PushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.background_endColor)) u'background-color: %s' % unicode(self.theme.background_endColor))
self.previewTheme(self.theme) self.previewTheme()
# #
#Other Tab #Other Tab
# #
@ -436,14 +428,14 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.display_outline = False self.theme.display_outline = False
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onOutlineColorPushButtonClicked(self): def onOutlineColorPushButtonClicked(self):
self.theme.display_outline_color = QtGui.QColorDialog.getColor( self.theme.display_outline_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.display_outline_color), self).name() QtGui.QColor(self.theme.display_outline_color), self).name()
self.OutlineColorPushButton.setStyleSheet( self.OutlineColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.display_outline_color)) u'background-color: %s' % unicode(self.theme.display_outline_color))
self.previewTheme(self.theme) self.previewTheme()
def onShadowCheckBoxChanged(self, value): def onShadowCheckBoxChanged(self, value):
if value == 2: # checked if value == 2: # checked
@ -451,24 +443,24 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.theme.display_shadow = False self.theme.display_shadow = False
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onShadowColorPushButtonClicked(self): def onShadowColorPushButtonClicked(self):
self.theme.display_shadow_color = QtGui.QColorDialog.getColor( self.theme.display_shadow_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.display_shadow_color), self).name() QtGui.QColor(self.theme.display_shadow_color), self).name()
self.ShadowColorPushButton.setStyleSheet( self.ShadowColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.display_shadow_color)) u'background-color: %s' % unicode(self.theme.display_shadow_color))
self.previewTheme(self.theme) self.previewTheme()
def onHorizontalComboBoxSelected(self, currentIndex): def onHorizontalComboBoxSelected(self, currentIndex):
self.theme.display_horizontalAlign = currentIndex self.theme.display_horizontalAlign = currentIndex
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
def onVerticalComboBoxSelected(self, currentIndex): def onVerticalComboBoxSelected(self, currentIndex):
self.theme.display_verticalAlign = currentIndex self.theme.display_verticalAlign = currentIndex
self.stateChanging(self.theme) self.stateChanging(self.theme)
self.previewTheme(self.theme) self.previewTheme()
# #
#Local Methods #Local Methods
# #
@ -661,18 +653,10 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
else: else:
self.ShadowColorPushButton.setEnabled(False) self.ShadowColorPushButton.setEnabled(False)
def previewTheme(self, theme): def previewTheme(self):
if self.allowPreview: if self.allowPreview:
#calculate main number of rows #calculate main number of rows
main_weight = 50 metrics = self._getThemeMetrics()
if self.theme.font_main_weight == u'Bold':
main_weight = 75
mainFont = QtGui.QFont(self.theme.font_main_name,
self.theme.font_main_proportion, # size
main_weight, # weight
self.theme.font_main_italics)# italic
mainFont.setPixelSize(self.theme.font_main_proportion)
metrics = QtGui.QFontMetrics(mainFont)
page_length = \ page_length = \
(self.FontMainHeightSpinBox.value() / metrics.height() - 2) - 1 (self.FontMainHeightSpinBox.value() / metrics.height() - 2) - 1
log.debug(u'Page Length area height %s, metrics %s, lines %s' % log.debug(u'Page Length area height %s, metrics %s, lines %s' %
@ -680,6 +664,22 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
page_length)) page_length))
page_length_text = unicode(self.trUtf8(u'Slide Height is %s rows')) page_length_text = unicode(self.trUtf8(u'Slide Height is %s rows'))
self.FontMainLinesPageLabel.setText(page_length_text % page_length) self.FontMainLinesPageLabel.setText(page_length_text % page_length)
frame = self.thememanager.generateImage(theme) #a=c
frame = self.thememanager.generateImage(self.theme)
self.ThemePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) self.ThemePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
def _getThemeMetrics(self):
main_weight = 50
if self.theme.font_main_weight == u'Bold':
main_weight = 75
mainFont = QtGui.QFont(self.theme.font_main_name,
self.theme.font_main_proportion, # size
main_weight, # weight
self.theme.font_main_italics)# italic
mainFont.setPixelSize(self.theme.font_main_proportion)
metrics = QtGui.QFontMetrics(mainFont)
#Validate that the screen width is big enough to display the text
if self.theme.font_main_width < metrics.maxWidth() * 2 + 64:
self.theme.font_main_width = metrics.maxWidth() * 2 + 64
self.FontMainWidthSpinBox.setValue(self.theme.font_main_width)
return metrics

View File

@ -28,9 +28,9 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, str_to_bool from openlp.core.lib import Receiver
class DisplayLabel(QtGui.QWidget): class DisplayWidget(QtGui.QWidget):
""" """
Customised version of QTableWidget which can respond to keyboard Customised version of QTableWidget which can respond to keyboard
events. events.
@ -40,23 +40,23 @@ class DisplayLabel(QtGui.QWidget):
log.info(u'MainDisplay loaded') log.info(u'MainDisplay loaded')
def __init__(self, parent=None, name=None): def __init__(self, parent=None, name=None):
QQtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.parent = parent self.parent = parent
def keyPressEvent(self, event): def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent: if type(event) == QtGui.QKeyEvent:
#here accept the event and do something #here accept the event and do something
if event.key() == QtCore.Qt.Key_Up: if event.key() == QtCore.Qt.Key_Up:
Receiver().send_message(u'slidecontroller_previous') Receiver.send_message(u'live_slidecontroller_previous')
event.accept() event.accept()
elif event.key() == QtCore.Qt.Key_Down: elif event.key() == QtCore.Qt.Key_Down:
Receiver().send_message(u'slidecontroller_next') Receiver.send_message(u'live_slidecontroller_next')
event.accept() event.accept()
elif event.key() == QtCore.Qt.Key_PageUp: elif event.key() == QtCore.Qt.Key_PageUp:
Receiver().send_message(u'slidecontroller_first') Receiver.send_message(u'live_slidecontroller_first')
event.accept() event.accept()
elif event.key() == QtCore.Qt.Key_PageDown: elif event.key() == QtCore.Qt.Key_PageDown:
Receiver().send_message(u'slidecontroller_last') Receiver.send_message(u'live_slidecontroller_last')
event.accept() event.accept()
elif event.key() == QtCore.Qt.Key_Escape: elif event.key() == QtCore.Qt.Key_Escape:
self.resetDisplay() self.resetDisplay()
@ -65,7 +65,7 @@ class DisplayLabel(QtGui.QWidget):
else: else:
event.ignore() event.ignore()
class MainDisplay(DisplayLabel): class MainDisplay(DisplayWidget):
""" """
This is the form that is used to display things on the projector. This is the form that is used to display things on the projector.
""" """
@ -84,7 +84,7 @@ class MainDisplay(DisplayLabel):
The list of screens. The list of screens.
""" """
log.debug(u'Initilisation started') log.debug(u'Initilisation started')
QtGui.QWidget.__init__(self, None) DisplayWidget.__init__(self, None)
self.parent = parent self.parent = parent
self.setWindowTitle(u'OpenLP Display') self.setWindowTitle(u'OpenLP Display')
self.screens = screens self.screens = screens
@ -107,18 +107,15 @@ class MainDisplay(DisplayLabel):
self.blankFrame = None self.blankFrame = None
self.frame = None self.frame = None
self.alertactive = False self.alertactive = False
self.alertTab = None
self.timer_id = 0 self.timer_id = 0
self.firstTime = True self.firstTime = True
self.mediaLoaded = False self.mediaLoaded = False
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_slide_blank'), self.blankDisplay)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'alert_text'), self.displayAlert) QtCore.SIGNAL(u'alert_text'), self.displayAlert)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'presentations_start'), self.hideDisplay) QtCore.SIGNAL(u'live_slide_hide'), self.hideDisplay)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'presentations_stop'), self.showDisplay) QtCore.SIGNAL(u'live_slide_show'), self.showDisplay)
QtCore.QObject.connect(self.mediaObject, QtCore.QObject.connect(self.mediaObject,
QtCore.SIGNAL(u'finished()'), self.onMediaFinish) QtCore.SIGNAL(u'finished()'), self.onMediaFinish)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -130,13 +127,13 @@ class MainDisplay(DisplayLabel):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_stop'), self.onMediaStop) QtCore.SIGNAL(u'media_stop'), self.onMediaStop)
def setup(self, screenNumber): def setup(self, screenNumber):
""" """
Sets up the screen on a particular screen. Sets up the screen on a particular screen.
@param (integer) screen This is the screen number. @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, screenNumber))
self.setVisible(False)
screen = self.screens[screenNumber] screen = self.screens[screenNumber]
if screen[u'number'] != screenNumber: if screen[u'number'] != screenNumber:
# We will most probably never actually hit this bit, but just in # We will most probably never actually hit this bit, but just in
@ -147,26 +144,19 @@ class MainDisplay(DisplayLabel):
screen = scrn screen = scrn
break break
self.setGeometry(screen[u'size']) self.setGeometry(screen[u'size'])
if not screen[u'primary']:
self.showFullScreen()
self.primary = False
else:
self.setVisible(False)
self.primary = True
#Build a custom splash screen #Build a custom splash screen
if str_to_bool(self.parent.generalConfig.get_config(u'show splash', u'True')): self.InitialFrame = QtGui.QImage(
self.InitialFrame = QtGui.QImage( screen[u'size'].width(), screen[u'size'].height(),
screen[u'size'].width(), screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied)
QtGui.QImage.Format_ARGB32_Premultiplied) splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png')
splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png') painter_image = QtGui.QPainter()
painter_image = QtGui.QPainter() painter_image.begin(self.InitialFrame)
painter_image.begin(self.InitialFrame) painter_image.fillRect(self.InitialFrame.rect(), QtCore.Qt.white)
painter_image.fillRect(self.InitialFrame.rect(), QtCore.Qt.white) painter_image.drawImage(
painter_image.drawImage( (screen[u'size'].width() - splash_image.width()) / 2,
(screen[u'size'].width() - splash_image.width()) / 2, (screen[u'size'].height() - splash_image.height()) / 2,
(screen[u'size'].height() - splash_image.height()) / 2, splash_image)
splash_image) self.frameView(self.InitialFrame)
self.frameView(self.InitialFrame)
#Build a Black screen #Build a Black screen
painter = QtGui.QPainter() painter = QtGui.QPainter()
self.blankFrame = QtGui.QImage( self.blankFrame = QtGui.QImage(
@ -174,6 +164,13 @@ class MainDisplay(DisplayLabel):
QtGui.QImage.Format_ARGB32_Premultiplied) QtGui.QImage.Format_ARGB32_Premultiplied)
painter.begin(self.blankFrame) painter.begin(self.blankFrame)
painter.fillRect(self.blankFrame.rect(), QtCore.Qt.black) painter.fillRect(self.blankFrame.rect(), QtCore.Qt.black)
# To display or not to display?
if not screen[u'primary']:
self.showFullScreen()
self.primary = False
else:
self.setVisible(False)
self.primary = True
def resetDisplay(self): def resetDisplay(self):
if self.primary: if self.primary:
@ -197,24 +194,28 @@ class MainDisplay(DisplayLabel):
if self.timer_id != 0 : if self.timer_id != 0 :
self.displayAlert() self.displayAlert()
elif not self.displayBlank: elif not self.displayBlank:
# self.setWindowOpacity(0.5)
# self.show()
self.display.setPixmap(QtGui.QPixmap.fromImage(frame)) self.display.setPixmap(QtGui.QPixmap.fromImage(frame))
# QtCore.QTimer.singleShot(500, self.aa )
if not self.isVisible(): if not self.isVisible():
self.setVisible(True) self.setVisible(True)
self.showFullScreen() self.showFullScreen()
#
# def aa(self):
# self.setWindowOpacity(1)
def blankDisplay(self): def blankDisplay(self, blanked=True):
if not self.displayBlank: if blanked:
self.displayBlank = True self.displayBlank = True
self.display.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) self.display.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame))
else: else:
self.displayBlank = False self.displayBlank = False
if self.frame: if self.frame:
self.frameView(self.frame) self.frameView(self.frame)
if self.parent.LiveController.blackPushButton.isChecked() != \ if blanked != self.parent.LiveController.blankButton.isChecked():
self.displayBlank: self.parent.LiveController.blankButton.setChecked(self.displayBlank)
self.parent.LiveController.blackPushButton.setChecked( self.parent.generalConfig.set_config(u'Screen Blank', self.displayBlank)
self.displayBlank)
self.parent.generalConfig.set_config(u'Screen Blank',self.displayBlank)
def displayAlert(self, text=u''): def displayAlert(self, text=u''):
""" """
@ -266,13 +267,14 @@ class MainDisplay(DisplayLabel):
self.onMediaPlay() self.onMediaPlay()
def onMediaPlay(self): def onMediaPlay(self):
log.debug(u'Play the new media') log.debug(u'Play the new media, Live ')
if not self.mediaLoaded and not self.displayBlank: if not self.mediaLoaded and not self.displayBlank:
self.blankDisplay() self.blankDisplay()
self.firstTime = True self.firstTime = True
self.mediaLoaded = True self.mediaLoaded = True
self.display.hide() self.display.hide()
self.video.setFullScreen(True) self.video.setFullScreen(True)
self.video.setVisible(True)
self.mediaObject.play() self.mediaObject.play()
if self.primary: if self.primary:
self.setVisible(True) self.setVisible(True)
@ -284,7 +286,6 @@ class MainDisplay(DisplayLabel):
def onMediaStop(self): def onMediaStop(self):
log.debug(u'Media stopped by user') log.debug(u'Media stopped by user')
self.mediaObject.stop() self.mediaObject.stop()
self.display.show()
def onMediaFinish(self): def onMediaFinish(self):
log.debug(u'Reached end of media playlist') log.debug(u'Reached end of media playlist')

View File

@ -84,6 +84,7 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.MainContent) MainWindow.setCentralWidget(self.MainContent)
self.ControlSplitter = QtGui.QSplitter(self.MainContent) self.ControlSplitter = QtGui.QSplitter(self.MainContent)
self.ControlSplitter.setOrientation(QtCore.Qt.Horizontal) self.ControlSplitter.setOrientation(QtCore.Qt.Horizontal)
self.ControlSplitter.setOpaqueResize(False)
self.ControlSplitter.setObjectName(u'ControlSplitter') self.ControlSplitter.setObjectName(u'ControlSplitter')
self.MainContentLayout.addWidget(self.ControlSplitter) self.MainContentLayout.addWidget(self.ControlSplitter)
# Create slide controllers # Create slide controllers
@ -300,8 +301,17 @@ class Ui_MainWindow(object):
# Connect up some signals and slots # Connect up some signals and slots
QtCore.QObject.connect(self.FileExitItem, QtCore.QObject.connect(self.FileExitItem,
QtCore.SIGNAL(u'triggered()'), MainWindow.close) QtCore.SIGNAL(u'triggered()'), MainWindow.close)
QtCore.QObject.connect(self.ControlSplitter,
QtCore.SIGNAL(u'splitterMoved(int, int)'), self.trackSplitter)
QtCore.QMetaObject.connectSlotsByName(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
def trackSplitter(self, tab, pos):
"""
Splitter between the Preview and Live Controllers.
"""
self.LiveController.widthChanged()
self.PreviewController.widthChanged()
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
""" """
Set up the translation system Set up the translation system
@ -526,6 +536,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.settingsForm.postSetUp() self.settingsForm.postSetUp()
def versionCheck(self): def versionCheck(self):
"""
Checks the version of the Application called from openlp.pyw
"""
applicationVersion = self.applicationVersion[u'Full'] applicationVersion = self.applicationVersion[u'Full']
version = check_latest_version(self.generalConfig, applicationVersion) version = check_latest_version(self.generalConfig, applicationVersion)
if applicationVersion != version: if applicationVersion != version:
@ -544,7 +557,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
monitor number does not exist. monitor number does not exist.
""" """
screen_number = int(self.generalConfig.get_config(u'Monitor', 0)) screen_number = int(self.generalConfig.get_config(u'Monitor', 0))
monitor_exists = False monitor_exists = False
for screen in self.screenList: for screen in self.screenList:
if screen[u'number'] == screen_number: if screen[u'number'] == screen_number:
@ -560,7 +572,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.showMaximized() self.showMaximized()
screen_number = self.getMonitorNumber() screen_number = self.getMonitorNumber()
self.mainDisplay.setup(screen_number) self.mainDisplay.setup(screen_number)
self.setFocus() if self.mainDisplay.isVisible():
self.mainDisplay.setFocus()
self.activateWindow()
if str_to_bool(self.generalConfig.get_config(u'Auto Open', False)): if str_to_bool(self.generalConfig.get_config(u'Auto Open', False)):
self.ServiceManagerContents.onLoadService(True) self.ServiceManagerContents.onLoadService(True)
if str_to_bool(self.generalConfig.get_config(u'Screen Blank', False)) \ if str_to_bool(self.generalConfig.get_config(u'Screen Blank', False)) \
@ -570,7 +584,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.trUtf8(u'The Main Display has been blanked out'), self.trUtf8(u'The Main Display has been blanked out'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok) QtGui.QMessageBox.Ok)
self.LiveController.blackPushButton.setChecked(True) #self.LiveController.blackPushButton.setChecked(True)
def onHelpAboutItemClicked(self): def onHelpAboutItemClicked(self):
""" """
@ -601,6 +615,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if updated_display != self.RenderManager.current_display: if updated_display != self.RenderManager.current_display:
self.RenderManager.update_display(updated_display) self.RenderManager.update_display(updated_display)
self.mainDisplay.setup(updated_display) self.mainDisplay.setup(updated_display)
self.activateWindow()
def closeEvent(self, event): def closeEvent(self, event):
""" """
@ -664,7 +679,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.setWindowTitle(title) self.setWindowTitle(title)
def defaultThemeChanged(self, theme): def defaultThemeChanged(self, theme):
self.DefaultThemeLabel.setText(self.defaultThemeText + theme) self.DefaultThemeLabel.setText(
u'%s %s' % (self.defaultThemeText, theme))
def toggleMediaManager(self, visible): def toggleMediaManager(self, visible):
if self.MediaManagerDock.isVisible() != visible: if self.MediaManagerDock.isVisible() != visible:

View File

@ -79,17 +79,16 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
self.StatusComboBox.setCurrentIndex(-1) self.StatusComboBox.setCurrentIndex(-1)
self.VersionNumberLabel.setText(u'') self.VersionNumberLabel.setText(u'')
self.AboutTextBrowser.setHtml(u'') self.AboutTextBrowser.setHtml(u'')
self.StatusComboBox.setEnabled(False)
def _setDetails(self): def _setDetails(self):
log.debug('PluginStatus: %s', str(self.activePlugin.status)) log.debug('PluginStatus: %s', str(self.activePlugin.status))
self.VersionNumberLabel.setText(self.activePlugin.version) self.VersionNumberLabel.setText(self.activePlugin.version)
self.AboutTextBrowser.setHtml(self.activePlugin.about()) self.AboutTextBrowser.setHtml(self.activePlugin.about())
if self.activePlugin.can_be_disabled(): self.programaticChange = True
self.programaticChange = True self.StatusComboBox.setCurrentIndex(int(self.activePlugin.status))
self.StatusComboBox.setCurrentIndex(int(self.activePlugin.status)) self.StatusComboBox.setEnabled(True)
self.StatusComboBox.setEnabled(True) self.programaticChange = False
else:
self.StatusComboBox.setEnabled(False)
def onPluginListWidgetSelectionChanged(self): def onPluginListWidgetSelectionChanged(self):
if self.PluginListWidget.currentItem() is None: if self.PluginListWidget.currentItem() is None:
@ -108,7 +107,6 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
def onStatusComboBoxChanged(self, status): def onStatusComboBoxChanged(self, status):
if self.programaticChange: if self.programaticChange:
self.programaticChange = False
return return
self.activePlugin.toggle_status(status) self.activePlugin.toggle_status(status)
if status == PluginStatus.Active: if status == PluginStatus.Active:

View File

@ -23,7 +23,6 @@
############################################################################### ###############################################################################
import os import os
import string
import logging import logging
import cPickle import cPickle
import zipfile import zipfile
@ -35,7 +34,7 @@ from openlp.core.lib import PluginConfig, OpenLPToolbar, ServiceItem, \
class ServiceManagerList(QtGui.QTreeWidget): class ServiceManagerList(QtGui.QTreeWidget):
def __init__(self,parent=None,name=None): def __init__(self, parent=None, name=None):
QtGui.QTreeWidget.__init__(self,parent) QtGui.QTreeWidget.__init__(self,parent)
self.parent = parent self.parent = parent
@ -48,7 +47,7 @@ class ServiceManagerList(QtGui.QTreeWidget):
# else: # else:
# pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] # pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
# serviceItem = self.parent.serviceItems[pos - 1] # serviceItem = self.parent.serviceItems[pos - 1]
# if serviceItem[u'data'].editEnabled: # if serviceItem[u'data'].edit_enabled:
# self.parent.editAction.setVisible(True) # self.parent.editAction.setVisible(True)
# else: # else:
# self.parent.editAction.setVisible(False) # self.parent.editAction.setVisible(False)
@ -56,7 +55,6 @@ class ServiceManagerList(QtGui.QTreeWidget):
# else: # else:
# event.ignore() # event.ignore()
def keyPressEvent(self, event): def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent: if type(event) == QtGui.QKeyEvent:
#here accept the event and do something #here accept the event and do something
@ -99,7 +97,6 @@ class ServiceManagerList(QtGui.QTreeWidget):
mimeData.setText(u'ServiceManager') mimeData.setText(u'ServiceManager')
dropAction = drag.start(QtCore.Qt.CopyAction) dropAction = drag.start(QtCore.Qt.CopyAction)
class ServiceManager(QtGui.QWidget): class ServiceManager(QtGui.QWidget):
""" """
Manages the services. This involves taking text strings from plugins and Manages the services. This involves taking text strings from plugins and
@ -390,14 +387,14 @@ class ServiceManager(QtGui.QWidget):
#Repaint the screen #Repaint the screen
self.ServiceManagerList.clear() self.ServiceManagerList.clear()
for itemcount, item in enumerate(self.serviceItems): for itemcount, item in enumerate(self.serviceItems):
serviceitem = item[u'data'] serviceitem = item[u'service_item']
treewidgetitem = QtGui.QTreeWidgetItem(self.ServiceManagerList) treewidgetitem = QtGui.QTreeWidgetItem(self.ServiceManagerList)
treewidgetitem.setText(0,serviceitem.title) treewidgetitem.setText(0,serviceitem.title)
treewidgetitem.setIcon(0,serviceitem.iconic_representation) treewidgetitem.setIcon(0,serviceitem.iconic_representation)
treewidgetitem.setData(0, QtCore.Qt.UserRole, treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order'])) QtCore.QVariant(item[u'order']))
treewidgetitem.setExpanded(item[u'expanded']) treewidgetitem.setExpanded(item[u'expanded'])
for count, frame in enumerate(serviceitem.frames): for count, frame in enumerate(serviceitem.get_frames()):
treewidgetitem1 = QtGui.QTreeWidgetItem(treewidgetitem) treewidgetitem1 = QtGui.QTreeWidgetItem(treewidgetitem)
text = frame[u'title'] text = frame[u'title']
treewidgetitem1.setText(0,text[:40]) treewidgetitem1.setText(0,text[:40])
@ -418,7 +415,7 @@ class ServiceManager(QtGui.QWidget):
u'Save Service', self.config.get_last_dir()) u'Save Service', self.config.get_last_dir())
else: else:
filename = self.config.get_last_dir() filename = self.config.get_last_dir()
if filename != u'': if filename:
splittedFile = filename.split(u'.') splittedFile = filename.split(u'.')
if splittedFile[-1] != u'osz': if splittedFile[-1] != u'osz':
filename = filename + u'.osz' filename = filename + u'.osz'
@ -427,21 +424,30 @@ class ServiceManager(QtGui.QWidget):
self.config.set_last_dir(filename) self.config.set_last_dir(filename)
service = [] service = []
servicefile = filename + u'.osd' servicefile = filename + u'.osd'
zip = zipfile.ZipFile(unicode(filename), 'w') zip = None
for item in self.serviceItems: file = None
service.append( try:
{u'serviceitem':item[u'data'].get_service_repr()}) zip = zipfile.ZipFile(unicode(filename), 'w')
if item[u'data'].service_item_type == ServiceItemType.Image or \ for item in self.serviceItems:
item[u'data'].service_item_type == ServiceItemType.Command: service.append(
for frame in item[u'data'].frames: {u'serviceitem':item[u'service_item'].get_service_repr()})
path_from = unicode(os.path.join( if item[u'service_item'].service_item_type == ServiceItemType.Image or \
item[u'data'].service_item_path, frame[u'title'])) item[u'service_item'].service_item_type == ServiceItemType.Command:
zip.write(path_from) for frame in item[u'service_item'].frames:
file = open(servicefile, u'wb') path_from = unicode(os.path.join(
cPickle.dump(service, file) item[u'service_item'].service_item_path, frame[u'title']))
file.close() zip.write(path_from)
zip.write(servicefile) file = open(servicefile, u'wb')
zip.close() cPickle.dump(service, file)
file.close()
zip.write(servicefile)
except:
log.exception(u'Failed to save service to disk')
finally:
if file:
file.close()
if zip:
zip.close()
try: try:
os.remove(servicefile) os.remove(servicefile)
except: except:
@ -453,7 +459,7 @@ class ServiceManager(QtGui.QWidget):
def onQuickSaveService(self): def onQuickSaveService(self):
self.onSaveService(True) self.onSaveService(True)
def onLoadService(self, lastService = False): def onLoadService(self, lastService=False):
""" """
Load an existing service from disk and rebuild the serviceitems. All Load an existing service from disk and rebuild the serviceitems. All
files retrieved from the zip file are placed in a temporary directory files retrieved from the zip file are placed in a temporary directory
@ -467,16 +473,15 @@ class ServiceManager(QtGui.QWidget):
self.config.get_last_dir(), u'Services (*.osz)') self.config.get_last_dir(), u'Services (*.osz)')
filename = unicode(filename) filename = unicode(filename)
name = filename.split(os.path.sep) name = filename.split(os.path.sep)
if filename != u'': if filename:
self.config.set_last_dir(filename) self.config.set_last_dir(filename)
zip = None
f = None
try: try:
zip = zipfile.ZipFile(unicode(filename)) zip = zipfile.ZipFile(unicode(filename))
for file in zip.namelist(): for file in zip.namelist():
if os.name == u'nt': osfile = unicode(QtCore.QDir.toNativeSeparators(file))
winfile = string.replace(file, '/', os.path.sep) names = osfile.split(os.path.sep)
names = winfile.split(os.path.sep)
else:
names = file.split(os.path.sep)
file_to = os.path.join(self.servicePath, file_to = os.path.join(self.servicePath,
names[len(names) - 1]) names[len(names) - 1])
f = open(file_to, u'wb') f = open(file_to, u'wb')
@ -492,7 +497,7 @@ class ServiceManager(QtGui.QWidget):
for item in items: for item in items:
serviceitem = ServiceItem() serviceitem = ServiceItem()
serviceitem.RenderManager = self.parent.RenderManager serviceitem.RenderManager = self.parent.RenderManager
serviceitem.set_from_service(item, self.servicePath ) serviceitem.set_from_service(item, self.servicePath)
self.addServiceItem(serviceitem) self.addServiceItem(serviceitem)
try: try:
if os.path.isfile(p_file): if os.path.isfile(p_file):
@ -501,6 +506,11 @@ class ServiceManager(QtGui.QWidget):
log.exception(u'Failed to remove osd file') log.exception(u'Failed to remove osd file')
except: except:
log.exception(u'Problem loading a service file') log.exception(u'Problem loading a service file')
finally:
if f:
f.close()
if zip:
zip.close()
self.isNew = False self.isNew = False
self.serviceName = name[len(name) - 1] self.serviceName = name[len(name) - 1]
self.parent.serviceChanged(True, self.serviceName) self.parent.serviceChanged(True, self.serviceName)
@ -531,7 +541,7 @@ class ServiceManager(QtGui.QWidget):
tempServiceItems = self.serviceItems tempServiceItems = self.serviceItems
self.onNewService() self.onNewService()
for item in tempServiceItems: for item in tempServiceItems:
self.addServiceItem(item[u'data']) self.addServiceItem(item[u'service_item'])
def addServiceItem(self, item): def addServiceItem(self, item):
""" """
@ -544,19 +554,19 @@ class ServiceManager(QtGui.QWidget):
sitem, count = self.findServiceItem() sitem, count = self.findServiceItem()
item.render() item.render()
if self.remoteEditTriggered: if self.remoteEditTriggered:
item.uuid = self.serviceItems[sitem][u'data'].uuid item.merge(self.serviceItems[sitem][u'service_item'])
self.serviceItems[sitem][u'data'] = item self.serviceItems[sitem][u'service_item'] = item
self.remoteEditTriggered = False self.remoteEditTriggered = False
self.repaintServiceList(sitem + 1, 0) self.repaintServiceList(sitem + 1, 0)
self.parent.LiveController.replaceServiceManagerItem(item) self.parent.LiveController.replaceServiceManagerItem(item)
else: else:
if sitem == -1: if sitem == -1:
self.serviceItems.append({u'data': item, self.serviceItems.append({u'service_item': item,
u'order': len(self.serviceItems) + 1, u'order': len(self.serviceItems) + 1,
u'expanded':True}) u'expanded':True})
self.repaintServiceList(len(self.serviceItems) + 1, 0) self.repaintServiceList(len(self.serviceItems) + 1, 0)
else: else:
self.serviceItems.insert(sitem + 1, {u'data': item, self.serviceItems.insert(sitem + 1, {u'service_item': item,
u'order': len(self.serviceItems)+1, u'order': len(self.serviceItems)+1,
u'expanded':True}) u'expanded':True})
self.repaintServiceList(sitem + 1, 0) self.repaintServiceList(sitem + 1, 0)
@ -568,7 +578,7 @@ class ServiceManager(QtGui.QWidget):
""" """
item, count = self.findServiceItem() item, count = self.findServiceItem()
self.parent.PreviewController.addServiceManagerItem( self.parent.PreviewController.addServiceManagerItem(
self.serviceItems[item][u'data'], count) self.serviceItems[item][u'service_item'], count)
def makeLive(self): def makeLive(self):
""" """
@ -576,17 +586,18 @@ class ServiceManager(QtGui.QWidget):
""" """
item, count = self.findServiceItem() item, count = self.findServiceItem()
self.parent.LiveController.addServiceManagerItem( self.parent.LiveController.addServiceManagerItem(
self.serviceItems[item][u'data'], count) self.serviceItems[item][u'service_item'], count)
def remoteEdit(self): def remoteEdit(self):
""" """
Posts a remote edit message to a plugin to allow item to be edited. Posts a remote edit message to a plugin to allow item to be edited.
""" """
item, count = self.findServiceItem() item, count = self.findServiceItem()
if self.serviceItems[item][u'data'].editEnabled: if self.serviceItems[item][u'service_item'].edit_enabled:
self.remoteEditTriggered = True self.remoteEditTriggered = True
Receiver().send_message(u'%s_edit' % self.serviceItems[item][u'data'].name, u'L:%s' % Receiver.send_message(u'%s_edit' %
self.serviceItems[item][u'data'].editId ) self.serviceItems[item][u'service_item'].name, u'L:%s' %
self.serviceItems[item][u'service_item'].editId )
def onRemoteEditClear(self): def onRemoteEditClear(self):
self.remoteEditTriggered = False self.remoteEditTriggered = False
@ -652,7 +663,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.insert(newpos, serviceItem) self.serviceItems.insert(newpos, serviceItem)
self.repaintServiceList(endpos, startCount) self.repaintServiceList(endpos, startCount)
else: else:
Receiver().send_message(u'%s_add_service_item' % plugin) Receiver.send_message(u'%s_add_service_item' % plugin)
def updateThemeList(self, theme_list): def updateThemeList(self, theme_list):
""" """
@ -684,5 +695,5 @@ class ServiceManager(QtGui.QWidget):
def onThemeChangeAction(self): def onThemeChangeAction(self):
theme = unicode(self.sender().text()) theme = unicode(self.sender().text())
item, count = self.findServiceItem() item, count = self.findServiceItem()
self.serviceItems[item][u'data'].theme = theme self.serviceItems[item][u'service_item'].theme = theme
self.regenerateServiceItems() self.regenerateServiceItems()

View File

@ -67,7 +67,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
def accept(self): def accept(self):
for tab_index in range(0, self.SettingsTabWidget.count()): for tab_index in range(0, self.SettingsTabWidget.count()):
self.SettingsTabWidget.widget(tab_index).save() self.SettingsTabWidget.widget(tab_index).save()
Receiver().send_message(u'config_updated') Receiver.send_message(u'config_updated')
return QtGui.QDialog.accept(self) return QtGui.QDialog.accept(self)
def postSetUp(self): def postSetUp(self):

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 # vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
@ -24,10 +23,12 @@
import logging import logging
import time import time
import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, ServiceItemType, \ from PyQt4.phonon import Phonon
str_to_bool, PluginConfig
from openlp.core.lib import OpenLPToolbar, Receiver, str_to_bool, PluginConfig
class SlideList(QtGui.QTableWidget): class SlideList(QtGui.QTableWidget):
""" """
@ -80,18 +81,13 @@ class SlideController(QtGui.QWidget):
u'Loop Separator', u'Loop Separator',
u'Image SpinBox' u'Image SpinBox'
] ]
self.media_list = [ self.song_edit_list = [
u'Media Start',
u'Media Stop',
u'Media Pause'
]
self.song_list = [
u'Edit Song', u'Edit Song',
] ]
self.timer_id = 0 self.timer_id = 0
self.commandItem = None
self.songEdit = False self.songEdit = False
self.row = 0 self.selectedRow = 0
self.serviceItem = None
self.Panel = QtGui.QWidget(parent.ControlSplitter) self.Panel = QtGui.QWidget(parent.ControlSplitter)
# Layout for holding panel # Layout for holding panel
self.PanelLayout = QtGui.QVBoxLayout(self.Panel) self.PanelLayout = QtGui.QVBoxLayout(self.Panel)
@ -102,14 +98,19 @@ class SlideController(QtGui.QWidget):
if self.isLive: if self.isLive:
self.TypeLabel.setText(u'<strong>%s</strong>' % self.TypeLabel.setText(u'<strong>%s</strong>' %
self.trUtf8(u'Live')) self.trUtf8(u'Live'))
self.split = 1
prefix = u'live_slidecontroller'
else: else:
self.TypeLabel.setText(u'<strong>%s</strong>' % self.TypeLabel.setText(u'<strong>%s</strong>' %
self.trUtf8(u'Preview')) self.trUtf8(u'Preview'))
self.split = 0
prefix = u'preview_slidecontroller'
self.TypeLabel.setAlignment(QtCore.Qt.AlignCenter) self.TypeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.PanelLayout.addWidget(self.TypeLabel) self.PanelLayout.addWidget(self.TypeLabel)
# Splitter # Splitter
self.Splitter = QtGui.QSplitter(self.Panel) self.Splitter = QtGui.QSplitter(self.Panel)
self.Splitter.setOrientation(QtCore.Qt.Vertical) self.Splitter.setOrientation(QtCore.Qt.Vertical)
self.Splitter.setOpaqueResize(False)
self.PanelLayout.addWidget(self.Splitter) self.PanelLayout.addWidget(self.Splitter)
# Actual controller section # Actual controller section
self.Controller = QtGui.QWidget(self.Splitter) self.Controller = QtGui.QWidget(self.Splitter)
@ -130,6 +131,7 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.setObjectName(u'PreviewListWidget') self.PreviewListWidget.setObjectName(u'PreviewListWidget')
self.PreviewListWidget.setEditTriggers( self.PreviewListWidget.setEditTriggers(
QtGui.QAbstractItemView.NoEditTriggers) QtGui.QAbstractItemView.NoEditTriggers)
self.PreviewListWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.ControllerLayout.addWidget(self.PreviewListWidget) self.ControllerLayout.addWidget(self.PreviewListWidget)
# Build the full toolbar # Build the full toolbar
self.Toolbar = OpenLPToolbar(self) self.Toolbar = OpenLPToolbar(self)
@ -156,8 +158,11 @@ class SlideController(QtGui.QWidget):
self.trUtf8(u'Move to last'), self.onSlideSelectedLast) self.trUtf8(u'Move to last'), self.onSlideSelectedLast)
if self.isLive: if self.isLive:
self.Toolbar.addToolbarSeparator(u'Close Separator') self.Toolbar.addToolbarSeparator(u'Close Separator')
self.blackPushButton = self.Toolbar.addPushButton( self.blankButton = self.Toolbar.addToolbarButton(
u':/slides/slide_close.png') u'Blank Screen', u':/slides/slide_close.png',
self.trUtf8(u'Blank Screen'), self.onBlankScreen, True)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_slide_blank'), self.onBlankDisplay)
if not self.isLive: if not self.isLive:
self.Toolbar.addToolbarSeparator(u'Close Separator') self.Toolbar.addToolbarSeparator(u'Close Separator')
self.Toolbar.addToolbarButton( self.Toolbar.addToolbarButton(
@ -180,31 +185,38 @@ class SlideController(QtGui.QWidget):
u'Image SpinBox', self.DelaySpinBox) u'Image SpinBox', self.DelaySpinBox)
self.DelaySpinBox.setSuffix(self.trUtf8(u's')) self.DelaySpinBox.setSuffix(self.trUtf8(u's'))
self.DelaySpinBox.setToolTip(self.trUtf8(u'Delay between slides in seconds')) self.DelaySpinBox.setToolTip(self.trUtf8(u'Delay between slides in seconds'))
self.Toolbar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
self.trUtf8(u'Start playing media'), self.onMediaPlay)
self.Toolbar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
self.trUtf8(u'Start playing media'), self.onMediaPause)
self.Toolbar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
self.trUtf8(u'Start playing media'), self.onMediaStop)
self.ControllerLayout.addWidget(self.Toolbar) self.ControllerLayout.addWidget(self.Toolbar)
#Build a Media ToolBar
self.Mediabar = OpenLPToolbar(self)
self.Mediabar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
self.trUtf8(u'Start playing media'), self.onMediaPlay)
self.Mediabar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
self.trUtf8(u'Start playing media'), self.onMediaPause)
self.Mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
self.trUtf8(u'Start playing media'), self.onMediaStop)
self.volumeSlider = Phonon.VolumeSlider()
self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
self.volumeSlider.setObjectName(u'volumeSlider')
self.Mediabar.addToolbarWidget(
u'Audio Volume', self.volumeSlider)
self.ControllerLayout.addWidget(self.Mediabar)
# Build the Song Toolbar # Build the Song Toolbar
if isLive: if isLive:
self.Songbar = OpenLPToolbar(self) self.Songbar = OpenLPToolbar(self)
self.Songbar.addToolbarButton( self.Songbar.addToolbarButton(
u'Bridge', u':/slides/slide_close.png', u'Bridge', u':/pages/page_bridge.png',
self.trUtf8(u'Bridge'), self.trUtf8(u'Bridge'),
self.onSongBarHandler) self.onSongBarHandler)
self.Songbar.addToolbarButton( self.Songbar.addToolbarButton(
u'Chorus', u':/slides/slide_close.png', u'Chorus', u':/pages/page_chorus.png',
self.trUtf8(u'Chorus'), self.trUtf8(u'Chorus'),
self.onSongBarHandler) self.onSongBarHandler)
for verse in range(1, 20): for verse in range(1, 12):
self.Songbar.addToolbarButton( self.Songbar.addToolbarButton(
unicode(verse), u':/slides/slide_close.png', unicode(verse), u':/pages/page_%s.png' % verse,
unicode(self.trUtf8(u'Verse %s'))%verse, unicode(self.trUtf8(u'Verse %s'))%verse,
self.onSongBarHandler) self.onSongBarHandler)
self.ControllerLayout.addWidget(self.Songbar) self.ControllerLayout.addWidget(self.Songbar)
@ -213,15 +225,26 @@ class SlideController(QtGui.QWidget):
self.PreviewFrame = QtGui.QFrame(self.Splitter) self.PreviewFrame = QtGui.QFrame(self.Splitter)
self.PreviewFrame.setGeometry(QtCore.QRect(0, 0, 300, 225)) self.PreviewFrame.setGeometry(QtCore.QRect(0, 0, 300, 225))
self.PreviewFrame.setSizePolicy(QtGui.QSizePolicy( self.PreviewFrame.setSizePolicy(QtGui.QSizePolicy(
QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)) QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Label))
self.PreviewFrame.setFrameShape(QtGui.QFrame.StyledPanel) self.PreviewFrame.setFrameShape(QtGui.QFrame.StyledPanel)
self.PreviewFrame.setFrameShadow(QtGui.QFrame.Sunken) self.PreviewFrame.setFrameShadow(QtGui.QFrame.Sunken)
self.PreviewFrame.setObjectName(u'PreviewFrame') self.PreviewFrame.setObjectName(u'PreviewFrame')
self.grid = QtGui.QGridLayout(self.PreviewFrame) self.grid = QtGui.QGridLayout(self.PreviewFrame)
self.grid.setMargin(8) self.grid.setMargin(8)
self.grid.setObjectName(u'grid') self.grid.setObjectName(u'grid')
self.SlideLayout = QtGui.QVBoxLayout()
self.SlideLayout.setSpacing(0)
self.SlideLayout.setMargin(0)
self.SlideLayout.setObjectName(u'SlideLayout')
self.mediaObject = Phonon.MediaObject(self)
self.video = Phonon.VideoWidget()
self.video.setVisible(False)
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.video)
Phonon.createPath(self.mediaObject, self.audio)
self.SlideLayout.insertWidget(0, self.video)
# Actual preview screen # Actual preview screen
self.SlidePreview = QtGui.QLabel(self.parent) self.SlidePreview = QtGui.QLabel(self)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Fixed) QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -236,33 +259,54 @@ class SlideController(QtGui.QWidget):
self.SlidePreview.setLineWidth(1) self.SlidePreview.setLineWidth(1)
self.SlidePreview.setScaledContents(True) self.SlidePreview.setScaledContents(True)
self.SlidePreview.setObjectName(u'SlidePreview') self.SlidePreview.setObjectName(u'SlidePreview')
self.grid.addWidget(self.SlidePreview, 0, 0, 1, 1) self.SlideLayout.insertWidget(0, self.SlidePreview)
self.grid.addLayout(self.SlideLayout, 0, 0, 1, 1)
# Signals # Signals
QtCore.QObject.connect(self.PreviewListWidget, QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
QtCore.QObject.connect(self.PreviewListWidget, QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'activated(QModelIndex)'), self.onSlideSelected) QtCore.SIGNAL(u'activated(QModelIndex)'), self.onSlideSelected)
if isLive: if isLive:
QtCore.QObject.connect(self.blackPushButton, #QtCore.QObject.connect(self.blackPushButton,
QtCore.SIGNAL(u'clicked(bool)'), self.onBlankScreen) # QtCore.SIGNAL(u'clicked(bool)'), self.onBlankScreen)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_spin_delay'), self.receiveSpinDelay) QtCore.SIGNAL(u'update_spin_delay'), self.receiveSpinDelay)
Receiver().send_message(u'request_spin_delay') Receiver.send_message(u'request_spin_delay')
if isLive: if isLive:
self.Toolbar.makeWidgetsInvisible(self.image_list) self.Toolbar.makeWidgetsInvisible(self.image_list)
self.Toolbar.makeWidgetsInvisible(self.media_list)
else: else:
self.Toolbar.makeWidgetsInvisible(self.song_list) self.Toolbar.makeWidgetsInvisible(self.song_edit_list)
self.Mediabar.setVisible(False)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_first'), self.onSlideSelectedFirst) QtCore.SIGNAL(u'%s_first' % prefix), self.onSlideSelectedFirst)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_next'), self.onSlideSelectedNext) QtCore.SIGNAL(u'%s_next' % prefix), self.onSlideSelectedNext)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_previous'), self.onSlideSelectedPrevious) QtCore.SIGNAL(u'%s_previous' % prefix), self.onSlideSelectedPrevious)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_last'), self.onSlideSelectedLast) QtCore.SIGNAL(u'%s_last' % prefix), self.onSlideSelectedLast)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_change'), self.onSlideChange) QtCore.SIGNAL(u'%s_change' % prefix), self.onSlideChange)
QtCore.QObject.connect(self.Splitter,
QtCore.SIGNAL(u'splitterMoved(int, int)'), self.trackSplitter)
def widthChanged(self):
"""
Handle changes of width from the splitter between the live and preview
controller. Event only issues when changes have finished
"""
width = self.parent.ControlSplitter.sizes()[self.split]
height = width * self.parent.RenderManager.screen_ratio
self.PreviewListWidget.setColumnWidth(0, width)
if self.serviceItem and not self.serviceItem.is_text():
for framenumber, frame in enumerate(self.serviceItem.get_frames()):
self.PreviewListWidget.setRowHeight(framenumber, height)
def trackSplitter(self, tab, pos):
"""
Splitter between the slide list and the preview panel
"""
pass
def onSongBarHandler(self): def onSongBarHandler(self):
request = self.sender().text() request = self.sender().text()
@ -296,92 +340,91 @@ class SlideController(QtGui.QWidget):
""" """
Allows the live toolbar to be customised Allows the live toolbar to be customised
""" """
self.Toolbar.setVisible(True)
self.Songbar.setVisible(False) self.Songbar.setVisible(False)
self.Mediabar.setVisible(False)
self.Toolbar.makeWidgetsInvisible(self.image_list) self.Toolbar.makeWidgetsInvisible(self.image_list)
self.Toolbar.makeWidgetsInvisible(self.media_list) if item.is_text():
if item.service_item_type == ServiceItemType.Text:
self.Toolbar.makeWidgetsInvisible(self.image_list) self.Toolbar.makeWidgetsInvisible(self.image_list)
if item.name == u'Songs' and \ if item.is_song() and \
str_to_bool(self.songsconfig.get_config(u'display songbar', True)): str_to_bool(self.songsconfig.get_config(u'display songbar', True)):
for action in self.Songbar.actions: for action in self.Songbar.actions:
self.Songbar.actions[action].setVisible(False) self.Songbar.actions[action].setVisible(False)
if item.verse_order: if item.verse_order:
verses = item.verse_order.split(u' ') verses = item.verse_order.split(u' ')
for verse in verses: for verse in verses:
if not verse or int(verse) > 12:
break
try: try:
self.Songbar.actions[verse].setVisible(True) self.Songbar.actions[verse].setVisible(True)
except: except:
#More than 20 verses hard luck #More than 20 verses hard luck
pass pass
self.Songbar.setVisible(True) self.Songbar.setVisible(True)
elif item.service_item_type == ServiceItemType.Image: elif item.is_image():
#Not sensible to allow loops with 1 frame #Not sensible to allow loops with 1 frame
if len(item.frames) > 1: if len(item.get_frames()) > 1:
self.Toolbar.makeWidgetsVisible(self.image_list) self.Toolbar.makeWidgetsVisible(self.image_list)
elif item.service_item_type == ServiceItemType.Command and \ elif item.is_media():
item.name == u'Media': self.Toolbar.setVisible(False)
self.Toolbar.makeWidgetsVisible(self.media_list) self.Mediabar.setVisible(True)
self.volumeSlider.setAudioOutput(self.parent.mainDisplay.audio)
def enablePreviewToolBar(self, item): def enablePreviewToolBar(self, item):
""" """
Allows the Preview toolbar to be customised Allows the Preview toolbar to be customised
""" """
if (item.name == u'Songs' or item.name == u'Custom') and item.fromPlugin: self.Toolbar.setVisible(True)
self.Toolbar.makeWidgetsVisible(self.song_list) self.Mediabar.setVisible(False)
else: self.Toolbar.makeWidgetsInvisible(self.song_edit_list)
self.Toolbar.makeWidgetsInvisible(self.song_list) if item.edit_enabled and item.fromPlugin:
self.Toolbar.makeWidgetsVisible(self.song_edit_list)
elif item.is_media():
self.Toolbar.setVisible(False)
self.Mediabar.setVisible(True)
self.volumeSlider.setAudioOutput(self.audio)
def addServiceItem(self, item): def addServiceItem(self, item):
""" """
Method to install the service item into the controller and Method to install the service item into the controller
request the correct the toolbar of the plugin
Called by plugins Called by plugins
""" """
log.debug(u'addServiceItem') log.debug(u'addServiceItem')
#If old item was a command tell it to stop
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_stop'% self.commandItem.name.lower())
self.commandItem = item
before = time.time() before = time.time()
item.render() item.render()
log.info(u'Rendering took %4s' % (time.time() - before)) log.log(15, u'Rendering took %4s' % (time.time() - before))
self.enableToolBar(item)
if item.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_start' % item.name.lower(), \
[item.shortname, item.service_item_path,
item.service_frames[0][u'title']])
slideno = 0 slideno = 0
if self.songEdit: if self.songEdit:
slideno = self.row slideno = self.selectedRow
self.songEdit = False self.songEdit = False
self.displayServiceManagerItems(item, slideno) self.addServiceManagerItem(item, slideno)
def replaceServiceManagerItem(self, item): def replaceServiceManagerItem(self, item):
""" """
Replacement item following a remote edit Replacement item following a remote edit
""" """
if self.commandItem and \ if item.__eq__(self.serviceItem):
item.uuid == self.commandItem.uuid:
self.addServiceManagerItem(item, self.PreviewListWidget.currentRow()) self.addServiceManagerItem(item, self.PreviewListWidget.currentRow())
def addServiceManagerItem(self, item, slideno): def addServiceManagerItem(self, item, slideno):
""" """
Method to install the service item into the controller and Method to install the service item into the controller and
request the correct the toolbar of the plugin request the correct toolbar for the plugin.
Called by ServiceManager Called by ServiceManager
""" """
log.debug(u'addServiceManagerItem') log.debug(u'addServiceManagerItem')
#If old item was a command tell it to stop #If old item was a command tell it to stop
if self.commandItem and \ if self.serviceItem and self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command: self.onMediaStop()
Receiver().send_message(u'%s_stop'% self.commandItem.name.lower())
self.commandItem = item
self.enableToolBar(item) self.enableToolBar(item)
if item.service_item_type == ServiceItemType.Command: if item.is_command():
Receiver().send_message(u'%s_start' % item.name.lower(), \ if self.isLive:
[item.shortname, item.service_item_path, Receiver.send_message(u'%s_start' % item.name.lower(), \
item.service_frames[0][u'title'], slideno]) [item.title, item.service_item_path,
item.get_frame_title(), slideno, self.isLive])
else:
if item.is_media():
self.onMediaStart(item)
self.displayServiceManagerItems(item, slideno) self.displayServiceManagerItems(item, slideno)
def displayServiceManagerItems(self, serviceitem, slideno): def displayServiceManagerItems(self, serviceitem, slideno):
@ -390,33 +433,34 @@ class SlideController(QtGui.QWidget):
Display the slide number passed Display the slide number passed
""" """
log.debug(u'displayServiceManagerItems Start') log.debug(u'displayServiceManagerItems Start')
width = self.parent.ControlSplitter.sizes()[self.split]
#Set pointing cursor when we have somthing to point at
self.PreviewListWidget.setCursor(QtCore.Qt.PointingHandCursor)
before = time.time() before = time.time()
self.serviceitem = serviceitem self.serviceItem = serviceitem
self.PreviewListWidget.clear() self.PreviewListWidget.clear()
self.PreviewListWidget.setRowCount(0) self.PreviewListWidget.setRowCount(0)
self.PreviewListWidget.setColumnWidth( self.PreviewListWidget.setColumnWidth(0, width)
0, self.settingsmanager.slidecontroller_image) for framenumber, frame in enumerate(self.serviceItem.get_frames()):
for framenumber, frame in enumerate(self.serviceitem.frames):
self.PreviewListWidget.setRowCount( self.PreviewListWidget.setRowCount(
self.PreviewListWidget.rowCount() + 1) self.PreviewListWidget.rowCount() + 1)
item = QtGui.QTableWidgetItem() item = QtGui.QTableWidgetItem()
slide_height = 0 slide_height = 0
#It is a Image #It is a Image
if frame[u'text'] is None: if not self.serviceItem.is_text():
label = QtGui.QLabel() label = QtGui.QLabel()
label.setMargin(4) label.setMargin(4)
pixmap = self.parent.RenderManager.resize_image(frame[u'image']) pixmap = self.parent.RenderManager.resize_image(frame[u'image'])
label.setScaledContents(True) label.setScaledContents(True)
label.setPixmap(QtGui.QPixmap.fromImage(pixmap)) label.setPixmap(QtGui.QPixmap.fromImage(pixmap))
self.PreviewListWidget.setCellWidget(framenumber, 0, label) self.PreviewListWidget.setCellWidget(framenumber, 0, label)
slide_height = self.settingsmanager.slidecontroller_image * \ slide_height = width * self.parent.RenderManager.screen_ratio
self.parent.RenderManager.screen_ratio
else: else:
item.setText(frame[u'text']) item.setText(frame[u'text'])
self.PreviewListWidget.setItem(framenumber, 0, item) self.PreviewListWidget.setItem(framenumber, 0, item)
if slide_height != 0: if slide_height != 0:
self.PreviewListWidget.setRowHeight(framenumber, slide_height) self.PreviewListWidget.setRowHeight(framenumber, slide_height)
if self.serviceitem.frames[0][u'text']: if self.serviceItem.is_text():
self.PreviewListWidget.resizeRowsToContents() self.PreviewListWidget.resizeRowsToContents()
self.PreviewListWidget.setColumnWidth( self.PreviewListWidget.setColumnWidth(
0, self.PreviewListWidget.viewport().size().width()) 0, self.PreviewListWidget.viewport().size().width())
@ -426,9 +470,9 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.selectRow(slideno) self.PreviewListWidget.selectRow(slideno)
self.onSlideSelected() self.onSlideSelected()
self.PreviewListWidget.setFocus() self.PreviewListWidget.setFocus()
log.info(u'Display Rendering took %4s' % (time.time() - before)) log.log(15, u'Display Rendering took %4s' % (time.time() - before))
if self.serviceitem.audit != u'' and self.isLive: if self.isLive:
Receiver().send_message(u'songusage_live', self.serviceitem.audit) self.serviceItem.request_audit()
log.debug(u'displayServiceManagerItems End') log.debug(u'displayServiceManagerItems End')
#Screen event methods #Screen event methods
@ -436,26 +480,27 @@ class SlideController(QtGui.QWidget):
""" """
Go to the first slide. Go to the first slide.
""" """
if self.commandItem and \ if self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command: Receiver.send_message(u'%s_first'% self.serviceItem.name.lower())
Receiver().send_message(u'%s_first'% self.commandItem.name.lower()) self.updatePreview()
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
else: else:
self.PreviewListWidget.selectRow(0) self.PreviewListWidget.selectRow(0)
self.onSlideSelected() self.onSlideSelected()
def onBlankDisplay(self):
self.blankButton.setChecked(self.parent.mainDisplay.displayBlank)
def onBlankScreen(self, blanked): def onBlankScreen(self, blanked):
""" """
Blank the screen. Blank the screen.
""" """
if self.commandItem and \ if self.serviceItem and self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command:
if blanked: if blanked:
Receiver().send_message(u'%s_blank'% self.commandItem.name.lower()) Receiver.send_message(u'%s_blank'% self.serviceItem.name.lower())
else: else:
Receiver().send_message(u'%s_unblank'% self.commandItem.name.lower()) Receiver.send_message(u'%s_unblank'% self.serviceItem.name.lower())
else: else:
self.parent.mainDisplay.blankDisplay() self.parent.mainDisplay.blankDisplay(blanked)
def onSlideSelected(self): def onSlideSelected(self):
""" """
@ -463,49 +508,54 @@ class SlideController(QtGui.QWidget):
if this is the Live Controller also display on the screen if this is the Live Controller also display on the screen
""" """
row = self.PreviewListWidget.currentRow() row = self.PreviewListWidget.currentRow()
self.row = 0 self.selectedRow = 0
if row > -1 and row < self.PreviewListWidget.rowCount(): if row > -1 and row < self.PreviewListWidget.rowCount():
if self.commandItem.service_item_type == ServiceItemType.Command: if self.serviceItem.is_command():
Receiver().send_message(u'%s_slide'% self.commandItem.name.lower(), [row]) Receiver.send_message(u'%s_slide'% self.serviceItem.name.lower(), [row])
if self.isLive: if self.isLive:
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) self.updatePreview()
else: else:
frame = self.serviceitem.frames[row][u'image']
before = time.time() before = time.time()
if frame is None: frame = self.serviceItem.get_rendered_frame(row)
frame = self.serviceitem.render_individual(row)
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
log.info(u'Slide Rendering took %4s' % (time.time() - before)) log.log(15, u'Slide Rendering took %4s' % (time.time() - before))
if self.isLive: if self.isLive:
self.parent.mainDisplay.frameView(frame) self.parent.mainDisplay.frameView(frame)
self.row = row self.selectedRow = row
def onSlideChange(self, row): def onSlideChange(self, row):
""" """
The slide has been changed. Update the slidecontroller accordingly The slide has been changed. Update the slidecontroller accordingly
""" """
self.PreviewListWidget.selectRow(row) self.PreviewListWidget.selectRow(row)
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) self.updatePreview()
def updatePreview(self):
rm = self.parent.RenderManager
if not rm.screen_list[rm.current_display][u'primary']:
# Grab now, but try again in a couple of seconds if slide change is slow
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
else:
label = self.PreviewListWidget.cellWidget(
self.PreviewListWidget.currentRow(), 0)
self.SlidePreview.setPixmap(label.pixmap())
def grabMainDisplay(self): def grabMainDisplay(self):
rm = self.parent.RenderManager rm = self.parent.RenderManager
if not rm.screen_list[rm.current_display][u'primary']: winid = QtGui.QApplication.desktop().winId()
winid = QtGui.QApplication.desktop().winId() rect = rm.screen_list[rm.current_display][u'size']
rect = rm.screen_list[rm.current_display][u'size'] winimg = QtGui.QPixmap.grabWindow(winid, rect.x(),
winimg = QtGui.QPixmap.grabWindow(winid, rect.x(), rect.y(), rect.width(), rect.height()) rect.y(), rect.width(), rect.height())
self.SlidePreview.setPixmap(winimg) self.SlidePreview.setPixmap(winimg)
else:
label = self.PreviewListWidget.cellWidget(self.PreviewListWidget.currentRow(), 0)
self.SlidePreview.setPixmap(label.pixmap())
def onSlideSelectedNext(self): def onSlideSelectedNext(self):
""" """
Go to the next slide. Go to the next slide.
""" """
if self.commandItem and \ if self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command: Receiver.send_message(u'%s_next'% self.serviceItem.name.lower())
Receiver().send_message(u'%s_next'% self.commandItem.name.lower()) self.updatePreview()
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
else: else:
row = self.PreviewListWidget.currentRow() + 1 row = self.PreviewListWidget.currentRow() + 1
if row == self.PreviewListWidget.rowCount(): if row == self.PreviewListWidget.rowCount():
@ -517,11 +567,10 @@ class SlideController(QtGui.QWidget):
""" """
Go to the previous slide. Go to the previous slide.
""" """
if self.commandItem and \ if self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command: Receiver.send_message(
Receiver().send_message( u'%s_previous'% self.serviceItem.name.lower())
u'%s_previous'% self.commandItem.name.lower()) self.updatePreview()
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
else: else:
row = self.PreviewListWidget.currentRow() - 1 row = self.PreviewListWidget.currentRow() - 1
if row == -1: if row == -1:
@ -533,10 +582,9 @@ class SlideController(QtGui.QWidget):
""" """
Go to the last slide. Go to the last slide.
""" """
if self.commandItem and \ if self.serviceItem.is_command():
self.commandItem.service_item_type == ServiceItemType.Command: Receiver.send_message(u'%s_last'% self.serviceItem.name.lower())
Receiver().send_message(u'%s_last'% self.commandItem.name.lower()) self.updatePreview()
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
else: else:
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1) self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1)
self.onSlideSelected() self.onSlideSelected()
@ -564,8 +612,8 @@ class SlideController(QtGui.QWidget):
def onEditSong(self): def onEditSong(self):
self.songEdit = True self.songEdit = True
Receiver().send_message(u'%s_edit' % self.commandItem.name, u'P:%s' % Receiver.send_message(u'%s_edit' % self.serviceItem.name, u'P:%s' %
self.commandItem.editId ) self.serviceItem.editId )
def onGoLive(self): def onGoLive(self):
""" """
@ -574,13 +622,34 @@ class SlideController(QtGui.QWidget):
row = self.PreviewListWidget.currentRow() row = self.PreviewListWidget.currentRow()
if row > -1 and row < self.PreviewListWidget.rowCount(): if row > -1 and row < self.PreviewListWidget.rowCount():
self.parent.LiveController.addServiceManagerItem( self.parent.LiveController.addServiceManagerItem(
self.commandItem, row) self.serviceItem, row)
def onMediaStart(self, item):
self.mediaObject.stop()
self.mediaObject.clearQueue()
file = os.path.join(item.service_item_path, item.get_frame_title())
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
self.onMediaPlay()
def onMediaPause(self): def onMediaPause(self):
Receiver().send_message(u'%s_pause'% self.commandItem.name.lower()) if self.isLive:
Receiver.send_message(u'%s_pause'% self.serviceItem.name.lower())
else:
self.mediaObject.pause()
def onMediaPlay(self): def onMediaPlay(self):
Receiver().send_message(u'%s_play'% self.commandItem.name.lower()) if self.isLive:
Receiver.send_message(u'%s_play'% self.serviceItem.name.lower(), self.isLive)
else:
self.SlidePreview.hide()
self.video.show()
self.mediaObject.play()
def onMediaStop(self): def onMediaStop(self):
Receiver().send_message(u'%s_stop'% self.commandItem.name.lower()) if self.isLive:
Receiver.send_message(u'%s_stop'% self.serviceItem.name.lower())
else:
self.mediaObject.stop()
self.video.hide()
self.SlidePreview.clear()
self.SlidePreview.show()

View File

@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.ui import AmendThemeForm from openlp.core.ui import AmendThemeForm
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.lib import PluginConfig, OpenLPToolbar, ThemeXML, \ from openlp.core.lib import PluginConfig, OpenLPToolbar, ThemeXML, \
str_to_bool, file_to_xml, buildIcon, Receiver, contextMenuAction, \ str_to_bool, get_text_file_string, buildIcon, Receiver, contextMenuAction, \
contextMenuSeparator contextMenuSeparator
from openlp.core.utils import ConfigHelper from openlp.core.utils import ConfigHelper
@ -145,20 +145,22 @@ class ThemeManager(QtGui.QWidget):
name = u'%s (%s)' % (self.global_theme, self.trUtf8(u'default')) name = u'%s (%s)' % (self.global_theme, self.trUtf8(u'default'))
self.ThemeListWidget.item(count).setText(name) self.ThemeListWidget.item(count).setText(name)
self.config.set_config(u'theme global theme', self.global_theme) self.config.set_config(u'theme global theme', self.global_theme)
Receiver().send_message( Receiver.send_message(
u'update_global_theme', self.global_theme) u'update_global_theme', self.global_theme)
self.pushThemes() self.pushThemes()
def onAddTheme(self): def onAddTheme(self):
self.amendThemeForm.loadTheme(None) theme = self.createThemeFromXml(self.baseTheme(), self.path)
self.amendThemeForm.loadTheme(theme)
self.saveThemeName = u'' self.saveThemeName = u''
self.amendThemeForm.exec_() self.amendThemeForm.exec_()
def onEditTheme(self): def onEditTheme(self):
item = self.ThemeListWidget.currentItem() item = self.ThemeListWidget.currentItem()
if item: if item:
self.amendThemeForm.loadTheme( theme = self.getThemeData(
unicode(item.data(QtCore.Qt.UserRole).toString())) unicode(item.data(QtCore.Qt.UserRole).toString()))
self.amendThemeForm.loadTheme(theme)
self.saveThemeName = unicode( self.saveThemeName = unicode(
item.data(QtCore.Qt.UserRole).toString()) item.data(QtCore.Qt.UserRole).toString())
self.amendThemeForm.exec_() self.amendThemeForm.exec_()
@ -182,10 +184,6 @@ class ThemeManager(QtGui.QWidget):
self.ThemeListWidget.takeItem(row) self.ThemeListWidget.takeItem(row)
try: try:
os.remove(os.path.join(self.path, th)) os.remove(os.path.join(self.path, th))
except:
#if not present do not worry
pass
try:
shutil.rmtree(os.path.join(self.path, theme)) shutil.rmtree(os.path.join(self.path, theme))
except: except:
#if not present do not worry #if not present do not worry
@ -210,16 +208,22 @@ class ThemeManager(QtGui.QWidget):
unicode(self.trUtf8(u'Save Theme - (%s)')) % theme, unicode(self.trUtf8(u'Save Theme - (%s)')) % theme,
self.config.get_last_dir(1) ) self.config.get_last_dir(1) )
path = unicode(path) path = unicode(path)
if path != u'': if path:
self.config.set_last_dir(path, 1) self.config.set_last_dir(path, 1)
themePath = os.path.join(path, theme + u'.theme') themePath = os.path.join(path, theme + u'.theme')
zip = zipfile.ZipFile(themePath, u'w') zip = None
source = os.path.join(self.path, theme) try:
for root, dirs, files in os.walk(source): zip = zipfile.ZipFile(themePath, u'w')
for name in files: source = os.path.join(self.path, theme)
zip.write( for root, dirs, files in os.walk(source):
os.path.join(source, name), os.path.join(theme, name)) for name in files:
zip.close() zip.write(
os.path.join(source, name), os.path.join(theme, name))
except:
log.exception(u'Export Theme Failed')
finally:
if zip:
zip.close()
def onImportTheme(self): def onImportTheme(self):
files = QtGui.QFileDialog.getOpenFileNames( files = QtGui.QFileDialog.getOpenFileNames(
@ -263,7 +267,7 @@ class ThemeManager(QtGui.QWidget):
self.pushThemes() self.pushThemes()
def pushThemes(self): def pushThemes(self):
Receiver().send_message(u'update_themes', self.getThemes() ) Receiver.send_message(u'update_themes', self.getThemes() )
def getThemes(self): def getThemes(self):
return self.themelist return self.themelist
@ -272,15 +276,10 @@ class ThemeManager(QtGui.QWidget):
log.debug(u'getthemedata for theme %s', themename) log.debug(u'getthemedata for theme %s', themename)
xml_file = os.path.join(self.path, unicode(themename), xml_file = os.path.join(self.path, unicode(themename),
unicode(themename) + u'.xml') unicode(themename) + u'.xml')
try: xml = get_text_file_string(xml_file)
xml = file_to_xml(xml_file) if not xml:
except:
xml = self.baseTheme() xml = self.baseTheme()
theme = ThemeXML() return self.createThemeFromXml(xml, self.path)
theme.parse(xml)
self.cleanTheme(theme)
theme.extend_image_filename(self.path)
return theme
def checkThemesExists(self, dir): def checkThemesExists(self, dir):
log.debug(u'check themes') log.debug(u'check themes')
@ -295,44 +294,49 @@ class ThemeManager(QtGui.QWidget):
""" """
log.debug(u'Unzipping theme %s', filename) log.debug(u'Unzipping theme %s', filename)
filename = unicode(filename) filename = unicode(filename)
zip = None
outfile = None
try: try:
zip = zipfile.ZipFile(filename) zip = zipfile.ZipFile(filename)
filexml = None
themename = None
for file in zip.namelist():
if file.endswith(os.path.sep):
theme_dir = os.path.join(dir, file)
if not os.path.exists(theme_dir):
os.mkdir(os.path.join(dir, file))
else:
fullpath = os.path.join(dir, file)
names = file.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
xml_data = zip.read(file)
if os.path.splitext(file)[1].lower() in [u'.xml']:
if self.checkVersion1(xml_data):
# upgrade theme xml
filexml = self.migrateVersion122(filename,
fullpath, xml_data)
else:
filexml = xml_data
outfile = open(fullpath, u'w')
outfile.write(filexml)
else:
outfile = open(fullpath, u'w')
outfile.write(zip.read(file))
self.generateAndSaveImage(dir, themename, filexml)
except: except:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
self, self.trUtf8(u'Error'), self, self.trUtf8(u'Error'),
self.trUtf8(u'File is not a valid theme!'), self.trUtf8(u'File is not a valid theme!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
return log.exception(u'Importing theme from zip file failed')
filexml = None finally:
themename = None if zip:
for file in zip.namelist(): zip.close()
if file.endswith(os.path.sep): if outfile:
theme_dir = os.path.join(dir, file) outfile.close()
if not os.path.exists(theme_dir):
os.mkdir(os.path.join(dir, file))
else:
fullpath = os.path.join(dir, file)
names = file.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
xml_data = zip.read(file)
if os.path.splitext(file)[1].lower() in [u'.xml']:
if self.checkVersion1(xml_data):
# upgrade theme xml
filexml = self.migrateVersion122(filename,
fullpath, xml_data)
else:
filexml = xml_data
outfile = open(fullpath, u'w')
outfile.write(filexml)
outfile.close()
else:
outfile = open(fullpath, u'w')
outfile.write(zip.read(file))
outfile.close()
self.generateAndSaveImage(dir, themename, filexml)
def checkVersion1(self, xmlfile): def checkVersion1(self, xmlfile):
""" """
@ -412,13 +416,22 @@ class ThemeManager(QtGui.QWidget):
result == QtGui.QMessageBox.Yes result == QtGui.QMessageBox.Yes
if result == QtGui.QMessageBox.Yes: if result == QtGui.QMessageBox.Yes:
# Save the theme, overwriting the existing theme if necessary. # Save the theme, overwriting the existing theme if necessary.
outfile = open(theme_file, u'w') outfile = None
outfile.write(theme_pretty_xml) try:
outfile.close() outfile = open(theme_file, u'w')
outfile.write(theme_pretty_xml)
except:
log.exception(u'Saving theme to file failed')
finally:
if outfile:
outfile.close()
if image_from and image_from != image_to: if image_from and image_from != image_to:
print "if", image_from print "if", image_from
print "it", image_to print "it", image_to
shutil.copyfile(image_from, image_to) try:
shutil.copyfile(image_from, image_to)
except:
log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme_xml) self.generateAndSaveImage(self.path, name, theme_xml)
self.loadThemes() self.loadThemes()
else: else:
@ -428,10 +441,7 @@ class ThemeManager(QtGui.QWidget):
def generateAndSaveImage(self, dir, name, theme_xml): def generateAndSaveImage(self, dir, name, theme_xml):
log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml) log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
theme = ThemeXML() theme = self.createThemeFromXml(theme_xml, dir)
theme.parse(theme_xml)
self.cleanTheme(theme)
theme.extend_image_filename(dir)
frame = self.generateImage(theme) frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png') samplepathname = os.path.join(self.path, name + u'.png')
if os.path.exists(samplepathname): if os.path.exists(samplepathname):
@ -465,6 +475,13 @@ class ThemeManager(QtGui.QWidget):
unicode(u'#FFFFFF'), unicode(0), unicode(0), unicode(0)) unicode(u'#FFFFFF'), unicode(0), unicode(0), unicode(0))
return newtheme.extract_xml() return newtheme.extract_xml()
def createThemeFromXml(self, theme_xml, path):
theme = ThemeXML()
theme.parse(theme_xml)
self.cleanTheme(theme)
theme.extend_image_filename(path)
return theme
def cleanTheme(self, theme): def cleanTheme(self, theme):
theme.background_color = theme.background_color.strip() theme.background_color = theme.background_color.strip()
theme.background_direction = theme.background_direction.strip() theme.background_direction = theme.background_direction.strip()
@ -486,6 +503,8 @@ class ThemeManager(QtGui.QWidget):
theme.display_wrapStyle = theme.display_wrapStyle.strip() theme.display_wrapStyle = theme.display_wrapStyle.strip()
theme.font_footer_color = theme.font_footer_color.strip() theme.font_footer_color = theme.font_footer_color.strip()
theme.font_footer_height = int(theme.font_footer_height.strip()) theme.font_footer_height = int(theme.font_footer_height.strip())
theme.font_footer_indentation = \
int(theme.font_footer_indentation.strip())
theme.font_footer_italics = str_to_bool(theme.font_footer_italics) theme.font_footer_italics = str_to_bool(theme.font_footer_italics)
theme.font_footer_name = theme.font_footer_name.strip() theme.font_footer_name = theme.font_footer_name.strip()
#theme.font_footer_override #theme.font_footer_override

View File

@ -135,10 +135,10 @@ class ThemesTab(SettingsTab):
def save(self): def save(self):
self.config.set_config(u'theme global style', self.global_style ) self.config.set_config(u'theme global style', self.global_style )
self.config.set_config(u'theme global theme',self.global_theme) self.config.set_config(u'theme global theme',self.global_theme)
Receiver().send_message(u'update_global_theme', self.global_theme ) Receiver.send_message(u'update_global_theme', self.global_theme )
def postSetUp(self): def postSetUp(self):
Receiver().send_message(u'update_global_theme', self.global_theme ) Receiver.send_message(u'update_global_theme', self.global_theme )
def onSongLevelButtonPressed(self): def onSongLevelButtonPressed(self):
self.global_style = u'Song' self.global_style = u'Song'

View File

@ -101,23 +101,29 @@ class Registry(object):
return False return False
def _load(self): def _load(self):
if not os.path.isfile(self.file_name):
return False
file_handle = None
try: try:
if not os.path.isfile(self.file_name):
return False
file_handle = open(self.file_name, u'r') file_handle = open(self.file_name, u'r')
self.config.readfp(file_handle) self.config.readfp(file_handle)
file_handle.close()
return True return True
except: except:
return False return False
finally:
if file_handle:
file_handle.close()
def _save(self): def _save(self):
file_handle = None
try: try:
if not os.path.exists(os.path.dirname(self.file_name)): if not os.path.exists(os.path.dirname(self.file_name)):
os.makedirs(os.path.dirname(self.file_name)) os.makedirs(os.path.dirname(self.file_name))
file_handle = open(self.file_name, u'w') file_handle = open(self.file_name, u'w')
self.config.write(file_handle) self.config.write(file_handle)
file_handle.close()
return self._load() return self._load()
except: except:
return False return False
finally:
if file_handle:
file_handle.close()

View File

@ -41,9 +41,6 @@ class BiblePlugin(Plugin):
#Register the bible Manager #Register the bible Manager
self.biblemanager = None self.biblemanager = None
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.info(u'bibles Initialising') log.info(u'bibles Initialising')
if self.biblemanager is None: if self.biblemanager is None:

View File

@ -59,6 +59,7 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(filepath, u'..', filepath = os.path.abspath(os.path.join(filepath, u'..',
u'resources', u'crosswalkbooks.csv')) u'resources', u'crosswalkbooks.csv'))
fbibles = None
try: try:
fbibles = open(filepath, 'r') fbibles = open(filepath, 'r')
for line in fbibles: for line in fbibles:
@ -66,6 +67,9 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
self.cwBibleVersions[p[0]] = p[1].replace(u'\n', u'') self.cwBibleVersions[p[0]] = p[1].replace(u'\n', u'')
except: except:
log.exception(u'Crosswalk resources missing') log.exception(u'Crosswalk resources missing')
finally:
if fbibles:
fbibles.close()
#Load and store BibleGateway Bibles #Load and store BibleGateway Bibles
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(filepath, u'..', filepath = os.path.abspath(os.path.join(filepath, u'..',
@ -77,6 +81,9 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
self.bgBibleVersions[p[0]] = p[1].replace(u'\n', u'') self.bgBibleVersions[p[0]] = p[1].replace(u'\n', u'')
except: except:
log.exception(u'Biblegateway resources missing') log.exception(u'Biblegateway resources missing')
finally:
if fbibles:
fbibles.close()
self.loadBibleCombo(self.cwBibleVersions) self.loadBibleCombo(self.cwBibleVersions)
self.cwActive = True self.cwActive = True
@ -125,7 +132,7 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
filename = QtGui.QFileDialog.getOpenFileName( filename = QtGui.QFileDialog.getOpenFileName(
self, self.trUtf8(u'Open Bible Verses file'), self, self.trUtf8(u'Open Bible Verses file'),
self.config.get_last_dir(1)) self.config.get_last_dir(1))
if filename != u'': if filename:
self.VerseLocationEdit.setText(filename) self.VerseLocationEdit.setText(filename)
self.config.set_last_dir(filename, 1) self.config.set_last_dir(filename, 1)
self.setCsv() self.setCsv()
@ -134,7 +141,7 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
filename = QtGui.QFileDialog.getOpenFileName( filename = QtGui.QFileDialog.getOpenFileName(
self, self.trUtf8(u'Open Bible Books file'), self, self.trUtf8(u'Open Bible Books file'),
self.config.get_last_dir(2)) self.config.get_last_dir(2))
if filename != u'': if filename:
self.BooksLocationEdit.setText(filename) self.BooksLocationEdit.setText(filename)
self.config.set_last_dir(filename, 2) self.config.set_last_dir(filename, 2)
self.setCsv() self.setCsv()
@ -143,7 +150,7 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
filename = QtGui.QFileDialog.getOpenFileName( filename = QtGui.QFileDialog.getOpenFileName(
self, self.trUtf8(u'Open OSIS import file'), self, self.trUtf8(u'Open OSIS import file'),
self.config.get_last_dir(3)) self.config.get_last_dir(3))
if filename != u'': if filename:
self.OSISLocationEdit.setText(filename) self.OSISLocationEdit.setText(filename)
self.config.set_last_dir(filename, 3) self.config.set_last_dir(filename, 3)
self.setOsis() self.setOsis()
@ -192,9 +199,9 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
def onCancelButtonClicked(self): def onCancelButtonClicked(self):
# tell import to stop # tell import to stop
self.message = self.trUtf8(u'Bible import stopped') self.message = self.trUtf8(u'Bible import stopped')
Receiver().send_message(u'stop_import') Receiver.send_message(u'stop_import')
# tell bibleplugin to reload the bibles # tell bibleplugin to reload the bibles
Receiver().send_message(u'pre_load_bibles') Receiver.send_message(u'pre_load_bibles')
self.close() self.close()
def onImportButtonClicked(self): def onImportButtonClicked(self):
@ -213,7 +220,7 @@ class BibleImportForm(QtGui.QDialog, Ui_BibleImportDialog):
self.MessageLabel.setText(message) self.MessageLabel.setText(message)
self.ProgressBar.setValue(self.barmax) self.ProgressBar.setValue(self.barmax)
# tell bibleplugin to reload the bibles # tell bibleplugin to reload the bibles
Receiver().send_message(u'pre_load_bibles') Receiver.send_message(u'pre_load_bibles')
QtGui.QMessageBox.information(self, QtGui.QMessageBox.information(self,
self.trUtf8(u'Information'), self.trUtf8(message)) self.trUtf8(u'Information'), self.trUtf8(message))

View File

@ -40,7 +40,7 @@ class BibleCSVImpl(BibleCommon):
""" """
self.bibledb = bibledb self.bibledb = bibledb
self.loadbible = True self.loadbible = True
QtCore.QObject.connect(Receiver().get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self): def stop_import(self):
@ -48,46 +48,59 @@ class BibleCSVImpl(BibleCommon):
def load_data(self, booksfile, versesfile, dialogobject): def load_data(self, booksfile, versesfile, dialogobject):
#Populate the Tables #Populate the Tables
fbooks = open(booksfile, 'r') fbooks = None
fverse = open(versesfile, 'r') try:
fbooks = open(booksfile, 'r')
count = 0
for line in fbooks:
# cancel pressed
if not self.loadbible:
break
details = chardet.detect(line)
line = unicode(line, details['encoding'])
p = line.split(u',')
p1 = p[1].replace(u'"', u'')
p2 = p[2].replace(u'"', u'')
p3 = p[3].replace(u'"', u'')
self.bibledb.create_book(p2, p3, int(p1))
count += 1
#Flush the screen events
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
except:
log.exception(u'Loading books from file failed')
finally:
if fbooks:
fbooks.close()
count = 0 fverse = None
for line in fbooks: try:
# cancel pressed fverse = open(versesfile, 'r')
if not self.loadbible: count = 0
break book_ptr = None
details = chardet.detect(line) for line in fverse:
line = unicode(line, details['encoding']) if not self.loadbible: # cancel pressed
p = line.split(u',') break
p1 = p[1].replace(u'"', u'') details = chardet.detect(line)
p2 = p[2].replace(u'"', u'') line = unicode(line, details['encoding'])
p3 = p[3].replace(u'"', u'') # split into 3 units and leave the rest as a single field
self.bibledb.create_book(p2, p3, int(p1)) p = line.split(u',', 3)
count += 1 p0 = p[0].replace(u'"', u'')
#Flush the screen events p3 = p[3].replace(u'"',u'')
if count % 3 == 0: if book_ptr is not p0:
Receiver().send_message(u'process_events') book = self.bibledb.get_bible_book(p0)
count = 0 book_ptr = book.name
# increament the progress bar
count = 0 dialogobject.incrementProgressBar(book.name)
book_ptr = None self.bibledb.add_verse(book.id, p[1], p[2], p3)
for line in fverse: count += 1
if not self.loadbible: # cancel pressed #Every x verses repaint the screen
break if count % 3 == 0:
details = chardet.detect(line) Receiver.send_message(u'process_events')
line = unicode(line, details['encoding']) count = 0
# split into 3 units and leave the rest as a single field except:
p = line.split(u',', 3) log.exception(u'Loading verses from file failed')
p0 = p[0].replace(u'"', u'') finally:
p3 = p[3].replace(u'"',u'') if fverse:
if book_ptr is not p0: fverse.close()
book = self.bibledb.get_bible_book(p0)
book_ptr = book.name
# increament the progress bar
dialogobject.incrementProgressBar(book.name)
self.bibledb.add_verse(book.id, p[1], p[2], p3)
count += 1
#Every x verses repaint the screen
if count % 3 == 0:
Receiver().send_message(u'process_events')
count = 0

View File

@ -60,13 +60,21 @@ class BibleOSISImpl():
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join( filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources',u'osisbooks.csv')) filepath, u'..', u'resources',u'osisbooks.csv'))
fbibles = open(filepath, u'r') fbibles = None
for line in fbibles: try:
p = line.split(u',') fbibles = open(filepath, u'r')
self.booksOfBible[p[0]] = p[1].replace(u'\n', u'') for line in fbibles:
self.abbrevOfBible[p[0]] = p[2].replace(u'\n', u'') p = line.split(u',')
self.loadbible = True self.booksOfBible[p[0]] = p[1].replace(u'\n', u'')
QtCore.QObject.connect(Receiver().get_receiver(), self.abbrevOfBible[p[0]] = p[2].replace(u'\n', u'')
self.loadbible = True
except:
log.exception(u'OSIS bible import failed')
finally:
self.loadbible = False
if fbibles:
fbibles.close()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self): def stop_import(self):
@ -86,82 +94,98 @@ class BibleOSISImpl():
The Import dialog, so that we can increase the counter on The Import dialog, so that we can increase the counter on
the progress bar. the progress bar.
""" """
detect_file = open(osisfile_record, u'r') detect_file = None
details = chardet.detect(detect_file.read(2048)) try:
detect_file.close() detect_file = open(osisfile_record, u'r')
osis = codecs.open(osisfile_record, u'r', details['encoding']) details = chardet.detect(detect_file.read(2048))
book_ptr = None except:
count = 0 log.exception(u'Failed to detect OSIS file encoding')
verseText = u'<verse osisID=' return
testament = 1 finally:
for file_record in osis.readlines(): if detect_file:
# cancel pressed on UI detect_file.close()
if not self.loadbible: osis = None
break try:
pos = file_record.find(verseText) osis = codecs.open(osisfile_record, u'r', details['encoding'])
# we have a verse book_ptr = None
if pos > -1: count = 0
epos = file_record.find(u'>', pos) verseText = u'<verse osisID='
# Book Reference testament = 1
ref = file_record[pos+15:epos-1] for file_record in osis.readlines():
#lets find the bible text only # cancel pressed on UI
# find start of text if not self.loadbible:
pos = epos + 1 break
# end of text pos = file_record.find(verseText)
epos = file_record.find(u'</verse>', pos) # we have a verse
text = file_record[pos : epos] if pos > -1:
#remove tags of extra information epos = file_record.find(u'>', pos)
text = self.remove_block(u'<title', u'</title>', text) # Book Reference
text = self.remove_block(u'<note', u'</note>', text) ref = file_record[pos+15:epos-1]
text = self.remove_block(u'<divineName', u'</divineName>', text) #lets find the bible text only
text = self.remove_tag(u'<lb', text) # find start of text
text = self.remove_tag(u'<q', text) pos = epos + 1
text = self.remove_tag(u'<l', text) # end of text
text = self.remove_tag(u'<lg', text) epos = file_record.find(u'</verse>', pos)
# Strange tags where the end is not the same as the start text = file_record[pos : epos]
# The must be in this order as at least one bible has them #remove tags of extra information
# crossing and the removal does not work. text = self.remove_block(u'<title', u'</title>', text)
pos = text.find(u'<FI>') text = self.remove_block(u'<note', u'</note>', text)
while pos > -1: text = self.remove_block(
epos = text.find(u'<Fi>', pos) u'<divineName', u'</divineName>', text)
if epos == -1: # TODO text = self.remove_tag(u'<lb', text)
pos = -1 text = self.remove_tag(u'<q', text)
else: text = self.remove_tag(u'<l', text)
text = text[:pos] + text[epos + 4: ] text = self.remove_tag(u'<lg', text)
pos = text.find(u'<FI>') # Strange tags where the end is not the same as the start
pos = text.find(u'<RF>') # The must be in this order as at least one bible has them
while pos > -1: # crossing and the removal does not work.
epos = text.find(u'<Rf>', pos) pos = text.find(u'<FI>')
text = text[:pos] + text[epos + 4: ] while pos > -1:
pos = text.find(u'<RF>') epos = text.find(u'<Fi>', pos)
# split up the reference if epos == -1: # TODO
p = ref.split(u'.', 3) pos = -1
if book_ptr != p[0]:
# first time through
if book_ptr is None:
# set the max book size depending on the first book read
if p[0] == u'Gen':
dialogobject.setMax(65)
else: else:
dialogobject.setMax(27) text = text[:pos] + text[epos + 4: ]
# First book of NT pos = text.find(u'<FI>')
if p[0] == u'Matt': pos = text.find(u'<RF>')
testament += 1 while pos > -1:
book_ptr = p[0] epos = text.find(u'<Rf>', pos)
book = self.bibledb.create_book( text = text[:pos] + text[epos + 4: ]
unicode(self.booksOfBible[p[0]]), pos = text.find(u'<RF>')
unicode(self.abbrevOfBible[p[0]]), # split up the reference
testament) p = ref.split(u'.', 3)
dialogobject.incrementProgressBar( if book_ptr != p[0]:
self.booksOfBible[p[0]]) # first time through
Receiver().send_message(u'process_events') if book_ptr is None:
count = 0 # set the max book size depending
self.bibledb.add_verse(book.id, p[1], p[2], text) # on the first book read
count += 1 if p[0] == u'Gen':
#Every 3 verses repaint the screen dialogobject.setMax(65)
if count % 3 == 0: else:
Receiver().send_message(u'process_events') dialogobject.setMax(27)
count = 0 # First book of NT
if p[0] == u'Matt':
testament += 1
book_ptr = p[0]
book = self.bibledb.create_book(
unicode(self.booksOfBible[p[0]]),
unicode(self.abbrevOfBible[p[0]]),
testament)
dialogobject.incrementProgressBar(
self.booksOfBible[p[0]])
Receiver.send_message(u'process_events')
count = 0
self.bibledb.add_verse(book.id, p[1], p[2], text)
count += 1
#Every 3 verses repaint the screen
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
except:
log.exception(u'Loading bible from OSIS file failed')
finally:
if osis:
osis.close()
def remove_block(self, start_tag, end_tag, text): def remove_block(self, start_tag, end_tag, text):
""" """

View File

@ -105,7 +105,8 @@ class BibleCommon(object):
xml_string = u'' xml_string = u''
req = urllib2.Request(urlstring) req = urllib2.Request(urlstring)
#Make us look like an IE Browser on XP to stop blocking by web site #Make us look like an IE Browser on XP to stop blocking by web site
req.add_header(u'User-Agent', u'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)') req.add_header(u'User-Agent',
u'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)')
try: try:
handle = urllib2.urlopen(req) handle = urllib2.urlopen(req)
html = handle.read() html = handle.read()
@ -164,4 +165,3 @@ class BibleCommon(object):
start_tag = text.find(u'<') start_tag = text.find(u'<')
text = text.replace(u'>', u'') text = text.replace(u'>', u'')
return text.rstrip().lstrip() return text.rstrip().lstrip()

View File

@ -71,7 +71,7 @@ class BibleManager(object):
def reload_bibles(self): def reload_bibles(self):
log.debug(u'Reload bibles') log.debug(u'Reload bibles')
files = self.config.get_files(self.bibleSuffix) files = self.config.get_files(self.bibleSuffix)
log.debug(u'Bible Files %s', files ) log.debug(u'Bible Files %s', files)
self.bible_db_cache = {} self.bible_db_cache = {}
self.bible_http_cache = {} self.bible_http_cache = {}
# books of the bible with testaments # books of the bible with testaments
@ -116,12 +116,19 @@ class BibleManager(object):
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join( filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources',u'httpbooks.csv')) filepath, u'..', u'resources',u'httpbooks.csv'))
fbibles = open(filepath, u'r') fbibles = None
for line in fbibles: try:
p = line.split(u',') fbibles = open(filepath, u'r')
self.book_abbreviations[p[0]] = p[1].replace(u'\n', '') for line in fbibles:
self.book_testaments[p[0]] = p[2].replace(u'\n', '') p = line.split(u',')
self.book_chapters.append({u'book':p[0], u'total':p[3].replace(u'\n', '')}) self.book_abbreviations[p[0]] = p[1].replace(u'\n', '')
self.book_testaments[p[0]] = p[2].replace(u'\n', '')
self.book_chapters.append({u'book':p[0], u'total':p[3].replace(u'\n', '')})
except:
log.exception(u'Failed to load bible')
finally:
if fbibles:
fbibles.close()
log.debug(u'Bible Initialised') log.debug(u'Bible Initialised')
def process_dialog(self, dialogobject): def process_dialog(self, dialogobject):

View File

@ -54,7 +54,7 @@ class BibleMediaItem(MediaManagerItem):
MediaManagerItem.__init__(self, parent, icon, title) MediaManagerItem.__init__(self, parent, icon, title)
# place to store the search results # place to store the search results
self.search_results = {} self.search_results = {}
QtCore.QObject.connect(Receiver().get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpreloadbibles'), self.reloadBibles) QtCore.SIGNAL(u'openlpreloadbibles'), self.reloadBibles)
def initPluginNameVisible(self): def initPluginNameVisible(self):
@ -284,7 +284,7 @@ class BibleMediaItem(MediaManagerItem):
def setQuickMessage(self, text): def setQuickMessage(self, text):
self.QuickMessage.setText(text) self.QuickMessage.setText(text)
self.AdvancedMessage.setText(text) self.AdvancedMessage.setText(text)
Receiver().send_message(u'process_events') Receiver.send_message(u'process_events')
#minor delay to get the events processed #minor delay to get the events processed
time.sleep(0.1) time.sleep(0.1)

View File

@ -54,9 +54,6 @@ class CustomPlugin(Plugin):
# Create the CustomManagerItem object # Create the CustomManagerItem object
return CustomMediaItem(self, self.icon, self.name) return CustomMediaItem(self, self.icon, self.name)
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.info(u'Plugin Initialising') log.info(u'Plugin Initialising')
Plugin.initialise(self) Plugin.initialise(self)

View File

@ -21,6 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -32,6 +33,9 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
""" """
Class documentation goes here. Class documentation goes here.
""" """
global log
log = logging.getLogger(u'EditCustomForm')
log.info(u'Custom Editor loaded')
def __init__(self, custommanager, parent = None): def __init__(self, custommanager, parent = None):
""" """
Constructor Constructor
@ -40,6 +44,12 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
#self.parent = parent #self.parent = parent
self.setupUi(self) self.setupUi(self)
# Connecting signals and slots # Connecting signals and slots
self.previewButton = QtGui.QPushButton()
self.previewButton.setText(self.trUtf8(u'Save && Preview'))
self.buttonBox.addButton(
self.previewButton, QtGui.QDialogButtonBox.ActionRole)
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'clicked(QAbstractButton*)'), self.onPreview)
QtCore.QObject.connect(self.AddButton, QtCore.QObject.connect(self.AddButton,
QtCore.SIGNAL(u'pressed()'), self.onAddButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onAddButtonPressed)
QtCore.QObject.connect(self.EditButton, QtCore.QObject.connect(self.EditButton,
@ -68,6 +78,12 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
self.custommanager = custommanager self.custommanager = custommanager
self.initialise() self.initialise()
def onPreview(self, button):
log.debug(u'onPreview')
if button.text() == unicode(self.trUtf8(u'Save && Preview')) \
and self.saveCustom():
Receiver.send_message(u'preview_custom')
def initialise(self): def initialise(self):
self.editAll = False self.editAll = False
self.DeleteButton.setEnabled(False) self.DeleteButton.setEnabled(False)
@ -89,7 +105,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
for themename in themelist: for themename in themelist:
self.ThemeComboBox.addItem(themename) self.ThemeComboBox.addItem(themename)
def loadCustom(self, id): def loadCustom(self, id, preview):
self.customSlide = CustomSlide() self.customSlide = CustomSlide()
self.initialise() self.initialise()
if id != 0: if id != 0:
@ -108,17 +124,27 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
self.ThemeComboBox.setCurrentIndex(id) self.ThemeComboBox.setCurrentIndex(id)
else: else:
self.ThemeComboBox.setCurrentIndex(0) self.ThemeComboBox.setCurrentIndex(0)
#if not preview hide the preview button
self.previewButton.setVisible(False)
if preview:
self.previewButton.setVisible(True)
def closePressed(self): def closePressed(self):
Receiver().send_message(u'remote_edit_clear') Receiver.send_message(u'remote_edit_clear')
self.close() self.close()
def accept(self): def accept(self):
log.debug(u'accept')
if self.saveCustom():
Receiver.send_message(u'load_custom_list')
self.close()
def saveCustom(self):
valid, message = self._validate() valid, message = self._validate()
if not valid: if not valid:
QtGui.QMessageBox.critical(self, self.trUtf8(u'Error'), message, QtGui.QMessageBox.critical(self, self.trUtf8(u'Error'), message,
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
return return False
sxml = SongXMLBuilder() sxml = SongXMLBuilder()
sxml.new_document() sxml.new_document()
sxml.add_lyrics_to_song() sxml.add_lyrics_to_song()
@ -132,8 +158,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
self.customSlide.credits = unicode(self.CreditEdit.displayText()) self.customSlide.credits = unicode(self.CreditEdit.displayText())
self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText()) self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText())
self.custommanager.save_slide(self.customSlide) self.custommanager.save_slide(self.customSlide)
Receiver().send_message(u'load_custom_list') return True
self.close()
def onUpButtonPressed(self): def onUpButtonPressed(self):
selectedRow = self.VerseListView.currentRow() selectedRow = self.VerseListView.currentRow()

View File

@ -50,7 +50,9 @@ class CustomMediaItem(MediaManagerItem):
self.ListViewWithDnD_class = CustomListView self.ListViewWithDnD_class = CustomListView
self.servicePath = None self.servicePath = None
MediaManagerItem.__init__(self, parent, icon, title) MediaManagerItem.__init__(self, parent, icon, title)
self.fromServiceManager = -1 # Holds information about whether the edit is remotly triggered and
# which Custom is required.
self.remoteCustom = -1
def addEndHeaderBar(self): def addEndHeaderBar(self):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -59,6 +61,8 @@ class CustomMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'remote_edit_clear' ), self.onRemoteEditClear) QtCore.SIGNAL(u'remote_edit_clear' ), self.onRemoteEditClear)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'load_custom_list'), self.initialise) QtCore.SIGNAL(u'load_custom_list'), self.initialise)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'preview_custom'), self.onPreviewClick)
def initPluginNameVisible(self): def initPluginNameVisible(self):
self.PluginNameVisible = self.trUtf8(u'Custom') self.PluginNameVisible = self.trUtf8(u'Custom')
@ -69,6 +73,14 @@ class CustomMediaItem(MediaManagerItem):
def initialise(self): def initialise(self):
self.loadCustomListView(self.parent.custommanager.get_all_slides()) self.loadCustomListView(self.parent.custommanager.get_all_slides())
#Called to redisplay the song list screen edith from a search
#or from the exit of the Song edit dialog. If remote editing is active
#Trigger it and clean up so it will not update again.
if self.remoteTriggered == u'L':
self.onAddClick()
if self.remoteTriggered == u'P':
self.onPreviewClick()
self.onRemoteEditClear()
def loadCustomListView(self, list): def loadCustomListView(self, list):
self.ListView.clear() self.ListView.clear()
@ -77,8 +89,6 @@ class CustomMediaItem(MediaManagerItem):
custom_name.setData( custom_name.setData(
QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id)) QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id))
self.ListView.addItem(custom_name) self.ListView.addItem(custom_name)
if CustomSlide.id == self.fromServiceManager:
self.onAddClick()
def onNewClick(self): def onNewClick(self):
self.parent.edit_custom_form.loadCustom(0) self.parent.edit_custom_form.loadCustom(0)
@ -86,20 +96,29 @@ class CustomMediaItem(MediaManagerItem):
self.initialise() self.initialise()
def onRemoteEditClear(self): def onRemoteEditClear(self):
self.fromServiceManager = -1 self.remoteTriggered = None
self.remoteCustom = -1
def onRemoteEdit(self, item_id): def onRemoteEdit(self, customid):
valid = self.parent.custommanager.get_custom(item_id) """
Called by ServiceManager or SlideController by event passing
the Song Id in the payload along with an indicator to say which
type of display is required.
"""
fields = customid.split(u':')
valid = self.parent.custommanager.get_custom(fields[1])
if valid: if valid:
self.fromServiceManager = item_id self.remoteCustom = fields[1]
self.parent.edit_custom_form.loadCustom(item_id) self.remoteTriggered = fields[0]
self.parent.edit_custom_form.loadCustom(fields[1],
(fields[0] == u'P'))
self.parent.edit_custom_form.exec_() self.parent.edit_custom_form.exec_()
def onEditClick(self): def onEditClick(self):
item = self.ListView.currentItem() item = self.ListView.currentItem()
if item: if item:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.parent.edit_custom_form.loadCustom(item_id) self.parent.edit_custom_form.loadCustom(item_id, False)
self.parent.edit_custom_form.exec_() self.parent.edit_custom_form.exec_()
self.initialise() self.initialise()
@ -116,18 +135,17 @@ class CustomMediaItem(MediaManagerItem):
raw_footer = [] raw_footer = []
slide = None slide = None
theme = None theme = None
if self.fromServiceManager == -1: if self.remoteTriggered is None:
item = self.ListView.currentItem() item = self.ListView.currentItem()
if item is None: if item is None:
return False return False
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else: else:
item_id = self.fromServiceManager item_id = self.remoteCustom
self.fromServiceManager = -1
customSlide = self.parent.custommanager.get_custom(item_id) customSlide = self.parent.custommanager.get_custom(item_id)
title = customSlide.title title = customSlide.title
credit = customSlide.credits credit = customSlide.credits
service_item.editEnabled = True service_item.edit_enabled = True
service_item.editId = item_id service_item.editId = item_id
theme = customSlide.theme_name theme = customSlide.theme_name
if len(theme) is not 0 : if len(theme) is not 0 :
@ -137,9 +155,8 @@ class CustomMediaItem(MediaManagerItem):
for verse in verseList: for verse in verseList:
raw_slides.append(verse[1]) raw_slides.append(verse[1])
raw_footer.append(title + u' '+ credit) raw_footer.append(title + u' '+ credit)
if theme: service_item.title = title
service_item.title = title for slide in raw_slides:
for slide in raw_slides: service_item.add_from_text(slide[:30], slide)
service_item.add_from_text(slide[:30], slide) service_item.raw_footer = raw_footer
service_item.raw_footer = raw_footer return True
return True

View File

@ -37,9 +37,6 @@ class ImagePlugin(Plugin):
self.weight = -7 self.weight = -7
self.icon = buildIcon(u':/media/media_image.png') self.icon = buildIcon(u':/media/media_image.png')
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.info(u'Plugin Initialising') log.info(u'Plugin Initialising')
Plugin.initialise(self) Plugin.initialise(self)
@ -60,7 +57,7 @@ class ImagePlugin(Plugin):
about_text = self.trUtf8(u'<b>Image Plugin</b><br>Allows images of ' about_text = self.trUtf8(u'<b>Image Plugin</b><br>Allows images of '
u'all types to be displayed. If a number of images are selected ' u'all types to be displayed. If a number of images are selected '
u'together and presented on the live controller it is possible ' u'together and presented on the live controller it is possible '
u'to turn them into a timed loop.<br>From the plugin if the ' u'to turn them into a timed loop.<br<br>From the plugin if the '
u'<i>Override background</i> is chosen and an image is selected ' u'<i>Override background</i> is chosen and an image is selected '
u'any somgs which are rendered will use the selected image from ' u'any somgs which are rendered will use the selected image from '
u'the background instead of the one provied by the theme.<br>') u'the background instead of the one provied by the theme.<br>')

View File

@ -74,7 +74,7 @@ class ImageTab(SettingsTab):
def save(self): def save(self):
self.config.set_config(u'loop delay', self.loop_delay) self.config.set_config(u'loop delay', self.loop_delay)
Receiver().send_message(u'update_spin_delay', self.loop_delay) Receiver.send_message(u'update_spin_delay', self.loop_delay)
def postSetUp(self): def postSetUp(self):
Receiver().send_message(u'update_spin_delay', self.loop_delay) Receiver.send_message(u'update_spin_delay', self.loop_delay)

View File

@ -79,7 +79,7 @@ class MediaMediaItem(MediaManagerItem):
items = self.ListView.selectedIndexes() items = self.ListView.selectedIndexes()
if len(items) > 1: if len(items) > 1:
return False return False
service_item.title = self.trUtf8(u'Media') service_item.title = unicode(self.trUtf8(u'Media'))
for item in items: for item in items:
bitem = self.ListView.item(item.row()) bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())

View File

@ -42,9 +42,6 @@ class MediaPlugin(Plugin):
def get_settings_tab(self): def get_settings_tab(self):
return MediaTab(self.name) return MediaTab(self.name)
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.info(u'Plugin Initialising') log.info(u'Plugin Initialising')
Plugin.initialise(self) Plugin.initialise(self)

View File

@ -272,7 +272,7 @@ class ImpressController(PresentationController):
self.goto_slide(1) self.goto_slide(1)
def get_slide_number(self): def get_slide_number(self):
return self.controller.getCurrentSlideIndex() return self.controller.getCurrentSlideIndex() + 1
def get_slide_count(self): def get_slide_count(self):
return self.document.getDrawPages().getCount() return self.document.getDrawPages().getCount()

View File

@ -136,18 +136,18 @@ class PresentationMediaItem(MediaManagerItem):
return False return False
service_item.title = unicode(self.DisplayTypeComboBox.currentText()) service_item.title = unicode(self.DisplayTypeComboBox.currentText())
service_item.shortname = unicode(self.DisplayTypeComboBox.currentText()) service_item.shortname = unicode(self.DisplayTypeComboBox.currentText())
cont = self.controllers[service_item.shortname] controller = self.controllers[service_item.shortname]
for item in items: for item in items:
bitem = self.ListView.item(item.row()) bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
cont.store_filename(filename) controller.store_filename(filename)
if cont.get_slide_preview_file(1) is None: if controller.get_slide_preview_file(1) is None:
cont.load_presentation(filename) controller.load_presentation(filename)
i = 1 i = 1
img = cont.get_slide_preview_file(i) img = controller.get_slide_preview_file(i)
while img: while img:
service_item.add_from_command(path, name, img) service_item.add_from_command(path, name, img)
i = i + 1 i = i + 1
img = cont.get_slide_preview_file(i) img = controller.get_slide_preview_file(i)
return True return True

View File

@ -41,6 +41,7 @@ class MessageListener(object):
def __init__(self, controllers): def __init__(self, controllers):
self.controllers = controllers self.controllers = controllers
self.handler = None self.handler = None
self.is_live = None
# messages are sent from core.ui.slidecontroller # messages are sent from core.ui.slidecontroller
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'presentations_start'), self.startup) QtCore.SIGNAL(u'presentations_start'), self.startup)
@ -60,20 +61,25 @@ class MessageListener(object):
QtCore.SIGNAL(u'presentations_blank'), self.blank) QtCore.SIGNAL(u'presentations_blank'), self.blank)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'presentations_unblank'), self.unblank) QtCore.SIGNAL(u'presentations_unblank'), self.unblank)
self.timer = QtCore.QTimer()
self.timer.setInterval(500)
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.timeout)
def startup(self, message): def startup(self, message):
""" """
Start of new presentation Start of new presentation
Save the handler as any new presentations start here Save the handler as any new presentations start here
""" """
self.handler, file = self.decodeMessage(message) self.handler, file, self.is_live = self.decodeMessage(message)
self.controller = self.controllers[self.handler] self.controller = self.controllers[self.handler]
if self.controller.is_loaded(): if self.controller.is_loaded():
self.shutdown(None) self.shutdown(None)
self.controller.load_presentation(file) self.controller.load_presentation(file)
self.controller.start_presentation() if self.is_live:
self.controller.start_presentation()
Receiver.send_message(u'live_slide_hide')
self.controller.slidenumber = 0 self.controller.slidenumber = 0
self.controller.timer.start() self.timer.start()
def activate(self): def activate(self):
if self.controller.is_active(): if self.controller.is_active():
@ -83,63 +89,79 @@ class MessageListener(object):
self.controller.start_presentation() self.controller.start_presentation()
if self.controller.slidenumber > 1: if self.controller.slidenumber > 1:
self.controller.goto_slide(self.controller.slidenumber) self.controller.goto_slide(self.controller.slidenumber)
def slide(self, message): def slide(self, message):
if not self.is_live:
return
self.activate() self.activate()
if message: if message:
self.controller.goto_slide(message[0]+1) self.controller.goto_slide(message[0]+1)
self.controller.poll_slidenumber() self.controller.poll_slidenumber(self.is_live)
def first(self, message): def first(self, message):
""" """
Based on the handler passed at startup triggers the first slide Based on the handler passed at startup triggers the first slide
""" """
if not self.is_live:
return
self.activate() self.activate()
self.controller.start_presentation() self.controller.start_presentation()
self.controller.poll_slidenumber() self.controller.poll_slidenumber(self.is_live)
def last(self, message): def last(self, message):
""" """
Based on the handler passed at startup triggers the first slide Based on the handler passed at startup triggers the first slide
""" """
if not self.is_live:
return
self.activate() self.activate()
self.controller.goto_slide(self.controller.get_slide_count()) self.controller.goto_slide(self.controller.get_slide_count())
self.controller.poll_slidenumber() self.controller.poll_slidenumber(self.is_live)
def next(self, message): def next(self, message):
""" """
Based on the handler passed at startup triggers the next slide event Based on the handler passed at startup triggers the next slide event
""" """
if not self.is_live:
return
self.activate() self.activate()
self.controller.next_step() self.controller.next_step()
self.controller.poll_slidenumber() self.controller.poll_slidenumber(self.is_live)
def previous(self, message): def previous(self, message):
""" """
Based on the handler passed at startup triggers the previous slide event Based on the handler passed at startup triggers the previous slide event
""" """
if not self.is_live:
return
self.activate() self.activate()
self.controller.previous_step() self.controller.previous_step()
self.controller.poll_slidenumber() self.controller.poll_slidenumber(self.is_live)
def shutdown(self, message): def shutdown(self, message):
""" """
Based on the handler passed at startup triggers slide show to shut down Based on the handler passed at startup triggers slide show to shut down
""" """
if self.is_live:
Receiver.send_message(u'live_slide_show')
self.controller.close_presentation() self.controller.close_presentation()
self.controller.slidenumber = 0 self.controller.slidenumber = 0
self.controller.timer.shutdown() self.timer.stop()
def blank(self): def blank(self):
if not self.is_live:
return
if not self.controller.is_loaded(): if not self.controller.is_loaded():
return return
if not self.controller.is_active(): if not self.controller.is_active():
return return
self.controller.blank_screen() self.controller.blank_screen()
def unblank(self): def unblank(self):
if not self.is_live:
return
self.activate() self.activate()
self.controller.unblank_screen() self.controller.unblank_screen()
def decodeMessage(self, message): def decodeMessage(self, message):
""" """
@ -149,4 +171,7 @@ class MessageListener(object):
Message containing Presentaion handler name and file to be presented. Message containing Presentaion handler name and file to be presented.
""" """
file = os.path.join(message[1], message[2]) file = os.path.join(message[1], message[2])
return message[0], file return message[0], file, message[3]
def timeout(self):
self.controller.poll_slidenumber(self.is_live)

View File

@ -50,25 +50,25 @@ class PresentationController(object):
``name`` ``name``
The name that appears in the options and the media manager The name that appears in the options and the media manager
``enabled`` ``enabled``
The controller is enabled The controller is enabled
``available`` ``available``
The controller is available on this machine. Set by init via The controller is available on this machine. Set by init via
call to check_available call to check_available
``plugin`` ``plugin``
The presentationplugin object The presentationplugin object
**Hook Functions** **Hook Functions**
``kill()`` ``kill()``
Called at system exit to clean up any running presentations Called at system exit to clean up any running presentations
``check_available()`` ``check_available()``
Returns True if presentation application is installed/can run on this machine Returns True if presentation application is installed/can run on this machine
``presentation_deleted()`` ``presentation_deleted()``
Deletes presentation specific files, e.g. thumbnails Deletes presentation specific files, e.g. thumbnails
@ -83,7 +83,7 @@ class PresentationController(object):
``is_active()`` ``is_active()``
Returns True if a presentation is currently running Returns True if a presentation is currently running
``blank_screen()`` ``blank_screen()``
Blanks the screen, making it black. Blanks the screen, making it black.
@ -118,7 +118,7 @@ class PresentationController(object):
global log global log
log = logging.getLogger(u'PresentationController') log = logging.getLogger(u'PresentationController')
log.info(u'loaded') log.info(u'loaded')
def __init__(self, plugin=None, name=u'PresentationController'): def __init__(self, plugin=None, name=u'PresentationController'):
""" """
This is the constructor for the presentationcontroller object. This is the constructor for the presentationcontroller object.
@ -149,9 +149,6 @@ class PresentationController(object):
self.thumbnailprefix = u'slide' self.thumbnailprefix = u'slide'
if not os.path.isdir(self.thumbnailroot): if not os.path.isdir(self.thumbnailroot):
os.makedirs(self.thumbnailroot) os.makedirs(self.thumbnailroot)
self.timer = QtCore.QTimer()
self.timer.setInterval(500)
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.poll_slidenumber)
def check_available(self): def check_available(self):
""" """
@ -166,7 +163,7 @@ class PresentationController(object):
""" """
self.store_filename(presentation) self.store_filename(presentation)
shutil.rmtree(self.thumbnailpath) shutil.rmtree(self.thumbnailpath)
def start_process(self): def start_process(self):
""" """
Loads a running version of the presentation application in the background. Loads a running version of the presentation application in the background.
@ -188,6 +185,7 @@ class PresentationController(object):
``presentation`` ``presentation``
The file name of the presentations to the run. The file name of the presentations to the run.
""" """
pass pass
@ -207,9 +205,7 @@ class PresentationController(object):
recent than the powerpoint recent than the powerpoint
""" """
lastimage = self.get_slide_preview_file(self.get_slide_count()) lastimage = self.get_slide_preview_file(self.get_slide_count())
if lastimage is None: if not (lastimage and os.path.isfile(lastimage)):
return False
if not os.path.isfile(lastimage):
return False return False
imgdate = os.stat(lastimage).st_mtime imgdate = os.stat(lastimage).st_mtime
pptdate = os.stat(self.filepath).st_mtime pptdate = os.stat(self.filepath).st_mtime
@ -233,7 +229,7 @@ class PresentationController(object):
Returns true if a presentation is loaded Returns true if a presentation is loaded
""" """
return False return False
def blank_screen(self): def blank_screen(self):
""" """
Blanks the screen, making it black. Blanks the screen, making it black.
@ -301,7 +297,7 @@ class PresentationController(object):
""" """
return None return None
def poll_slidenumber(self): def poll_slidenumber(self, is_live):
""" """
Check the current slide number Check the current slide number
""" """
@ -311,5 +307,9 @@ class PresentationController(object):
if current == self.slidenumber: if current == self.slidenumber:
return return
self.slidenumber = current self.slidenumber = current
Receiver().send_message(u'slidecontroller_change', self.slidenumber - 1) if is_live:
prefix = u'live'
else:
prefix = u'preview'
Receiver.send_message(u'%s_slidecontroller_change' % prefix,
self.slidenumber - 1)

View File

@ -46,9 +46,6 @@ class PresentationPlugin(Plugin):
""" """
return PresentationTab(self.name, self.controllers) return PresentationTab(self.name, self.controllers)
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.info(u'Presentations Initialising') log.info(u'Presentations Initialising')
Plugin.initialise(self) Plugin.initialise(self)

View File

@ -40,9 +40,6 @@ class RemotesPlugin(Plugin):
self.weight = -1 self.weight = -1
self.server = None self.server = None
def can_be_disabled(self):
return True
def initialise(self): def initialise(self):
log.debug(u'initialise') log.debug(u'initialise')
Plugin.initialise(self) Plugin.initialise(self)
@ -76,9 +73,9 @@ class RemotesPlugin(Plugin):
pos = datagram.find(u':') pos = datagram.find(u':')
event = unicode(datagram[:pos].lower()) event = unicode(datagram[:pos].lower())
if event == u'alert': if event == u'alert':
Receiver().send_message(u'alert_text', unicode(datagram[pos + 1:])) Receiver.send_message(u'alert_text', unicode(datagram[pos + 1:]))
if event == u'next_slide': if event == u'next_slide':
Receiver().send_message(u'live_slide_next') Receiver.send_message(u'live_slide_next')
def about(self): def about(self):
about_text = self.trUtf8(u'<b>Remote Plugin</b><br>This plugin ' about_text = self.trUtf8(u'<b>Remote Plugin</b><br>This plugin '

View File

@ -404,16 +404,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
log.debug(u'onPreview') log.debug(u'onPreview')
if button.text() == unicode(self.trUtf8(u'Save && Preview')) \ if button.text() == unicode(self.trUtf8(u'Save && Preview')) \
and self.saveSong(): and self.saveSong():
Receiver().send_message(u'preview_song') Receiver.send_message(u'preview_song')
def closePressed(self): def closePressed(self):
Receiver().send_message(u'remote_edit_clear') Receiver.send_message(u'remote_edit_clear')
self.close() self.close()
def accept(self): def accept(self):
log.debug(u'accept') log.debug(u'accept')
if self.saveSong(): if self.saveSong():
Receiver().send_message(u'load_song_list') Receiver.send_message(u'load_song_list')
self.close() self.close()
def saveSong(self): def saveSong(self):
@ -462,7 +462,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
text = text.replace(u'}', u'') text = text.replace(u'}', u'')
text = text.replace(u'?', u'') text = text.replace(u'?', u'')
self.song.search_lyrics = unicode(text) self.song.search_lyrics = unicode(text)
self.song.lyrics = unicode(sxml.extract_xml()) self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
except: except:
log.exception(u'Problem processing song Lyrics \n%s', log.exception(u'Problem processing song Lyrics \n%s',
sxml.dump_xml()) sxml.dump_xml())

View File

@ -287,11 +287,11 @@ class SongMediaItem(MediaManagerItem):
item_id = self.remoteSong item_id = self.remoteSong
song = self.parent.songmanager.get_song(item_id) song = self.parent.songmanager.get_song(item_id)
service_item.theme = song.theme_name service_item.theme = song.theme_name
service_item.editEnabled = True service_item.edit_enabled = True
service_item.editId = item_id service_item.editId = item_id
service_item.verse_order = song.verse_order service_item.verse_order = song.verse_order
if song.lyrics.startswith(u'<?xml version='): if song.lyrics.startswith(u'<?xml version='):
songXML=SongXMLParser(song.lyrics) songXML = SongXMLParser(song.lyrics)
verseList = songXML.get_verses() verseList = songXML.get_verses()
for verse in verseList: for verse in verseList:
if verse[1]: if verse[1]:
@ -320,4 +320,3 @@ class SongMediaItem(MediaManagerItem):
song.title, author_audit, song.copyright, song.ccli_number song.title, author_audit, song.copyright, song.ccli_number
] ]
return True return True

View File

@ -94,13 +94,10 @@ class _OpenSong(XmlRootClass):
in OpenSong an author list may be separated by '/' in OpenSong an author list may be separated by '/'
return as a string return as a string
""" """
res = []
if self.author: if self.author:
lst = self.author.split(u' and ') list = self.author.split(u' and ')
for l in lst: res = [item.strip() for item in list]
res.append(l.strip()) return u', '.join(res)
s = u', '.join(res)
return s
def get_category_array(self): def get_category_array(self):
"""Convert theme and alttheme into category_array """Convert theme and alttheme into category_array
@ -116,8 +113,8 @@ class _OpenSong(XmlRootClass):
return s return s
def _reorder_verse(self, tag, tmpVerse): def _reorder_verse(self, tag, tmpVerse):
"""Reorder the verse in case of first char is a number """
Reorder the verse in case of first char is a number
tag -- the tag of this verse / verse group tag -- the tag of this verse / verse group
tmpVerse -- list of strings tmpVerse -- list of strings
""" """
@ -147,8 +144,8 @@ class _OpenSong(XmlRootClass):
return res return res
def get_lyrics(self): def get_lyrics(self):
"""Convert the lyrics to openlp lyrics format """
Convert the lyrics to openlp lyrics format
return as list of strings return as list of strings
""" """
lyrics = self.lyrics.split(u'\n') lyrics = self.lyrics.split(u'\n')
@ -277,17 +274,22 @@ class Song(object):
self.set_lyrics(opensong.get_lyrics()) self.set_lyrics(opensong.get_lyrics())
def from_opensong_file(self, xmlfilename): def from_opensong_file(self, xmlfilename):
"""Initialize from file containing xml """
Initialize from file containing xml
xmlfilename -- path to xml file xmlfilename -- path to xml file
""" """
lst = [] osfile = None
f = open(xmlfilename, 'r') try:
for line in f: osfile = open(xmlfilename, 'r')
lst.append(line) list = [line for line in osfile]
f.close() osfile.close()
xml = "".join(lst) xml = "".join(list)
self.from_opensong_buffer(xml) self.from_opensong_buffer(xml)
except:
log.exception(u'Failed to load opensong xml file')
finally:
if osfile:
osfile.close()
def _remove_punctuation(self, title): def _remove_punctuation(self, title):
"""Remove the puntuation chars from title """Remove the puntuation chars from title
@ -380,16 +382,20 @@ class Song(object):
self.set_lyrics(lyrics) self.set_lyrics(lyrics)
def from_ccli_text_file(self, textFileName): def from_ccli_text_file(self, textFileName):
"""Create song from a list of texts read from given file """
Create song from a list of texts read from given file
textFileName -- path to text file textFileName -- path to text file
""" """
lines = [] ccli_file = None
f = open(textFileName, 'r') try:
for orgline in f: ccli_file = open(textFileName, 'r')
lines.append(orgline.rstrip()) lines = [orgline.rstrip() for orgline in ccli_file]
f.close() self.from_ccli_text_buffer(lines)
self.from_ccli_text_buffer(lines) except:
log.exception(u'Failed to load CCLI text file')
finally:
if ccli_file:
ccli_file.close()
def _assure_string(self, string_in): def _assure_string(self, string_in):
"""Force a string is returned""" """Force a string is returned"""
@ -401,13 +407,10 @@ class Song(object):
def _split_to_list(self, aString): def _split_to_list(self, aString):
"""Split a string into a list - comma separated""" """Split a string into a list - comma separated"""
res = []
if aString: if aString:
lst = aString.split(u',') list = aString.split(u',')
for l in lst: res = [item.strip() for item in list]
# remove whitespace return res
res.append(l.strip())
return res
def _list_to_string(self, strOrList): def _list_to_string(self, strOrList):
"""Force a possibly list into a string""" """Force a possibly list into a string"""
@ -419,8 +422,8 @@ class Song(object):
lst = [] lst = []
else: else:
raise SongTypeError(u'Variable not String or List') raise SongTypeError(u'Variable not String or List')
s = u', '.join(lst) string = u', '.join(lst)
return s return string
def get_copyright(self): def get_copyright(self):
"""Return copyright info string""" """Return copyright info string"""

View File

@ -57,9 +57,6 @@ class SongsPlugin(Plugin):
self.opensong_export_form = OpenSongExportForm() self.opensong_export_form = OpenSongExportForm()
self.icon = buildIcon(u':/media/media_song.png') self.icon = buildIcon(u':/media/media_song.png')
def can_be_disabled(self):
return True
def get_settings_tab(self): def get_settings_tab(self):
return SongsTab(self.name) return SongsTab(self.name)

View File

@ -111,13 +111,19 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
self.ToDateEdit.date().toString(u'ddMMyyyy')) self.ToDateEdit.date().toString(u'ddMMyyyy'))
audits = self.parent.auditmanager.get_all_audits() audits = self.parent.auditmanager.get_all_audits()
outname = os.path.join(unicode(self.FileLineEdit.text()), filename) outname = os.path.join(unicode(self.FileLineEdit.text()), filename)
file = open(outname, u'w') file = None
for audit in audits: try:
record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ file = open(outname, u'w')
(audit.auditdate,audit.audittime, audit.title, for audit in audits:
audit.copyright, audit.ccl_number , audit.authors) record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \
file.write(record) (audit.auditdate,audit.audittime, audit.title,
file.close() audit.copyright, audit.ccl_number , audit.authors)
file.write(record)
except:
log.exception(u'Failed to write out audit records')
finally:
if file:
file.close()
def summaryReport(self): def summaryReport(self):
print "summary" print "summary"

View File

@ -44,9 +44,6 @@ class SongUsagePlugin(Plugin):
self.songusagemanager = None self.songusagemanager = None
self.songusageActive = False self.songusageActive = False
def can_be_disabled(self):
return True
def add_tools_menu_item(self, tools_menu): def add_tools_menu_item(self, tools_menu):
""" """
Give the SongUsage plugin the opportunity to add items to the Give the SongUsage plugin the opportunity to add items to the

View File

@ -126,4 +126,20 @@
<file>theme_export.png</file> <file>theme_export.png</file>
<file>theme_import.png</file> <file>theme_import.png</file>
</qresource> </qresource>
<qresource prefix="pages" >
<file>page_chorus.png</file>
<file>page_bridge.png</file>
<file>page_1.png</file>
<file>page_2.png</file>
<file>page_3.png</file>
<file>page_4.png</file>
<file>page_5.png</file>
<file>page_6.png</file>
<file>page_7.png</file>
<file>page_8.png</file>
<file>page_9.png</file>
<file>page_10.png</file>
<file>page_11.png</file>
<file>page_12.png</file>
</qresource>
</RCC> </RCC>

BIN
resources/images/page_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

BIN
resources/images/page_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

BIN
resources/images/page_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
resources/images/page_4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

BIN
resources/images/page_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

BIN
resources/images/page_6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

BIN
resources/images/page_7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

BIN
resources/images/page_8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

BIN
resources/images/page_9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

View File

@ -1 +1 @@
1.9.0-656 1.9.0-675