This commit is contained in:
Andreas Preikschat 2011-10-30 22:38:42 +01:00
commit 482c741665
74 changed files with 5365 additions and 4557 deletions

View File

@ -7,7 +7,7 @@
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #

View File

@ -143,7 +143,7 @@ class OpenLP(QtGui.QApplication):
u'general/update check', QtCore.QVariant(True)).toBool()
if update_check:
VersionThread(self.mainWindow).start()
Receiver.send_message(u'maindisplay_blank_check')
Receiver.send_message(u'live_display_blank_check')
self.mainWindow.appStartup()
DelayStartThread(self.mainWindow).start()
# Skip exec_() for gui tests

View File

@ -35,200 +35,190 @@ log = logging.getLogger(__name__)
class EventReceiver(QtCore.QObject):
"""
Class to allow events to be passed from different parts of the
system. This is a private class and should not be used directly
but rather via the Receiver class.
Class to allow events to be passed from different parts of the system. This
is a private class and should not be used directly but rather via the
Receiver class.
**Mainwindow related and generic signals**
``mainwindow_status_text``
Changes the bottom status bar text on the mainwindow.
``openlp_warning_message``
Displays a standalone Warning Message.
``openlp_error_message``
Displays a standalone Error Message.
``openlp_information_message``
Displays a standalone Information Message.
``cursor_busy``
Makes the cursor got to a busy form.
``cursor_normal``
Resets the cursor to default.
``openlp_process_events``
Requests the Application to flush the events queue
Requests the Application to flush the events queue.
``openlp_version_check``
Version has changed so pop up window.
``openlp_stop_wizard``
Stops a wizard before completion.
**Setting related signals**
``config_updated``
Informs components the config has changed
Informs components that the config has changed.
``config_screen_changed``
The display monitor has been changed
The display monitor has been changed.
``slidecontroller_{live|preview}_first``
Moves to the first slide
**Slidecontroller signals**
``slidecontroller_{live|preview}_next``
Moves to the next slide
Moves to the next slide.
``slidecontroller_{live|preview}_next_noloop``
Moves to the next slide without auto advance
Moves to the next slide without auto advance.
``slidecontroller_{live|preview}_previous``
Moves to the previous slide
Moves to the previous slide.
``slidecontroller_{live|preview}_previous_noloop``
Moves to the previous slide, without auto advance
``slidecontroller_{live|preview}_last``
Moves to the last slide
Moves to the previous slide, without auto advance.
``slidecontroller_{live|preview}_set``
Moves to a specific slide, by index
Moves to a specific slide, by index.
``slidecontroller_{live|preview}_started``
Broadcasts that an item has been made live/previewed
Broadcasts that an item has been made live/previewed.
``slidecontroller_{live|preview}_change``
Informs the slidecontroller that a slide change has occurred and to
update itself
update itself.
``slidecontroller_{live|preview}_changed``
Broadcasts that the slidecontroller has changed the current slide
``slidecontroller_{live|preview}_text_request``
Request the text for the current item in the controller
Returns a slidecontroller_{live|preview}_text_response with an
array of dictionaries with the tag and verse text
Broadcasts that the slidecontroller has changed the current slide.
``slidecontroller_{live|preview}_blank``
Request that the output screen is blanked
Request that the output screen is blanked.
``slidecontroller_{live|preview}_unblank``
Request that the output screen is unblanked
Request that the output screen is unblanked.
``slidecontroller_live_spin_delay``
Pushes out the loop delay
Pushes out the loop delay.
``slidecontroller_live_stop_loop``
Stop the loop on the main display
Stop the loop on the main display.
**Servicemanager related signals**
``servicemanager_previous_item``
Display the previous item in the service
Display the previous item in the service.
``servicemanager_preview_live``
Requests a Preview item from the Service Manager to update live and
add a new item to the preview panel
Requests a Preview item from the Service Manager to update live and add
a new item to the preview panel.
``servicemanager_next_item``
Display the next item in the service
Display the next item in the service.
``servicemanager_set_item``
Go live on a specific item, by index
``maindisplay_blank``
Blank the maindisplay window
``maindisplay_hide``
Hide the maindisplay window
``maindisplay_show``
Return the maindisplay window
``maindisplay_active``
The maindisplay has been made active
``maindisplay_status_text``
Changes the bottom status bar text on the maindisplay window
``maindisplay_blank_check``
Check to see if the blank display message is required
``videodisplay_start``
Open a media item and prepare for playing
``videodisplay_play``
Start playing a media item
``videodisplay_pause``
Pause a media item
``videodisplay_stop``
Stop playing a media item
``videodisplay_background``
Replace the background video
``theme_update_list``
send out message with new themes
``theme_update_global``
Tell the components we have a new global theme
``{plugin}_start``
Requests a plugin to start a external program
Path and file provided in message
``{plugin}_first``
Requests a plugin to handle a first event
``{plugin}_previous``
Requests a plugin to handle a previous event
``{plugin}_next``
Requests a plugin to handle a next event
``{plugin}_last``
Requests a plugin to handle a last event
``{plugin}_slide``
Requests a plugin to handle a go to specific slide event
``{plugin}_stop``
Requests a plugin to handle a stop event
``{plugin}_blank``
Requests a plugin to handle a blank screen event
``{plugin}_unblank``
Requests a plugin to handle an unblank screen event
``{plugin}_edit``
Requests a plugin edit a database item with the key as the payload
``{plugin}_edit_clear``
Editing has been completed
``{plugin}_load_list``
Tells the the plugin to reload the media manager list
``{plugin}_preview``
Tells the plugin it's item can be previewed
``{plugin}_add_service_item``
Ask the plugin to push the selected items to the service item
``{plugin}_service_load``
Ask the plugin to process an individual service item after it has been
loaded
Go live on a specific item, by index.
``service_item_update``
Passes back to the service manager the service item after it has been
processed by the plugin
processed by the plugin.
**Display signals**
``update_display_css``
CSS has been updated which needs to be changed on the main display.
**Live Display signals**
``live_display_hide``
Hide the live display.
``live_display_show``
Return the live display.
``live_display_active``
The live display has been made active.
``live_display_blank_check``
Check to see if the blank display message is required.
**Theme related singlas**
``theme_update_list``
send out message with new themes.
``theme_update_global``
Tell the components we have a new global theme.
**Plugin specific signals**
``{plugin}_start``
Requests a plugin to start a external program. Path and file have to
be provided in the message.
``{plugin}_first``
Requests a plugin to handle a first event.
``{plugin}_previous``
Requests a plugin to handle a previous event.
``{plugin}_next``
Requests a plugin to handle a next event.
``{plugin}_last``
Requests a plugin to handle a last event.
``{plugin}_slide``
Requests a plugin to handle a go to specific slide event.
``{plugin}_stop``
Requests a plugin to handle a stop event.
``{plugin}_blank``
Requests a plugin to handle a blank screen event.
``{plugin}_unblank``
Requests a plugin to handle an unblank screen event.
``{plugin}_edit``
Requests a plugin edit a database item with the key as the payload.
``{plugin}_edit_clear``
Editing has been completed.
``{plugin}_load_list``
Tells the the plugin to reload the media manager list.
``{plugin}_preview``
Tells the plugin it's item can be previewed.
``{plugin}_add_service_item``
Ask the plugin to push the selected items to the service item.
``{plugin}_service_load``
Ask the plugin to process an individual service item after it has been
loaded.
``alerts_text``
Displays an alert message
Displays an alert message.
``bibles_nobook``
Attempt to find book resulted in no match
``openlp_stop_wizard``
Stops a wizard before completion
Attempt to find book resulted in no match.
``remotes_poll_request``
Waits for openlp to do something "interesting" and sends a
remotes_poll_response signal when it does
``openlp_warning_message``
Displays a standalone Warning Message
``openlp_error_message``
Displays a standalone Error Message
``openlp_information_message``
Displays a standalone Information Message
``cursor_busy``
Makes the cursor got to a busy form
``cursor_normal``
Resets the cursor to default
``remotes_poll_response`` signal when it does.
"""
def __init__(self):

View File

