forked from openlp/openlp
r1790
This commit is contained in:
commit
eb7b7a19d8
@ -143,7 +143,7 @@ class OpenLP(QtGui.QApplication):
|
|||||||
u'general/update check', QtCore.QVariant(True)).toBool()
|
u'general/update check', QtCore.QVariant(True)).toBool()
|
||||||
if update_check:
|
if update_check:
|
||||||
VersionThread(self.mainWindow).start()
|
VersionThread(self.mainWindow).start()
|
||||||
Receiver.send_message(u'maindisplay_blank_check')
|
Receiver.send_message(u'live_display_blank_check')
|
||||||
self.mainWindow.appStartup()
|
self.mainWindow.appStartup()
|
||||||
DelayStartThread(self.mainWindow).start()
|
DelayStartThread(self.mainWindow).start()
|
||||||
# Skip exec_() for gui tests
|
# Skip exec_() for gui tests
|
||||||
|
@ -35,189 +35,190 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class EventReceiver(QtCore.QObject):
|
class EventReceiver(QtCore.QObject):
|
||||||
"""
|
"""
|
||||||
Class to allow events to be passed from different parts of the
|
Class to allow events to be passed from different parts of the system. This
|
||||||
system. This is a private class and should not be used directly
|
is a private class and should not be used directly but rather via the
|
||||||
but rather via the Receiver class.
|
Receiver class.
|
||||||
|
|
||||||
|
**Mainwindow related and generic signals**
|
||||||
|
|
||||||
|
``mainwindow_status_text``
|
||||||
|
Changes the bottom status bar text on the mainwindow.
|
||||||
|
|
||||||
|
``openlp_warning_message``
|
||||||
|
Displays a standalone Warning Message.
|
||||||
|
|
||||||
|
``openlp_error_message``
|
||||||
|
Displays a standalone Error Message.
|
||||||
|
|
||||||
|
``openlp_information_message``
|
||||||
|
Displays a standalone Information Message.
|
||||||
|
|
||||||
|
``cursor_busy``
|
||||||
|
Makes the cursor got to a busy form.
|
||||||
|
|
||||||
|
``cursor_normal``
|
||||||
|
Resets the cursor to default.
|
||||||
|
|
||||||
``openlp_process_events``
|
``openlp_process_events``
|
||||||
Requests the Application to flush the events queue
|
Requests the Application to flush the events queue.
|
||||||
|
|
||||||
``openlp_version_check``
|
``openlp_version_check``
|
||||||
Version has changed so pop up window.
|
Version has changed so pop up window.
|
||||||
|
|
||||||
|
``openlp_stop_wizard``
|
||||||
|
Stops a wizard before completion.
|
||||||
|
|
||||||
|
**Setting related signals**
|
||||||
|
|
||||||
``config_updated``
|
``config_updated``
|
||||||
Informs components the config has changed
|
Informs components that the config has changed.
|
||||||
|
|
||||||
``config_screen_changed``
|
``config_screen_changed``
|
||||||
The display monitor has been changed
|
The display monitor has been changed.
|
||||||
|
|
||||||
|
**Slidecontroller signals**
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_next``
|
``slidecontroller_{live|preview}_next``
|
||||||
Moves to the next slide
|
Moves to the next slide.
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_next_noloop``
|
``slidecontroller_{live|preview}_next_noloop``
|
||||||
Moves to the next slide without auto advance
|
Moves to the next slide without auto advance.
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_previous``
|
``slidecontroller_{live|preview}_previous``
|
||||||
Moves to the previous slide
|
Moves to the previous slide.
|
||||||
|
|
||||||
``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}_set``
|
``slidecontroller_{live|preview}_set``
|
||||||
Moves to a specific slide, by index
|
Moves to a specific slide, by index.
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_started``
|
``slidecontroller_{live|preview}_started``
|
||||||
Broadcasts that an item has been made live/previewed
|
Broadcasts that an item has been made live/previewed.
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_change``
|
``slidecontroller_{live|preview}_change``
|
||||||
Informs the slidecontroller that a slide change has occurred and to
|
Informs the slidecontroller that a slide change has occurred and to
|
||||||
update itself
|
update itself.
|
||||||
|
|
||||||
``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}_blank``
|
``slidecontroller_{live|preview}_blank``
|
||||||
Request that the output screen is blanked
|
Request that the output screen is blanked.
|
||||||
|
|
||||||
``slidecontroller_{live|preview}_unblank``
|
``slidecontroller_{live|preview}_unblank``
|
||||||
Request that the output screen is unblanked
|
Request that the output screen is unblanked.
|
||||||
|
|
||||||
``slidecontroller_live_spin_delay``
|
``slidecontroller_live_spin_delay``
|
||||||
Pushes out the loop delay
|
Pushes out the loop delay.
|
||||||
|
|
||||||
``slidecontroller_live_stop_loop``
|
``slidecontroller_live_stop_loop``
|
||||||
Stop the loop on the main display
|
Stop the loop on the main display.
|
||||||
|
|
||||||
|
**Servicemanager related signals**
|
||||||
|
|
||||||
``servicemanager_previous_item``
|
``servicemanager_previous_item``
|
||||||
Display the previous item in the service
|
Display the previous item in the service.
|
||||||
|
|
||||||
``servicemanager_preview_live``
|
``servicemanager_preview_live``
|
||||||
Requests a Preview item from the Service Manager to update live and
|
Requests a Preview item from the Service Manager to update live and add
|
||||||
add a new item to the preview panel
|
a new item to the preview panel.
|
||||||
|
|
||||||
``servicemanager_next_item``
|
``servicemanager_next_item``
|
||||||
Display the next item in the service
|
Display the next item in the service.
|
||||||
|
|
||||||
``servicemanager_set_item``
|
``servicemanager_set_item``
|
||||||
Go live on a specific item, by index
|
Go live on a specific item, by index.
|
||||||
|
|
||||||
``maindisplay_blank``
|
|
||||||
Blank the maindisplay window
|
|
||||||
|
|
||||||
``maindisplay_hide``
|
|
||||||
Hide the maindisplay window
|
|
||||||
|
|
||||||
``maindisplay_show``
|
|
||||||
Return the maindisplay window
|
|
||||||
|
|
||||||
``maindisplay_active``
|
|
||||||
The maindisplay has been made active
|
|
||||||
|
|
||||||
``maindisplay_status_text``
|
|
||||||
Changes the bottom status bar text on the maindisplay window
|
|
||||||
|
|
||||||
``maindisplay_blank_check``
|
|
||||||
Check to see if the blank display message is required
|
|
||||||
|
|
||||||
``videodisplay_start``
|
|
||||||
Open a media item and prepare for playing
|
|
||||||
|
|
||||||
``videodisplay_play``
|
|
||||||
Start playing a media item
|
|
||||||
|
|
||||||
``videodisplay_pause``
|
|
||||||
Pause a media item
|
|
||||||
|
|
||||||
``videodisplay_stop``
|
|
||||||
Stop playing a media item
|
|
||||||
|
|
||||||
``videodisplay_background``
|
|
||||||
Replace the background video
|
|
||||||
|
|
||||||
``theme_update_list``
|
|
||||||
send out message with new themes
|
|
||||||
|
|
||||||
``theme_update_global``
|
|
||||||
Tell the components we have a new global theme
|
|
||||||
|
|
||||||
``{plugin}_start``
|
|
||||||
Requests a plugin to start a external program
|
|
||||||
Path and file provided in message
|
|
||||||
|
|
||||||
``{plugin}_first``
|
|
||||||
Requests a plugin to handle a first event
|
|
||||||
|
|
||||||
``{plugin}_previous``
|
|
||||||
Requests a plugin to handle a previous event
|
|
||||||
|
|
||||||
``{plugin}_next``
|
|
||||||
Requests a plugin to handle a next event
|
|
||||||
|
|
||||||
``{plugin}_last``
|
|
||||||
Requests a plugin to handle a last event
|
|
||||||
|
|
||||||
``{plugin}_slide``
|
|
||||||
Requests a plugin to handle a go to specific slide event
|
|
||||||
|
|
||||||
``{plugin}_stop``
|
|
||||||
Requests a plugin to handle a stop event
|
|
||||||
|
|
||||||
``{plugin}_blank``
|
|
||||||
Requests a plugin to handle a blank screen event
|
|
||||||
|
|
||||||
``{plugin}_unblank``
|
|
||||||
Requests a plugin to handle an unblank screen event
|
|
||||||
|
|
||||||
``{plugin}_edit``
|
|
||||||
Requests a plugin edit a database item with the key as the payload
|
|
||||||
|
|
||||||
``{plugin}_edit_clear``
|
|
||||||
Editing has been completed
|
|
||||||
|
|
||||||
``{plugin}_load_list``
|
|
||||||
Tells the the plugin to reload the media manager list
|
|
||||||
|
|
||||||
``{plugin}_preview``
|
|
||||||
Tells the plugin it's item can be previewed
|
|
||||||
|
|
||||||
``{plugin}_add_service_item``
|
|
||||||
Ask the plugin to push the selected items to the service item
|
|
||||||
|
|
||||||
``{plugin}_service_load``
|
|
||||||
Ask the plugin to process an individual service item after it has been
|
|
||||||
loaded
|
|
||||||
|
|
||||||
``service_item_update``
|
``service_item_update``
|
||||||
Passes back to the service manager the service item after it has been
|
Passes back to the service manager the service item after it has been
|
||||||
processed by the plugin
|
processed by the plugin.
|
||||||
|
|
||||||
|
**Display signals**
|
||||||
|
|
||||||
|
``update_display_css``
|
||||||
|
CSS has been updated which needs to be changed on the main display.
|
||||||
|
|
||||||
|
**Live Display signals**
|
||||||
|
|
||||||
|
``live_display_hide``
|
||||||
|
Hide the live display.
|
||||||
|
|
||||||
|
``live_display_show``
|
||||||
|
Return the live display.
|
||||||
|
|
||||||
|
``live_display_active``
|
||||||
|
The live display has been made active.
|
||||||
|
|
||||||
|
``live_display_blank_check``
|
||||||
|
Check to see if the blank display message is required.
|
||||||
|
|
||||||
|
**Theme related singlas**
|
||||||
|
|
||||||
|
``theme_update_list``
|
||||||
|
send out message with new themes.
|
||||||
|
|
||||||
|
``theme_update_global``
|
||||||
|
Tell the components we have a new global theme.
|
||||||
|
|
||||||
|
**Plugin specific signals**
|
||||||
|
|
||||||
|
``{plugin}_start``
|
||||||
|
Requests a plugin to start a external program. Path and file have to
|
||||||
|
be provided in the message.
|
||||||
|
|
||||||
|
``{plugin}_first``
|
||||||
|
Requests a plugin to handle a first event.
|
||||||
|
|
||||||
|
``{plugin}_previous``
|
||||||
|
Requests a plugin to handle a previous event.
|
||||||
|
|
||||||
|
``{plugin}_next``
|
||||||
|
Requests a plugin to handle a next event.
|
||||||
|
|
||||||
|
``{plugin}_last``
|
||||||
|
Requests a plugin to handle a last event.
|
||||||
|
|
||||||
|
``{plugin}_slide``
|
||||||
|
Requests a plugin to handle a go to specific slide event.
|
||||||
|
|
||||||
|
``{plugin}_stop``
|
||||||
|
Requests a plugin to handle a stop event.
|
||||||
|
|
||||||
|
``{plugin}_blank``
|
||||||
|
Requests a plugin to handle a blank screen event.
|
||||||
|
|
||||||
|
``{plugin}_unblank``
|
||||||
|
Requests a plugin to handle an unblank screen event.
|
||||||
|
|
||||||
|
``{plugin}_edit``
|
||||||
|
Requests a plugin edit a database item with the key as the payload.
|
||||||
|
|
||||||
|
``{plugin}_edit_clear``
|
||||||
|
Editing has been completed.
|
||||||
|
|
||||||
|
``{plugin}_load_list``
|
||||||
|
Tells the the plugin to reload the media manager list.
|
||||||
|
|
||||||
|
``{plugin}_preview``
|
||||||
|
Tells the plugin it's item can be previewed.
|
||||||
|
|
||||||
|
``{plugin}_add_service_item``
|
||||||
|
Ask the plugin to push the selected items to the service item.
|
||||||
|
|
||||||
|
``{plugin}_service_load``
|
||||||
|
Ask the plugin to process an individual service item after it has been
|
||||||
|
loaded.
|
||||||
|
|
||||||
``alerts_text``
|
``alerts_text``
|
||||||
Displays an alert message
|
Displays an alert message.
|
||||||
|
|
||||||
``bibles_nobook``
|
``bibles_nobook``
|
||||||
Attempt to find book resulted in no match
|
Attempt to find book resulted in no match.
|
||||||
|
|
||||||
``openlp_stop_wizard``
|
|
||||||
Stops a wizard before completion
|
|
||||||
|
|
||||||
``remotes_poll_request``
|
``remotes_poll_request``
|
||||||
Waits for openlp to do something "interesting" and sends a
|
Waits for openlp to do something "interesting" and sends a
|
||||||
remotes_poll_response signal when it does
|
``remotes_poll_response`` signal when it does.
|
||||||
|
|
||||||
``openlp_warning_message``
|
|
||||||
Displays a standalone Warning Message
|
|
||||||
|
|
||||||
``openlp_error_message``
|
|
||||||
Displays a standalone Error Message
|
|
||||||
|
|
||||||
``openlp_information_message``
|
|
||||||
Displays a standalone Information Message
|
|
||||||
|
|
||||||
``cursor_busy``
|
|
||||||
Makes the cursor got to a busy form
|
|
||||||
|
|
||||||
``cursor_normal``
|
|
||||||
Resets the cursor to default
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
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
|
||||||
|
|
||||||
@ -633,24 +610,3 @@ def build_footer_css(item, height):
|
|||||||
theme.font_footer_size, theme.font_footer_color)
|
theme.font_footer_size, theme.font_footer_color)
|
||||||
return lyrics_html
|
return lyrics_html
|
||||||
|
|
||||||
def build_alert_css(alertTab, width):
|
|
||||||
"""
|
|
||||||
Build the display of the footer
|
|
||||||
|
|
||||||
``alertTab``
|
|
||||||
Details from the Alert tab for fonts etc
|
|
||||||
"""
|
|
||||||
style = u"""
|
|
||||||
width: %spx;
|
|
||||||
vertical-align: %s;
|
|
||||||
font-family: %s;
|
|
||||||
font-size: %spt;
|
|
||||||
color: %s;
|
|
||||||
background-color: %s;
|
|
||||||
"""
|
|
||||||
if not alertTab:
|
|
||||||
return u''
|
|
||||||
align = VerticalType.Names[alertTab.location]
|
|
||||||
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
|
|
||||||
alertTab.font_color, alertTab.bg_color)
|
|
||||||
return alert
|
|
||||||
|
@ -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)
|
||||||
|
@ -52,6 +52,24 @@ class HideMode(object):
|
|||||||
Theme = 2
|
Theme = 2
|
||||||
Screen = 3
|
Screen = 3
|
||||||
|
|
||||||
|
class AlertLocation(object):
|
||||||
|
"""
|
||||||
|
This is an enumeration class which controls where Alerts are placed on the
|
||||||
|
screen.
|
||||||
|
|
||||||
|
``Top``
|
||||||
|
Place the text at the top of the screen.
|
||||||
|
|
||||||
|
``Middle``
|
||||||
|
Place the text in the middle of the screen.
|
||||||
|
|
||||||
|
``Bottom``
|
||||||
|
Place the text at the bottom of the screen.
|
||||||
|
"""
|
||||||
|
Top = 0
|
||||||
|
Middle = 1
|
||||||
|
Bottom = 2
|
||||||
|
|
||||||
from firsttimeform import FirstTimeForm
|
from firsttimeform import FirstTimeForm
|
||||||
from firsttimelanguageform import FirstTimeLanguageForm
|
from firsttimelanguageform import FirstTimeLanguageForm
|
||||||
from themelayoutform import ThemeLayoutForm
|
from themelayoutform import ThemeLayoutForm
|
||||||
|
@ -39,6 +39,11 @@ try:
|
|||||||
PHONON_VERSION = Phonon.phononVersion()
|
PHONON_VERSION = Phonon.phononVersion()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PHONON_VERSION = u'-'
|
PHONON_VERSION = u'-'
|
||||||
|
try:
|
||||||
|
import migrate
|
||||||
|
MIGRATE_VERSION = getattr(migrate, u'__version__', u'< 0.7')
|
||||||
|
except ImportError:
|
||||||
|
MIGRATE_VERSION = u'-'
|
||||||
try:
|
try:
|
||||||
import chardet
|
import chardet
|
||||||
CHARDET_VERSION = chardet.__version__
|
CHARDET_VERSION = chardet.__version__
|
||||||
@ -54,9 +59,26 @@ try:
|
|||||||
SQLITE_VERSION = sqlite.version
|
SQLITE_VERSION = sqlite.version
|
||||||
except ImportError:
|
except ImportError:
|
||||||
SQLITE_VERSION = u'-'
|
SQLITE_VERSION = u'-'
|
||||||
|
try:
|
||||||
|
import mako
|
||||||
|
MAKO_VERSION = mako.__version__
|
||||||
|
except ImportError:
|
||||||
|
MAKO_VERSION = u'-'
|
||||||
|
try:
|
||||||
|
import uno
|
||||||
|
arg = uno.createUnoStruct(u'com.sun.star.beans.PropertyValue')
|
||||||
|
arg.Name = u'nodepath'
|
||||||
|
arg.Value = u'/org.openoffice.Setup/Product'
|
||||||
|
context = uno.getComponentContext()
|
||||||
|
provider = context.ServiceManager.createInstance(
|
||||||
|
u'com.sun.star.configuration.ConfigurationProvider')
|
||||||
|
node = provider.createInstanceWithArguments(
|
||||||
|
u'com.sun.star.configuration.ConfigurationAccess', (arg,))
|
||||||
|
UNO_VERSION = node.getByName(u'ooSetupVersion')
|
||||||
|
except ImportError:
|
||||||
|
UNO_VERSION = u'-'
|
||||||
|
|
||||||
from openlp.core.lib import translate, SettingsManager
|
from openlp.core.lib 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
|
||||||
|
|
||||||
@ -90,11 +112,14 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
|||||||
u'Phonon: %s\n' % PHONON_VERSION + \
|
u'Phonon: %s\n' % PHONON_VERSION + \
|
||||||
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
|
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
|
||||||
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
|
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
|
||||||
|
u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \
|
||||||
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
|
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
|
||||||
u'lxml: %s\n' % etree.__version__ + \
|
u'lxml: %s\n' % etree.__version__ + \
|
||||||
u'Chardet: %s\n' % CHARDET_VERSION + \
|
u'Chardet: %s\n' % CHARDET_VERSION + \
|
||||||
u'PyEnchant: %s\n' % ENCHANT_VERSION + \
|
u'PyEnchant: %s\n' % ENCHANT_VERSION + \
|
||||||
u'PySQLite: %s\n' % SQLITE_VERSION
|
u'PySQLite: %s\n' % SQLITE_VERSION + \
|
||||||
|
u'Mako: %s\n' % MAKO_VERSION + \
|
||||||
|
u'pyUNO bridge: %s\n' % UNO_VERSION
|
||||||
if platform.system() == u'Linux':
|
if platform.system() == u'Linux':
|
||||||
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
|
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
|
||||||
system = system + u'Desktop: KDE SC\n'
|
system = system + u'Desktop: KDE SC\n'
|
||||||
@ -153,18 +178,20 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
|||||||
'Please add the information that bug reports are favoured written '
|
'Please add the information that bug reports are favoured written '
|
||||||
'in English.'))
|
'in English.'))
|
||||||
content = self._createReport()
|
content = self._createReport()
|
||||||
|
source = u''
|
||||||
|
exception = u''
|
||||||
for line in content[2].split(u'\n'):
|
for line in content[2].split(u'\n'):
|
||||||
if re.search(r'[/\\]openlp[/\\]', line):
|
if re.search(r'[/\\]openlp[/\\]', line):
|
||||||
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
|
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
|
||||||
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,9 +35,9 @@ 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, AlertLocation
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -58,7 +58,8 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
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 = {}
|
||||||
@ -76,12 +77,32 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
|
QtCore.SIGNAL(u'live_display_hide'), self.hideDisplay)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay)
|
QtCore.SIGNAL(u'live_display_show'), self.showDisplay)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.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):
|
||||||
"""
|
"""
|
||||||
@ -113,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)
|
||||||
@ -147,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']:
|
||||||
@ -189,7 +213,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
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'\\\"'))
|
||||||
|
|
||||||
def alert(self, text):
|
def alert(self, text, location):
|
||||||
"""
|
"""
|
||||||
Display an alert.
|
Display an alert.
|
||||||
|
|
||||||
@ -217,10 +241,10 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
alert_height = int(height.toString())
|
alert_height = int(height.toString())
|
||||||
shrinkItem.resize(self.width(), alert_height)
|
shrinkItem.resize(self.width(), alert_height)
|
||||||
shrinkItem.setVisible(True)
|
shrinkItem.setVisible(True)
|
||||||
if self.alertTab.location == 1:
|
if location == AlertLocation.Middle:
|
||||||
shrinkItem.move(self.screen[u'size'].left(),
|
shrinkItem.move(self.screen[u'size'].left(),
|
||||||
(self.screen[u'size'].height() - alert_height) / 2)
|
(self.screen[u'size'].height() - alert_height) / 2)
|
||||||
elif self.alertTab.location == 2:
|
elif location == AlertLocation.Bottom:
|
||||||
shrinkItem.move(self.screen[u'size'].left(),
|
shrinkItem.move(self.screen[u'size'].left(),
|
||||||
self.screen[u'size'].height() - alert_height)
|
self.screen[u'size'].height() - alert_height)
|
||||||
else:
|
else:
|
||||||
@ -479,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')
|
||||||
@ -546,7 +570,7 @@ class MainDisplay(QtGui.QGraphicsView):
|
|||||||
self.hideMode = None
|
self.hideMode = None
|
||||||
# Trigger actions when display is active again
|
# Trigger actions when display is active again
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
Receiver.send_message(u'maindisplay_active')
|
Receiver.send_message(u'live_display_active')
|
||||||
|
|
||||||
def __hideMouse(self):
|
def __hideMouse(self):
|
||||||
# Hide mouse cursor when moved over display if enabled in settings
|
# Hide mouse cursor when moved over display if enabled in settings
|
||||||
|
@ -611,11 +611,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_version_check'), self.versionNotice)
|
QtCore.SIGNAL(u'openlp_version_check'), self.versionNotice)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'maindisplay_blank_check'), self.blankCheck)
|
QtCore.SIGNAL(u'live_display_blank_check'), self.blankCheck)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
|
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'maindisplay_status_text'), self.showStatusMessage)
|
QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage)
|
||||||
# Media Manager
|
# Media Manager
|
||||||
QtCore.QObject.connect(self.mediaToolBox,
|
QtCore.QObject.connect(self.mediaToolBox,
|
||||||
QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
|
QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
|
||||||
|
@ -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
|
||||||
@ -423,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)
|
||||||
@ -745,9 +743,9 @@ class SlideController(QtGui.QWidget):
|
|||||||
elif display_type == u'blanked':
|
elif display_type == u'blanked':
|
||||||
self.onBlankDisplay(True)
|
self.onBlankDisplay(True)
|
||||||
else:
|
else:
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
else:
|
else:
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
|
|
||||||
def onSlideBlank(self):
|
def onSlideBlank(self):
|
||||||
"""
|
"""
|
||||||
@ -833,21 +831,21 @@ class SlideController(QtGui.QWidget):
|
|||||||
if self.serviceItem is not None:
|
if self.serviceItem is not None:
|
||||||
if hide_mode:
|
if hide_mode:
|
||||||
if not self.serviceItem.is_command():
|
if not self.serviceItem.is_command():
|
||||||
Receiver.send_message(u'maindisplay_hide', hide_mode)
|
Receiver.send_message(u'live_display_hide', hide_mode)
|
||||||
Receiver.send_message(u'%s_blank'
|
Receiver.send_message(u'%s_blank'
|
||||||
% self.serviceItem.name.lower(),
|
% self.serviceItem.name.lower(),
|
||||||
[self.serviceItem, self.isLive, hide_mode])
|
[self.serviceItem, self.isLive, hide_mode])
|
||||||
else:
|
else:
|
||||||
if not self.serviceItem.is_command():
|
if not self.serviceItem.is_command():
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
Receiver.send_message(u'%s_unblank'
|
Receiver.send_message(u'%s_unblank'
|
||||||
% self.serviceItem.name.lower(),
|
% self.serviceItem.name.lower(),
|
||||||
[self.serviceItem, self.isLive])
|
[self.serviceItem, self.isLive])
|
||||||
else:
|
else:
|
||||||
if hide_mode:
|
if hide_mode:
|
||||||
Receiver.send_message(u'maindisplay_hide', hide_mode)
|
Receiver.send_message(u'live_display_hide', hide_mode)
|
||||||
else:
|
else:
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
|
|
||||||
def hidePlugin(self, hide):
|
def hidePlugin(self, hide):
|
||||||
"""
|
"""
|
||||||
@ -856,21 +854,21 @@ class SlideController(QtGui.QWidget):
|
|||||||
log.debug(u'hidePlugin %s ', hide)
|
log.debug(u'hidePlugin %s ', hide)
|
||||||
if self.serviceItem is not None:
|
if self.serviceItem is not None:
|
||||||
if hide:
|
if hide:
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
Receiver.send_message(u'%s_hide'
|
Receiver.send_message(u'%s_hide'
|
||||||
% self.serviceItem.name.lower(),
|
% self.serviceItem.name.lower(),
|
||||||
[self.serviceItem, self.isLive])
|
[self.serviceItem, self.isLive])
|
||||||
else:
|
else:
|
||||||
if not self.serviceItem.is_command():
|
if not self.serviceItem.is_command():
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
Receiver.send_message(u'%s_unblank'
|
Receiver.send_message(u'%s_unblank'
|
||||||
% self.serviceItem.name.lower(),
|
% self.serviceItem.name.lower(),
|
||||||
[self.serviceItem, self.isLive])
|
[self.serviceItem, self.isLive])
|
||||||
else:
|
else:
|
||||||
if hide:
|
if hide:
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
else:
|
else:
|
||||||
Receiver.send_message(u'maindisplay_show')
|
Receiver.send_message(u'live_display_show')
|
||||||
|
|
||||||
def onSlideSelected(self, start=False):
|
def onSlideSelected(self, start=False):
|
||||||
"""
|
"""
|
||||||
|
@ -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,76 @@ 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.fontSize = size + "pt";
|
||||||
|
text.style.fontFamily = font;
|
||||||
|
text.style.color = color;
|
||||||
|
text.style.backgroundColor = bgcolor;
|
||||||
|
switch(align)
|
||||||
|
{
|
||||||
|
case 'top':
|
||||||
|
text.style.top = '0px';
|
||||||
|
break;
|
||||||
|
case 'middle':
|
||||||
|
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
text.style.top = (window.innerHeight - text.clientHeight)
|
||||||
|
+ 'px';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
CSS = """
|
||||||
|
#alert {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 10;
|
||||||
|
width: 100%%;
|
||||||
|
vertical-align: %s;
|
||||||
|
font-family: %s;
|
||||||
|
font-size: %spt;
|
||||||
|
color: %s;
|
||||||
|
background-color: %s;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
HTML = """
|
||||||
|
<div id="alert" style="visibility:hidden"></div>
|
||||||
|
"""
|
||||||
|
|
||||||
class AlertsPlugin(Plugin):
|
class AlertsPlugin(Plugin):
|
||||||
log.info(u'Alerts Plugin loaded')
|
log.info(u'Alerts Plugin loaded')
|
||||||
|
|
||||||
@ -79,7 +150,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 +191,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))
|
||||||
|
@ -45,7 +45,7 @@ class AlertsManager(QtCore.QObject):
|
|||||||
self.timer_id = 0
|
self.timer_id = 0
|
||||||
self.alertList = []
|
self.alertList = []
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'maindisplay_active'), self.generateAlert)
|
QtCore.SIGNAL(u'live_display_active'), self.generateAlert)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'alerts_text'), self.onAlertText)
|
QtCore.SIGNAL(u'alerts_text'), self.onAlertText)
|
||||||
|
|
||||||
@ -69,11 +69,11 @@ class AlertsManager(QtCore.QObject):
|
|||||||
log.debug(u'display alert called %s' % text)
|
log.debug(u'display alert called %s' % text)
|
||||||
self.alertList.append(text)
|
self.alertList.append(text)
|
||||||
if self.timer_id != 0:
|
if self.timer_id != 0:
|
||||||
Receiver.send_message(u'maindisplay_status_text',
|
Receiver.send_message(u'mainwindow_status_text',
|
||||||
translate('AlertsPlugin.AlertsManager',
|
translate('AlertsPlugin.AlertsManager',
|
||||||
'Alert message created and displayed.'))
|
'Alert message created and displayed.'))
|
||||||
return
|
return
|
||||||
Receiver.send_message(u'maindisplay_status_text', u'')
|
Receiver.send_message(u'mainwindow_status_text', u'')
|
||||||
self.generateAlert()
|
self.generateAlert()
|
||||||
|
|
||||||
def generateAlert(self):
|
def generateAlert(self):
|
||||||
@ -85,7 +85,7 @@ class AlertsManager(QtCore.QObject):
|
|||||||
return
|
return
|
||||||
text = self.alertList.pop(0)
|
text = self.alertList.pop(0)
|
||||||
alertTab = self.parent().settings_tab
|
alertTab = self.parent().settings_tab
|
||||||
self.parent().liveController.display.alert(text)
|
self.parent().liveController.display.alert(text, alertTab.location)
|
||||||
# Check to see if we have a timer running.
|
# Check to see if we have a timer running.
|
||||||
if self.timer_id == 0:
|
if self.timer_id == 0:
|
||||||
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
|
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
|
||||||
@ -100,7 +100,8 @@ class AlertsManager(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
log.debug(u'timer event')
|
log.debug(u'timer event')
|
||||||
if event.timerId() == self.timer_id:
|
if event.timerId() == self.timer_id:
|
||||||
self.parent().liveController.display.alert(u'')
|
alertTab = self.parent().settings_tab
|
||||||
|
self.parent().liveController.display.alert(u'', alertTab.location)
|
||||||
self.killTimer(self.timer_id)
|
self.killTimer(self.timer_id)
|
||||||
self.timer_id = 0
|
self.timer_id = 0
|
||||||
self.generateAlert()
|
self.generateAlert()
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
|
|
||||||
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.ui import AlertLocation
|
||||||
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 +141,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()
|
||||||
@ -158,7 +160,7 @@ class AlertsTab(SettingsTab):
|
|||||||
self.font_face = unicode(settings.value(
|
self.font_face = unicode(settings.value(
|
||||||
u'font face', QtCore.QVariant(QtGui.QFont().family())).toString())
|
u'font face', QtCore.QVariant(QtGui.QFont().family())).toString())
|
||||||
self.location = settings.value(
|
self.location = settings.value(
|
||||||
u'location', QtCore.QVariant(1)).toInt()[0]
|
u'location', QtCore.QVariant(AlertLocation.Bottom)).toInt()[0]
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.fontSizeSpinBox.setValue(self.font_size)
|
self.fontSizeSpinBox.setValue(self.font_size)
|
||||||
self.timeoutSpinBox.setValue(self.timeout)
|
self.timeoutSpinBox.setValue(self.timeout)
|
||||||
@ -171,10 +173,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 +191,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 +203,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
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class Controller(object):
|
|||||||
self.doc.slidenumber = slide_no
|
self.doc.slidenumber = slide_no
|
||||||
if self.is_live:
|
if self.is_live:
|
||||||
if hide_mode == HideMode.Screen:
|
if hide_mode == HideMode.Screen:
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
self.stop()
|
self.stop()
|
||||||
elif hide_mode == HideMode.Theme:
|
elif hide_mode == HideMode.Theme:
|
||||||
self.blank(hide_mode)
|
self.blank(hide_mode)
|
||||||
@ -76,7 +76,7 @@ class Controller(object):
|
|||||||
self.blank(hide_mode)
|
self.blank(hide_mode)
|
||||||
else:
|
else:
|
||||||
self.doc.start_presentation()
|
self.doc.start_presentation()
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
self.doc.slidenumber = 0
|
self.doc.slidenumber = 0
|
||||||
if slide_no > 1:
|
if slide_no > 1:
|
||||||
self.slide(slide_no)
|
self.slide(slide_no)
|
||||||
@ -196,7 +196,7 @@ class Controller(object):
|
|||||||
if not self.doc.is_active():
|
if not self.doc.is_active():
|
||||||
return
|
return
|
||||||
if hide_mode == HideMode.Theme:
|
if hide_mode == HideMode.Theme:
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Theme)
|
Receiver.send_message(u'live_display_hide', HideMode.Theme)
|
||||||
self.doc.blank_screen()
|
self.doc.blank_screen()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -224,7 +224,7 @@ class Controller(object):
|
|||||||
self.doc.slidenumber != self.doc.get_slide_number():
|
self.doc.slidenumber != self.doc.get_slide_number():
|
||||||
self.doc.goto_slide(self.doc.slidenumber)
|
self.doc.goto_slide(self.doc.slidenumber)
|
||||||
self.doc.unblank_screen()
|
self.doc.unblank_screen()
|
||||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
self.doc.poll_slidenumber(self.is_live)
|
self.doc.poll_slidenumber(self.is_live)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class OooImport(SongImport):
|
|||||||
if not isinstance(self.importSource, list):
|
if not isinstance(self.importSource, list):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
self.start_ooo()
|
self.startOoo()
|
||||||
except NoConnectException as exc:
|
except NoConnectException as exc:
|
||||||
self.logError(
|
self.logError(
|
||||||
self.importSource[0],
|
self.importSource[0],
|
||||||
@ -145,7 +145,7 @@ class OooImport(SongImport):
|
|||||||
process.waitForStarted()
|
process.waitForStarted()
|
||||||
self.processStarted = True
|
self.processStarted = True
|
||||||
except:
|
except:
|
||||||
log.exception("start_ooo_process failed")
|
log.exception("startOooProcess failed")
|
||||||
|
|
||||||
def openOooFile(self, filepath):
|
def openOooFile(self, filepath):
|
||||||
"""
|
"""
|
||||||
@ -171,7 +171,7 @@ class OooImport(SongImport):
|
|||||||
self.importWizard.incrementProgressBar(
|
self.importWizard.incrementProgressBar(
|
||||||
u'Processing file ' + filepath, 0)
|
u'Processing file ' + filepath, 0)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.exception("open_ooo_file failed: %s", url)
|
log.exception("openOooFile failed: %s", url)
|
||||||
return
|
return
|
||||||
|
|
||||||
def closeOooFile(self):
|
def closeOooFile(self):
|
||||||
|
@ -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:
|
||||||
|
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
@ -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: AnsiString ): 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;
|
@ -73,6 +73,7 @@ MODULES = [
|
|||||||
'BeautifulSoup',
|
'BeautifulSoup',
|
||||||
'mako',
|
'mako',
|
||||||
'migrate',
|
'migrate',
|
||||||
|
'uno',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,10 +48,10 @@ Inno Setup 5
|
|||||||
|
|
||||||
Sphinx
|
Sphinx
|
||||||
This is used to build the documentation. The documentation trunk must be at
|
This is used to build the documentation. The documentation trunk must be at
|
||||||
the same directory level as Openlp trunk and named "documentation"
|
the same directory level as Openlp trunk and named "documentation".
|
||||||
|
|
||||||
HTML Help Workshop
|
HTML Help Workshop
|
||||||
This is used to create the help file
|
This is used to create the help file.
|
||||||
|
|
||||||
PyInstaller
|
PyInstaller
|
||||||
PyInstaller should be a checkout of revision 1470 of trunk, and in a
|
PyInstaller should be a checkout of revision 1470 of trunk, and in a
|
||||||
@ -65,10 +65,6 @@ PyInstaller
|
|||||||
|
|
||||||
http://svn.pyinstaller.org/trunk
|
http://svn.pyinstaller.org/trunk
|
||||||
|
|
||||||
Then you need to copy the two hook-*.py files from the "pyinstaller"
|
|
||||||
subdirectory in OpenLP's "resources" directory into PyInstaller's
|
|
||||||
"PyInstaller/hooks" directory.
|
|
||||||
|
|
||||||
Bazaar
|
Bazaar
|
||||||
You need the command line "bzr" client installed.
|
You need the command line "bzr" client installed.
|
||||||
|
|
||||||
@ -79,7 +75,7 @@ OpenLP
|
|||||||
|
|
||||||
Visual C++ 2008 Express Edition
|
Visual C++ 2008 Express Edition
|
||||||
This is to build pptviewlib.dll, the library for controlling the
|
This is to build pptviewlib.dll, the library for controlling the
|
||||||
PowerPointViewer
|
PowerPointViewer.
|
||||||
|
|
||||||
windows-builder.py
|
windows-builder.py
|
||||||
This script, of course. It should be in the "scripts" directory of OpenLP.
|
This script, of course. It should be in the "scripts" directory of OpenLP.
|
||||||
@ -88,15 +84,25 @@ psvince.dll
|
|||||||
This dll is used during the actual install of OpenLP to check if OpenLP is
|
This dll is used during the actual install of OpenLP to check if OpenLP is
|
||||||
running on the users machine prior to the setup. If OpenLP is running,
|
running on the users machine prior to the setup. If OpenLP is running,
|
||||||
the install will fail. The dll can be obtained from here:
|
the install will fail. The dll can be obtained from here:
|
||||||
|
|
||||||
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
|
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
|
||||||
|
|
||||||
|
The dll is presently included in .\\resources\\windows
|
||||||
|
|
||||||
Mako
|
Mako
|
||||||
Mako Templates for Python. This package is required for building the
|
Mako Templates for Python. This package is required for building the
|
||||||
remote plugin. It can be installed by going to your
|
remote plugin. It can be installed by going to your
|
||||||
python_directory\scripts\.. and running "easy_install Mako". If you do not
|
python_directory\scripts\.. and running "easy_install Mako". If you do not
|
||||||
have easy_install, the Mako package can be obtained here:
|
have easy_install, the Mako package can be obtained here:
|
||||||
|
|
||||||
http://www.makotemplates.org/download.html
|
http://www.makotemplates.org/download.html
|
||||||
|
|
||||||
|
Sqlalchemy Migrate
|
||||||
|
Required for the data-bases used in OpenLP. The package can be
|
||||||
|
obtained here:
|
||||||
|
|
||||||
|
http://code.google.com/p/sqlalchemy-migrate/
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -149,6 +155,7 @@ build_path = os.path.join(branch_path, u'build')
|
|||||||
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
||||||
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
|
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
|
||||||
u'lib', u'pptviewlib')
|
u'lib', u'pptviewlib')
|
||||||
|
hooks_path = os.path.join(branch_path , u'resources', u'pyinstaller')
|
||||||
|
|
||||||
def update_code():
|
def update_code():
|
||||||
os.chdir(branch_path)
|
os.chdir(branch_path)
|
||||||
@ -174,6 +181,7 @@ def run_pyinstaller():
|
|||||||
u'--noconfirm',
|
u'--noconfirm',
|
||||||
u'--windowed',
|
u'--windowed',
|
||||||
u'--noupx',
|
u'--noupx',
|
||||||
|
u'--additional-hooks-dir', hooks_path,
|
||||||
u'-o', branch_path,
|
u'-o', branch_path,
|
||||||
u'-i', win32_icon,
|
u'-i', win32_icon,
|
||||||
u'-p', branch_path,
|
u'-p', branch_path,
|
||||||
|
Loading…
Reference in New Issue
Block a user