forked from openlp/openlp
r1782
This commit is contained in:
commit
76b30a99de
@ -7,7 +7,7 @@
|
|||||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
# 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, #
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
@ -51,9 +51,6 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``config_screen_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_{live|preview}_next``
|
``slidecontroller_{live|preview}_next``
|
||||||
Moves to the next slide
|
Moves to the next slide
|
||||||
|
|
||||||
@ -66,9 +63,6 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``slidecontroller_{live|preview}_previous_noloop``
|
``slidecontroller_{live|preview}_previous_noloop``
|
||||||
Moves to the previous slide, without auto advance
|
Moves to the previous slide, without auto advance
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_last``
|
|
||||||
Moves to the last slide
|
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_set``
|
``slidecontroller_{live|preview}_set``
|
||||||
Moves to a specific slide, by index
|
Moves to a specific slide, by index
|
||||||
|
|
||||||
@ -82,11 +76,6 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``slidecontroller_{live|preview}_changed``
|
``slidecontroller_{live|preview}_changed``
|
||||||
Broadcasts that the slidecontroller has changed the current slide
|
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
|
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_blank``
|
``slidecontroller_{live|preview}_blank``
|
||||||
Request that the output screen is blanked
|
Request that the output screen is blanked
|
||||||
|
|
||||||
@ -230,6 +219,10 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``cursor_normal``
|
``cursor_normal``
|
||||||
Resets the cursor to default
|
Resets the cursor to default
|
||||||
|
|
||||||
|
``update_display_css``
|
||||||
|
CSS has been updated which needs to be changed on the main display.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
|
@ -73,13 +73,7 @@ body {
|
|||||||
#video2 {
|
#video2 {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
#alert {
|
%s
|
||||||
position: absolute;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
z-index: 10;
|
|
||||||
%s
|
|
||||||
}
|
|
||||||
#footer {
|
#footer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 6;
|
z-index: 6;
|
||||||
@ -179,7 +173,7 @@ sup {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
%s
|
||||||
function show_image(src){
|
function show_image(src){
|
||||||
var img = document.getElementById('image');
|
var img = document.getElementById('image');
|
||||||
img.src = src;
|
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){
|
function show_footer(footertext){
|
||||||
document.getElementById('footer').innerHTML = footertext;
|
document.getElementById('footer').innerHTML = footertext;
|
||||||
}
|
}
|
||||||
@ -316,14 +282,15 @@ sup {
|
|||||||
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
|
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
|
||||||
</video>
|
</video>
|
||||||
%s
|
%s
|
||||||
|
%s
|
||||||
<div id="footer" class="footer"></div>
|
<div id="footer" class="footer"></div>
|
||||||
<div id="black" class="size"></div>
|
<div id="black" class="size"></div>
|
||||||
<div id="alert" style="visibility:hidden"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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
|
Build the full web paged structure for display
|
||||||
|
|
||||||
@ -333,9 +300,6 @@ def build_html(item, screen, alert, islive, background, image=None):
|
|||||||
``screen``
|
``screen``
|
||||||
Current display information
|
Current display information
|
||||||
|
|
||||||
``alert``
|
|
||||||
Alert display display information
|
|
||||||
|
|
||||||
``islive``
|
``islive``
|
||||||
Item is going live, rather than preview/theme building
|
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``
|
||||||
Image media item - bytes
|
Image media item - bytes
|
||||||
|
|
||||||
|
``plugins``
|
||||||
|
The List of available plugins
|
||||||
"""
|
"""
|
||||||
width = screen[u'size'].width()
|
width = screen[u'size'].width()
|
||||||
height = screen[u'size'].height()
|
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
|
image_src = u'src="data:image/png;base64,%s"' % image
|
||||||
else:
|
else:
|
||||||
image_src = u'style="display:none;"'
|
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),
|
html = HTMLSRC % (build_background_css(item, width, height),
|
||||||
width, height,
|
width, height,
|
||||||
build_alert_css(alert, width),
|
css_additions,
|
||||||
build_footer_css(item, height),
|
build_footer_css(item, height),
|
||||||
build_lyrics_css(item, webkitvers),
|
build_lyrics_css(item, webkitvers),
|
||||||
u'true' if theme and theme.display_slide_transition and islive \
|
u'true' if theme and theme.display_slide_transition and islive \
|
||||||
else u'false',
|
else u'false',
|
||||||
|
js_additions,
|
||||||
bgimage_src, image_src,
|
bgimage_src, image_src,
|
||||||
|
html_additions,
|
||||||
build_lyrics_html(item, webkitvers))
|
build_lyrics_html(item, webkitvers))
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
@ -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.
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -369,3 +369,30 @@ class Plugin(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
self.textStrings[name] = {u'title': title, u'tooltip': tooltip}
|
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''
|
||||||
|
|
||||||
|
@ -42,6 +42,13 @@ class PluginManager(object):
|
|||||||
"""
|
"""
|
||||||
log.info(u'Plugin manager loaded')
|
log.info(u'Plugin manager loaded')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_instance():
|
||||||
|
"""
|
||||||
|
Obtain a single instance of class.
|
||||||
|
"""
|
||||||
|
return PluginManager.instance
|
||||||
|
|
||||||
def __init__(self, plugin_dir):
|
def __init__(self, plugin_dir):
|
||||||
"""
|
"""
|
||||||
The constructor for the plugin manager. Passes the controllers on to
|
The constructor for the plugin manager. Passes the controllers on to
|
||||||
@ -51,6 +58,7 @@ class PluginManager(object):
|
|||||||
The directory to search for plugins.
|
The directory to search for plugins.
|
||||||
"""
|
"""
|
||||||
log.info(u'Plugin manager Initialising')
|
log.info(u'Plugin manager Initialising')
|
||||||
|
PluginManager.instance = self
|
||||||
if not plugin_dir in sys.path:
|
if not plugin_dir in sys.path:
|
||||||
log.debug(u'Inserting %s into sys.path', plugin_dir)
|
log.debug(u'Inserting %s into sys.path', plugin_dir)
|
||||||
sys.path.insert(0, plugin_dir)
|
sys.path.insert(0, plugin_dir)
|
||||||
|
@ -57,14 +57,14 @@ class Renderer(object):
|
|||||||
|
|
||||||
def __init__(self, imageManager, themeManager):
|
def __init__(self, imageManager, themeManager):
|
||||||
"""
|
"""
|
||||||
Initialise the render manager.
|
Initialise the renderer.
|
||||||
|
|
||||||
``imageManager``
|
``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.
|
images.
|
||||||
|
|
||||||
``themeManager``
|
``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')
|
log.debug(u'Initialisation started')
|
||||||
self.themeManager = themeManager
|
self.themeManager = themeManager
|
||||||
@ -81,7 +81,7 @@ class Renderer(object):
|
|||||||
|
|
||||||
def update_display(self):
|
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')
|
log.debug(u'Update Display')
|
||||||
self._calculate_default()
|
self._calculate_default()
|
||||||
@ -201,7 +201,8 @@ class Renderer(object):
|
|||||||
if not self.force_page:
|
if not self.force_page:
|
||||||
self.display.buildHtml(serviceItem)
|
self.display.buildHtml(serviceItem)
|
||||||
raw_html = serviceItem.get_rendered_frame(0)
|
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
|
# Reset the real screen size for subsequent render requests
|
||||||
self._calculate_default()
|
self._calculate_default()
|
||||||
return preview
|
return preview
|
||||||
@ -304,21 +305,37 @@ class Renderer(object):
|
|||||||
The theme to build a text block for.
|
The theme to build a text block for.
|
||||||
"""
|
"""
|
||||||
log.debug(u'_build_text_rectangle')
|
log.debug(u'_build_text_rectangle')
|
||||||
main_rect = None
|
main_rect = self.get_main_rectangle(theme)
|
||||||
footer_rect = None
|
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:
|
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:
|
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)
|
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:
|
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)
|
self.height - self.footer_start)
|
||||||
else:
|
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_y, theme.font_footer_width - 1,
|
||||||
theme.font_footer_height - 1)
|
theme.font_footer_height - 1)
|
||||||
self._set_text_rectangle(main_rect, footer_rect)
|
|
||||||
|
|
||||||
def _set_text_rectangle(self, rect_main, rect_footer):
|
def _set_text_rectangle(self, rect_main, rect_footer):
|
||||||
"""
|
"""
|
||||||
|
@ -122,9 +122,8 @@ class ServiceItem(object):
|
|||||||
|
|
||||||
def _new_item(self):
|
def _new_item(self):
|
||||||
"""
|
"""
|
||||||
Method to set the internal id of the item
|
Method to set the internal id of the item. This is used to compare
|
||||||
This is used to compare service items to see if they are
|
service items to see if they are the same.
|
||||||
the same
|
|
||||||
"""
|
"""
|
||||||
self._uuid = unicode(uuid.uuid1())
|
self._uuid = unicode(uuid.uuid1())
|
||||||
|
|
||||||
@ -160,9 +159,8 @@ class ServiceItem(object):
|
|||||||
def render(self, use_override=False):
|
def render(self, use_override=False):
|
||||||
"""
|
"""
|
||||||
The render method is what generates the frames for the screen and
|
The render method is what generates the frames for the screen and
|
||||||
obtains the display information from the renderemanager.
|
obtains the display information from the renderer. At this point all
|
||||||
At this point all the slides are built for the given
|
slides are built for the given display size.
|
||||||
display size.
|
|
||||||
"""
|
"""
|
||||||
log.debug(u'Render called')
|
log.debug(u'Render called')
|
||||||
self._display_frames = []
|
self._display_frames = []
|
||||||
@ -364,6 +362,11 @@ class ServiceItem(object):
|
|||||||
"""
|
"""
|
||||||
self._uuid = other._uuid
|
self._uuid = other._uuid
|
||||||
self.notes = other.notes
|
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):
|
if self.is_capable(ItemCapabilities.HasBackgroundAudio):
|
||||||
log.debug(self.background_audio)
|
log.debug(self.background_audio)
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ class HideMode(object):
|
|||||||
|
|
||||||
from firsttimeform import FirstTimeForm
|
from firsttimeform import FirstTimeForm
|
||||||
from firsttimelanguageform import FirstTimeLanguageForm
|
from firsttimelanguageform import FirstTimeLanguageForm
|
||||||
|
from themelayoutform import ThemeLayoutForm
|
||||||
from themeform import ThemeForm
|
from themeform import ThemeForm
|
||||||
from filerenameform import FileRenameForm
|
from filerenameform import FileRenameForm
|
||||||
from starttimeform import StartTimeForm
|
from starttimeform import StartTimeForm
|
||||||
|
@ -56,7 +56,6 @@ except ImportError:
|
|||||||
SQLITE_VERSION = u'-'
|
SQLITE_VERSION = u'-'
|
||||||
|
|
||||||
from openlp.core.lib import translate, SettingsManager
|
from openlp.core.lib import translate, SettingsManager
|
||||||
from openlp.core.lib.mailto import mailto
|
|
||||||
from openlp.core.lib.ui import UiStrings
|
from openlp.core.lib.ui import UiStrings
|
||||||
from openlp.core.utils import get_application_version
|
from openlp.core.utils import get_application_version
|
||||||
|
|
||||||
@ -159,12 +158,12 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
|||||||
if u':' in line:
|
if u':' in line:
|
||||||
exception = line.split(u'\n')[-1].split(u':')[0]
|
exception = line.split(u'\n')[-1].split(u':')[0]
|
||||||
subject = u'Bug report: %s in %s' % (exception, source)
|
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:
|
if self.fileAttachment:
|
||||||
mailto(address=u'bugs@openlp.org', subject=subject,
|
mailto_url.addQueryItem(u'attach', self.fileAttachment)
|
||||||
body=body % content, attach=self.fileAttachment)
|
QtGui.QDesktopServices.openUrl(mailto_url)
|
||||||
else:
|
|
||||||
mailto(address=u'bugs@openlp.org', subject=subject,
|
|
||||||
body=body % content)
|
|
||||||
|
|
||||||
def onDescriptionUpdated(self):
|
def onDescriptionUpdated(self):
|
||||||
count = int(20 - len(self.descriptionTextEdit.toPlainText()))
|
count = int(20 - len(self.descriptionTextEdit.toPlainText()))
|
||||||
|
@ -35,7 +35,7 @@ from PyQt4 import QtCore, QtGui, QtWebKit
|
|||||||
from PyQt4.phonon import Phonon
|
from PyQt4.phonon import Phonon
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
|
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
|
||||||
|
|
||||||
@ -51,12 +51,15 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
def __init__(self, parent, imageManager, live):
|
def __init__(self, parent, imageManager, live):
|
||||||
if live:
|
if live:
|
||||||
QtGui.QGraphicsView.__init__(self)
|
QtGui.QGraphicsView.__init__(self)
|
||||||
|
# Do not overwrite the parent() method.
|
||||||
|
self.parent = lambda: parent
|
||||||
else:
|
else:
|
||||||
QtGui.QGraphicsView.__init__(self, parent)
|
QtGui.QGraphicsView.__init__(self, parent)
|
||||||
self.isLive = live
|
self.isLive = live
|
||||||
self.imageManager = imageManager
|
self.imageManager = imageManager
|
||||||
self.screens = ScreenList.get_instance()
|
self.screens = ScreenList.get_instance()
|
||||||
self.alertTab = None
|
self.plugins = PluginManager.get_instance().plugins
|
||||||
|
self.rebuildCSS = False
|
||||||
self.hideMode = None
|
self.hideMode = None
|
||||||
self.videoHide = False
|
self.videoHide = False
|
||||||
self.override = {}
|
self.override = {}
|
||||||
@ -80,6 +83,26 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_phonon_creation'),
|
QtCore.SIGNAL(u'openlp_phonon_creation'),
|
||||||
self.createMediaObject)
|
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):
|
def retranslateUi(self):
|
||||||
"""
|
"""
|
||||||
@ -111,6 +134,9 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.screen[u'size'].width(), self.screen[u'size'].height())
|
self.screen[u'size'].width(), self.screen[u'size'].height())
|
||||||
self.page = self.webView.page()
|
self.page = self.webView.page()
|
||||||
self.frame = self.page.mainFrame()
|
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.QObject.connect(self.webView,
|
||||||
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
|
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
|
||||||
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
@ -120,14 +146,6 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
|
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
|
||||||
QtCore.Qt.ScrollBarAlwaysOff)
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
if self.isLive:
|
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.
|
# Build the initial frame.
|
||||||
image_file = QtCore.QSettings().value(u'advanced/default image',
|
image_file = QtCore.QSettings().value(u'advanced/default image',
|
||||||
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
|
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
|
||||||
@ -153,7 +171,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
serviceItem = ServiceItem()
|
serviceItem = ServiceItem()
|
||||||
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
|
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
|
||||||
self.webView.setHtml(build_html(serviceItem, self.screen,
|
self.webView.setHtml(build_html(serviceItem, self.screen,
|
||||||
self.alertTab, self.isLive, None))
|
self.isLive, None))
|
||||||
self.__hideMouse()
|
self.__hideMouse()
|
||||||
# To display or not to display?
|
# To display or not to display?
|
||||||
if not self.screen[u'primary']:
|
if not self.screen[u'primary']:
|
||||||
@ -184,7 +202,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
"""
|
"""
|
||||||
Add the slide text from slideController
|
Add the slide text from slideController
|
||||||
|
|
||||||
`slide`
|
``slide``
|
||||||
The slide text to be displayed
|
The slide text to be displayed
|
||||||
"""
|
"""
|
||||||
log.debug(u'text to display')
|
log.debug(u'text to display')
|
||||||
@ -194,24 +212,25 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.setGeometry(self.screen[u'size'])
|
self.setGeometry(self.screen[u'size'])
|
||||||
self.frame.evaluateJavaScript(u'show_text("%s")' %
|
self.frame.evaluateJavaScript(u'show_text("%s")' %
|
||||||
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||||
return self.preview()
|
|
||||||
|
|
||||||
def alert(self, text):
|
def alert(self, text):
|
||||||
"""
|
"""
|
||||||
Add the alert text
|
Display an alert.
|
||||||
|
|
||||||
`slide`
|
``text``
|
||||||
The slide text to be displayed
|
The text to be displayed.
|
||||||
"""
|
"""
|
||||||
log.debug(u'alert to display')
|
log.debug(u'alert to display')
|
||||||
if self.height() != self.screen[u'size'].height() or not \
|
if self.height() != self.screen[u'size'].height() or not \
|
||||||
self.isVisible() or self.videoWidget.isVisible():
|
self.isVisible() or self.videoWidget.isVisible():
|
||||||
shrink = True
|
shrink = True
|
||||||
|
js = u'show_alert("%s", "%s")' % (
|
||||||
|
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'),
|
||||||
|
u'top')
|
||||||
else:
|
else:
|
||||||
shrink = False
|
shrink = False
|
||||||
js = u'show_alert("%s", "%s")' % (
|
js = u'show_alert("%s", "")' % (
|
||||||
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'),
|
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||||
u'top' if shrink else u'')
|
|
||||||
height = self.frame.evaluateJavaScript(js)
|
height = self.frame.evaluateJavaScript(js)
|
||||||
if shrink:
|
if shrink:
|
||||||
if self.phononActive:
|
if self.phononActive:
|
||||||
@ -234,13 +253,16 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
|
|
||||||
def directImage(self, name, path, background):
|
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)
|
self.imageManager.add_image(name, path, u'image', background)
|
||||||
if hasattr(self, u'serviceItem'):
|
if hasattr(self, u'serviceItem'):
|
||||||
self.override[u'image'] = name
|
self.override[u'image'] = name
|
||||||
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
self.override[u'theme'] = self.serviceItem.themedata.theme_name
|
||||||
self.image(name)
|
self.image(name)
|
||||||
|
# Update the preview frame.
|
||||||
|
if self.isLive:
|
||||||
|
self.parent().updatePreview()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -249,14 +271,13 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
Add an image as the background. The image has already been added
|
Add an image as the background. The image has already been added
|
||||||
to the cache.
|
to the cache.
|
||||||
|
|
||||||
`Image`
|
``Image``
|
||||||
The name of the image to be displayed
|
The name of the image to be displayed.
|
||||||
"""
|
"""
|
||||||
log.debug(u'image to display')
|
log.debug(u'image to display')
|
||||||
image = self.imageManager.get_image_bytes(name)
|
image = self.imageManager.get_image_bytes(name)
|
||||||
self.resetVideo()
|
self.resetVideo()
|
||||||
self.displayImage(image)
|
self.displayImage(image)
|
||||||
return self.preview()
|
|
||||||
|
|
||||||
def displayImage(self, image):
|
def displayImage(self, image):
|
||||||
"""
|
"""
|
||||||
@ -268,14 +289,11 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
else:
|
else:
|
||||||
js = u'show_image("");'
|
js = u'show_image("");'
|
||||||
self.frame.evaluateJavaScript(js)
|
self.frame.evaluateJavaScript(js)
|
||||||
# Update the preview frame.
|
|
||||||
if self.isLive:
|
|
||||||
Receiver.send_message(u'maindisplay_active')
|
|
||||||
|
|
||||||
def resetImage(self):
|
def resetImage(self):
|
||||||
"""
|
"""
|
||||||
Reset the backgound image to the service item image.
|
Reset the backgound image to the service item image. Used after the
|
||||||
Used after Image plugin has changed the background
|
image plugin has changed the background.
|
||||||
"""
|
"""
|
||||||
log.debug(u'resetImage')
|
log.debug(u'resetImage')
|
||||||
if hasattr(self, u'serviceItem'):
|
if hasattr(self, u'serviceItem'):
|
||||||
@ -284,9 +302,6 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.displayImage(None)
|
self.displayImage(None)
|
||||||
# clear the cache
|
# clear the cache
|
||||||
self.override = {}
|
self.override = {}
|
||||||
# Update the preview frame.
|
|
||||||
if self.isLive:
|
|
||||||
Receiver.send_message(u'maindisplay_active')
|
|
||||||
|
|
||||||
def resetVideo(self):
|
def resetVideo(self):
|
||||||
"""
|
"""
|
||||||
@ -302,9 +317,6 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
else:
|
else:
|
||||||
self.frame.evaluateJavaScript(u'show_video("close");')
|
self.frame.evaluateJavaScript(u'show_video("close");')
|
||||||
self.override = {}
|
self.override = {}
|
||||||
# Update the preview frame.
|
|
||||||
if self.isLive:
|
|
||||||
Receiver.send_message(u'maindisplay_active')
|
|
||||||
|
|
||||||
def videoPlay(self):
|
def videoPlay(self):
|
||||||
"""
|
"""
|
||||||
@ -357,7 +369,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
"""
|
"""
|
||||||
# We request a background video but have no service Item
|
# We request a background video but have no service Item
|
||||||
if isBackground and not hasattr(self, u'serviceItem'):
|
if isBackground and not hasattr(self, u'serviceItem'):
|
||||||
return None
|
return False
|
||||||
if not self.mediaObject:
|
if not self.mediaObject:
|
||||||
self.createMediaObject()
|
self.createMediaObject()
|
||||||
log.debug(u'video')
|
log.debug(u'video')
|
||||||
@ -384,10 +396,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.webView.setVisible(False)
|
self.webView.setVisible(False)
|
||||||
self.videoWidget.setVisible(True)
|
self.videoWidget.setVisible(True)
|
||||||
self.audio.setVolume(vol)
|
self.audio.setVolume(vol)
|
||||||
# Update the preview frame.
|
return True
|
||||||
if self.isLive:
|
|
||||||
Receiver.send_message(u'maindisplay_active')
|
|
||||||
return self.preview()
|
|
||||||
|
|
||||||
def videoState(self, newState, oldState):
|
def videoState(self, newState, oldState):
|
||||||
"""
|
"""
|
||||||
@ -455,9 +464,8 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.setVisible(True)
|
self.setVisible(True)
|
||||||
else:
|
else:
|
||||||
self.setVisible(True)
|
self.setVisible(True)
|
||||||
preview = QtGui.QImage(self.screen[u'size'].width(),
|
preview = QtGui.QPixmap(self.screen[u'size'].width(),
|
||||||
self.screen[u'size'].height(),
|
self.screen[u'size'].height())
|
||||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
|
||||||
painter = QtGui.QPainter(preview)
|
painter = QtGui.QPainter(preview)
|
||||||
painter.setRenderHint(QtGui.QPainter.Antialiasing)
|
painter.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||||
self.frame.render(painter)
|
self.frame.render(painter)
|
||||||
@ -495,8 +503,8 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
image_bytes = self.imageManager.get_image_bytes(image)
|
image_bytes = self.imageManager.get_image_bytes(image)
|
||||||
else:
|
else:
|
||||||
image_bytes = None
|
image_bytes = None
|
||||||
html = build_html(self.serviceItem, self.screen, self.alertTab,
|
html = build_html(self.serviceItem, self.screen, self.isLive,
|
||||||
self.isLive, background, image_bytes)
|
background, image_bytes, self.plugins)
|
||||||
log.debug(u'buildHtml - pre setHtml')
|
log.debug(u'buildHtml - pre setHtml')
|
||||||
self.webView.setHtml(html)
|
self.webView.setHtml(html)
|
||||||
log.debug(u'buildHtml - post setHtml')
|
log.debug(u'buildHtml - post setHtml')
|
||||||
|
@ -1160,7 +1160,6 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
# if not passed set to config value
|
# if not passed set to config value
|
||||||
if expand is None:
|
if expand is None:
|
||||||
expand = self.expandTabs
|
expand = self.expandTabs
|
||||||
item.render()
|
|
||||||
item.from_service = True
|
item.from_service = True
|
||||||
if replace:
|
if replace:
|
||||||
sitem, child = self.findServiceItem()
|
sitem, child = self.findServiceItem()
|
||||||
@ -1169,6 +1168,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.repaintServiceList(sitem, child)
|
self.repaintServiceList(sitem, child)
|
||||||
self.mainwindow.liveController.replaceServiceManagerItem(item)
|
self.mainwindow.liveController.replaceServiceManagerItem(item)
|
||||||
else:
|
else:
|
||||||
|
item.render()
|
||||||
# nothing selected for dnd
|
# nothing selected for dnd
|
||||||
if self.dropPosition == 0:
|
if self.dropPosition == 0:
|
||||||
if isinstance(item, list):
|
if isinstance(item, list):
|
||||||
|
@ -58,7 +58,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
|||||||
# load all the settings
|
# load all the settings
|
||||||
self.settingListWidget.clear()
|
self.settingListWidget.clear()
|
||||||
for tabIndex in range(0, self.stackedLayout.count() + 1):
|
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.stackedLayout.takeAt(0)
|
||||||
self.insertTab(self.generalTab, 0, PluginStatus.Active)
|
self.insertTab(self.generalTab, 0, PluginStatus.Active)
|
||||||
self.insertTab(self.themesTab, 1, PluginStatus.Active)
|
self.insertTab(self.themesTab, 1, PluginStatus.Active)
|
||||||
|
@ -79,7 +79,6 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.songEdit = False
|
self.songEdit = False
|
||||||
self.selectedRow = 0
|
self.selectedRow = 0
|
||||||
self.serviceItem = None
|
self.serviceItem = None
|
||||||
self.alertTab = None
|
|
||||||
self.panel = QtGui.QWidget(parent.controlSplitter)
|
self.panel = QtGui.QWidget(parent.controlSplitter)
|
||||||
self.slideList = {}
|
self.slideList = {}
|
||||||
# Layout for holding panel
|
# Layout for holding panel
|
||||||
@ -118,7 +117,7 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.previewListWidget.horizontalHeader().setVisible(False)
|
self.previewListWidget.horizontalHeader().setVisible(False)
|
||||||
self.previewListWidget.setColumnWidth(0, self.controller.width())
|
self.previewListWidget.setColumnWidth(0, self.controller.width())
|
||||||
self.previewListWidget.isLive = self.isLive
|
self.previewListWidget.isLive = self.isLive
|
||||||
self.previewListWidget.setObjectName(u'PreviewListWidget')
|
self.previewListWidget.setObjectName(u'previewListWidget')
|
||||||
self.previewListWidget.setSelectionBehavior(
|
self.previewListWidget.setSelectionBehavior(
|
||||||
QtGui.QAbstractItemView.SelectRows)
|
QtGui.QAbstractItemView.SelectRows)
|
||||||
self.previewListWidget.setSelectionMode(
|
self.previewListWidget.setSelectionMode(
|
||||||
@ -288,14 +287,14 @@ class SlideController(QtGui.QWidget):
|
|||||||
QtGui.QSizePolicy.Label))
|
QtGui.QSizePolicy.Label))
|
||||||
self.previewFrame.setFrameShape(QtGui.QFrame.StyledPanel)
|
self.previewFrame.setFrameShape(QtGui.QFrame.StyledPanel)
|
||||||
self.previewFrame.setFrameShadow(QtGui.QFrame.Sunken)
|
self.previewFrame.setFrameShadow(QtGui.QFrame.Sunken)
|
||||||
self.previewFrame.setObjectName(u'PreviewFrame')
|
self.previewFrame.setObjectName(u'previewFrame')
|
||||||
self.grid = QtGui.QGridLayout(self.previewFrame)
|
self.grid = QtGui.QGridLayout(self.previewFrame)
|
||||||
self.grid.setMargin(8)
|
self.grid.setMargin(8)
|
||||||
self.grid.setObjectName(u'grid')
|
self.grid.setObjectName(u'grid')
|
||||||
self.slideLayout = QtGui.QVBoxLayout()
|
self.slideLayout = QtGui.QVBoxLayout()
|
||||||
self.slideLayout.setSpacing(0)
|
self.slideLayout.setSpacing(0)
|
||||||
self.slideLayout.setMargin(0)
|
self.slideLayout.setMargin(0)
|
||||||
self.slideLayout.setObjectName(u'SlideLayout')
|
self.slideLayout.setObjectName(u'slideLayout')
|
||||||
if not self.isLive:
|
if not self.isLive:
|
||||||
self.mediaObject = Phonon.MediaObject(self)
|
self.mediaObject = Phonon.MediaObject(self)
|
||||||
self.video = Phonon.VideoWidget()
|
self.video = Phonon.VideoWidget()
|
||||||
@ -319,7 +318,7 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.slidePreview.setFrameShadow(QtGui.QFrame.Plain)
|
self.slidePreview.setFrameShadow(QtGui.QFrame.Plain)
|
||||||
self.slidePreview.setLineWidth(1)
|
self.slidePreview.setLineWidth(1)
|
||||||
self.slidePreview.setScaledContents(True)
|
self.slidePreview.setScaledContents(True)
|
||||||
self.slidePreview.setObjectName(u'SlidePreview')
|
self.slidePreview.setObjectName(u'slidePreview')
|
||||||
self.slideLayout.insertWidget(0, self.slidePreview)
|
self.slideLayout.insertWidget(0, self.slidePreview)
|
||||||
self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
|
self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
|
||||||
# Signals
|
# Signals
|
||||||
@ -328,8 +327,6 @@ class SlideController(QtGui.QWidget):
|
|||||||
if self.isLive:
|
if self.isLive:
|
||||||
QtCore.QObject.connect(self.volumeSlider,
|
QtCore.QObject.connect(self.volumeSlider,
|
||||||
QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume)
|
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.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
||||||
self.receiveSpinDelay)
|
self.receiveSpinDelay)
|
||||||
@ -351,18 +348,12 @@ class SlideController(QtGui.QWidget):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
|
||||||
self.onStopLoop)
|
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.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_next' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_next' % self.typePrefix),
|
||||||
self.onSlideSelectedNext)
|
self.onSlideSelectedNext)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_previous' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_previous' % self.typePrefix),
|
||||||
self.onSlideSelectedPrevious)
|
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.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_change' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_change' % self.typePrefix),
|
||||||
self.onSlideChange)
|
self.onSlideChange)
|
||||||
@ -375,9 +366,6 @@ class SlideController(QtGui.QWidget):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
|
||||||
self.onSlideUnblank)
|
self.onSlideUnblank)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix),
|
|
||||||
self.onTextRequest)
|
|
||||||
|
|
||||||
def setPreviewHotkeys(self, parent=None):
|
def setPreviewHotkeys(self, parent=None):
|
||||||
self.previousItem.setObjectName(u'previousItemPreview')
|
self.previousItem.setObjectName(u'previousItemPreview')
|
||||||
@ -434,7 +422,6 @@ class SlideController(QtGui.QWidget):
|
|||||||
if self.display:
|
if self.display:
|
||||||
self.display.close()
|
self.display.close()
|
||||||
self.display = MainDisplay(self, self.imageManager, self.isLive)
|
self.display = MainDisplay(self, self.imageManager, self.isLive)
|
||||||
self.display.alertTab = self.alertTab
|
|
||||||
self.display.setup()
|
self.display.setup()
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
self.__addActionsToWidget(self.display)
|
self.__addActionsToWidget(self.display)
|
||||||
@ -723,41 +710,7 @@ class SlideController(QtGui.QWidget):
|
|||||||
else:
|
else:
|
||||||
self.__checkUpdateSelectedSlide(slideno)
|
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
|
# 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):
|
def onSlideSelectedIndex(self, message):
|
||||||
"""
|
"""
|
||||||
Go to the requested slide
|
Go to the requested slide
|
||||||
@ -936,20 +889,18 @@ class SlideController(QtGui.QWidget):
|
|||||||
Receiver.send_message(
|
Receiver.send_message(
|
||||||
u'%s_slide' % self.serviceItem.name.lower(),
|
u'%s_slide' % self.serviceItem.name.lower(),
|
||||||
[self.serviceItem, self.isLive, row])
|
[self.serviceItem, self.isLive, row])
|
||||||
self.updatePreview()
|
|
||||||
else:
|
else:
|
||||||
toDisplay = self.serviceItem.get_rendered_frame(row)
|
toDisplay = self.serviceItem.get_rendered_frame(row)
|
||||||
if self.serviceItem.is_text():
|
if self.serviceItem.is_text():
|
||||||
frame = self.display.text(toDisplay)
|
self.display.text(toDisplay)
|
||||||
else:
|
else:
|
||||||
if start:
|
if start:
|
||||||
self.display.buildHtml(self.serviceItem, toDisplay)
|
self.display.buildHtml(self.serviceItem, toDisplay)
|
||||||
frame = self.display.preview()
|
|
||||||
else:
|
else:
|
||||||
frame = self.display.image(toDisplay)
|
self.display.image(toDisplay)
|
||||||
# reset the store used to display first image
|
# reset the store used to display first image
|
||||||
self.serviceItem.bg_image_bytes = None
|
self.serviceItem.bg_image_bytes = None
|
||||||
self.slidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
|
self.updatePreview()
|
||||||
self.selectedRow = row
|
self.selectedRow = row
|
||||||
self.__checkUpdateSelectedSlide(row)
|
self.__checkUpdateSelectedSlide(row)
|
||||||
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
|
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(0.5, self.grabMainDisplay)
|
||||||
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
|
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
|
||||||
else:
|
else:
|
||||||
self.slidePreview.setPixmap(
|
self.slidePreview.setPixmap(self.display.preview())
|
||||||
QtGui.QPixmap.fromImage(self.display.preview()))
|
|
||||||
|
|
||||||
def grabMainDisplay(self):
|
def grabMainDisplay(self):
|
||||||
"""
|
"""
|
||||||
@ -1041,21 +991,6 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.previewListWidget.item(row + 1, 0))
|
self.previewListWidget.item(row + 1, 0))
|
||||||
self.previewListWidget.selectRow(row)
|
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):
|
def onToggleLoop(self):
|
||||||
"""
|
"""
|
||||||
Toggles the loop state.
|
Toggles the loop state.
|
||||||
|
@ -36,8 +36,7 @@ class SplashScreen(QtGui.QSplashScreen):
|
|||||||
QtCore.SIGNAL(u'close_splash'), self.close)
|
QtCore.SIGNAL(u'close_splash'), self.close)
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
self.setObjectName(u'splash_screen')
|
self.setObjectName(u'splashScreen')
|
||||||
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
|
|
||||||
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||||
splash_image = QtGui.QPixmap(u':/graphics/openlp-splash-screen.png')
|
splash_image = QtGui.QPixmap(u':/graphics/openlp-splash-screen.png')
|
||||||
self.setPixmap(splash_image)
|
self.setPixmap(splash_image)
|
||||||
|
@ -33,6 +33,7 @@ from PyQt4 import QtCore, QtGui
|
|||||||
from openlp.core.lib import Receiver, translate
|
from openlp.core.lib import Receiver, translate
|
||||||
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
|
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
|
||||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
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 openlp.core.utils import get_images_filter
|
||||||
from themewizard import Ui_ThemeWizard
|
from themewizard import Ui_ThemeWizard
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
self.registerFields()
|
self.registerFields()
|
||||||
self.updateThemeAllowed = True
|
self.updateThemeAllowed = True
|
||||||
self.temp_background_filename = u''
|
self.temp_background_filename = u''
|
||||||
|
self.themeLayoutForm = ThemeLayoutForm(self)
|
||||||
QtCore.QObject.connect(self.backgroundComboBox,
|
QtCore.QObject.connect(self.backgroundComboBox,
|
||||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||||
self.onBackgroundComboBoxCurrentIndexChanged)
|
self.onBackgroundComboBoxCurrentIndexChanged)
|
||||||
@ -88,6 +90,9 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
self.onShadowCheckCheckBoxStateChanged)
|
self.onShadowCheckCheckBoxStateChanged)
|
||||||
QtCore.QObject.connect(self.footerColorButton,
|
QtCore.QObject.connect(self.footerColorButton,
|
||||||
QtCore.SIGNAL(u'clicked()'), self.onFooterColorButtonClicked)
|
QtCore.SIGNAL(u'clicked()'), self.onFooterColorButtonClicked)
|
||||||
|
QtCore.QObject.connect(self,
|
||||||
|
QtCore.SIGNAL(u'customButtonClicked(int)'),
|
||||||
|
self.onCustom1ButtonClicked)
|
||||||
QtCore.QObject.connect(self.mainPositionCheckBox,
|
QtCore.QObject.connect(self.mainPositionCheckBox,
|
||||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||||
self.onMainPositionCheckBoxStateChanged)
|
self.onMainPositionCheckBoxStateChanged)
|
||||||
@ -229,13 +234,36 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
"""
|
"""
|
||||||
Detects Page changes and updates as approprate.
|
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:
|
if self.page(pageId) == self.previewPage:
|
||||||
self.updateTheme()
|
self.updateTheme()
|
||||||
frame = self.thememanager.generateImage(self.theme)
|
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.displayAspectRatio = float(frame.width()) / frame.height()
|
||||||
self.resizeEvent()
|
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):
|
def onOutlineCheckCheckBoxStateChanged(self, state):
|
||||||
"""
|
"""
|
||||||
Change state as Outline check box changed
|
Change state as Outline check box changed
|
||||||
|
75
openlp/core/ui/themelayoutdialog.py
Normal file
75
openlp/core/ui/themelayoutdialog.py
Normal 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.'))
|
||||||
|
|
55
openlp/core/ui/themelayoutform.py
Normal file
55
openlp/core/ui/themelayoutform.py
Normal 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)
|
||||||
|
|
@ -38,7 +38,8 @@ class Ui_ThemeWizard(object):
|
|||||||
themeWizard.setModal(True)
|
themeWizard.setModal(True)
|
||||||
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||||
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
|
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
|
||||||
QtGui.QWizard.NoBackButtonOnStartPage)
|
QtGui.QWizard.NoBackButtonOnStartPage |
|
||||||
|
QtGui.QWizard.HaveCustomButton1)
|
||||||
self.spacer = QtGui.QSpacerItem(10, 0,
|
self.spacer = QtGui.QSpacerItem(10, 0,
|
||||||
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
|
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
|
||||||
# Welcome Page
|
# Welcome Page
|
||||||
@ -535,6 +536,9 @@ class Ui_ThemeWizard(object):
|
|||||||
translate('OpenLP.ThemeWizard', 'px'))
|
translate('OpenLP.ThemeWizard', 'px'))
|
||||||
self.footerPositionCheckBox.setText(
|
self.footerPositionCheckBox.setText(
|
||||||
translate('OpenLP.ThemeWizard', 'Use default location'))
|
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(
|
self.previewPage.setTitle(
|
||||||
translate('OpenLP.ThemeWizard', 'Save and Preview'))
|
translate('OpenLP.ThemeWizard', 'Save and Preview'))
|
||||||
self.previewPage.setSubTitle(
|
self.previewPage.setSubTitle(
|
||||||
|
@ -32,6 +32,7 @@ from PyQt4 import QtCore
|
|||||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||||
from openlp.core.lib.db import Manager
|
from openlp.core.lib.db import Manager
|
||||||
from openlp.core.lib.ui import icon_action, UiStrings
|
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.core.utils.actions import ActionList
|
||||||
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
|
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
|
||||||
from openlp.plugins.alerts.lib.db import init_schema
|
from openlp.plugins.alerts.lib.db import init_schema
|
||||||
@ -39,6 +40,63 @@ from openlp.plugins.alerts.forms import AlertForm
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
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.verticalAlign = align;
|
||||||
|
text.style.fontSize = size + "pt";
|
||||||
|
text.style.fontFamily = font;
|
||||||
|
text.style.color = color;
|
||||||
|
text.style.backgroundColor = bgcolor;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
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):
|
class AlertsPlugin(Plugin):
|
||||||
log.info(u'Alerts Plugin loaded')
|
log.info(u'Alerts Plugin loaded')
|
||||||
|
|
||||||
@ -79,7 +137,6 @@ class AlertsPlugin(Plugin):
|
|||||||
self.toolsAlertItem.setVisible(True)
|
self.toolsAlertItem.setVisible(True)
|
||||||
action_list = ActionList.get_instance()
|
action_list = ActionList.get_instance()
|
||||||
action_list.add_action(self.toolsAlertItem, UiStrings().Tools)
|
action_list.add_action(self.toolsAlertItem, UiStrings().Tools)
|
||||||
self.liveController.alertTab = self.settings_tab
|
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
"""
|
"""
|
||||||
@ -121,3 +178,35 @@ class AlertsPlugin(Plugin):
|
|||||||
u'title': translate('AlertsPlugin', 'Alerts', 'container title')
|
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))
|
||||||
|
@ -81,7 +81,7 @@ class AlertsManager(QtCore.QObject):
|
|||||||
Format and request the Alert and start the timer
|
Format and request the Alert and start the timer
|
||||||
"""
|
"""
|
||||||
log.debug(u'Generate Alert called')
|
log.debug(u'Generate Alert called')
|
||||||
if len(self.alertList) == 0:
|
if not self.alertList:
|
||||||
return
|
return
|
||||||
text = self.alertList.pop(0)
|
text = self.alertList.pop(0)
|
||||||
alertTab = self.parent().settings_tab
|
alertTab = self.parent().settings_tab
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.lib import SettingsTab, translate
|
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||||
from openlp.core.lib.ui import UiStrings, create_valign_combo
|
from openlp.core.lib.ui import UiStrings, create_valign_combo
|
||||||
|
|
||||||
class AlertsTab(SettingsTab):
|
class AlertsTab(SettingsTab):
|
||||||
@ -140,6 +140,7 @@ class AlertsTab(SettingsTab):
|
|||||||
|
|
||||||
def onTimeoutSpinBoxChanged(self):
|
def onTimeoutSpinBoxChanged(self):
|
||||||
self.timeout = self.timeoutSpinBox.value()
|
self.timeout = self.timeoutSpinBox.value()
|
||||||
|
self.changed = True
|
||||||
|
|
||||||
def onFontSizeSpinBoxChanged(self):
|
def onFontSizeSpinBoxChanged(self):
|
||||||
self.font_size = self.fontSizeSpinBox.value()
|
self.font_size = self.fontSizeSpinBox.value()
|
||||||
@ -171,10 +172,15 @@ class AlertsTab(SettingsTab):
|
|||||||
font.setFamily(self.font_face)
|
font.setFamily(self.font_face)
|
||||||
self.fontComboBox.setCurrentFont(font)
|
self.fontComboBox.setCurrentFont(font)
|
||||||
self.updateDisplay()
|
self.updateDisplay()
|
||||||
|
self.changed = False
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
settings.beginGroup(self.settingsSection)
|
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'background color', QtCore.QVariant(self.bg_color))
|
||||||
settings.setValue(u'font color', QtCore.QVariant(self.font_color))
|
settings.setValue(u'font color', QtCore.QVariant(self.font_color))
|
||||||
settings.setValue(u'font size', QtCore.QVariant(self.font_size))
|
settings.setValue(u'font size', QtCore.QVariant(self.font_size))
|
||||||
@ -184,6 +190,9 @@ class AlertsTab(SettingsTab):
|
|||||||
self.location = self.verticalComboBox.currentIndex()
|
self.location = self.verticalComboBox.currentIndex()
|
||||||
settings.setValue(u'location', QtCore.QVariant(self.location))
|
settings.setValue(u'location', QtCore.QVariant(self.location))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
if self.changed:
|
||||||
|
Receiver.send_message(u'update_display_css')
|
||||||
|
self.changed = False
|
||||||
|
|
||||||
def updateDisplay(self):
|
def updateDisplay(self):
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
@ -193,4 +202,5 @@ class AlertsTab(SettingsTab):
|
|||||||
self.fontPreview.setFont(font)
|
self.fontPreview.setFont(font)
|
||||||
self.fontPreview.setStyleSheet(u'background-color: %s; color: %s' %
|
self.fontPreview.setStyleSheet(u'background-color: %s; color: %s' %
|
||||||
(self.bg_color, self.font_color))
|
(self.bg_color, self.font_color))
|
||||||
|
self.changed = True
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
CLAPPERBOARD = QtGui.QPixmap(u':/media/media_video.png').toImage()
|
CLAPPERBOARD = QtGui.QImage(u':/media/media_video.png')
|
||||||
|
|
||||||
class MediaMediaItem(MediaManagerItem):
|
class MediaMediaItem(MediaManagerItem):
|
||||||
"""
|
"""
|
||||||
@ -95,14 +95,14 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def onResetClick(self):
|
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.resetAction.setVisible(False)
|
||||||
self.plugin.liveController.display.resetVideo()
|
self.plugin.liveController.display.resetVideo()
|
||||||
|
|
||||||
def videobackgroundReplaced(self):
|
def videobackgroundReplaced(self):
|
||||||
"""
|
"""
|
||||||
Triggered by main display on change of serviceitem
|
Triggered by main display on change of serviceitem.
|
||||||
"""
|
"""
|
||||||
self.resetAction.setVisible(False)
|
self.resetAction.setVisible(False)
|
||||||
|
|
||||||
@ -179,8 +179,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def mediaStateWait(self, mediaState):
|
def mediaStateWait(self, mediaState):
|
||||||
"""
|
"""
|
||||||
Wait for the video to change its state
|
Wait for the video to change its state. Wait no longer than 5 seconds.
|
||||||
Wait no longer than 5 seconds.
|
|
||||||
"""
|
"""
|
||||||
start = datetime.now()
|
start = datetime.now()
|
||||||
while self.mediaObject.state() != mediaState:
|
while self.mediaObject.state() != mediaState:
|
||||||
@ -198,7 +197,7 @@ class MediaMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
def onDeleteClick(self):
|
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',
|
if check_item_selected(self.listView, translate('MediaPlugin.MediaItem',
|
||||||
'You must select a media file to delete.')):
|
'You must select a media file to delete.')):
|
||||||
|
@ -121,11 +121,11 @@ window.OpenLP = {
|
|||||||
$("#nextslide").html(text);
|
$("#nextslide").html(text);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateClock: function() {
|
updateClock: function(data) {
|
||||||
var div = $("#clock");
|
var div = $("#clock");
|
||||||
var t = new Date();
|
var t = new Date();
|
||||||
var h = t.getHours();
|
var h = t.getHours();
|
||||||
if (h > 12)
|
if (data.results.twelve && h > 12)
|
||||||
h = h - 12;
|
h = h - 12;
|
||||||
var m = t.getMinutes();
|
var m = t.getMinutes();
|
||||||
if (m < 10)
|
if (m < 10)
|
||||||
@ -136,7 +136,7 @@ window.OpenLP = {
|
|||||||
$.getJSON(
|
$.getJSON(
|
||||||
"/api/poll",
|
"/api/poll",
|
||||||
function (data, status) {
|
function (data, status) {
|
||||||
OpenLP.updateClock();
|
OpenLP.updateClock(data);
|
||||||
if (OpenLP.currentItem != data.results.item) {
|
if (OpenLP.currentItem != data.results.item) {
|
||||||
OpenLP.currentItem = data.results.item;
|
OpenLP.currentItem = data.results.item;
|
||||||
OpenLP.loadSlides();
|
OpenLP.loadSlides();
|
||||||
|
@ -315,7 +315,7 @@ class HttpConnection(object):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'ready to read socket')
|
log.debug(u'ready to read socket')
|
||||||
if self.socket.canReadLine():
|
if self.socket.canReadLine():
|
||||||
data = unicode(self.socket.readLine())
|
data = unicode(self.socket.readLine()).encode(u'utf-8')
|
||||||
log.debug(u'received: ' + data)
|
log.debug(u'received: ' + data)
|
||||||
words = data.split(u' ')
|
words = data.split(u' ')
|
||||||
response = None
|
response = None
|
||||||
@ -397,7 +397,9 @@ class HttpConnection(object):
|
|||||||
result = {
|
result = {
|
||||||
u'slide': self.parent.current_slide or 0,
|
u'slide': self.parent.current_slide or 0,
|
||||||
u'item': self.parent.current_item._uuid \
|
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}),
|
return HttpResponse(json.dumps({u'results': result}),
|
||||||
{u'Content-Type': u'application/json'})
|
{u'Content-Type': u'application/json'})
|
||||||
|
@ -57,6 +57,9 @@ class RemoteTab(SettingsTab):
|
|||||||
QtCore.QObject.connect(self.addressEdit,
|
QtCore.QObject.connect(self.addressEdit,
|
||||||
QtCore.SIGNAL(u'textChanged(const QString&)'), self.setUrls)
|
QtCore.SIGNAL(u'textChanged(const QString&)'), self.setUrls)
|
||||||
self.serverSettingsLayout.addRow(self.addressLabel, self.addressEdit)
|
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 = QtGui.QLabel(self.serverSettingsGroupBox)
|
||||||
self.portLabel.setObjectName(u'portLabel')
|
self.portLabel.setObjectName(u'portLabel')
|
||||||
self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
|
self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
|
||||||
@ -80,6 +83,9 @@ class RemoteTab(SettingsTab):
|
|||||||
self.leftLayout.addWidget(self.serverSettingsGroupBox)
|
self.leftLayout.addWidget(self.serverSettingsGroupBox)
|
||||||
self.leftLayout.addStretch()
|
self.leftLayout.addStretch()
|
||||||
self.rightLayout.addStretch()
|
self.rightLayout.addStretch()
|
||||||
|
QtCore.QObject.connect(self.twelveHourCheckBox,
|
||||||
|
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||||
|
self.onTwelveHourCheckBoxChanged)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.serverSettingsGroupBox.setTitle(
|
self.serverSettingsGroupBox.setTitle(
|
||||||
@ -92,6 +98,9 @@ class RemoteTab(SettingsTab):
|
|||||||
'Remote URL:'))
|
'Remote URL:'))
|
||||||
self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
|
self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
|
||||||
'Stage view URL:'))
|
'Stage view URL:'))
|
||||||
|
self.twelveHourCheckBox.setText(
|
||||||
|
translate('RemotePlugin.RemoteTab',
|
||||||
|
'Display stage time in 12h format'))
|
||||||
|
|
||||||
def setUrls(self):
|
def setUrls(self):
|
||||||
ipAddress = u'localhost'
|
ipAddress = u'localhost'
|
||||||
@ -123,6 +132,10 @@ class RemoteTab(SettingsTab):
|
|||||||
self.addressEdit.setText(
|
self.addressEdit.setText(
|
||||||
QtCore.QSettings().value(self.settingsSection + u'/ip address',
|
QtCore.QSettings().value(self.settingsSection + u'/ip address',
|
||||||
QtCore.QVariant(ZERO_URL)).toString())
|
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()
|
self.setUrls()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
@ -130,3 +143,11 @@ class RemoteTab(SettingsTab):
|
|||||||
QtCore.QVariant(self.portSpinBox.value()))
|
QtCore.QVariant(self.portSpinBox.value()))
|
||||||
QtCore.QSettings().setValue(self.settingsSection + u'/ip address',
|
QtCore.QSettings().setValue(self.settingsSection + u'/ip address',
|
||||||
QtCore.QVariant(self.addressEdit.text()))
|
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
|
||||||
|
@ -240,8 +240,9 @@ class SongImportForm(OpenLPWizard):
|
|||||||
self.formatLabel.setText(WizardStrings.FormatLabel)
|
self.formatLabel.setText(WizardStrings.FormatLabel)
|
||||||
self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2)
|
self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2)
|
||||||
self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1)
|
self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1)
|
||||||
self.formatComboBox.setItemText(
|
self.formatComboBox.setItemText(SongFormat.OpenLyrics,
|
||||||
SongFormat.OpenLyrics, WizardStrings.OL)
|
translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'OpenLyrics or OpenLP 2.0 Exported Song'))
|
||||||
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
|
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
|
||||||
self.formatComboBox.setItemText(
|
self.formatComboBox.setItemText(
|
||||||
SongFormat.WordsOfWorship, WizardStrings.WoW)
|
SongFormat.WordsOfWorship, WizardStrings.WoW)
|
||||||
@ -508,7 +509,8 @@ class SongImportForm(OpenLPWizard):
|
|||||||
Get OpenLyrics song database files
|
Get OpenLyrics song database files
|
||||||
"""
|
"""
|
||||||
self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL,
|
self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL,
|
||||||
self.openLyricsFileListWidget)
|
self.openLyricsFileListWidget, u'%s (*.xml)' %
|
||||||
|
translate('SongsPlugin.ImportWizardForm', 'OpenLyrics Files'))
|
||||||
|
|
||||||
def onOpenLyricsRemoveButtonClicked(self):
|
def onOpenLyricsRemoveButtonClicked(self):
|
||||||
"""
|
"""
|
||||||
|
@ -258,7 +258,7 @@ class EasiSlidesImport(SongImport):
|
|||||||
verses[reg][vt][vn] = {}
|
verses[reg][vt][vn] = {}
|
||||||
if not verses[reg][vt][vn].has_key(inst):
|
if not verses[reg][vt][vn].has_key(inst):
|
||||||
verses[reg][vt][vn][inst] = []
|
verses[reg][vt][vn][inst] = []
|
||||||
words = self.tidy_text(line)
|
words = self.tidyText(line)
|
||||||
verses[reg][vt][vn][inst].append(words)
|
verses[reg][vt][vn][inst].append(words)
|
||||||
# done parsing
|
# done parsing
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ class SofImport(OooImport):
|
|||||||
into line
|
into line
|
||||||
"""
|
"""
|
||||||
text = textportion.getString()
|
text = textportion.getString()
|
||||||
text = self.tidy_text(text)
|
text = self.tidyText(text)
|
||||||
if text.strip() == u'':
|
if text.strip() == u'':
|
||||||
return text
|
return text
|
||||||
if textportion.CharWeight == BOLD:
|
if textportion.CharWeight == BOLD:
|
||||||
|
@ -60,7 +60,7 @@ The XML of an `OpenLyrics <http://openlyrics.info/>`_ song looks like this::
|
|||||||
</lyrics>
|
</lyrics>
|
||||||
</song>
|
</song>
|
||||||
"""
|
"""
|
||||||
|
import cgi
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -257,11 +257,12 @@ class OpenLyrics(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
IMPLEMENTED_VERSION = u'0.8'
|
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):
|
def __init__(self, manager):
|
||||||
self.manager = 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):
|
def song_to_xml(self, song):
|
||||||
"""
|
"""
|
||||||
@ -334,7 +335,8 @@ class OpenLyrics(object):
|
|||||||
if u'lang' in verse[0]:
|
if u'lang' in verse[0]:
|
||||||
verse_element.set(u'lang', verse[0][u'lang'])
|
verse_element.set(u'lang', verse[0][u'lang'])
|
||||||
# Create a list with all "virtual" verses.
|
# 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):
|
for index, virtual_verse in enumerate(virtual_verses):
|
||||||
# Add formatting tags to text
|
# Add formatting tags to text
|
||||||
lines_element = self._add_text_with_tags_to_lines(verse_element,
|
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):
|
def _add_tag_to_formatting(self, tag_name, tags_element):
|
||||||
"""
|
"""
|
||||||
Add new formatting tag to the element ``<format>``
|
Add new formatting tag to the element ``<format>`` if the tag is not
|
||||||
if the tag is not present yet.
|
present yet.
|
||||||
"""
|
"""
|
||||||
available_tags = FormattingTags.get_html_tags()
|
available_tags = FormattingTags.get_html_tags()
|
||||||
start_tag = '{%s}' % tag_name
|
start_tag = '{%s}' % tag_name
|
||||||
for t in available_tags:
|
for tag in available_tags:
|
||||||
if t[u'start tag'] == start_tag:
|
if tag[u'start tag'] == start_tag:
|
||||||
# Create new formatting tag in openlyrics xml.
|
# Create new formatting tag in openlyrics xml.
|
||||||
el = self._add_text_to_element(u'tag', tags_element)
|
element = self._add_text_to_element(u'tag', tags_element)
|
||||||
el.set(u'name', tag_name)
|
element.set(u'name', tag_name)
|
||||||
el_open = self._add_text_to_element(u'open', el)
|
element_open = self._add_text_to_element(u'open', element)
|
||||||
el_open.text = etree.CDATA(t[u'start html'])
|
element_open.text = etree.CDATA(tag[u'start html'])
|
||||||
# Check if formatting tag contains end tag. Some formatting
|
# Check if formatting tag contains end tag. Some formatting
|
||||||
# tags e.g. {br} has only start tag. If no end tag is present
|
# tags e.g. {br} has only start tag. If no end tag is present
|
||||||
# <close> element has not to be in OpenLyrics xml.
|
# <close> element has not to be in OpenLyrics xml.
|
||||||
if t['end tag']:
|
if tag['end tag']:
|
||||||
el_close = self._add_text_to_element(u'close', el)
|
element_close = self._add_text_to_element(u'close', element)
|
||||||
el_close.text = etree.CDATA(t[u'end html'])
|
element_close.text = etree.CDATA(tag[u'end html'])
|
||||||
|
|
||||||
def _add_text_with_tags_to_lines(self, verse_element, text, tags_element):
|
def _add_text_with_tags_to_lines(self, verse_element, text, tags_element):
|
||||||
"""
|
"""
|
||||||
Convert text with formatting tags from OpenLP format to OpenLyrics
|
Convert text with formatting tags from OpenLP format to OpenLyrics
|
||||||
format and append it to element ``<lines>``.
|
format and append it to element ``<lines>``.
|
||||||
"""
|
"""
|
||||||
start_tags = self.start_tags_regex.findall(text)
|
start_tags = OpenLyrics.START_TAGS_REGEX.findall(text)
|
||||||
end_tags = self.end_tags_regex.findall(text)
|
end_tags = OpenLyrics.END_TAGS_REGEX.findall(text)
|
||||||
# Replace start tags with xml syntax.
|
# Replace start tags with xml syntax.
|
||||||
for tag in start_tags:
|
for tag in start_tags:
|
||||||
# Tags already converted to xml structure.
|
# Tags already converted to xml structure.
|
||||||
@ -442,12 +444,11 @@ class OpenLyrics(object):
|
|||||||
if tag not in xml_tags:
|
if tag not in xml_tags:
|
||||||
self._add_tag_to_formatting(tag, tags_element)
|
self._add_tag_to_formatting(tag, tags_element)
|
||||||
# Replace end tags.
|
# Replace end tags.
|
||||||
for t in end_tags:
|
for tag in end_tags:
|
||||||
text = text.replace(u'{/%s}' % t, u'</tag>')
|
text = text.replace(u'{/%s}' % tag, u'</tag>')
|
||||||
# Replace \n with <br/>.
|
# Replace \n with <br/>.
|
||||||
text = text.replace(u'\n', u'<br/>')
|
text = text.replace(u'\n', u'<br/>')
|
||||||
text = u'<lines>' + text + u'</lines>'
|
element = etree.XML(u'<lines>%s</lines>' % text)
|
||||||
element = etree.XML(text)
|
|
||||||
verse_element.append(element)
|
verse_element.append(element)
|
||||||
return element
|
return element
|
||||||
|
|
||||||
@ -692,7 +693,7 @@ class OpenLyrics(object):
|
|||||||
verse_tag = verse_def[0]
|
verse_tag = verse_def[0]
|
||||||
else:
|
else:
|
||||||
verse_tag = VerseType.Tags[VerseType.Other]
|
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
|
# OpenLyrics allows e. g. "c", but we need "c1". However, this does
|
||||||
# not correct the verse order.
|
# not correct the verse order.
|
||||||
if not verse_number:
|
if not verse_number:
|
||||||
|
81
resources/forms/themelayout.ui
Normal file
81
resources/forms/themelayout.ui
Normal 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
@ -60,8 +60,6 @@
|
|||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="slides">
|
<qresource prefix="slides">
|
||||||
<file>slide_close.png</file>
|
<file>slide_close.png</file>
|
||||||
<file>slide_first.png</file>
|
|
||||||
<file>slide_last.png</file>
|
|
||||||
<file>slide_next.png</file>
|
<file>slide_next.png</file>
|
||||||
<file>slide_blank.png</file>
|
<file>slide_blank.png</file>
|
||||||
<file>slide_desktop.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 |
@ -65,8 +65,11 @@ Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription
|
|||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
Source: psvince.dll; Flags: dontcopy
|
; DLL used to check if the target program is running at install time
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
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]
|
[Icons]
|
||||||
Name: {group}\{#AppName}; Filename: {app}\{#AppExeName}
|
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"""
|
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
function IsModuleLoaded(modulename: String ): Boolean;
|
// Function to call psvince.dll at install time
|
||||||
external 'IsModuleLoaded@files:psvince.dll stdcall';
|
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;
|
function GetUninstallString(): String;
|
||||||
var
|
var
|
||||||
@ -133,7 +141,7 @@ end;
|
|||||||
function InitializeSetup(): Boolean;
|
function InitializeSetup(): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := true;
|
Result := true;
|
||||||
while IsModuleLoaded( 'OpenLP.exe' ) and Result do
|
while IsModuleLoadedInstall( 'OpenLP.exe' ) and Result do
|
||||||
begin
|
begin
|
||||||
if MsgBox( 'Openlp is currently running, please close it to continue the install.',
|
if MsgBox( 'Openlp is currently running, please close it to continue the install.',
|
||||||
mbError, MB_OKCANCEL ) = IDCANCEL then
|
mbError, MB_OKCANCEL ) = IDCANCEL then
|
||||||
@ -153,3 +161,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
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;
|
@ -8,7 +8,7 @@
|
|||||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
# 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, #
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
# OpenLP - Open Source Lyrics Projection #
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
|
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||||
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
|
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||||
# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode #
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
# Woldsund #
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# This program is free software; you can redistribute it and/or modify it #
|
# 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 #
|
# under the terms of the GNU General Public License as published by the Free #
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
# 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, #
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
# Copyright (c) 2008-2011 Raoul Snyman #
|
# Copyright (c) 2008-2011 Raoul Snyman #
|
||||||
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
# 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, #
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
|
Loading…
Reference in New Issue
Block a user