@ -73,13 +73,7 @@ body {
#video2 {
z-index: 3;
}
#alert {
position: absolute;
left: 0px;
top: 0px;
z-index: 10;
%s
}
%s
#footer {
position: absolute;
z-index: 6;
@ -179,7 +173,7 @@ sup {
break;
}
}
%s
function show_image(src){
var img = document.getElementById('image');
img.src = src;
@ -225,34 +219,6 @@ sup {
}
}
function show_alert(alerttext, position){
var text = document.getElementById('alert');
text.innerHTML = alerttext;
if(alerttext == '') {
text.style.visibility = 'hidden';
return 0;
}
if(position == ''){
position = getComputedStyle(text, '').verticalAlign;
}
switch(position)
{
case 'top':
text.style.top = '0px';
break;
case 'middle':
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
+ 'px';
break;
case 'bottom':
text.style.top = (window.innerHeight - text.clientHeight)
+ 'px';
break;
}
text.style.visibility = 'visible';
return text.clientHeight;
}
function show_footer(footertext){
document.getElementById('footer').innerHTML = footertext;
}
@ -316,14 +282,15 @@ sup {
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
</video>
%s
%s
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
<div id="alert" style="visibility:hidden"></div>
</body>
</html>
"""
def build_html(item, screen, alert, islive, background, image=None):
def build_html(item, screen, islive, background, image=None,
plugins=None):
"""
Build the full web paged structure for display
@ -333,9 +300,6 @@ def build_html(item, screen, alert, islive, background, image=None):
``screen``
Current display information
``alert``
Alert display display information
``islive``
Item is going live, rather than preview/theme building
@ -344,6 +308,9 @@ def build_html(item, screen, alert, islive, background, image=None):
``image``
Image media item - bytes
``plugins``
The List of available plugins
"""
width = screen[u'size'].width()
height = screen[u'size'].height()
@ -360,14 +327,24 @@ def build_html(item, screen, alert, islive, background, image=None):
image_src = u'src="data:image/png;base64,%s"' % image
else:
image_src = u'style="display:none;"'
css_additions = u''
js_additions = u''
html_additions = u''
if plugins:
for plugin in plugins:
css_additions += plugin.getDisplayCss()
js_additions += plugin.getDisplayJavaScript()
html_additions += plugin.getDisplayHtml()
html = HTMLSRC % (build_background_css(item, width, height),
width, height,
build_alert_css(alert, width),
css_additions,
build_footer_css(item, height),
build_lyrics_css(item, webkitvers),
u'true' if theme and theme.display_slide_transition and islive \
else u'false',
js_additions,
bgimage_src, image_src,
html_additions,
build_lyrics_html(item, webkitvers))
return html
@ -633,24 +610,3 @@ def build_footer_css(item, height):
theme.font_footer_size, theme.font_footer_color)
return lyrics_html
def build_alert_css(alertTab, width):
"""
Build the display of the footer
``alertTab``
Details from the Alert tab for fonts etc
"""
style = u"""
width: %spx;
vertical-align: %s;
font-family: %s;
font-size: %spt;
color: %s;
background-color: %s;
"""
if not alertTab:
return u''
align = VerticalType.Names[alertTab.location]
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
alertTab.font_color, alertTab.bg_color)
return alert

View File

@ -1,38 +0,0 @@
PSF LICENSE AGREEMENT FOR PYTHON 2.7.1
1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"),
and the Individual or Organization ("Licensee") accessing and otherwise
using Python 2.7.1 software in source or binary form and its associated
documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to
reproduce, analyze, test, perform and/or display publicly, prepare
derivative works, distribute, and otherwise use Python 2.7.1 alone or in any
derivative version, provided, however, that PSF's License Agreement and
PSF's notice of copyright, i.e., "Copyright (c) 2001-2010 Python Software
Foundation; All Rights Reserved" are retained in Python 2.7.1 alone or in
any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on or
incorporates Python 2.7.1 or any part thereof, and wants to make the
derivative work available to others as provided herein, then Licensee hereby
agrees to include in any such work a brief summary of the changes made to
Python 2.7.1.
4. PSF is making Python 2.7.1 available to Licensee on an "AS IS" basis. PSF
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION
OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
THE USE OF PYTHON 2.7.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.1 FOR
ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.1, OR ANY DERIVATIVE
THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material breach
of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any relationship
of agency, partnership, or joint venture between PSF and Licensee. This
License Agreement does not grant permission to use PSF trademarks or trade
name in a trademark sense to endorse or promote products or services of
Licensee, or any third party.
8. By copying, installing or otherwise using Python 2.7.1, Licensee agrees to
be bound by the terms and conditions of this License Agreement.

View File

@ -1,321 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# Utilities for opening files or URLs in the registered default application #
# and for sending e-mail using the user's preferred composer. #
# --------------------------------------------------------------------------- #
# Copyright (c) 2007 Antonio Valentino #
# All rights reserved. #
# --------------------------------------------------------------------------- #
# This program offered under the PSF License as published by the Python #
# Software Foundation. #
# #
# The license text can be found at http://docs.python.org/license.html #
# #
# This code is taken from: http://code.activestate.com/recipes/511443 #
# Modified for use in OpenLP #
###############################################################################
__version__ = u'1.1'
__all__ = [u'open', u'mailto']
import os
import sys
import webbrowser
import subprocess
from email.Utils import encode_rfc2231
_controllers = {}
_open = None
class BaseController(object):
"""
Base class for open program controllers.
"""
def __init__(self, name):
self.name = name
def open(self, filename):
raise NotImplementedError
class Controller(BaseController):
"""
Controller for a generic open program.
"""
def __init__(self, *args):
super(Controller, self).__init__(os.path.basename(args[0]))
self.args = list(args)
def _invoke(self, cmdline):
if sys.platform[:3] == u'win':
closefds = False
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
closefds = True
startupinfo = None
if (os.environ.get(u'DISPLAY') or sys.platform[:3] == u'win' or \
sys.platform == u'darwin'):
inout = file(os.devnull, u'r+')
else:
# for TTY programs, we need stdin/out
inout = None
# if possible, put the child precess in separate process group,
# so keyboard interrupts don't affect child precess as well as
# Python
setsid = getattr(os, u'setsid', None)
if not setsid:
setsid = getattr(os, u'setpgrp', None)
pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
stderr=inout, close_fds=closefds, preexec_fn=setsid,
startupinfo=startupinfo)
# It is assumed that this kind of tools (gnome-open, kfmclient,
# exo-open, xdg-open and open for OSX) immediately exit after lauching
# the specific application
returncode = pipe.wait()
if hasattr(self, u'fixreturncode'):
returncode = self.fixreturncode(returncode)
return not returncode
def open(self, filename):
if isinstance(filename, basestring):
cmdline = self.args + [filename]
else:
# assume it is a sequence
cmdline = self.args + filename
try:
return self._invoke(cmdline)
except OSError:
return False
# Platform support for Windows
if sys.platform[:3] == u'win':
class Start(BaseController):
"""
Controller for the win32 start progam through os.startfile.
"""
def open(self, filename):
try:
os.startfile(filename)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True
_controllers[u'windows-default'] = Start(u'start')
_open = _controllers[u'windows-default'].open
# Platform support for MacOS
elif sys.platform == u'darwin':
_controllers[u'open'] = Controller(u'open')
_open = _controllers[u'open'].open
# Platform support for Unix
else:
import commands
# @WARNING: use the private API of the webbrowser module
from webbrowser import _iscommand
class KfmClient(Controller):
"""
Controller for the KDE kfmclient program.
"""
def __init__(self, kfmclient=u'kfmclient'):
super(KfmClient, self).__init__(kfmclient, u'exec')
self.kde_version = self.detect_kde_version()
def detect_kde_version(self):
kde_version = None
try:
info = commands.getoutput(u'kfmclient --version')
for line in info.splitlines():
if line.startswith(u'KDE'):
kde_version = line.split(u':')[-1].strip()
break
except (OSError, RuntimeError):
pass
return kde_version
def fixreturncode(self, returncode):
if returncode is not None and self.kde_version > u'3.5.4':
return returncode
else:
return os.EX_OK
def detect_desktop_environment():
"""
Checks for known desktop environments
Return the desktop environments name, lowercase (kde, gnome, xfce)
or "generic"
"""
desktop_environment = u'generic'
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
desktop_environment = u'kde'
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
desktop_environment = u'gnome'
else:
try:
info = commands.getoutput(u'xprop -root _DT_SAVE_MODE')
if u' = "xfce4"' in info:
desktop_environment = u'xfce'
except (OSError, RuntimeError):
pass
return desktop_environment
def register_X_controllers():
if _iscommand(u'kfmclient'):
_controllers[u'kde-open'] = KfmClient()
for command in (u'gnome-open', u'exo-open', u'xdg-open'):
if _iscommand(command):
_controllers[command] = Controller(command)
def get():
controllers_map = {
u'gnome': u'gnome-open',
u'kde': u'kde-open',
u'xfce': u'exo-open',
}
desktop_environment = detect_desktop_environment()
try:
controller_name = controllers_map[desktop_environment]
return _controllers[controller_name].open
except KeyError:
if _controllers.has_key(u'xdg-open'):
return _controllers[u'xdg-open'].open
else:
return webbrowser.open
if os.environ.get(u'DISPLAY'):
register_X_controllers()
_open = get()
def open(filename):
"""
Open a file or an URL in the registered default application.
"""
return _open(filename)
def _fix_addresses(**kwargs):
for headername in (u'address', u'to', u'cc', u'bcc'):
try:
headervalue = kwargs[headername]
if not headervalue:
del kwargs[headername]
continue
elif not isinstance(headervalue, basestring):
# assume it is a sequence
headervalue = u','.join(headervalue)
except KeyError:
pass
except TypeError:
raise TypeError(u'string or sequence expected for "%s", %s '
u'found' % (headername, type(headervalue).__name__))
else:
translation_map = {u'%': u'%25', u'&': u'%26', u'?': u'%3F'}
for char, replacement in translation_map.items():
headervalue = headervalue.replace(char, replacement)
kwargs[headername] = headervalue
return kwargs
def mailto_format(**kwargs):
"""
Compile mailto string from call parameters
"""
# @TODO: implement utf8 option
kwargs = _fix_addresses(**kwargs)
parts = []
for headername in (u'to', u'cc', u'bcc', u'subject', u'body', u'attach'):
if kwargs.has_key(headername):
headervalue = kwargs[headername]
if not headervalue:
continue
if headername in (u'address', u'to', u'cc', u'bcc'):
parts.append(u'%s=%s' % (headername, headervalue))
else:
headervalue = encode_rfc2231(headervalue) # @TODO: check
parts.append(u'%s=%s' % (headername, headervalue))
mailto_string = u'mailto:%s' % kwargs.get(u'address', '')
if parts:
mailto_string = u'%s?%s' % (mailto_string, u'&'.join(parts))
return mailto_string
def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None,
attach=None):
"""
Send an e-mail using the user's preferred composer.
Open the user's preferred e-mail composer in order to send a mail to
address(es) that must follow the syntax of RFC822. Multiple addresses
may be provided (for address, cc and bcc parameters) as separate
arguments.
All parameters provided are used to prefill corresponding fields in
the user's e-mail composer. The user will have the opportunity to
change any of this information before actually sending the e-mail.
``address``
specify the destination recipient
``cc``
specify a recipient to be copied on the e-mail
``bcc``
specify a recipient to be blindly copied on the e-mail
``subject``
specify a subject for the e-mail
``body``
specify a body for the e-mail. Since the user will be able to make
changes before actually sending the e-mail, this can be used to provide
the user with a template for the e-mail text may contain linebreaks
``attach``
specify an attachment for the e-mail. file must point to an existing
file
"""
mailto_string = mailto_format(**locals())
return open(mailto_string)

View File

@ -369,3 +369,30 @@ class Plugin(QtCore.QObject):
"""
self.textStrings[name] = {u'title': title, u'tooltip': tooltip}
def getDisplayCss(self):
"""
Add css style sheets to htmlbuilder.
"""
return u''
def getDisplayJavaScript(self):
"""
Add javascript functions to htmlbuilder.
"""
return u''
def refreshCss(self, frame):
"""
Allow plugins to refresh javascript on displayed screen.
``frame``
The Web frame holding the page.
"""
return u''
def getDisplayHtml(self):
"""
Add html code to htmlbuilder.
"""
return u''

View File

@ -42,6 +42,13 @@ class PluginManager(object):
"""
log.info(u'Plugin manager loaded')
@staticmethod
def get_instance():
"""
Obtain a single instance of class.
"""
return PluginManager.instance
def __init__(self, plugin_dir):
"""
The constructor for the plugin manager. Passes the controllers on to
@ -51,6 +58,7 @@ class PluginManager(object):
The directory to search for plugins.
"""
log.info(u'Plugin manager Initialising')
PluginManager.instance = self
if not plugin_dir in sys.path:
log.debug(u'Inserting %s into sys.path', plugin_dir)
sys.path.insert(0, plugin_dir)

View File

@ -57,14 +57,14 @@ class Renderer(object):
def __init__(self, imageManager, themeManager):
"""
Initialise the render manager.
Initialise the renderer.
``imageManager``
A ImageManager instance which takes care of e. g. caching and resizing
A imageManager instance which takes care of e. g. caching and resizing
images.
``themeManager``
The ThemeManager instance, used to get the current theme details.
The themeManager instance, used to get the current theme details.
"""
log.debug(u'Initialisation started')
self.themeManager = themeManager
@ -81,7 +81,7 @@ class Renderer(object):
def update_display(self):
"""
Updates the render manager's information about the current screen.
Updates the renderer's information about the current screen.
"""
log.debug(u'Update Display')
self._calculate_default()
@ -201,7 +201,8 @@ class Renderer(object):
if not self.force_page:
self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)
preview = self.display.text(raw_html)
self.display.text(raw_html)
preview = self.display.preview()
# Reset the real screen size for subsequent render requests
self._calculate_default()
return preview
@ -304,21 +305,37 @@ class Renderer(object):
The theme to build a text block for.
"""
log.debug(u'_build_text_rectangle')
main_rect = None
footer_rect = None
main_rect = self.get_main_rectangle(theme)
footer_rect = self.get_footer_rectangle(theme)
self._set_text_rectangle(main_rect, footer_rect)
def get_main_rectangle(self, theme):
"""
Calculates the placement and size of the main rectangle.
``theme``
The theme information
"""
if not theme.font_main_override:
main_rect = QtCore.QRect(10, 0, self.width - 20, self.footer_start)
return QtCore.QRect(10, 0, self.width - 20, self.footer_start)
else:
main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y,
return QtCore.QRect(theme.font_main_x, theme.font_main_y,
theme.font_main_width - 1, theme.font_main_height - 1)
def get_footer_rectangle(self, theme):
"""
Calculates the placement and size of the footer rectangle.
``theme``
The theme information
"""
if not theme.font_footer_override:
footer_rect = QtCore.QRect(10, self.footer_start, self.width - 20,
return QtCore.QRect(10, self.footer_start, self.width - 20,
self.height - self.footer_start)
else:
footer_rect = QtCore.QRect(theme.font_footer_x,
return QtCore.QRect(theme.font_footer_x,
theme.font_footer_y, theme.font_footer_width - 1,
theme.font_footer_height - 1)
self._set_text_rectangle(main_rect, footer_rect)
def _set_text_rectangle(self, rect_main, rect_footer):
"""

View File

@ -122,9 +122,8 @@ class ServiceItem(object):
def _new_item(self):
"""
Method to set the internal id of the item
This is used to compare service items to see if they are
the same
Method to set the internal id of the item. This is used to compare
service items to see if they are the same.
"""
self._uuid = unicode(uuid.uuid1())
@ -160,9 +159,8 @@ class ServiceItem(object):
def render(self, use_override=False):
"""
The render method is what generates the frames for the screen and
obtains the display information from the renderemanager.
At this point all the slides are built for the given
display size.
obtains the display information from the renderer. At this point all
slides are built for the given display size.
"""
log.debug(u'Render called')
self._display_frames = []
@ -364,6 +362,11 @@ class ServiceItem(object):
"""
self._uuid = other._uuid
self.notes = other.notes
# Copy theme over if present.
if other.theme is not None:
self.theme = other.theme
self._new_item()
self.render()
if self.is_capable(ItemCapabilities.HasBackgroundAudio):
log.debug(self.background_audio)

View File

@ -52,8 +52,27 @@ class HideMode(object):
Theme = 2
Screen = 3
class AlertLocation(object):
"""
This is an enumeration class which controls where Alerts are placed on the
screen.
``Top``
Place the text at the top of the screen.
``Middle``
Place the text in the middle of the screen.
``Bottom``
Place the text at the bottom of the screen.
"""
Top = 0
Middle = 1
Bottom = 2
from firsttimeform import FirstTimeForm
from firsttimelanguageform import FirstTimeLanguageForm
from themelayoutform import ThemeLayoutForm
from themeform import ThemeForm
from filerenameform import FileRenameForm
from starttimeform import StartTimeForm

View File

@ -39,6 +39,11 @@ try:
PHONON_VERSION = Phonon.phononVersion()
except ImportError:
PHONON_VERSION = u'-'
try:
import migrate
MIGRATE_VERSION = getattr(migrate, u'__version__', u'< 0.7')
except ImportError:
MIGRATE_VERSION = u'-'
try:
import chardet
CHARDET_VERSION = chardet.__version__
@ -54,9 +59,26 @@ try:
SQLITE_VERSION = sqlite.version
except ImportError:
SQLITE_VERSION = u'-'
try:
import mako
MAKO_VERSION = mako.__version__
except ImportError:
MAKO_VERSION = u'-'
try:
import uno
arg = uno.createUnoStruct(u'com.sun.star.beans.PropertyValue')
arg.Name = u'nodepath'
arg.Value = u'/org.openoffice.Setup/Product'
context = uno.getComponentContext()
provider = context.ServiceManager.createInstance(
u'com.sun.star.configuration.ConfigurationProvider')
node = provider.createInstanceWithArguments(
u'com.sun.star.configuration.ConfigurationAccess', (arg,))
UNO_VERSION = node.getByName(u'ooSetupVersion')
except ImportError:
UNO_VERSION = u'-'
from openlp.core.lib import translate, SettingsManager
from openlp.core.lib.mailto import mailto
from openlp.core.lib.ui import UiStrings
from openlp.core.utils import get_application_version
@ -90,11 +112,14 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
u'Phonon: %s\n' % PHONON_VERSION + \
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
u'lxml: %s\n' % etree.__version__ + \
u'Chardet: %s\n' % CHARDET_VERSION + \
u'PyEnchant: %s\n' % ENCHANT_VERSION + \
u'PySQLite: %s\n' % SQLITE_VERSION
u'PySQLite: %s\n' % SQLITE_VERSION + \
u'Mako: %s\n' % MAKO_VERSION + \
u'pyUNO bridge: %s\n' % UNO_VERSION
if platform.system() == u'Linux':
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
system = system + u'Desktop: KDE SC\n'
@ -153,18 +178,20 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
'Please add the information that bug reports are favoured written '
'in English.'))
content = self._createReport()
source = u''
exception = u''
for line in content[2].split(u'\n'):
if re.search(r'[/\\]openlp[/\\]', line):
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
if u':' in line:
exception = line.split(u'\n')[-1].split(u':')[0]
subject = u'Bug report: %s in %s' % (exception, source)
mailto_url = QtCore.QUrl(u'mailto:bugs@openlp.org')
mailto_url.addQueryItem(u'subject', subject)
mailto_url.addQueryItem(u'body', body % content)
if self.fileAttachment:
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content, attach=self.fileAttachment)
else:
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content)
mailto_url.addQueryItem(u'attach', self.fileAttachment)
QtGui.QDesktopServices.openUrl(mailto_url)
def onDescriptionUpdated(self):
count = int(20 - len(self.descriptionTextEdit.toPlainText()))

