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
filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(filepath, u'version.txt'))
fversion = None
try:
fversion = open(filepath, 'r')
for line in fversion:
bits = unicode(line).split(u'-')
applicationVersion = {u'Full':unicode(line).rstrip(),
u'version':bits[0], u'build':bits[1]}
log.info(u'Openlp version %s build %s' %
(applicationVersion[u'version'],applicationVersion[u'build'] ))
except:
applicationVersion = {u'Full':u'1.9.0-000',
u'version':u'1.9.0', u'build':u'000'}
finally:
if fversion:
fversion.close()
#set the default string encoding
try:
sys.setappdefaultencoding(u'utf-8')
@ -127,24 +133,40 @@ def main():
# Set up command line options.
usage = u'Usage: %prog [options] [qt-options]'
parser = OptionParser(usage=usage)
parser.add_option("-d", "--debug", dest="debug",
action="store_true", help="set logging to DEBUG level")
parser.add_option("-l", "--log-level", dest="loglevel",
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
filename = u'openlp.log'
logfile = RotatingFileHandler(filename, maxBytes=200000, backupCount=5)
logfile.setFormatter(logging.Formatter(
u'%(asctime)s %(name)-15s %(levelname)-8s %(message)s'))
log.addHandler(logfile)
logging.addLevelName(15, u'Timer')
# Parse command line options and deal with them.
(options, args) = parser.parse_args()
if options.debug:
qt_args = []
if options.loglevel.lower() in ['d', 'debug']:
log.setLevel(logging.DEBUG)
elif options.loglevel.lower() in ['w', 'warning']:
log.setLevel(logging.WARNING)
else:
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
qInitResources()
# Now create and actually run the application.
app = OpenLP(sys.argv)
app = OpenLP(qt_args)
sys.exit(app.run())
if __name__ == u'__main__':

View File

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

View File

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

View File

@ -139,14 +139,6 @@ class Plugin(QtCore.QObject):
"""
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):
"""
Sets the status of the plugin

View File

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

View File

@ -168,35 +168,45 @@ class Renderer(object):
line_width = self._rect.width() - self._right_margin
#number of lines on a page - adjust for rounding up.
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 = 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' %
(int(self._rect.height()), metrics.height(), page_length ))
split_pages = []
page = []
split_lines = []
count = 0
for line in text:
#Must be a blank line so keep it.
if len(line) == 0:
line = u' '
while len(line) > 0:
if len(line) > ave_line_width:
pos = line.find(u' ', ave_line_width)
split_text = line[:pos]
else:
pos = len(line)
split_text = line
while metrics.width(split_text, -1) > line_width:
#Find the next space to the left
pos = line[:pos].rfind(u' ')
#no more spaces found
if pos == 0:
split_text = line
pos = char_per_line
split_text = line[:pos]
#line needs splitting
if metrics.width(split_text, -1) > line_width:
#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:
split_text = split_text[:-1]
pos = len(split_text)
pos = len(split_text)
else:
split_text = line[:pos]
#We have spaces so split at previous one
while metrics.width(split_text, -1) > line_width:
pos = split_text.rfind(u' ')
#no more spaces and we are still too long
if pos == -1:
while metrics.width(split_text, -1) > line_width:
split_text = split_text[:-1]
pos = len(split_text)
else:
split_text = line[:pos]
split_lines.append(split_text)
line = line[pos:].lstrip()
#if we have more text add up to 10 spaces on the front.
@ -450,32 +460,32 @@ class Renderer(object):
draw=True, color = self._theme.display_shadow_color)
if self._theme.display_outline:
self._get_extent_and_render(line, footer,
(x+self._outline_offset, y), draw=True,
(x + self._outline_offset, y), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x, y+self._outline_offset), draw=True,
(x, y + self._outline_offset), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x, y-self._outline_offset), draw=True,
(x, y - self._outline_offset), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x-self._outline_offset, y), draw=True,
(x - self._outline_offset, y), draw=True,
color = self._theme.display_outline_color)
if self._outline_offset > 1:
self._get_extent_and_render(line, footer,
(x+self._outline_offset, y+self._outline_offset),
(x + self._outline_offset, y + self._outline_offset),
draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x-self._outline_offset, y+self._outline_offset),
(x - self._outline_offset, y + self._outline_offset),
draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x+self._outline_offset, y-self._outline_offset),
(x + self._outline_offset, y - self._outline_offset),
draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,
(x-self._outline_offset, y-self._outline_offset),
(x - self._outline_offset, y - self._outline_offset),
draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,tlcorner=(x, y),

View File

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

View File

