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,30 +168,40 @@ 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]
else: #line needs splitting
pos = len(line) if metrics.width(split_text, -1) > line_width:
split_text = line #We have no spaces
if split_text.find(u' ') == -1:
#Move back 1 char at a time till it fits
while metrics.width(split_text, -1) > line_width: while metrics.width(split_text, -1) > line_width:
#Find the next space to the left split_text = split_text[:-1]
pos = line[:pos].rfind(u' ') pos = len(split_text)
#no more spaces found else:
if pos == 0: #We have spaces so split at previous one
split_text = line 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: 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)

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):
""" """

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':
@ -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,9 +653,22 @@ 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
metrics = self._getThemeMetrics()
page_length = \
(self.FontMainHeightSpinBox.value() / metrics.height() - 2) - 1
log.debug(u'Page Length area height %s, metrics %s, lines %s' %
(self.FontMainHeightSpinBox.value(), metrics.height(),
page_length))
page_length_text = unicode(self.trUtf8(u'Slide Height is %s rows'))
self.FontMainLinesPageLabel.setText(page_length_text % page_length)
#a=c
frame = self.thememanager.generateImage(self.theme)
self.ThemePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
def _getThemeMetrics(self):
main_weight = 50 main_weight = 50
if self.theme.font_main_weight == u'Bold': if self.theme.font_main_weight == u'Bold':
main_weight = 75 main_weight = 75
@ -673,13 +678,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
self.theme.font_main_italics)# italic self.theme.font_main_italics)# italic
mainFont.setPixelSize(self.theme.font_main_proportion) mainFont.setPixelSize(self.theme.font_main_proportion)
metrics = QtGui.QFontMetrics(mainFont) metrics = QtGui.QFontMetrics(mainFont)
page_length = \ #Validate that the screen width is big enough to display the text
(self.FontMainHeightSpinBox.value() / metrics.height() - 2) - 1 if self.theme.font_main_width < metrics.maxWidth() * 2 + 64:
log.debug(u'Page Length area height %s, metrics %s, lines %s' % self.theme.font_main_width = metrics.maxWidth() * 2 + 64
(self.FontMainHeightSpinBox.value(), metrics.height(), self.FontMainWidthSpinBox.setValue(self.theme.font_main_width)
page_length)) return metrics
page_length_text = unicode(self.trUtf8(u'Slide Height is %s rows'))
self.FontMainLinesPageLabel.setText(page_length_text % page_length)
frame = self.thememanager.generateImage(theme)
self.ThemePreview.setPixmap(QtGui.QPixmap.fromImage(frame))

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,14 +144,7 @@ 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)
@ -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,23 +194,27 @@ 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.displayBlank)
self.parent.generalConfig.set_config(u'Screen Blank', 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)
else: self.programaticChange = False
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
@ -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,20 +424,29 @@ 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 = None
file = None
try:
zip = zipfile.ZipFile(unicode(filename), 'w') zip = zipfile.ZipFile(unicode(filename), 'w')
for item in self.serviceItems: for item in self.serviceItems:
service.append( service.append(
{u'serviceitem':item[u'data'].get_service_repr()}) {u'serviceitem':item[u'service_item'].get_service_repr()})
if item[u'data'].service_item_type == ServiceItemType.Image or \ if item[u'service_item'].service_item_type == ServiceItemType.Image or \
item[u'data'].service_item_type == ServiceItemType.Command: item[u'service_item'].service_item_type == ServiceItemType.Command:
for frame in item[u'data'].frames: for frame in item[u'service_item'].frames:
path_from = unicode(os.path.join( path_from = unicode(os.path.join(
item[u'data'].service_item_path, frame[u'title'])) item[u'service_item'].service_item_path, frame[u'title']))
zip.write(path_from) zip.write(path_from)
file = open(servicefile, u'wb') file = open(servicefile, u'wb')
cPickle.dump(service, file) cPickle.dump(service, file)
file.close() file.close()
zip.write(servicefile) zip.write(servicefile)
except:
log.exception(u'Failed to save service to disk')
finally:
if file:
file.close()
if zip:
zip.close() zip.close()
try: try:
os.remove(servicefile) os.remove(servicefile)
@ -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')
@ -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( 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', u'Media Start', u':/slides/media_playback_start.png',
self.trUtf8(u'Start playing media'), self.onMediaPlay) self.trUtf8(u'Start playing media'), self.onMediaPlay)
self.Toolbar.addToolbarButton( self.Mediabar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png', u'Media Pause', u':/slides/media_playback_pause.png',
self.trUtf8(u'Start playing media'), self.onMediaPause) self.trUtf8(u'Start playing media'), self.onMediaPause)
self.Toolbar.addToolbarButton( self.Mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png', u'Media Stop', u':/slides/media_playback_stop.png',
self.trUtf8(u'Start playing media'), self.onMediaStop) self.trUtf8(u'Start playing media'), self.onMediaStop)
self.volumeSlider = Phonon.VolumeSlider()
self.ControllerLayout.addWidget(self.Toolbar) 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)
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(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(), rect.y(), rect.width(), rect.height()) winimg = QtGui.QPixmap.grabWindow(winid, rect.x(),
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,15 +208,21 @@ 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 = None
try:
zip = zipfile.ZipFile(themePath, u'w') zip = zipfile.ZipFile(themePath, u'w')
source = os.path.join(self.path, theme) source = os.path.join(self.path, theme)
for root, dirs, files in os.walk(source): for root, dirs, files in os.walk(source):
for name in files: for name in files:
zip.write( zip.write(
os.path.join(source, name), os.path.join(theme, name)) os.path.join(source, name), os.path.join(theme, name))
except:
log.exception(u'Export Theme Failed')
finally:
if zip:
zip.close() zip.close()
def onImportTheme(self): def onImportTheme(self):
@ -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,14 +294,10 @@ 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)
except:
QtGui.QMessageBox.critical(
self, self.trUtf8(u'Error'),
self.trUtf8(u'File is not a valid theme!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
return
filexml = None filexml = None
themename = None themename = None
for file in zip.namelist(): for file in zip.namelist():
@ -327,12 +322,21 @@ class ThemeManager(QtGui.QWidget):
filexml = xml_data filexml = xml_data
outfile = open(fullpath, u'w') outfile = open(fullpath, u'w')
outfile.write(filexml) outfile.write(filexml)
outfile.close()
else: else:
outfile = open(fullpath, u'w') outfile = open(fullpath, u'w')
outfile.write(zip.read(file)) outfile.write(zip.read(file))
outfile.close()
self.generateAndSaveImage(dir, themename, filexml) self.generateAndSaveImage(dir, themename, filexml)
except:
QtGui.QMessageBox.critical(
self, self.trUtf8(u'Error'),
self.trUtf8(u'File is not a valid theme!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
log.exception(u'Importing theme from zip file failed')
finally:
if zip:
zip.close()
if outfile:
outfile.close()
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 = None
try:
outfile = open(theme_file, u'w') outfile = open(theme_file, u'w')
outfile.write(theme_pretty_xml) outfile.write(theme_pretty_xml)
except:
log.exception(u'Saving theme to file failed')
finally:
if outfile:
outfile.close() 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
try:
shutil.copyfile(image_from, image_to) 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):
try:
if not os.path.isfile(self.file_name): if not os.path.isfile(self.file_name):
return False return False
file_handle = None
try:
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,9 +48,9 @@ class BibleCSVImpl(BibleCommon):
def load_data(self, booksfile, versesfile, dialogobject): def load_data(self, booksfile, versesfile, dialogobject):
#Populate the Tables #Populate the Tables
fbooks = None
try:
fbooks = open(booksfile, 'r') fbooks = open(booksfile, 'r')
fverse = open(versesfile, 'r')
count = 0 count = 0
for line in fbooks: for line in fbooks:
# cancel pressed # cancel pressed
@ -66,9 +66,17 @@ class BibleCSVImpl(BibleCommon):
count += 1 count += 1
#Flush the screen events #Flush the screen events
if count % 3 == 0: if count % 3 == 0:
Receiver().send_message(u'process_events') Receiver.send_message(u'process_events')
count = 0 count = 0
except:
log.exception(u'Loading books from file failed')
finally:
if fbooks:
fbooks.close()
fverse = None
try:
fverse = open(versesfile, 'r')
count = 0 count = 0
book_ptr = None book_ptr = None
for line in fverse: for line in fverse:
@ -89,5 +97,10 @@ class BibleCSVImpl(BibleCommon):
count += 1 count += 1
#Every x verses repaint the screen #Every x verses repaint the screen
if count % 3 == 0: if count % 3 == 0:
Receiver().send_message(u'process_events') Receiver.send_message(u'process_events')
count = 0 count = 0
except:
log.exception(u'Loading verses from file failed')
finally:
if fverse:
fverse.close()

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 = None
try:
fbibles = open(filepath, u'r') fbibles = open(filepath, u'r')
for line in fbibles: for line in fbibles:
p = line.split(u',') p = line.split(u',')
self.booksOfBible[p[0]] = p[1].replace(u'\n', u'') self.booksOfBible[p[0]] = p[1].replace(u'\n', u'')
self.abbrevOfBible[p[0]] = p[2].replace(u'\n', u'') self.abbrevOfBible[p[0]] = p[2].replace(u'\n', u'')
self.loadbible = True self.loadbible = True
QtCore.QObject.connect(Receiver().get_receiver(), 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,9 +94,18 @@ 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 = None
try:
detect_file = open(osisfile_record, u'r') detect_file = open(osisfile_record, u'r')
details = chardet.detect(detect_file.read(2048)) details = chardet.detect(detect_file.read(2048))
except:
log.exception(u'Failed to detect OSIS file encoding')
return
finally:
if detect_file:
detect_file.close() detect_file.close()
osis = None
try:
osis = codecs.open(osisfile_record, u'r', details['encoding']) osis = codecs.open(osisfile_record, u'r', details['encoding'])
book_ptr = None book_ptr = None
count = 0 count = 0
@ -113,7 +130,8 @@ class BibleOSISImpl():
#remove tags of extra information #remove tags of extra information
text = self.remove_block(u'<title', u'</title>', text) text = self.remove_block(u'<title', u'</title>', text)
text = self.remove_block(u'<note', u'</note>', text) text = self.remove_block(u'<note', u'</note>', text)
text = self.remove_block(u'<divineName', u'</divineName>', text) text = self.remove_block(
u'<divineName', u'</divineName>', text)
text = self.remove_tag(u'<lb', text) text = self.remove_tag(u'<lb', text)
text = self.remove_tag(u'<q', text) text = self.remove_tag(u'<q', text)
text = self.remove_tag(u'<l', text) text = self.remove_tag(u'<l', text)
@ -139,7 +157,8 @@ class BibleOSISImpl():
if book_ptr != p[0]: if book_ptr != p[0]:
# first time through # first time through
if book_ptr is None: if book_ptr is None:
# set the max book size depending on the first book read # set the max book size depending
# on the first book read
if p[0] == u'Gen': if p[0] == u'Gen':
dialogobject.setMax(65) dialogobject.setMax(65)
else: else:
@ -154,14 +173,19 @@ class BibleOSISImpl():
testament) testament)
dialogobject.incrementProgressBar( dialogobject.incrementProgressBar(
self.booksOfBible[p[0]]) self.booksOfBible[p[0]])
Receiver().send_message(u'process_events') Receiver.send_message(u'process_events')
count = 0 count = 0
self.bibledb.add_verse(book.id, p[1], p[2], text) self.bibledb.add_verse(book.id, p[1], p[2], text)
count += 1 count += 1
#Every 3 verses repaint the screen #Every 3 verses repaint the screen
if count % 3 == 0: if count % 3 == 0:
Receiver().send_message(u'process_events') Receiver.send_message(u'process_events')
count = 0 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

@ -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 = None
try:
fbibles = open(filepath, u'r') fbibles = open(filepath, u'r')
for line in fbibles: for line in fbibles:
p = line.split(u',') p = line.split(u',')
self.book_abbreviations[p[0]] = p[1].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_testaments[p[0]] = p[2].replace(u'\n', '')
self.book_chapters.append({u'book':p[0], u'total':p[3].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,7 +155,6 @@ 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)

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)
if self.is_live:
self.controller.start_presentation() 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():
@ -85,52 +91,66 @@ class MessageListener(object):
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():
@ -138,6 +158,8 @@ class MessageListener(object):
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()
@ -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

@ -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):
""" """
@ -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
@ -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,7 +287,7 @@ 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='):
@ -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,12 +407,9 @@ 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
res.append(l.strip())
return res return res
def _list_to_string(self, strOrList): def _list_to_string(self, strOrList):
@ -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,12 +111,18 @@ 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 = None
try:
file = open(outname, u'w') file = open(outname, u'w')
for audit in audits: for audit in audits:
record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \
(audit.auditdate,audit.audittime, audit.title, (audit.auditdate,audit.audittime, audit.title,
audit.copyright, audit.ccl_number , audit.authors) audit.copyright, audit.ccl_number , audit.authors)
file.write(record) file.write(record)
except:
log.exception(u'Failed to write out audit records')
finally:
if file:
file.close() file.close()
def summaryReport(self): def summaryReport(self):

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