View File

@ -35,9 +35,9 @@ from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
translate
translate, PluginManager
from openlp.core.ui import HideMode, ScreenList
from openlp.core.ui import HideMode, ScreenList, AlertLocation
log = logging.getLogger(__name__)
@ -51,12 +51,15 @@ class MainDisplay(QtGui.QGraphicsView):
def __init__(self, parent, imageManager, live):
if live:
QtGui.QGraphicsView.__init__(self)
# Do not overwrite the parent() method.
self.parent = lambda: parent
else:
QtGui.QGraphicsView.__init__(self, parent)
self.isLive = live
self.imageManager = imageManager
self.screens = ScreenList.get_instance()
self.alertTab = None
self.plugins = PluginManager.get_instance().plugins
self.rebuildCSS = False
self.hideMode = None
self.videoHide = False
self.override = {}
@ -74,12 +77,32 @@ class MainDisplay(QtGui.QGraphicsView):
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
if self.isLive:
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
QtCore.SIGNAL(u'live_display_hide'), self.hideDisplay)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay)
QtCore.SIGNAL(u'live_display_show'), self.showDisplay)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_phonon_creation'),
self.createMediaObject)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_display_css'), self.cssChanged)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configChanged)
def cssChanged(self):
"""
We may need to rebuild the CSS on the live display.
"""
self.rebuildCSS = True
def configChanged(self):
"""
Call the plugins to rebuild the Live display CSS as the screen has
not been rebuild on exit of config.
"""
if self.rebuildCSS and self.plugins:
for plugin in self.plugins:
plugin.refreshCss(self.frame)
self.rebuildCSS = False
def retranslateUi(self):
"""
@ -111,6 +134,9 @@ class MainDisplay(QtGui.QGraphicsView):
self.screen[u'size'].width(), self.screen[u'size'].height())
self.page = self.webView.page()
self.frame = self.page.mainFrame()
if self.isLive and log.getEffectiveLevel() == logging.DEBUG:
self.webView.settings().setAttribute(
QtWebKit.QWebSettings.DeveloperExtrasEnabled, True)
QtCore.QObject.connect(self.webView,
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
@ -120,14 +146,6 @@ class MainDisplay(QtGui.QGraphicsView):
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
QtCore.Qt.ScrollBarAlwaysOff)
if self.isLive:
# Build the initial frame.
self.black = QtGui.QImage(
self.screen[u'size'].width(),
self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
painter_image = QtGui.QPainter()
painter_image.begin(self.black)
painter_image.fillRect(self.black.rect(), QtCore.Qt.black)
# Build the initial frame.
image_file = QtCore.QSettings().value(u'advanced/default image',
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
@ -153,7 +171,7 @@ class MainDisplay(QtGui.QGraphicsView):
serviceItem = ServiceItem()
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
self.webView.setHtml(build_html(serviceItem, self.screen,
self.alertTab, self.isLive, None))
self.isLive, None))
self.__hideMouse()
# To display or not to display?
if not self.screen[u'primary']:
@ -184,7 +202,7 @@ class MainDisplay(QtGui.QGraphicsView):
"""
Add the slide text from slideController
`slide`
``slide``
The slide text to be displayed
"""
log.debug(u'text to display')
@ -194,24 +212,25 @@ class MainDisplay(QtGui.QGraphicsView):
self.setGeometry(self.screen[u'size'])
self.frame.evaluateJavaScript(u'show_text("%s")' %
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
return self.preview()
def alert(self, text):
def alert(self, text, location):
"""
Add the alert text
Display an alert.
`slide`
The slide text to be displayed
``text``
The text to be displayed.
"""
log.debug(u'alert to display')
if self.height() != self.screen[u'size'].height() or not \
self.isVisible() or self.videoWidget.isVisible():
shrink = True
else:
shrink = False
js = u'show_alert("%s", "%s")' % (
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'),
u'top' if shrink else u'')
u'top')
else:
shrink = False
js = u'show_alert("%s", "")' % (
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
height = self.frame.evaluateJavaScript(js)
if shrink:
if self.phononActive:
@ -222,10 +241,10 @@ class MainDisplay(QtGui.QGraphicsView):
alert_height = int(height.toString())
shrinkItem.resize(self.width(), alert_height)
shrinkItem.setVisible(True)
if self.alertTab.location == 1:
if location == AlertLocation.Middle:
shrinkItem.move(self.screen[u'size'].left(),
(self.screen[u'size'].height() - alert_height) / 2)
elif self.alertTab.location == 2:
elif location == AlertLocation.Bottom:
shrinkItem.move(self.screen[u'size'].left(),
self.screen[u'size'].height() - alert_height)
else:
@ -234,13 +253,16 @@ class MainDisplay(QtGui.QGraphicsView):
def directImage(self, name, path, background):
"""
API for replacement backgrounds so Images are added directly to cache
API for replacement backgrounds so Images are added directly to cache.
"""
self.imageManager.add_image(name, path, u'image', background)
if hasattr(self, u'serviceItem'):
self.override[u'image'] = name
self.override[u'theme'] = self.serviceItem.themedata.theme_name
self.image(name)
# Update the preview frame.
if self.isLive:
self.parent().updatePreview()
return True
return False
@ -249,14 +271,13 @@ class MainDisplay(QtGui.QGraphicsView):
Add an image as the background. The image has already been added
to the cache.
`Image`
The name of the image to be displayed
``Image``
The name of the image to be displayed.
"""
log.debug(u'image to display')
image = self.imageManager.get_image_bytes(name)
self.resetVideo()
self.displayImage(image)
return self.preview()
def displayImage(self, image):
"""
@ -268,14 +289,11 @@ class MainDisplay(QtGui.QGraphicsView):
else:
js = u'show_image("");'
self.frame.evaluateJavaScript(js)
# Update the preview frame.
if self.isLive:
Receiver.send_message(u'maindisplay_active')
def resetImage(self):
"""
Reset the backgound image to the service item image.
Used after Image plugin has changed the background
Reset the backgound image to the service item image. Used after the
image plugin has changed the background.
"""
log.debug(u'resetImage')
if hasattr(self, u'serviceItem'):
@ -284,9 +302,6 @@ class MainDisplay(QtGui.QGraphicsView):
self.displayImage(None)
# clear the cache
self.override = {}
# Update the preview frame.
if self.isLive:
Receiver.send_message(u'maindisplay_active')
def resetVideo(self):
"""
@ -302,9 +317,6 @@ class MainDisplay(QtGui.QGraphicsView):
else:
self.frame.evaluateJavaScript(u'show_video("close");')
self.override = {}
# Update the preview frame.
if self.isLive:
Receiver.send_message(u'maindisplay_active')
def videoPlay(self):
"""
@ -357,7 +369,7 @@ class MainDisplay(QtGui.QGraphicsView):
"""
# We request a background video but have no service Item
if isBackground and not hasattr(self, u'serviceItem'):
return None
return False
if not self.mediaObject:
self.createMediaObject()
log.debug(u'video')
@ -384,10 +396,7 @@ class MainDisplay(QtGui.QGraphicsView):
self.webView.setVisible(False)
self.videoWidget.setVisible(True)
self.audio.setVolume(vol)
# Update the preview frame.
if self.isLive:
Receiver.send_message(u'maindisplay_active')
return self.preview()
return True
def videoState(self, newState, oldState):
"""
@ -455,9 +464,8 @@ class MainDisplay(QtGui.QGraphicsView):
self.setVisible(True)
else:
self.setVisible(True)
preview = QtGui.QImage(self.screen[u'size'].width(),
self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
preview = QtGui.QPixmap(self.screen[u'size'].width(),
self.screen[u'size'].height())
painter = QtGui.QPainter(preview)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
self.frame.render(painter)
@ -495,8 +503,8 @@ class MainDisplay(QtGui.QGraphicsView):
image_bytes = self.imageManager.get_image_bytes(image)
else:
image_bytes = None
html = build_html(self.serviceItem, self.screen, self.alertTab,
self.isLive, background, image_bytes)
html = build_html(self.serviceItem, self.screen, self.isLive,
background, image_bytes, self.plugins)
log.debug(u'buildHtml - pre setHtml')
self.webView.setHtml(html)
log.debug(u'buildHtml - post setHtml')
@ -562,7 +570,7 @@ class MainDisplay(QtGui.QGraphicsView):
self.hideMode = None
# Trigger actions when display is active again
if self.isLive:
Receiver.send_message(u'maindisplay_active')
Receiver.send_message(u'live_display_active')
def __hideMouse(self):
# Hide mouse cursor when moved over display if enabled in settings

View File

@ -611,11 +611,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_version_check'), self.versionNotice)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_blank_check'), self.blankCheck)
QtCore.SIGNAL(u'live_display_blank_check'), self.blankCheck)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_status_text'), self.showStatusMessage)
QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage)
# Media Manager
QtCore.QObject.connect(self.mediaToolBox,
QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)

View File

@ -1160,7 +1160,6 @@ class ServiceManager(QtGui.QWidget):
# if not passed set to config value
if expand is None:
expand = self.expandTabs
item.render()
item.from_service = True
if replace:
sitem, child = self.findServiceItem()
@ -1169,6 +1168,7 @@ class ServiceManager(QtGui.QWidget):
self.repaintServiceList(sitem, child)
self.mainwindow.liveController.replaceServiceManagerItem(item)
else:
item.render()
# nothing selected for dnd
if self.dropPosition == 0:
if isinstance(item, list):

View File

@ -58,7 +58,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
# load all the settings
self.settingListWidget.clear()
for tabIndex in range(0, self.stackedLayout.count() + 1):
# take at 0 and the rest shuffell up.
# take at 0 and the rest shuffle up.
self.stackedLayout.takeAt(0)
self.insertTab(self.generalTab, 0, PluginStatus.Active)
self.insertTab(self.themesTab, 1, PluginStatus.Active)

View File

@ -79,7 +79,6 @@ class SlideController(QtGui.QWidget):
self.songEdit = False
self.selectedRow = 0
self.serviceItem = None
self.alertTab = None
self.panel = QtGui.QWidget(parent.controlSplitter)
self.slideList = {}
# Layout for holding panel
@ -118,7 +117,7 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.horizontalHeader().setVisible(False)
self.previewListWidget.setColumnWidth(0, self.controller.width())
self.previewListWidget.isLive = self.isLive
self.previewListWidget.setObjectName(u'PreviewListWidget')
self.previewListWidget.setObjectName(u'previewListWidget')
self.previewListWidget.setSelectionBehavior(
QtGui.QAbstractItemView.SelectRows)
self.previewListWidget.setSelectionMode(
@ -288,14 +287,14 @@ class SlideController(QtGui.QWidget):
QtGui.QSizePolicy.Label))
self.previewFrame.setFrameShape(QtGui.QFrame.StyledPanel)
self.previewFrame.setFrameShadow(QtGui.QFrame.Sunken)
self.previewFrame.setObjectName(u'PreviewFrame')
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.slideLayout.setObjectName(u'slideLayout')
if not self.isLive:
self.mediaObject = Phonon.MediaObject(self)
self.video = Phonon.VideoWidget()
@ -319,7 +318,7 @@ class SlideController(QtGui.QWidget):
self.slidePreview.setFrameShadow(QtGui.QFrame.Plain)
self.slidePreview.setLineWidth(1)
self.slidePreview.setScaledContents(True)
self.slidePreview.setObjectName(u'SlidePreview')
self.slidePreview.setObjectName(u'slidePreview')
self.slideLayout.insertWidget(0, self.slidePreview)
self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
# Signals
@ -328,8 +327,6 @@ class SlideController(QtGui.QWidget):
if self.isLive:
QtCore.QObject.connect(self.volumeSlider,
QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
self.receiveSpinDelay)
@ -351,18 +348,12 @@ class SlideController(QtGui.QWidget):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
self.onStopLoop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_first' % self.typePrefix),
self.onSlideSelectedFirst)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_next' % self.typePrefix),
self.onSlideSelectedNext)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_previous' % self.typePrefix),
self.onSlideSelectedPrevious)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_last' % self.typePrefix),
self.onSlideSelectedLast)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_change' % self.typePrefix),
self.onSlideChange)
@ -375,9 +366,6 @@ class SlideController(QtGui.QWidget):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
self.onSlideUnblank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix),
self.onTextRequest)
def setPreviewHotkeys(self, parent=None):
self.previousItem.setObjectName(u'previousItemPreview')
@ -434,7 +422,6 @@ class SlideController(QtGui.QWidget):
if self.display:
self.display.close()
self.display = MainDisplay(self, self.imageManager, self.isLive)
self.display.alertTab = self.alertTab
self.display.setup()
if self.isLive:
self.__addActionsToWidget(self.display)
@ -723,41 +710,7 @@ class SlideController(QtGui.QWidget):
else:
self.__checkUpdateSelectedSlide(slideno)
def onTextRequest(self):
"""
Return the text for the current item in controller
"""
data = []
if self.serviceItem:
for framenumber, frame in enumerate(self.serviceItem.get_frames()):
dataItem = {}
if self.serviceItem.is_text():
dataItem[u'tag'] = unicode(frame[u'verseTag'])
dataItem[u'text'] = unicode(frame[u'html'])
else:
dataItem[u'tag'] = unicode(framenumber)
dataItem[u'text'] = u''
dataItem[u'selected'] = \
(self.previewListWidget.currentRow() == framenumber)
data.append(dataItem)
Receiver.send_message(u'slidecontroller_%s_text_response'
% self.typePrefix, data)
# Screen event methods
def onSlideSelectedFirst(self):
"""
Go to the first slide.
"""
if not self.serviceItem:
return
if self.serviceItem.is_command():
Receiver.send_message(u'%s_first' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
self.updatePreview()
else:
self.previewListWidget.selectRow(0)
self.slideSelected()
def onSlideSelectedIndex(self, message):
"""
Go to the requested slide
@ -790,9 +743,9 @@ class SlideController(QtGui.QWidget):
elif display_type == u'blanked':
self.onBlankDisplay(True)
else:
Receiver.send_message(u'maindisplay_show')
Receiver.send_message(u'live_display_show')
else:
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
def onSlideBlank(self):
"""
@ -878,21 +831,21 @@ class SlideController(QtGui.QWidget):
if self.serviceItem is not None:
if hide_mode:
if not self.serviceItem.is_command():
Receiver.send_message(u'maindisplay_hide', hide_mode)
Receiver.send_message(u'live_display_hide', hide_mode)
Receiver.send_message(u'%s_blank'
% self.serviceItem.name.lower(),
[self.serviceItem, self.isLive, hide_mode])
else:
if not self.serviceItem.is_command():
Receiver.send_message(u'maindisplay_show')
Receiver.send_message(u'live_display_show')
Receiver.send_message(u'%s_unblank'
% self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
else:
if hide_mode:
Receiver.send_message(u'maindisplay_hide', hide_mode)
Receiver.send_message(u'live_display_hide', hide_mode)
else:
Receiver.send_message(u'maindisplay_show')
Receiver.send_message(u'live_display_show')
def hidePlugin(self, hide):
"""
@ -901,21 +854,21 @@ class SlideController(QtGui.QWidget):
log.debug(u'hidePlugin %s ', hide)
if self.serviceItem is not None:
if hide:
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
Receiver.send_message(u'%s_hide'
% self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
else:
if not self.serviceItem.is_command():
Receiver.send_message(u'maindisplay_show')
Receiver.send_message(u'live_display_show')
Receiver.send_message(u'%s_unblank'
% self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
else:
if hide:
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
else:
Receiver.send_message(u'maindisplay_show')
Receiver.send_message(u'live_display_show')
def onSlideSelected(self, start=False):
"""
@ -936,20 +889,18 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(
u'%s_slide' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive, row])
self.updatePreview()
else:
toDisplay = self.serviceItem.get_rendered_frame(row)
if self.serviceItem.is_text():
frame = self.display.text(toDisplay)
self.display.text(toDisplay)
else:
if start:
self.display.buildHtml(self.serviceItem, toDisplay)
frame = self.display.preview()
else:
frame = self.display.image(toDisplay)
self.display.image(toDisplay)
# reset the store used to display first image
self.serviceItem.bg_image_bytes = None
self.slidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
self.updatePreview()
self.selectedRow = row
self.__checkUpdateSelectedSlide(row)
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
@ -977,8 +928,7 @@ class SlideController(QtGui.QWidget):
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
else:
self.slidePreview.setPixmap(
QtGui.QPixmap.fromImage(self.display.preview()))
self.slidePreview.setPixmap(self.display.preview())
def grabMainDisplay(self):
"""
@ -1041,21 +991,6 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.item(row + 1, 0))
self.previewListWidget.selectRow(row)
def onSlideSelectedLast(self):
"""
Go to the last slide.
"""
if not self.serviceItem:
return
Receiver.send_message(u'%s_last' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive])
if self.serviceItem.is_command():
self.updatePreview()
else:
self.previewListWidget.selectRow(
self.previewListWidget.rowCount() - 1)
self.slideSelected()
def onToggleLoop(self):
"""
Toggles the loop state.

View File

@ -36,8 +36,7 @@ class SplashScreen(QtGui.QSplashScreen):
QtCore.SIGNAL(u'close_splash'), self.close)
def setupUi(self):
self.setObjectName(u'splash_screen')
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.setObjectName(u'splashScreen')
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
splash_image = QtGui.QPixmap(u':/graphics/openlp-splash-screen.png')
self.setPixmap(splash_image)

View File

@ -33,6 +33,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui import ThemeLayoutForm
from openlp.core.utils import get_images_filter
from themewizard import Ui_ThemeWizard
@ -58,6 +59,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.registerFields()
self.updateThemeAllowed = True
self.temp_background_filename = u''
self.themeLayoutForm = ThemeLayoutForm(self)
QtCore.QObject.connect(self.backgroundComboBox,
QtCore.SIGNAL(u'currentIndexChanged(int)'),
self.onBackgroundComboBoxCurrentIndexChanged)
@ -88,6 +90,9 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.onShadowCheckCheckBoxStateChanged)
QtCore.QObject.connect(self.footerColorButton,
QtCore.SIGNAL(u'clicked()'), self.onFooterColorButtonClicked)
QtCore.QObject.connect(self,
QtCore.SIGNAL(u'customButtonClicked(int)'),
self.onCustom1ButtonClicked)
QtCore.QObject.connect(self.mainPositionCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onMainPositionCheckBoxStateChanged)
@ -229,13 +234,36 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
"""
Detects Page changes and updates as approprate.
"""
if self.page(pageId) == self.areaPositionPage:
self.setOption(QtGui.QWizard.HaveCustomButton1, True)
else:
self.setOption(QtGui.QWizard.HaveCustomButton1, False)
if self.page(pageId) == self.previewPage:
self.updateTheme()
frame = self.thememanager.generateImage(self.theme)
self.previewBoxLabel.setPixmap(QtGui.QPixmap.fromImage(frame))
self.previewBoxLabel.setPixmap(frame)
self.displayAspectRatio = float(frame.width()) / frame.height()
self.resizeEvent()
def onCustom1ButtonClicked(self, number):
"""
Generate layout preview and display the form.
"""
self.updateTheme()
width = self.thememanager.mainwindow.renderer.width
height = self.thememanager.mainwindow.renderer.height
pixmap = QtGui.QPixmap(width, height)
pixmap.fill(QtCore.Qt.white)
paint = QtGui.QPainter(pixmap)
paint.setPen(QtGui.QPen(QtCore.Qt.blue, 2))
paint.drawRect(self.thememanager.mainwindow.renderer.
get_main_rectangle(self.theme))
paint.setPen(QtGui.QPen(QtCore.Qt.red, 2))
paint.drawRect(self.thememanager.mainwindow.renderer.
get_footer_rectangle(self.theme))
paint.end()
self.themeLayoutForm.exec_(pixmap)
def onOutlineCheckCheckBoxStateChanged(self, state):
"""
Change state as Outline check box changed