@ -29,7 +29,7 @@ import uuid
from PyQt4 import QtGui
from openlp.core.lib import buildIcon
from openlp.core.lib import buildIcon, Receiver
class ServiceItemType(object):
"""
@ -38,7 +38,6 @@ class ServiceItemType(object):
Text = 1
Image = 2
Command = 3
Video = 4
class ServiceItem(object):
"""
@ -50,31 +49,28 @@ class ServiceItem(object):
log = logging.getLogger(u'ServiceItem')
log.info(u'Service Item created')
def __init__(self, hostplugin=None):
def __init__(self, plugin=None):
"""
Set up the service item.
``hostplugin``
``plugin``
The plugin that this service item belongs to.
"""
self.plugin = hostplugin
if hostplugin:
self.RenderManager = self.plugin.render_manager
self.shortname = hostplugin.name
self.name = self.plugin.name
if plugin:
self.RenderManager = plugin.render_manager
self.name = plugin.name
self.title = u''
self.audit = u''
self.items = []
self.iconic_representation = None
self.raw_slides = None
self.frames = []
self.raw_footer = None
self.theme = None
self.service_item_path = None
self.service_item_type = None
self.editEnabled = False
self.service_frames = []
self.uuid = unicode(uuid.uuid1())
self.edit_enabled = False
self._raw_frames = []
self._display_frames = []
self._uuid = unicode(uuid.uuid1())
def addIcon(self, icon):
"""
@ -93,32 +89,27 @@ class ServiceItem(object):
The render method is what generates the frames for the screen.
"""
log.debug(u'Render called')
self.frames = []
self._display_frames = []
if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides')
if self.theme is None:
self.RenderManager.set_override_theme(None)
else:
self.RenderManager.set_override_theme(self.theme)
for slide in self.service_frames:
for slide in self._raw_frames:
before = time.time()
formated = self.RenderManager.format_slide(slide[u'raw_slide'])
for format in formated:
frame = None
lines = u''
for line in format:
lines += line + u'\n'
title = lines.split(u'\n')[0]
self.frames.append({u'title': title, u'text': lines,
u'image': frame})
log.info(u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Command:
self.frames = self.service_frames
self._display_frames.append({u'title': title, u'text': lines})
log.log(15, u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Image:
for slide in self.service_frames:
for slide in self._raw_frames:
slide[u'image'] = \
self.RenderManager.resize_image(slide[u'image'])
self.frames = self.service_frames
else:
log.error(u'Invalid value renderer :%s' % self.service_item_type)
@ -133,19 +124,19 @@ class ServiceItem(object):
self.RenderManager.set_override_theme(None)
else:
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,
self.raw_footer)
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.
``path``
The directory in which the image file is located.
``frame_title``
``title``
A title for the slide in the service item.
``image``
@ -153,16 +144,10 @@ class ServiceItem(object):
"""
self.service_item_type = ServiceItemType.Image
self.service_item_path = path
self.service_frames.append(
{u'title': frame_title, u'text': None, u'image': image})
self._raw_frames.append(
{u'title': title, u'image': image})
def add_from_media(self, path, frame_title, image):
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):
def add_from_text(self, title, raw_slide):
"""
Add a text slide to the service item.
@ -173,24 +158,27 @@ class ServiceItem(object):
The raw text of the slide.
"""
self.service_item_type = ServiceItemType.Text
frame_title = frame_title.split(u'\n')[0]
self.service_frames.append(
{u'title': frame_title, u'raw_slide': raw_slide})
title = title.split(u'\n')[0]
self._raw_frames.append(
{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.
``frame_title``
``path``
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.
"""
self.service_item_type = ServiceItemType.Command
self.service_item_path = path
self.service_frames.append(
{u'title': frame_title, u'command': None, u'text':None, u'image': image})
self._raw_frames.append(
{u'title': file_name, u'image': image})
def get_service_repr(self):
"""
@ -199,7 +187,7 @@ class ServiceItem(object):
"""
service_header = {
u'name': self.name.lower(),
u'plugin': self.shortname,
u'plugin': self.name,
u'theme':self.theme,
u'title':self.title,
u'icon':self.icon,
@ -209,17 +197,14 @@ class ServiceItem(object):
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
for slide in self.service_frames:
for slide in self._raw_frames:
service_data.append(slide)
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'])
elif self.service_item_type == ServiceItemType.Command:
for slide in self.service_frames:
service_data.append(slide[u'title'])
elif self.service_item_type == ServiceItemType.Video:
for slide in self.service_frames:
service_data.append(slide[u'title'])
for slide in self._raw_frames:
service_data.append({u'title':slide[u'title'], u'image':slide[u'image']})
return {u'header': service_header, u'data': service_data}
def set_from_service(self, serviceitem, path=None):
@ -244,7 +229,7 @@ class ServiceItem(object):
self.audit = header[u'audit']
if self.service_item_type == ServiceItemType.Text:
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:
for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image)
@ -252,7 +237,68 @@ class ServiceItem(object):
self.add_from_image(path, text_image, real_image)
elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image)
self.add_from_command(path, text_image)
elif self.service_item_type == ServiceItemType.Video:
pass
filename = os.path.join(path, text_image[u'title'])
self.add_from_command(path, text_image[u'title'], text_image[u'image'] )
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:
self.mainwindow_left = mainwindow_docbars
self.mainwindow_right = mainwindow_docbars
self.slidecontroller = (self.width - (
self.mainwindow_left + self.mainwindow_right) - 100 ) / 2
self.slidecontroller_image = self.slidecontroller - 50
@ -60,7 +59,7 @@ class SettingsManager(object):
u'user interface', u'display previewpanel', True))
def setUIItemVisibility(self, item=u'', isVisible=True):
if item != u'':
if item:
if item == u'ThemeManagerDock':
ConfigHelper.set_config(u'user interface',
u'display thememanager', isVisible)

View File

@ -134,7 +134,8 @@ class SongXMLParser(object):
The XML of the song to be parsed.
"""
try:
self.song_xml = ElementTree(element=XML(xml))
self.song_xml = ElementTree(
element=XML(unicode(xml).encode('unicode-escape')))
except:
log.exception(u'Invalid xml %s', xml)
@ -147,7 +148,8 @@ class SongXMLParser(object):
verse_list = []
for element in iter:
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
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
blankthemexml=\
'''<?xml version="1.0" encoding="iso-8859-1"?>
'''<?xml version="1.0" encoding="utf-8"?>
<theme version="1.0">
<name>BlankStyle</name>
<background mode="transparent"/>
@ -348,6 +348,7 @@ class ThemeXML(object):
iter = theme_xml.getiterator()
master = u''
for element in iter:
element.text = unicode(element.text).decode('unicode-escape')
if len(element.getchildren()) > 0:
master = element.tag + u'_'
else:

View File

@ -46,7 +46,7 @@ class OpenLPToolbar(QtGui.QToolBar):
self.log.debug(u'Init done')
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.
@ -69,14 +69,19 @@ class OpenLPToolbar(QtGui.QToolBar):
"""
ButtonIcon = buildIcon(icon)
if ButtonIcon:
if slot:
if slot and not checkable:
ToolbarButton = self.addAction(ButtonIcon, title, slot)
else:
ToolbarButton = self.addAction(ButtonIcon, title)
if tooltip:
ToolbarButton.setToolTip(tooltip)
if checkable:
ToolbarButton.setCheckable(True)
QtCore.QObject.connect(ToolbarButton,
QtCore.SIGNAL(u'toggled(bool)'), slot)
self.icons[title] = ButtonIcon
self.actions[title] = ToolbarButton
return ToolbarButton
def addToolbarSeparator(self, handle):
"""

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
@ -24,10 +23,12 @@
import logging
import time
import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, ServiceItemType, \
str_to_bool, PluginConfig
from PyQt4.phonon import Phonon
from openlp.core.lib import OpenLPToolbar, Receiver, str_to_bool, PluginConfig
class SlideList(QtGui.QTableWidget):
"""
@ -80,18 +81,13 @@ class SlideController(QtGui.QWidget):
u'Loop Separator',
u'Image SpinBox'
]
self.media_list = [
u'Media Start',
u'Media Stop',
u'Media Pause'
]
self.song_list = [
self.song_edit_list = [
u'Edit Song',
]
self.timer_id = 0
self.commandItem = None
self.songEdit = False
self.row = 0
self.selectedRow = 0
self.serviceItem = None
self.Panel = QtGui.QWidget(parent.ControlSplitter)
# Layout for holding panel
self.PanelLayout = QtGui.QVBoxLayout(self.Panel)
@ -102,14 +98,19 @@ class SlideController(QtGui.QWidget):
if self.isLive:
self.TypeLabel.setText(u'<strong>%s</strong>' %
self.trUtf8(u'Live'))
self.split = 1
prefix = u'live_slidecontroller'
else:
self.TypeLabel.setText(u'<strong>%s</strong>' %
self.trUtf8(u'Preview'))
self.split = 0
prefix = u'preview_slidecontroller'
self.TypeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.PanelLayout.addWidget(self.TypeLabel)
# Splitter
self.Splitter = QtGui.QSplitter(self.Panel)
self.Splitter.setOrientation(QtCore.Qt.Vertical)
self.Splitter.setOpaqueResize(False)
self.PanelLayout.addWidget(self.Splitter)
# Actual controller section
self.Controller = QtGui.QWidget(self.Splitter)
@ -130,6 +131,7 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.setObjectName(u'PreviewListWidget')
self.PreviewListWidget.setEditTriggers(
QtGui.QAbstractItemView.NoEditTriggers)
self.PreviewListWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.ControllerLayout.addWidget(self.PreviewListWidget)
# Build the full toolbar
self.Toolbar = OpenLPToolbar(self)
@ -156,8 +158,11 @@ class SlideController(QtGui.QWidget):
self.trUtf8(u'Move to last'), self.onSlideSelectedLast)
if self.isLive:
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.blackPushButton = self.Toolbar.addPushButton(
u':/slides/slide_close.png')
self.blankButton = self.Toolbar.addToolbarButton(
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:
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.Toolbar.addToolbarButton(
@ -180,31 +185,38 @@ class SlideController(QtGui.QWidget):
u'Image SpinBox', self.DelaySpinBox)
self.DelaySpinBox.setSuffix(self.trUtf8(u's'))
self.DelaySpinBox.setToolTip(self.trUtf8(u'Delay between slides in seconds'))
self.Toolbar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
self.trUtf8(u'Start playing media'), self.onMediaPlay)
self.Toolbar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
self.trUtf8(u'Start playing media'), self.onMediaPause)
self.Toolbar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
self.trUtf8(u'Start playing media'), self.onMediaStop)
self.ControllerLayout.addWidget(self.Toolbar)
#Build a Media ToolBar
self.Mediabar = OpenLPToolbar(self)
self.Mediabar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
self.trUtf8(u'Start playing media'), self.onMediaPlay)
self.Mediabar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
self.trUtf8(u'Start playing media'), self.onMediaPause)
self.Mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
self.trUtf8(u'Start playing media'), self.onMediaStop)
self.volumeSlider = Phonon.VolumeSlider()
self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
self.volumeSlider.setObjectName(u'volumeSlider')
self.Mediabar.addToolbarWidget(
u'Audio Volume', self.volumeSlider)
self.ControllerLayout.addWidget(self.Mediabar)
# Build the Song Toolbar
if isLive:
self.Songbar = OpenLPToolbar(self)
self.Songbar.addToolbarButton(
u'Bridge', u':/slides/slide_close.png',
u'Bridge', u':/pages/page_bridge.png',
self.trUtf8(u'Bridge'),
self.onSongBarHandler)
self.Songbar.addToolbarButton(
u'Chorus', u':/slides/slide_close.png',
u'Chorus', u':/pages/page_chorus.png',
self.trUtf8(u'Chorus'),
self.onSongBarHandler)
for verse in range(1, 20):
for verse in range(1, 12):
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,
self.onSongBarHandler)
self.ControllerLayout.addWidget(self.Songbar)
@ -213,15 +225,26 @@ class SlideController(QtGui.QWidget):
self.PreviewFrame = QtGui.QFrame(self.Splitter)
self.PreviewFrame.setGeometry(QtCore.QRect(0, 0, 300, 225))
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.setFrameShadow(QtGui.QFrame.Sunken)
self.PreviewFrame.setObjectName(u'PreviewFrame')
self.grid = QtGui.QGridLayout(self.PreviewFrame)
self.grid.setMargin(8)
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
self.SlidePreview = QtGui.QLabel(self.parent)
self.SlidePreview = QtGui.QLabel(self)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@ -236,33 +259,54 @@ class SlideController(QtGui.QWidget):
self.SlidePreview.setLineWidth(1)
self.SlidePreview.setScaledContents(True)
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
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'activated(QModelIndex)'), self.onSlideSelected)
if isLive:
QtCore.QObject.connect(self.blackPushButton,
QtCore.SIGNAL(u'clicked(bool)'), self.onBlankScreen)
#QtCore.QObject.connect(self.blackPushButton,
# QtCore.SIGNAL(u'clicked(bool)'), self.onBlankScreen)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_spin_delay'), self.receiveSpinDelay)
Receiver().send_message(u'request_spin_delay')
Receiver.send_message(u'request_spin_delay')
if isLive:
self.Toolbar.makeWidgetsInvisible(self.image_list)
self.Toolbar.makeWidgetsInvisible(self.media_list)
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.SIGNAL(u'slidecontroller_first'), self.onSlideSelectedFirst)
QtCore.SIGNAL(u'%s_first' % prefix), self.onSlideSelectedFirst)
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.SIGNAL(u'slidecontroller_previous'), self.onSlideSelectedPrevious)
QtCore.SIGNAL(u'%s_previous' % prefix), self.onSlideSelectedPrevious)
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.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):
request = self.sender().text()
@ -296,92 +340,91 @@ class SlideController(QtGui.QWidget):
"""
Allows the live toolbar to be customised
"""
self.Toolbar.setVisible(True)
self.Songbar.setVisible(False)
self.Mediabar.setVisible(False)
self.Toolbar.makeWidgetsInvisible(self.image_list)
self.Toolbar.makeWidgetsInvisible(self.media_list)
if item.service_item_type == ServiceItemType.Text:
if item.is_text():
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)):
for action in self.Songbar.actions:
self.Songbar.actions[action].setVisible(False)
if item.verse_order:
verses = item.verse_order.split(u' ')
for verse in verses:
if not verse or int(verse) > 12:
break
try:
self.Songbar.actions[verse].setVisible(True)
except:
#More than 20 verses hard luck
pass
self.Songbar.setVisible(True)
elif item.service_item_type == ServiceItemType.Image:
elif item.is_image():
#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)
elif item.service_item_type == ServiceItemType.Command and \
item.name == u'Media':
self.Toolbar.makeWidgetsVisible(self.media_list)
elif item.is_media():
self.Toolbar.setVisible(False)
self.Mediabar.setVisible(True)
self.volumeSlider.setAudioOutput(self.parent.mainDisplay.audio)
def enablePreviewToolBar(self, item):
"""
Allows the Preview toolbar to be customised
"""
if (item.name == u'Songs' or item.name == u'Custom') and item.fromPlugin:
self.Toolbar.makeWidgetsVisible(self.song_list)
else:
self.Toolbar.makeWidgetsInvisible(self.song_list)
self.Toolbar.setVisible(True)
self.Mediabar.setVisible(False)
self.Toolbar.makeWidgetsInvisible(self.song_edit_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):
"""
Method to install the service item into the controller and
request the correct the toolbar of the plugin
Method to install the service item into the controller
Called by plugins
"""
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()
item.render()
log.info(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']])
log.log(15, u'Rendering took %4s' % (time.time() - before))
slideno = 0
if self.songEdit:
slideno = self.row
slideno = self.selectedRow
self.songEdit = False
self.displayServiceManagerItems(item, slideno)
self.addServiceManagerItem(item, slideno)
def replaceServiceManagerItem(self, item):
"""
Replacement item following a remote edit
"""
if self.commandItem and \
item.uuid == self.commandItem.uuid:
if item.__eq__(self.serviceItem):
self.addServiceManagerItem(item, self.PreviewListWidget.currentRow())
def addServiceManagerItem(self, item, slideno):
"""
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
"""
log.debug(u'addServiceManagerItem')
#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
if self.serviceItem and self.serviceItem.is_command():
self.onMediaStop()
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])
if item.is_command():
if self.isLive:
Receiver.send_message(u'%s_start' % item.name.lower(), \
[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)
def displayServiceManagerItems(self, serviceitem, slideno):
@ -390,33 +433,34 @@ class SlideController(QtGui.QWidget):
Display the slide number passed
"""
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()
self.serviceitem = serviceitem
self.serviceItem = serviceitem
self.PreviewListWidget.clear()
self.PreviewListWidget.setRowCount(0)
self.PreviewListWidget.setColumnWidth(
0, self.settingsmanager.slidecontroller_image)
for framenumber, frame in enumerate(self.serviceitem.frames):
self.PreviewListWidget.setColumnWidth(0, width)
for framenumber, frame in enumerate(self.serviceItem.get_frames()):
self.PreviewListWidget.setRowCount(
self.PreviewListWidget.rowCount() + 1)
item = QtGui.QTableWidgetItem()
slide_height = 0
#It is a Image
if frame[u'text'] is None:
if not self.serviceItem.is_text():
label = QtGui.QLabel()
label.setMargin(4)
pixmap = self.parent.RenderManager.resize_image(frame[u'image'])
label.setScaledContents(True)
label.setPixmap(QtGui.QPixmap.fromImage(pixmap))
self.PreviewListWidget.setCellWidget(framenumber, 0, label)
slide_height = self.settingsmanager.slidecontroller_image * \
self.parent.RenderManager.screen_ratio
slide_height = width * self.parent.RenderManager.screen_ratio
else:
item.setText(frame[u'text'])
self.PreviewListWidget.setItem(framenumber, 0, item)
if slide_height != 0:
self.PreviewListWidget.setRowHeight(framenumber, slide_height)
if self.serviceitem.frames[0][u'text']:
if self.serviceItem.is_text():
self.PreviewListWidget.resizeRowsToContents()
self.PreviewListWidget.setColumnWidth(
0, self.PreviewListWidget.viewport().size().width())
@ -426,9 +470,9 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.selectRow(slideno)
self.onSlideSelected()
self.PreviewListWidget.setFocus()
log.info(u'Display Rendering took %4s' % (time.time() - before))
if self.serviceitem.audit != u'' and self.isLive:
Receiver().send_message(u'songusage_live', self.serviceitem.audit)
log.log(15, u'Display Rendering took %4s' % (time.time() - before))
if self.isLive:
self.serviceItem.request_audit()
log.debug(u'displayServiceManagerItems End')
#Screen event methods
@ -436,26 +480,27 @@ class SlideController(QtGui.QWidget):
"""
Go to the first slide.
"""
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_first'% self.commandItem.name.lower())
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
if self.serviceItem.is_command():
Receiver.send_message(u'%s_first'% self.serviceItem.name.lower())
self.updatePreview()
else:
self.PreviewListWidget.selectRow(0)
self.onSlideSelected()
def onBlankDisplay(self):
self.blankButton.setChecked(self.parent.mainDisplay.displayBlank)
def onBlankScreen(self, blanked):
"""
Blank the screen.
"""
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
if self.serviceItem and self.serviceItem.is_command():
if blanked:
Receiver().send_message(u'%s_blank'% self.commandItem.name.lower())
Receiver.send_message(u'%s_blank'% self.serviceItem.name.lower())
else:
Receiver().send_message(u'%s_unblank'% self.commandItem.name.lower())
Receiver.send_message(u'%s_unblank'% self.serviceItem.name.lower())
else:
self.parent.mainDisplay.blankDisplay()
self.parent.mainDisplay.blankDisplay(blanked)
def onSlideSelected(self):
"""
@ -463,49 +508,54 @@ class SlideController(QtGui.QWidget):
if this is the Live Controller also display on the screen
"""
row = self.PreviewListWidget.currentRow()
self.row = 0
self.selectedRow = 0
if row > -1 and row < self.PreviewListWidget.rowCount():
if self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_slide'% self.commandItem.name.lower(), [row])
if self.serviceItem.is_command():
Receiver.send_message(u'%s_slide'% self.serviceItem.name.lower(), [row])
if self.isLive:
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
self.updatePreview()
else:
frame = self.serviceitem.frames[row][u'image']
before = time.time()
if frame is None:
frame = self.serviceitem.render_individual(row)
frame = self.serviceItem.get_rendered_frame(row)
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:
self.parent.mainDisplay.frameView(frame)
self.row = row
self.selectedRow = row
def onSlideChange(self, row):
"""
The slide has been changed. Update the slidecontroller accordingly
"""
self.PreviewListWidget.selectRow(row)
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
self.updatePreview()
def updatePreview(self):
rm = self.parent.RenderManager
if not rm.screen_list[rm.current_display][u'primary']:
# Grab now, but try again in a couple of seconds if slide change is slow
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
else:
label = self.PreviewListWidget.cellWidget(
self.PreviewListWidget.currentRow(), 0)
self.SlidePreview.setPixmap(label.pixmap())
def grabMainDisplay(self):
rm = self.parent.RenderManager
if not rm.screen_list[rm.current_display][u'primary']:
winid = QtGui.QApplication.desktop().winId()
rect = rm.screen_list[rm.current_display][u'size']
winimg = QtGui.QPixmap.grabWindow(winid, rect.x(), rect.y(), rect.width(), rect.height())
self.SlidePreview.setPixmap(winimg)
else:
label = self.PreviewListWidget.cellWidget(self.PreviewListWidget.currentRow(), 0)
self.SlidePreview.setPixmap(label.pixmap())
winid = QtGui.QApplication.desktop().winId()
rect = rm.screen_list[rm.current_display][u'size']
winimg = QtGui.QPixmap.grabWindow(winid, rect.x(),
rect.y(), rect.width(), rect.height())
self.SlidePreview.setPixmap(winimg)
def onSlideSelectedNext(self):
"""
Go to the next slide.
"""
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_next'% self.commandItem.name.lower())
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
if self.serviceItem.is_command():
Receiver.send_message(u'%s_next'% self.serviceItem.name.lower())
self.updatePreview()
else:
row = self.PreviewListWidget.currentRow() + 1
if row == self.PreviewListWidget.rowCount():
@ -517,11 +567,10 @@ class SlideController(QtGui.QWidget):
"""
Go to the previous slide.
"""
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(
u'%s_previous'% self.commandItem.name.lower())
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
if self.serviceItem.is_command():
Receiver.send_message(
u'%s_previous'% self.serviceItem.name.lower())
self.updatePreview()
else:
row = self.PreviewListWidget.currentRow() - 1
if row == -1:
@ -533,10 +582,9 @@ class SlideController(QtGui.QWidget):
"""
Go to the last slide.
"""
if self.commandItem and \
self.commandItem.service_item_type == ServiceItemType.Command:
Receiver().send_message(u'%s_last'% self.commandItem.name.lower())
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
if self.serviceItem.is_command():
Receiver.send_message(u'%s_last'% self.serviceItem.name.lower())
self.updatePreview()
else:
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1)
self.onSlideSelected()
@ -564,8 +612,8 @@ class SlideController(QtGui.QWidget):
def onEditSong(self):
self.songEdit = True
Receiver().send_message(u'%s_edit' % self.commandItem.name, u'P:%s' %
self.commandItem.editId )
Receiver.send_message(u'%s_edit' % self.serviceItem.name, u'P:%s' %
self.serviceItem.editId )
def onGoLive(self):
"""
@ -574,13 +622,34 @@ class SlideController(QtGui.QWidget):
row = self.PreviewListWidget.currentRow()
if row > -1 and row < self.PreviewListWidget.rowCount():
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):
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):
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):
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.theme import Theme
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
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'))
self.ThemeListWidget.item(count).setText(name)
self.config.set_config(u'theme global theme', self.global_theme)
Receiver().send_message(
Receiver.send_message(
u'update_global_theme', self.global_theme)
self.pushThemes()
def onAddTheme(self):
self.amendThemeForm.loadTheme(None)
theme = self.createThemeFromXml(self.baseTheme(), self.path)
self.amendThemeForm.loadTheme(theme)
self.saveThemeName = u''
self.amendThemeForm.exec_()
def onEditTheme(self):
item = self.ThemeListWidget.currentItem()
if item:
self.amendThemeForm.loadTheme(
theme = self.getThemeData(
unicode(item.data(QtCore.Qt.UserRole).toString()))
self.amendThemeForm.loadTheme(theme)
self.saveThemeName = unicode(
item.data(QtCore.Qt.UserRole).toString())
self.amendThemeForm.exec_()
@ -182,10 +184,6 @@ class ThemeManager(QtGui.QWidget):
self.ThemeListWidget.takeItem(row)
try:
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))
except:
#if not present do not worry
@ -210,16 +208,22 @@ class ThemeManager(QtGui.QWidget):
unicode(self.trUtf8(u'Save Theme - (%s)')) % theme,
self.config.get_last_dir(1) )
path = unicode(path)
if path != u'':
if path:
self.config.set_last_dir(path, 1)
themePath = os.path.join(path, theme + u'.theme')
zip = zipfile.ZipFile(themePath, u'w')
source = os.path.join(self.path, theme)
for root, dirs, files in os.walk(source):
for name in files:
zip.write(
os.path.join(source, name), os.path.join(theme, name))
zip.close()
zip = None
try:
zip = zipfile.ZipFile(themePath, u'w')
source = os.path.join(self.path, theme)
for root, dirs, files in os.walk(source):
for name in files:
zip.write(
os.path.join(source, name), os.path.join(theme, name))
except:
log.exception(u'Export Theme Failed')
finally:
if zip:
zip.close()
def onImportTheme(self):
files = QtGui.QFileDialog.getOpenFileNames(
@ -263,7 +267,7 @@ class ThemeManager(QtGui.QWidget):
self.pushThemes()
def pushThemes(self):
Receiver().send_message(u'update_themes', self.getThemes() )
Receiver.send_message(u'update_themes', self.getThemes() )
def getThemes(self):
return self.themelist
@ -272,15 +276,10 @@ class ThemeManager(QtGui.QWidget):
log.debug(u'getthemedata for theme %s', themename)
xml_file = os.path.join(self.path, unicode(themename),
unicode(themename) + u'.xml')
try:
xml = file_to_xml(xml_file)
except:
xml = get_text_file_string(xml_file)
if not xml:
xml = self.baseTheme()
theme = ThemeXML()
theme.parse(xml)
self.cleanTheme(theme)
theme.extend_image_filename(self.path)
return theme
return self.createThemeFromXml(xml, self.path)
def checkThemesExists(self, dir):
log.debug(u'check themes')
@ -295,44 +294,49 @@ class ThemeManager(QtGui.QWidget):
"""
log.debug(u'Unzipping theme %s', filename)
filename = unicode(filename)
zip = None
outfile = None
try:
zip = zipfile.ZipFile(filename)
filexml = None
themename = None
for file in zip.namelist():
if file.endswith(os.path.sep):
theme_dir = os.path.join(dir, file)
if not os.path.exists(theme_dir):
os.mkdir(os.path.join(dir, file))
else:
fullpath = os.path.join(dir, file)
names = file.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
xml_data = zip.read(file)
if os.path.splitext(file)[1].lower() in [u'.xml']:
if self.checkVersion1(xml_data):
# upgrade theme xml
filexml = self.migrateVersion122(filename,
fullpath, xml_data)
else:
filexml = xml_data
outfile = open(fullpath, u'w')
outfile.write(filexml)
else:
outfile = open(fullpath, u'w')
outfile.write(zip.read(file))
self.generateAndSaveImage(dir, themename, filexml)
except:
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
themename = None
for file in zip.namelist():
if file.endswith(os.path.sep):
theme_dir = os.path.join(dir, file)
if not os.path.exists(theme_dir):
os.mkdir(os.path.join(dir, file))
else:
fullpath = os.path.join(dir, file)
names = file.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
xml_data = zip.read(file)
if os.path.splitext(file)[1].lower() in [u'.xml']:
if self.checkVersion1(xml_data):
# upgrade theme xml
filexml = self.migrateVersion122(filename,
fullpath, xml_data)
else:
filexml = xml_data
outfile = open(fullpath, u'w')
outfile.write(filexml)
outfile.close()
else:
outfile = open(fullpath, u'w')
outfile.write(zip.read(file))
outfile.close()
self.generateAndSaveImage(dir, themename, filexml)
log.exception(u'Importing theme from zip file failed')
finally:
if zip:
zip.close()
if outfile:
outfile.close()
def checkVersion1(self, xmlfile):
"""
@ -412,13 +416,22 @@ class ThemeManager(QtGui.QWidget):
result == QtGui.QMessageBox.Yes
if result == QtGui.QMessageBox.Yes:
# Save the theme, overwriting the existing theme if necessary.
outfile = open(theme_file, u'w')
outfile.write(theme_pretty_xml)
outfile.close()
outfile = None
try:
outfile = open(theme_file, u'w')
outfile.write(theme_pretty_xml)
except:
log.exception(u'Saving theme to file failed')
finally:
if outfile:
outfile.close()
if image_from and image_from != image_to:
print "if", image_from
print "it", image_to
shutil.copyfile(image_from, image_to)
try:
shutil.copyfile(image_from, image_to)
except:
log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme_xml)
self.loadThemes()
else:
@ -428,10 +441,7 @@ class ThemeManager(QtGui.QWidget):
def generateAndSaveImage(self, dir, name, theme_xml):
log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
theme = ThemeXML()
theme.parse(theme_xml)
self.cleanTheme(theme)
theme.extend_image_filename(dir)
theme = self.createThemeFromXml(theme_xml, dir)
frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png')
if os.path.exists(samplepathname):
@ -465,6 +475,13 @@ class ThemeManager(QtGui.QWidget):
unicode(u'#FFFFFF'), unicode(0), unicode(0), unicode(0))
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):
theme.background_color = theme.background_color.strip()
theme.background_direction = theme.background_direction.strip()
@ -486,6 +503,8 @@ class ThemeManager(QtGui.QWidget):
theme.display_wrapStyle = theme.display_wrapStyle.strip()
theme.font_footer_color = theme.font_footer_color.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_name = theme.font_footer_name.strip()
#theme.font_footer_override