View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_ThemeLayoutDialog(object):
def setupUi(self, themeLayoutDialog):
themeLayoutDialog.setObjectName(u'themeLayoutDialogDialog')
#themeLayoutDialog.resize(300, 200)
self.previewLayout = QtGui.QVBoxLayout(themeLayoutDialog)
self.previewLayout.setObjectName(u'PreviewLayout')
self.previewArea = QtGui.QWidget(themeLayoutDialog)
self.previewArea.setObjectName(u'PreviewArea')
self.previewAreaLayout = QtGui.QGridLayout(self.previewArea)
self.previewAreaLayout.setMargin(0)
self.previewAreaLayout.setColumnStretch(0, 1)
self.previewAreaLayout.setRowStretch(0, 1)
self.previewAreaLayout.setObjectName(u'PreviewAreaLayout')
self.themeDisplayLabel = QtGui.QLabel(self.previewArea)
self.themeDisplayLabel.setFrameShape(QtGui.QFrame.Box)
self.themeDisplayLabel.setScaledContents(True)
self.themeDisplayLabel.setObjectName(u'ThemeDisplayLabel')
self.previewAreaLayout.addWidget(self.themeDisplayLabel)
self.previewLayout.addWidget(self.previewArea)
self.mainColourLabel = QtGui.QLabel(self.previewArea)
self.mainColourLabel.setObjectName(u'MainColourLabel')
self.previewLayout.addWidget(self.mainColourLabel)
self.footerColourLabel = QtGui.QLabel(self.previewArea)
self.footerColourLabel.setObjectName(u'FooterColourLabel')
self.previewLayout.addWidget(self.footerColourLabel)
self.buttonBox = QtGui.QDialogButtonBox(themeLayoutDialog)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(u'ButtonBox')
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
themeLayoutDialog.accept)
self.previewLayout.addWidget(self.buttonBox)
self.retranslateUi(themeLayoutDialog)
QtCore.QMetaObject.connectSlotsByName(themeLayoutDialog)
def retranslateUi(self, themeLayoutDialog):
themeLayoutDialog.setWindowTitle(
translate('OpenLP.StartTimeForm', 'Theme Layout'))
self.mainColourLabel.setText(translate('OpenLP.StartTimeForm',
'The blue box shows the main area.'))
self.footerColourLabel.setText(translate('OpenLP.StartTimeForm',
'The red box shows the footer.'))

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtGui, QtCore
from themelayoutdialog import Ui_ThemeLayoutDialog
from openlp.core.lib import translate
from openlp.core.lib.ui import UiStrings, critical_error_message_box
class ThemeLayoutForm(QtGui.QDialog, Ui_ThemeLayoutDialog):
"""
The exception dialog
"""
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
def exec_(self, image):
"""
Run the Dialog with correct heading.
"""
pixmap = image.scaledToHeight(400, QtCore.Qt.SmoothTransformation)
self.themeDisplayLabel.setPixmap(image)
displayAspectRatio = float(image.width()) / image.height()
self.themeDisplayLabel.setFixedSize(400, 400 / displayAspectRatio )
return QtGui.QDialog.exec_(self)
def accept(self):
return QtGui.QDialog.accept(self)