View File

@ -135,10 +135,10 @@ class ThemesTab(SettingsTab):
def save(self):
self.config.set_config(u'theme global style', self.global_style )
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):
Receiver().send_message(u'update_global_theme', self.global_theme )
Receiver.send_message(u'update_global_theme', self.global_theme )
def onSongLevelButtonPressed(self):
self.global_style = u'Song'

View File

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

View File

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

View File

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

View File

@ -105,7 +105,8 @@ class BibleCommon(object):
xml_string = u''
req = urllib2.Request(urlstring)
#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:
handle = urllib2.urlopen(req)
html = handle.read()
@ -164,4 +165,3 @@ class BibleCommon(object):
start_tag = text.find(u'<')
text = text.replace(u'>', u'')
return text.rstrip().lstrip()

View File

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

View File

@ -54,7 +54,7 @@ class BibleMediaItem(MediaManagerItem):
MediaManagerItem.__init__(self, parent, icon, title)
# place to store the search results
self.search_results = {}
QtCore.QObject.connect(Receiver().get_receiver(),
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpreloadbibles'), self.reloadBibles)
def initPluginNameVisible(self):
@ -284,7 +284,7 @@ class BibleMediaItem(MediaManagerItem):
def setQuickMessage(self, text):
self.QuickMessage.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
time.sleep(0.1)

View File

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

View File

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

View File

@ -50,7 +50,9 @@ class CustomMediaItem(MediaManagerItem):
self.ListViewWithDnD_class = CustomListView
self.servicePath = None
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):
QtCore.QObject.connect(Receiver.get_receiver(),
@ -59,6 +61,8 @@ class CustomMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'remote_edit_clear' ), self.onRemoteEditClear)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'load_custom_list'), self.initialise)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'preview_custom'), self.onPreviewClick)
def initPluginNameVisible(self):
self.PluginNameVisible = self.trUtf8(u'Custom')
@ -69,6 +73,14 @@ class CustomMediaItem(MediaManagerItem):
def initialise(self):
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):
self.ListView.clear()
@ -77,8 +89,6 @@ class CustomMediaItem(MediaManagerItem):
custom_name.setData(
QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id))
self.ListView.addItem(custom_name)
if CustomSlide.id == self.fromServiceManager:
self.onAddClick()
def onNewClick(self):
self.parent.edit_custom_form.loadCustom(0)
@ -86,20 +96,29 @@ class CustomMediaItem(MediaManagerItem):
self.initialise()
def onRemoteEditClear(self):
self.fromServiceManager = -1
self.remoteTriggered = None
self.remoteCustom = -1
def onRemoteEdit(self, item_id):
valid = self.parent.custommanager.get_custom(item_id)
def onRemoteEdit(self, customid):
"""
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:
self.fromServiceManager = item_id
self.parent.edit_custom_form.loadCustom(item_id)
self.remoteCustom = fields[1]
self.remoteTriggered = fields[0]
self.parent.edit_custom_form.loadCustom(fields[1],
(fields[0] == u'P'))
self.parent.edit_custom_form.exec_()
def onEditClick(self):
item = self.ListView.currentItem()
if item:
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.initialise()
@ -116,18 +135,17 @@ class CustomMediaItem(MediaManagerItem):
raw_footer = []
slide = None
theme = None
if self.fromServiceManager == -1:
if self.remoteTriggered is None:
item = self.ListView.currentItem()
if item is None:
return False
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else:
item_id = self.fromServiceManager
self.fromServiceManager = -1
item_id = self.remoteCustom
customSlide = self.parent.custommanager.get_custom(item_id)
title = customSlide.title
credit = customSlide.credits
service_item.editEnabled = True
service_item.edit_enabled = True
service_item.editId = item_id
theme = customSlide.theme_name
if len(theme) is not 0 :
@ -137,9 +155,8 @@ class CustomMediaItem(MediaManagerItem):
for verse in verseList:
raw_slides.append(verse[1])
raw_footer.append(title + u' '+ credit)
if theme:
service_item.title = title
for slide in raw_slides:
service_item.add_from_text(slide[:30], slide)
service_item.raw_footer = raw_footer
return True
service_item.title = title
for slide in raw_slides:
service_item.add_from_text(slide[:30], slide)
service_item.raw_footer = raw_footer
return True

View File

@ -37,9 +37,6 @@ class ImagePlugin(Plugin):
self.weight = -7
self.icon = buildIcon(u':/media/media_image.png')
def can_be_disabled(self):
return True
def initialise(self):
log.info(u'Plugin Initialising')
Plugin.initialise(self)
@ -60,7 +57,7 @@ class ImagePlugin(Plugin):
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'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'any somgs which are rendered will use the selected image from '
u'the background instead of the one provied by the theme.<br>')

View File

@ -74,7 +74,7 @@ class ImageTab(SettingsTab):
def save(self):
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):
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()
if len(items) > 1:
return False
service_item.title = self.trUtf8(u'Media')
service_item.title = unicode(self.trUtf8(u'Media'))
for item in items:
bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())

View File

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

View File

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

View File

@ -136,18 +136,18 @@ class PresentationMediaItem(MediaManagerItem):
return False
service_item.title = 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:
bitem = self.ListView.item(item.row())
filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString())
(path, name) = os.path.split(filename)
cont.store_filename(filename)
if cont.get_slide_preview_file(1) is None:
cont.load_presentation(filename)
controller.store_filename(filename)
if controller.get_slide_preview_file(1) is None:
controller.load_presentation(filename)
i = 1
img = cont.get_slide_preview_file(i)
img = controller.get_slide_preview_file(i)
while img:
service_item.add_from_command(path, name, img)
i = i + 1
img = cont.get_slide_preview_file(i)
img = controller.get_slide_preview_file(i)
return True

View File

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

View File

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

View File

@ -40,9 +40,6 @@ class RemotesPlugin(Plugin):
self.weight = -1
self.server = None
def can_be_disabled(self):
return True
def initialise(self):
log.debug(u'initialise')
Plugin.initialise(self)
@ -76,9 +73,9 @@ class RemotesPlugin(Plugin):
pos = datagram.find(u':')
event = unicode(datagram[:pos].lower())
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':
Receiver().send_message(u'live_slide_next')
Receiver.send_message(u'live_slide_next')
def about(self):
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')
if button.text() == unicode(self.trUtf8(u'Save && Preview')) \
and self.saveSong():
Receiver().send_message(u'preview_song')
Receiver.send_message(u'preview_song')
def closePressed(self):
Receiver().send_message(u'remote_edit_clear')
Receiver.send_message(u'remote_edit_clear')
self.close()
def accept(self):
log.debug(u'accept')
if self.saveSong():
Receiver().send_message(u'load_song_list')
Receiver.send_message(u'load_song_list')
self.close()
def saveSong(self):
@ -462,7 +462,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
text = text.replace(u'}', u'')
text = text.replace(u'?', u'')
self.song.search_lyrics = unicode(text)
self.song.lyrics = unicode(sxml.extract_xml())
self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
except:
log.exception(u'Problem processing song Lyrics \n%s',
sxml.dump_xml())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -126,4 +126,20 @@
<file>theme_export.png</file>
<file>theme_import.png</file>
</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>

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