View File

@ -38,7 +38,8 @@ class Ui_ThemeWizard(object):
themeWizard.setModal(True)
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
QtGui.QWizard.NoBackButtonOnStartPage)
QtGui.QWizard.NoBackButtonOnStartPage |
QtGui.QWizard.HaveCustomButton1)
self.spacer = QtGui.QSpacerItem(10, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
# Welcome Page
@ -535,6 +536,9 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'px'))
self.footerPositionCheckBox.setText(
translate('OpenLP.ThemeWizard', 'Use default location'))
themeWizard.setOption(QtGui.QWizard.HaveCustomButton1, False)
themeWizard.setButtonText(QtGui.QWizard.CustomButton1,
translate('OpenLP.ThemeWizard', 'Layout Preview'))
self.previewPage.setTitle(
translate('OpenLP.ThemeWizard', 'Save and Preview'))
self.previewPage.setSubTitle(

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager
from openlp.core.lib.ui import icon_action, UiStrings
from openlp.core.lib.theme import VerticalType
from openlp.core.utils.actions import ActionList
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
from openlp.plugins.alerts.lib.db import init_schema
@ -39,6 +40,76 @@ from openlp.plugins.alerts.forms import AlertForm
log = logging.getLogger(__name__)
JAVASCRIPT = """
function show_alert(alerttext, position){
var text = document.getElementById('alert');
text.innerHTML = alerttext;
if(alerttext == '') {
text.style.visibility = 'hidden';
return 0;
}
if(position == ''){
position = getComputedStyle(text, '').verticalAlign;
}
switch(position)
{
case 'top':
text.style.top = '0px';
break;
case 'middle':
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
+ 'px';
break;
case 'bottom':
text.style.top = (window.innerHeight - text.clientHeight)
+ 'px';
break;
}
text.style.visibility = 'visible';
return text.clientHeight;
}
function update_css(align, font, size, color, bgcolor){
var text = document.getElementById('alert');
text.style.fontSize = size + "pt";
text.style.fontFamily = font;
text.style.color = color;
text.style.backgroundColor = bgcolor;
switch(align)
{
case 'top':
text.style.top = '0px';
break;
case 'middle':
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
+ 'px';
break;
case 'bottom':
text.style.top = (window.innerHeight - text.clientHeight)
+ 'px';
break;
}
}
"""
CSS = """
#alert {
position: absolute;
left: 0px;
top: 0px;
z-index: 10;
width: 100%%;
vertical-align: %s;
font-family: %s;
font-size: %spt;
color: %s;
background-color: %s;
}
"""
HTML = """
<div id="alert" style="visibility:hidden"></div>
"""
class AlertsPlugin(Plugin):
log.info(u'Alerts Plugin loaded')
@ -79,7 +150,6 @@ class AlertsPlugin(Plugin):
self.toolsAlertItem.setVisible(True)
action_list = ActionList.get_instance()
action_list.add_action(self.toolsAlertItem, UiStrings().Tools)
self.liveController.alertTab = self.settings_tab
def finalise(self):
"""
@ -121,3 +191,35 @@ class AlertsPlugin(Plugin):
u'title': translate('AlertsPlugin', 'Alerts', 'container title')
}
def getDisplayJavaScript(self):
"""
Add Javascript to the main display.
"""
return JAVASCRIPT
def getDisplayCss(self):
"""
Add CSS to the main display.
"""
align = VerticalType.Names[self.settings_tab.location]
return CSS % (align, self.settings_tab.font_face,
self.settings_tab.font_size, self.settings_tab.font_color,
self.settings_tab.bg_color)
def getDisplayHtml(self):
"""
Add HTML to the main display.
"""
return HTML
def refreshCss(self, frame):
"""
Trigger an update of the CSS in the maindisplay.
``frame``
The Web frame holding the page.
"""
align = VerticalType.Names[self.settings_tab.location]
frame.evaluateJavaScript(u'update_css("%s", "%s", "%s", "%s", "%s")' %
(align, self.settings_tab.font_face, self.settings_tab.font_size,
self.settings_tab.font_color, self.settings_tab.bg_color))

View File

@ -45,7 +45,7 @@ class AlertsManager(QtCore.QObject):
self.timer_id = 0
self.alertList = []
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_active'), self.generateAlert)
QtCore.SIGNAL(u'live_display_active'), self.generateAlert)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'alerts_text'), self.onAlertText)
@ -69,11 +69,11 @@ class AlertsManager(QtCore.QObject):
log.debug(u'display alert called %s' % text)
self.alertList.append(text)
if self.timer_id != 0:
Receiver.send_message(u'maindisplay_status_text',
Receiver.send_message(u'mainwindow_status_text',
translate('AlertsPlugin.AlertsManager',
'Alert message created and displayed.'))
return
Receiver.send_message(u'maindisplay_status_text', u'')
Receiver.send_message(u'mainwindow_status_text', u'')
self.generateAlert()
def generateAlert(self):
@ -81,11 +81,11 @@ class AlertsManager(QtCore.QObject):
Format and request the Alert and start the timer
"""
log.debug(u'Generate Alert called')
if len(self.alertList) == 0:
if not self.alertList:
return
text = self.alertList.pop(0)
alertTab = self.parent().settings_tab
self.parent().liveController.display.alert(text)
self.parent().liveController.display.alert(text, alertTab.location)
# Check to see if we have a timer running.
if self.timer_id == 0:
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
@ -100,7 +100,8 @@ class AlertsManager(QtCore.QObject):
"""
log.debug(u'timer event')
if event.timerId() == self.timer_id:
self.parent().liveController.display.alert(u'')
alertTab = self.parent().settings_tab
self.parent().liveController.display.alert(u'', alertTab.location)
self.killTimer(self.timer_id)
self.timer_id = 0
self.generateAlert()

View File

@ -27,7 +27,8 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate
from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.ui import AlertLocation
from openlp.core.lib.ui import UiStrings, create_valign_combo
class AlertsTab(SettingsTab):
@ -140,6 +141,7 @@ class AlertsTab(SettingsTab):
def onTimeoutSpinBoxChanged(self):
self.timeout = self.timeoutSpinBox.value()
self.changed = True
def onFontSizeSpinBoxChanged(self):
self.font_size = self.fontSizeSpinBox.value()
@ -158,7 +160,7 @@ class AlertsTab(SettingsTab):
self.font_face = unicode(settings.value(
u'font face', QtCore.QVariant(QtGui.QFont().family())).toString())
self.location = settings.value(
u'location', QtCore.QVariant(1)).toInt()[0]
u'location', QtCore.QVariant(AlertLocation.Bottom)).toInt()[0]
settings.endGroup()
self.fontSizeSpinBox.setValue(self.font_size)
self.timeoutSpinBox.setValue(self.timeout)
@ -171,10 +173,15 @@ class AlertsTab(SettingsTab):
font.setFamily(self.font_face)
self.fontComboBox.setCurrentFont(font)
self.updateDisplay()
self.changed = False
def save(self):
settings = QtCore.QSettings()
settings.beginGroup(self.settingsSection)
# Check value has changed as no event handles this field
if settings.value(u'location', QtCore.QVariant(1)).toInt()[0] != \
self.verticalComboBox.currentIndex():
self.changed = True
settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
settings.setValue(u'font color', QtCore.QVariant(self.font_color))
settings.setValue(u'font size', QtCore.QVariant(self.font_size))
@ -184,6 +191,9 @@ class AlertsTab(SettingsTab):
self.location = self.verticalComboBox.currentIndex()
settings.setValue(u'location', QtCore.QVariant(self.location))
settings.endGroup()
if self.changed:
Receiver.send_message(u'update_display_css')
self.changed = False
def updateDisplay(self):
font = QtGui.QFont()
@ -193,4 +203,5 @@ class AlertsTab(SettingsTab):
self.fontPreview.setFont(font)
self.fontPreview.setStyleSheet(u'background-color: %s; color: %s' %
(self.bg_color, self.font_color))
self.changed = True

View File

@ -461,6 +461,11 @@ class BibleImportForm(OpenLPWizard):
WizardStrings.YouSpecifyFile % WizardStrings.OS)
self.openSongFileEdit.setFocus()
return False
elif self.field(u'source_format').toInt()[0] == \
BibleFormat.WebDownload:
self.versionNameEdit.setText(
self.webTranslationComboBox.currentText())
return True
elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1:
if not self.field(u'openlp1_location').toString():
critical_error_message_box(UiStrings().NFSs,

View File

@ -28,7 +28,6 @@
import logging
import chardet
import os
import re
import sqlite3
from PyQt4 import QtCore

View File

@ -82,13 +82,16 @@ class BGExtract(object):
Receiver.send_message(u'openlp_process_events')
footnotes = soup.findAll(u'sup', u'footnote')
if footnotes:
[footnote.extract() for footnote in footnotes]
for footnote in footnotes:
footnote.extract()
crossrefs = soup.findAll(u'sup', u'xref')
if crossrefs:
[crossref.extract() for crossref in crossrefs]
for crossref in crossrefs:
crossref.extract()
headings = soup.findAll(u'h5')
if headings:
[heading.extract() for heading in headings]
for heading in headings:
heading.extract()
cleanup = [(re.compile('\s+'), lambda match: ' ')]
verses = BeautifulSoup(str(soup), markupMassage=cleanup)
verse_list = {}

View File

@ -28,7 +28,6 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.lib.ui import UiStrings, create_valign_combo
class ImageTab(SettingsTab):
"""

View File

@ -39,7 +39,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box
log = logging.getLogger(__name__)
CLAPPERBOARD = QtGui.QPixmap(u':/media/media_video.png').toImage()
CLAPPERBOARD = QtGui.QImage(u':/media/media_video.png')
class MediaMediaItem(MediaManagerItem):
"""
@ -95,14 +95,14 @@ class MediaMediaItem(MediaManagerItem):
def onResetClick(self):
"""
Called to reset the Live backgound with the media selected,
Called to reset the Live backgound with the media selected.
"""
self.resetAction.setVisible(False)
self.plugin.liveController.display.resetVideo()
def videobackgroundReplaced(self):
"""
Triggered by main display on change of serviceitem
Triggered by main display on change of serviceitem.
"""
self.resetAction.setVisible(False)
@ -179,8 +179,7 @@ class MediaMediaItem(MediaManagerItem):
def mediaStateWait(self, mediaState):
"""
Wait for the video to change its state
Wait no longer than 5 seconds.
Wait for the video to change its state. Wait no longer than 5 seconds.
"""
start = datetime.now()
while self.mediaObject.state() != mediaState:
@ -198,7 +197,7 @@ class MediaMediaItem(MediaManagerItem):
def onDeleteClick(self):
"""
Remove a media item from the list
Remove a media item from the list.
"""
if check_item_selected(self.listView, translate('MediaPlugin.MediaItem',
'You must select a media file to delete.')):

View File

@ -68,7 +68,7 @@ class Controller(object):
self.doc.slidenumber = slide_no
if self.is_live:
if hide_mode == HideMode.Screen:
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
self.stop()
elif hide_mode == HideMode.Theme:
self.blank(hide_mode)
@ -76,7 +76,7 @@ class Controller(object):
self.blank(hide_mode)
else:
self.doc.start_presentation()
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
self.doc.slidenumber = 0
if slide_no > 1:
self.slide(slide_no)
@ -196,7 +196,7 @@ class Controller(object):
if not self.doc.is_active():
return
if hide_mode == HideMode.Theme:
Receiver.send_message(u'maindisplay_hide', HideMode.Theme)
Receiver.send_message(u'live_display_hide', HideMode.Theme)
self.doc.blank_screen()
def stop(self):
@ -224,7 +224,7 @@ class Controller(object):
self.doc.slidenumber != self.doc.get_slide_number():
self.doc.goto_slide(self.doc.slidenumber)
self.doc.unblank_screen()
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
Receiver.send_message(u'live_display_hide', HideMode.Screen)
def poll(self):
self.doc.poll_slidenumber(self.is_live)

View File

@ -32,7 +32,7 @@ import shutil
from PyQt4 import QtCore
from openlp.core.lib import Receiver, check_directory_exists, create_thumb, \
resize_image, validate_thumb
validate_thumb
from openlp.core.utils import AppLocation
log = logging.getLogger(__name__)

View File

@ -87,7 +87,7 @@ class PresentationPlugin(Plugin):
to close down their applications and release resources.
"""
log.info(u'Plugin Finalise')
#Ask each controller to tidy up
# Ask each controller to tidy up.
for key in self.controllers:
controller = self.controllers[key]
if controller.enabled():

View File

@ -121,11 +121,11 @@ window.OpenLP = {
$("#nextslide").html(text);
}
},
updateClock: function() {
updateClock: function(data) {
var div = $("#clock");
var t = new Date();
var h = t.getHours();
if (h > 12)
if (data.results.twelve && h > 12)
h = h - 12;
var m = t.getMinutes();
if (m < 10)
@ -136,7 +136,7 @@ window.OpenLP = {
$.getJSON(
"/api/poll",
function (data, status) {
OpenLP.updateClock();
OpenLP.updateClock(data);
if (OpenLP.currentItem != data.results.item) {
OpenLP.currentItem = data.results.item;
OpenLP.loadSlides();

View File

@ -315,7 +315,7 @@ class HttpConnection(object):
"""
log.debug(u'ready to read socket')
if self.socket.canReadLine():
data = unicode(self.socket.readLine())
data = unicode(self.socket.readLine()).encode(u'utf-8')
log.debug(u'received: ' + data)
words = data.split(u' ')
response = None
@ -397,7 +397,9 @@ class HttpConnection(object):
result = {
u'slide': self.parent.current_slide or 0,
u'item': self.parent.current_item._uuid \
if self.parent.current_item else u''
if self.parent.current_item else u'',
u'twelve':QtCore.QSettings().value(
u'remotes/twelve hour', QtCore.QVariant(True)).toBool()
}
return HttpResponse(json.dumps({u'results': result}),
{u'Content-Type': u'application/json'})

View File

@ -57,6 +57,9 @@ class RemoteTab(SettingsTab):
QtCore.QObject.connect(self.addressEdit,
QtCore.SIGNAL(u'textChanged(const QString&)'), self.setUrls)
self.serverSettingsLayout.addRow(self.addressLabel, self.addressEdit)
self.twelveHourCheckBox = QtGui.QCheckBox(self.serverSettingsGroupBox)
self.twelveHourCheckBox.setObjectName(u'twelveHourCheckBox')
self.serverSettingsLayout.addRow(self.twelveHourCheckBox)
self.portLabel = QtGui.QLabel(self.serverSettingsGroupBox)
self.portLabel.setObjectName(u'portLabel')
self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
@ -80,6 +83,9 @@ class RemoteTab(SettingsTab):
self.leftLayout.addWidget(self.serverSettingsGroupBox)
self.leftLayout.addStretch()
self.rightLayout.addStretch()
QtCore.QObject.connect(self.twelveHourCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onTwelveHourCheckBoxChanged)
def retranslateUi(self):
self.serverSettingsGroupBox.setTitle(
@ -92,6 +98,9 @@ class RemoteTab(SettingsTab):
'Remote URL:'))
self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
'Stage view URL:'))
self.twelveHourCheckBox.setText(
translate('RemotePlugin.RemoteTab',
'Display stage time in 12h format'))
def setUrls(self):
ipAddress = u'localhost'
@ -123,6 +132,10 @@ class RemoteTab(SettingsTab):
self.addressEdit.setText(
QtCore.QSettings().value(self.settingsSection + u'/ip address',
QtCore.QVariant(ZERO_URL)).toString())
self.twelveHour = QtCore.QSettings().value(
self.settingsSection + u'/twelve hour',
QtCore.QVariant(True)).toBool()
self.twelveHourCheckBox.setChecked(self.twelveHour)
self.setUrls()
def save(self):
@ -130,3 +143,11 @@ class RemoteTab(SettingsTab):
QtCore.QVariant(self.portSpinBox.value()))
QtCore.QSettings().setValue(self.settingsSection + u'/ip address',
QtCore.QVariant(self.addressEdit.text()))
QtCore.QSettings().setValue(self.settingsSection + u'/twelve hour',
QtCore.QVariant(self.twelveHour))
def onTwelveHourCheckBoxChanged(self, check_state):
self.twelveHour = False
# we have a set value convert to True/False
if check_state == QtCore.Qt.Checked:
self.twelveHour = True

View File

@ -240,8 +240,9 @@ class SongImportForm(OpenLPWizard):
self.formatLabel.setText(WizardStrings.FormatLabel)
self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2)
self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1)
self.formatComboBox.setItemText(
SongFormat.OpenLyrics, WizardStrings.OL)
self.formatComboBox.setItemText(SongFormat.OpenLyrics,
translate('SongsPlugin.ImportWizardForm',
'OpenLyrics or OpenLP 2.0 Exported Song'))
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
self.formatComboBox.setItemText(
SongFormat.WordsOfWorship, WizardStrings.WoW)
@ -508,7 +509,8 @@ class SongImportForm(OpenLPWizard):
Get OpenLyrics song database files
"""
self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL,
self.openLyricsFileListWidget)
self.openLyricsFileListWidget, u'%s (*.xml)' %
translate('SongsPlugin.ImportWizardForm', 'OpenLyrics Files'))
def onOpenLyricsRemoveButtonClicked(self):
"""

View File

@ -333,5 +333,6 @@ class CCLIFileImport(SongImport):
if len(author_list) < 2:
author_list = song_author.split(u'|')
# Clean spaces before and after author names.
[self.addAuthor(author_name.strip()) for author_name in author_list]
for author_name in author_list:
self.addAuthor(author_name.strip())
return self.finish()

View File

@ -258,7 +258,7 @@ class EasiSlidesImport(SongImport):
verses[reg][vt][vn] = {}
if not verses[reg][vt][vn].has_key(inst):
verses[reg][vt][vn][inst] = []
words = self.tidy_text(line)
words = self.tidyText(line)
verses[reg][vt][vn][inst].append(words)
# done parsing

View File

@ -397,7 +397,8 @@ class SongMediaItem(MediaManagerItem):
try:
os.remove(media_file.file_name)
except:
log.exception('Could not remove file: %s', audio)
log.exception('Could not remove file: %s',
media_file.file_name)
try:
save_path = os.path.join(AppLocation.get_section_data_path(
self.plugin.name), 'audio', str(item_id))

View File

@ -30,7 +30,6 @@ songs from the database to the OpenLyrics format.
"""
import logging
import os
import re
from lxml import etree

View File

@ -194,7 +194,7 @@ class SofImport(OooImport):
into line
"""
text = textportion.getString()
text = self.tidy_text(text)
text = self.tidyText(text)
if text.strip() == u'':
return text
if textportion.CharWeight == BOLD:

View File

@ -29,7 +29,7 @@ The :mod:`upgrade` module provides a way for the database and schema that is the
backend for the Songs plugin
"""
from sqlalchemy import Column, ForeignKey, Table, types
from sqlalchemy import Column, Table, types
from sqlalchemy.sql.expression import func
from migrate import changeset
from migrate.changeset.constraint import ForeignKeyConstraint

View File

@ -60,7 +60,7 @@ The XML of an `OpenLyrics <http://openlyrics.info/>`_ song looks like this::
</lyrics>
</song>
"""
import cgi
import logging
import re
@ -257,11 +257,12 @@ class OpenLyrics(object):
"""
IMPLEMENTED_VERSION = u'0.8'
START_TAGS_REGEX = re.compile(r'\{(\w+)\}')
END_TAGS_REGEX = re.compile(r'\{\/(\w+)\}')
VERSE_NUMBER_REGEX = re.compile(u'[a-zA-Z]*')
def __init__(self, manager):
self.manager = manager
self.start_tags_regex = re.compile(r'\{(\w+)\}') # {abc} -> abc
self.end_tags_regex = re.compile(r'\{\/(\w+)\}') # {/abc} -> abc
def song_to_xml(self, song):
"""
@ -334,7 +335,8 @@ class OpenLyrics(object):
if u'lang' in verse[0]:
verse_element.set(u'lang', verse[0][u'lang'])
# Create a list with all "virtual" verses.
virtual_verses = verse[1].split(u'[---]')
virtual_verses = cgi.escape(verse[1])
virtual_verses = virtual_verses.split(u'[---]')
for index, virtual_verse in enumerate(virtual_verses):
# Add formatting tags to text
lines_element = self._add_text_with_tags_to_lines(verse_element,
@ -402,32 +404,32 @@ class OpenLyrics(object):
def _add_tag_to_formatting(self, tag_name, tags_element):
"""
Add new formatting tag to the element ``<format>``
if the tag is not present yet.
Add new formatting tag to the element ``<format>`` if the tag is not
present yet.
"""
available_tags = FormattingTags.get_html_tags()
start_tag = '{%s}' % tag_name
for t in available_tags:
if t[u'start tag'] == start_tag:
for tag in available_tags:
if tag[u'start tag'] == start_tag:
# Create new formatting tag in openlyrics xml.
el = self._add_text_to_element(u'tag', tags_element)
el.set(u'name', tag_name)
el_open = self._add_text_to_element(u'open', el)
el_open.text = etree.CDATA(t[u'start html'])
element = self._add_text_to_element(u'tag', tags_element)
element.set(u'name', tag_name)
element_open = self._add_text_to_element(u'open', element)
element_open.text = etree.CDATA(tag[u'start html'])
# Check if formatting tag contains end tag. Some formatting
# tags e.g. {br} has only start tag. If no end tag is present
# <close> element has not to be in OpenLyrics xml.
if t['end tag']:
el_close = self._add_text_to_element(u'close', el)
el_close.text = etree.CDATA(t[u'end html'])
if tag['end tag']:
element_close = self._add_text_to_element(u'close', element)
element_close.text = etree.CDATA(tag[u'end html'])
def _add_text_with_tags_to_lines(self, verse_element, text, tags_element):
"""
Convert text with formatting tags from OpenLP format to OpenLyrics
format and append it to element ``<lines>``.
"""
start_tags = self.start_tags_regex.findall(text)
end_tags = self.end_tags_regex.findall(text)
start_tags = OpenLyrics.START_TAGS_REGEX.findall(text)
end_tags = OpenLyrics.END_TAGS_REGEX.findall(text)
# Replace start tags with xml syntax.
for tag in start_tags:
# Tags already converted to xml structure.
@ -442,12 +444,11 @@ class OpenLyrics(object):
if tag not in xml_tags:
self._add_tag_to_formatting(tag, tags_element)
# Replace end tags.
for t in end_tags:
text = text.replace(u'{/%s}' % t, u'</tag>')
for tag in end_tags:
text = text.replace(u'{/%s}' % tag, u'</tag>')
# Replace \n with <br/>.
text = text.replace(u'\n', u'<br/>')
text = u'<lines>' + text + u'</lines>'
element = etree.XML(text)
element = etree.XML(u'<lines>%s</lines>' % text)
verse_element.append(element)
return element
@ -692,7 +693,7 @@ class OpenLyrics(object):
verse_tag = verse_def[0]
else:
verse_tag = VerseType.Tags[VerseType.Other]
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_def)
verse_number = OpenLyrics.VERSE_NUMBER_REGEX.sub(u'', verse_def)
# OpenLyrics allows e. g. "c", but we need "c1". However, this does
# not correct the verse order.
if not verse_number:

View File

@ -28,7 +28,6 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_SongUsageDeleteDialog(object):
def setupUi(self, songUsageDeleteDialog):

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ThemeLayout</class>
<widget class="QDialog" name="ThemeLayout">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Theme Layout</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>50</x>
<y>260</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="themeDisplayLabel">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>361</width>
<height>231</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ThemeLayout</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ThemeLayout</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -60,8 +60,6 @@
</qresource>
<qresource prefix="slides">
<file>slide_close.png</file>
<file>slide_first.png</file>
<file>slide_last.png</file>
<file>slide_next.png</file>
<file>slide_blank.png</file>
<file>slide_desktop.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

View File

@ -65,8 +65,11 @@ Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription
[Files]
Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
Source: psvince.dll; Flags: dontcopy
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
; DLL used to check if the target program is running at install time
Source: psvince.dll; flags: dontcopy
; psvince is installed in {app} folder, so it will be loaded at
; uninstall time to check if the target program is running
Source: psvince.dll; DestDir: {app}
[Icons]
Name: {group}\{#AppName}; Filename: {app}\{#AppExeName}
@ -87,8 +90,13 @@ Root: HKCR; Subkey: "OpenLP\DefaultIcon"; ValueType: string; ValueName: ""; Valu
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
[Code]
function IsModuleLoaded(modulename: String ): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';
// Function to call psvince.dll at install time
function IsModuleLoadedInstall(modulename: AnsiString ): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall setuponly';
// Function to call psvince.dll at uninstall time
function IsModuleLoadedUninstall(modulename: AnsiString ): Boolean;
external 'IsModuleLoaded@{app}\psvince.dll stdcall uninstallonly' ;
function GetUninstallString(): String;
var
@ -133,7 +141,7 @@ end;
function InitializeSetup(): Boolean;
begin
Result := true;
while IsModuleLoaded( 'OpenLP.exe' ) and Result do
while IsModuleLoadedInstall( 'OpenLP.exe' ) and Result do
begin
if MsgBox( 'Openlp is currently running, please close it to continue the install.',
mbError, MB_OKCANCEL ) = IDCANCEL then
@ -153,3 +161,16 @@ begin
end;
end;
end;
function InitializeUninstall(): Boolean;
begin
Result := true;
while IsModuleLoadedUninstall( 'OpenLP.exe' ) and Result do
begin
if MsgBox( 'Openlp is currently running, please close it to continue the uninstall.',
mbError, MB_OKCANCEL ) = IDCANCEL then
begin
Result := false;
end;
end;
end;

View File

@ -8,7 +8,7 @@
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
@ -73,6 +73,7 @@ MODULES = [
'BeautifulSoup',
'mako',
'migrate',
'uno',
]

View File

@ -5,11 +5,11 @@
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode #
# Woldsund #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #

View File

@ -48,10 +48,10 @@ Inno Setup 5
Sphinx
This is used to build the documentation. The documentation trunk must be at
the same directory level as Openlp trunk and named "documentation"
the same directory level as Openlp trunk and named "documentation".
HTML Help Workshop
This is used to create the help file
This is used to create the help file.
PyInstaller
PyInstaller should be a checkout of revision 1470 of trunk, and in a
@ -65,10 +65,6 @@ PyInstaller
http://svn.pyinstaller.org/trunk
Then you need to copy the two hook-*.py files from the "pyinstaller"
subdirectory in OpenLP's "resources" directory into PyInstaller's
"PyInstaller/hooks" directory.
Bazaar
You need the command line "bzr" client installed.
@ -79,7 +75,7 @@ OpenLP
Visual C++ 2008 Express Edition
This is to build pptviewlib.dll, the library for controlling the
PowerPointViewer
PowerPointViewer.
windows-builder.py
This script, of course. It should be in the "scripts" directory of OpenLP.
@ -88,15 +84,25 @@ psvince.dll
This dll is used during the actual install of OpenLP to check if OpenLP is
running on the users machine prior to the setup. If OpenLP is running,
the install will fail. The dll can be obtained from here:
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
The dll is presently included in .\\resources\\windows
Mako
Mako Templates for Python. This package is required for building the
remote plugin. It can be installed by going to your
python_directory\scripts\.. and running "easy_install Mako". If you do not
have easy_install, the Mako package can be obtained here:
http://www.makotemplates.org/download.html
Sqlalchemy Migrate
Required for the data-bases used in OpenLP. The package can be
obtained here:
http://code.google.com/p/sqlalchemy-migrate/
"""
import os
@ -149,6 +155,7 @@ build_path = os.path.join(branch_path, u'build')
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
u'lib', u'pptviewlib')
hooks_path = os.path.join(branch_path , u'resources', u'pyinstaller')
def update_code():
os.chdir(branch_path)
@ -174,6 +181,7 @@ def run_pyinstaller():
u'--noconfirm',
u'--windowed',
u'--noupx',
u'--additional-hooks-dir', hooks_path,
u'-o', branch_path,
u'-i', win32_icon,
u'-p', branch_path,

View File

@ -8,7 +8,7 @@
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #

View File

@ -8,7 +8,7 @@
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Millar, Stevan Pettit, Andreas Preikschat, Mattias #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #