Trunk & fixes

This commit is contained in:
Dmitriy Marmyshev 2013-10-27 02:53:32 +04:00
commit 70144c0da4
193 changed files with 4263 additions and 2531 deletions

View File

@ -43,14 +43,15 @@ from traceback import format_exception
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Settings, ScreenList, UiStrings, Registry, check_directory_exists from openlp.core.common import AppLocation, Settings, UiStrings, check_directory_exists
from openlp.core.lib import ScreenList, Registry
from openlp.core.resources import qInitResources from openlp.core.resources import qInitResources
from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.mainwindow import MainWindow
from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimeform import FirstTimeForm
from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui.exceptionform import ExceptionForm
from openlp.core.ui import SplashScreen from openlp.core.ui import SplashScreen
from openlp.core.utils import AppLocation, LanguageManager, VersionThread, get_application_version from openlp.core.utils import LanguageManager, VersionThread, get_application_version
__all__ = ['OpenLP', 'main'] __all__ = ['OpenLP', 'main']

View File

@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
The :mod:`common` module contains most of the components and libraries that make
OpenLP work.
"""
import os
import logging
import sys
from PyQt4 import QtCore
log = logging.getLogger(__name__)
def check_directory_exists(directory, do_not_log=False):
"""
Check a theme directory exists and if not create it
``directory``
The directory to make sure exists
``do_not_log``
To not log anything. This is need for the start up, when the log isn't ready.
"""
if not do_not_log:
log.debug('check_directory_exists %s' % directory)
try:
if not os.path.exists(directory):
os.makedirs(directory)
except IOError:
pass
def get_frozen_path(frozen_option, non_frozen_option):
"""
Return a path based on the system status.
"""
if hasattr(sys, 'frozen') and sys.frozen == 1:
return frozen_option
return non_frozen_option
class ThemeLevel(object):
"""
Provides an enumeration for the level a theme applies to
"""
Global = 1
Service = 2
Song = 3
def translate(context, text, comment=None, encoding=QtCore.QCoreApplication.CodecForTr, n=-1,
qt_translate=QtCore.QCoreApplication.translate):
"""
A special shortcut method to wrap around the Qt4 translation functions. This abstracts the translation procedure so
that we can change it if at a later date if necessary, without having to redo the whole of OpenLP.
``context``
The translation context, used to give each string a context or a namespace.
``text``
The text to put into the translation tables for translation.
``comment``
An identifying string for when the same text is used in different roles within the same context.
"""
return qt_translate(context, text, comment, encoding, n)
class SlideLimits(object):
"""
Provides an enumeration for behaviour of OpenLP at the end limits of each service item when pressing the up/down
arrow keys
"""
End = 1
Wrap = 2
Next = 3
from .uistrings import UiStrings
from .settings import Settings
from .applocation import AppLocation

View File

@ -27,14 +27,13 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
""" """
The :mod:`openlp.core.utils.applocation` module provides an utility for OpenLP receiving the data path etc. The :mod:`openlp.core.common.applocation` module provides an utility for OpenLP receiving the data path etc.
""" """
import logging import logging
import os import os
import sys import sys
from openlp.core.lib import Settings from openlp.core.common import Settings
from openlp.core.utils import _get_frozen_path
if sys.platform != 'win32' and sys.platform != 'darwin': if sys.platform != 'win32' and sys.platform != 'darwin':
@ -45,7 +44,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
XDG_BASE_AVAILABLE = False XDG_BASE_AVAILABLE = False
import openlp import openlp
from openlp.core.lib import check_directory_exists from openlp.core.common import check_directory_exists, get_frozen_path
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -74,15 +73,15 @@ class AppLocation(object):
The directory type you want, for instance the data directory. Default *AppLocation.AppDir* The directory type you want, for instance the data directory. Default *AppLocation.AppDir*
""" """
if dir_type == AppLocation.AppDir: if dir_type == AppLocation.AppDir:
return _get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0]) return get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0])
elif dir_type == AppLocation.PluginsDir: elif dir_type == AppLocation.PluginsDir:
app_path = os.path.abspath(os.path.split(sys.argv[0])[0]) app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
return _get_frozen_path(os.path.join(app_path, 'plugins'), return get_frozen_path(os.path.join(app_path, 'plugins'),
os.path.join(os.path.split(openlp.__file__)[0], 'plugins')) os.path.join(os.path.split(openlp.__file__)[0], 'plugins'))
elif dir_type == AppLocation.VersionDir: elif dir_type == AppLocation.VersionDir:
return _get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0]) return get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0])
elif dir_type == AppLocation.LanguageDir: elif dir_type == AppLocation.LanguageDir:
app_path = _get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), _get_os_dir_path(dir_type)) app_path = get_frozen_path(os.path.abspath(os.path.split(sys.argv[0])[0]), _get_os_dir_path(dir_type))
return os.path.join(app_path, 'i18n') return os.path.join(app_path, 'i18n')
elif dir_type == AppLocation.DataDir and AppLocation.BaseDir: elif dir_type == AppLocation.DataDir and AppLocation.BaseDir:
return os.path.join(AppLocation.BaseDir, 'data') return os.path.join(AppLocation.BaseDir, 'data')
@ -171,4 +170,3 @@ def _get_os_dir_path(dir_type):
if dir_type == AppLocation.DataDir: if dir_type == AppLocation.DataDir:
return os.path.join(str(os.getenv('HOME')), '.openlp', 'data') return os.path.join(str(os.getenv('HOME')), '.openlp', 'data')
return os.path.join(str(os.getenv('HOME')), '.openlp') return os.path.join(str(os.getenv('HOME')), '.openlp')

View File

@ -36,8 +36,7 @@ import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SlideLimits, UiStrings from openlp.core.common import ThemeLevel, SlideLimits, UiStrings
from openlp.core.lib.theme import ThemeLevel
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,7 +31,7 @@ The :mod:`uistrings` module provides standard strings for OpenLP.
""" """
import logging import logging
from openlp.core.lib import translate from openlp.core.common import translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -37,6 +37,8 @@ import os
from PyQt4 import QtCore, QtGui, Qt from PyQt4 import QtCore, QtGui, Qt
from openlp.core.common import translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -72,16 +74,6 @@ class MediaType(object):
Video = 2 Video = 2
class SlideLimits(object):
"""
Provides an enumeration for behaviour of OpenLP at the end limits of each service item when pressing the up/down
arrow keys
"""
End = 1
Wrap = 2
Next = 3
class ServiceItemAction(object): class ServiceItemAction(object):
""" """
Provides an enumeration for the required action moving between service items by left/right arrow keys Provides an enumeration for the required action moving between service items by left/right arrow keys
@ -91,24 +83,6 @@ class ServiceItemAction(object):
Next = 3 Next = 3
def translate(context, text, comment=None, encoding=QtCore.QCoreApplication.CodecForTr, n=-1,
qt_translate=QtCore.QCoreApplication.translate):
"""
A special shortcut method to wrap around the Qt4 translation functions. This abstracts the translation procedure so
that we can change it if at a later date if necessary, without having to redo the whole of OpenLP.
``context``
The translation context, used to give each string a context or a namespace.
``text``
The text to put into the translation tables for translation.
``comment``
An identifying string for when the same text is used in different roles within the same context.
"""
return qt_translate(context, text, comment, encoding, n)
def get_text_file_string(text_file): def get_text_file_string(text_file):
""" """
Open a file and return its content as unicode string. If the supplied file name is not a file then the function Open a file and return its content as unicode string. If the supplied file name is not a file then the function
@ -327,57 +301,36 @@ def expand_tags(text):
return text return text
def check_directory_exists(directory, do_not_log=False): def create_separated_list(string_list):
"""
Check a theme directory exists and if not create it
``directory``
The directory to make sure exists
``do_not_log``
To not log anything. This is need for the start up, when the log isn't ready.
"""
if not do_not_log:
log.debug('check_directory_exists %s' % directory)
try:
if not os.path.exists(directory):
os.makedirs(directory)
except IOError:
pass
def create_separated_list(stringlist):
""" """
Returns a string that represents a join of a list of strings with a localized separator. This function corresponds Returns a string that represents a join of a list of strings with a localized separator. This function corresponds
to QLocale::createSeparatedList which was introduced in Qt 4.8 and implements the algorithm from to QLocale::createSeparatedList which was introduced in Qt 4.8 and implements the algorithm from
http://www.unicode.org/reports/tr35/#ListPatterns http://www.unicode.org/reports/tr35/#ListPatterns
``stringlist`` ``string_list``
List of unicode strings List of unicode strings
""" """
if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and \ if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and \
LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'): LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'):
return QtCore.QLocale().createSeparatedList(stringlist) return QtCore.QLocale().createSeparatedList(string_list)
if not stringlist: if not string_list:
return '' return ''
elif len(stringlist) == 1: elif len(string_list) == 1:
return stringlist[0] return string_list[0]
elif len(stringlist) == 2: elif len(string_list) == 2:
return translate('OpenLP.core.lib', '%s and %s', return translate('OpenLP.core.lib', '%s and %s',
'Locale list separator: 2 items') % (stringlist[0], stringlist[1]) 'Locale list separator: 2 items') % (string_list[0], string_list[1])
else: else:
merged = translate('OpenLP.core.lib', '%s, and %s', merged = translate('OpenLP.core.lib', '%s, and %s',
'Locale list separator: end') % (stringlist[-2], stringlist[-1]) 'Locale list separator: end') % (string_list[-2], string_list[-1])
for index in reversed(list(range(1, len(stringlist) - 2))): for index in reversed(list(range(1, len(string_list) - 2))):
merged = translate('OpenLP.core.lib', '%s, %s', merged = translate('OpenLP.core.lib', '%s, %s',
'Locale list separator: middle') % (stringlist[index], merged) 'Locale list separator: middle') % (string_list[index], merged)
return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (stringlist[0], merged) return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (string_list[0], merged)
from .registry import Registry from .registry import Registry
from .uistrings import UiStrings
from .screen import ScreenList from .screen import ScreenList
from .settings import Settings
from .listwidgetwithdnd import ListWidgetWithDnD from .listwidgetwithdnd import ListWidgetWithDnD
from .treewidgetwithdnd import TreeWidgetWithDnD from .treewidgetwithdnd import TreeWidgetWithDnD
from .formattingtags import FormattingTags from .formattingtags import FormattingTags

View File

@ -41,9 +41,9 @@ from sqlalchemy.pool import NullPool
from alembic.migration import MigrationContext from alembic.migration import MigrationContext
from alembic.operations import Operations from alembic.operations import Operations
from openlp.core.lib import translate, Settings from openlp.core.common import AppLocation, Settings, translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import delete_file
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,12 +31,13 @@ Provide HTML Tag management and Formatting Tag access class
""" """
import json import json
from openlp.core.lib import Settings, translate from openlp.core.common import Settings
from openlp.core.lib import translate
class FormattingTags(object): class FormattingTags(object):
""" """
Static Class to HTML Tags to be access around the code the list is managed by the Options Tab. Static Class for HTML Tags to be access around the code the list is managed by the Options Tab.
""" """
html_expands = [] html_expands = []
@ -48,22 +49,15 @@ class FormattingTags(object):
return FormattingTags.html_expands return FormattingTags.html_expands
@staticmethod @staticmethod
def save_html_tags(): def save_html_tags(new_tags):
""" """
Saves all formatting tags except protected ones. Saves all formatting tags except protected ones
`new_tags`
The tags to be saved..
""" """
tags = []
for tag in FormattingTags.html_expands:
if not tag['protected'] and not tag.get('temporary'):
# Using dict ensures that copy is made and encoding of values a little later does not affect tags in
# the original list
tags.append(dict(tag))
tag = tags[-1]
# Remove key 'temporary' from tags. It is not needed to be saved.
if 'temporary' in tag:
del tag['temporary']
# Formatting Tags were also known as display tags. # Formatting Tags were also known as display tags.
Settings().setValue('formattingTags/html_tags', json.dumps(tags) if tags else '') Settings().setValue('formattingTags/html_tags', json.dumps(new_tags) if new_tags else '')
@staticmethod @staticmethod
def load_tags(): def load_tags():

View File

@ -26,7 +26,372 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
"""
This module is responsible for generating the HTML for :class:`~openlp.core.ui.maindisplay`. The ``build_html`` function
is the function which has to be called from outside. The generated and returned HTML will look similar to this::
<!DOCTYPE html>
<html>
<head>
<title>OpenLP Display</title>
<style>
*{
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
-webkit-user-select: none;
}
body {
background-color: #000000;
}
.size {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
#black {
z-index: 8;
background-color: black;
display: none;
}
#bgimage {
z-index: 1;
}
#image {
z-index: 2;
}
#videobackboard {
z-index:3;
background-color: #000000;
}
#video {
background-color: #000000;
z-index:4;
}
#flash {
z-index:5;
}
#alert {
position: absolute;
left: 0px;
top: 0px;
z-index: 10;
width: 100%;
vertical-align: bottom;
font-family: DejaVu Sans;
font-size: 40pt;
color: #ffffff;
background-color: #660000;
word-wrap: break-word;
}
#footer {
position: absolute;
z-index: 6;
left: 10px;
bottom: 0px;
width: 1580px;
font-family: Nimbus Sans L;
font-size: 12pt;
color: #FFFFFF;
text-align: left;
white-space: nowrap;
}
/* lyric css */
.lyricstable {
z-index: 5;
position: absolute;
display: table;
left: 10px; top: 0px;
}
.lyricscell {
display: table-cell;
word-wrap: break-word;
-webkit-transition: opacity 0.4s ease;
white-space:pre-wrap; word-wrap: break-word; text-align: left; vertical-align: top; font-family: Nimbus Sans L; font-size: 40pt; color: #FFFFFF; line-height: 100%; margin: 0;padding: 0; padding-bottom: 0; padding-left: 4px; width: 1580px; height: 810px;
}
.lyricsmain {
-webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF; text-shadow: #000000 5px 5px;
}
sup {
font-size: 0.6em;
vertical-align: top;
position: relative;
top: -0.3em;
}
</style>
<script>
var timer = null;
var transition = false;
function show_video(state, path, volume, loop, variable_value){
// Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent!
var video = document.getElementById('video');
if(volume != null){
video.volume = volume;
}
switch(state){
case 'load':
video.src = 'file:///' + path;
if(loop == true) {
video.loop = true;
}
video.load();
break;
case 'play':
video.play();
break;
case 'pause':
video.pause();
break;
case 'stop':
show_video('pause');
video.currentTime = 0;
break;
case 'close':
show_video('stop');
video.src = '';
break;
case 'length':
return video.duration;
case 'current_time':
return video.currentTime;
case 'seek':
video.currentTime = variable_value;
break;
case 'isEnded':
return video.ended;
case 'setVisible':
video.style.visibility = variable_value;
break;
case 'setBackBoard':
var back = document.getElementById('videobackboard');
back.style.visibility = variable_value;
break;
}
}
function getFlashMovieObject(movieName)
{
if (window.document[movieName]){
return window.document[movieName];
}
if (document.embeds && document.embeds[movieName]){
return document.embeds[movieName];
}
}
function show_flash(state, path, volume, variable_value){
var text = document.getElementById('flash');
var flashMovie = getFlashMovieObject("OpenLPFlashMovie");
var src = "src = 'file:///" + path + "'";
var view_parm = " wmode='opaque'" + " width='100%%'" + " height='100%%'";
var swf_parm = " name='OpenLPFlashMovie'" + " autostart='true' loop='false' play='true'" +
" hidden='false' swliveconnect='true' allowscriptaccess='always'" + " volume='" + volume + "'";
switch(state){
case 'load':
text.innerHTML = "<embed " + src + view_parm + swf_parm + "/>";
flashMovie = getFlashMovieObject("OpenLPFlashMovie");
flashMovie.Play();
break;
case 'play':
flashMovie.Play();
break;
case 'pause':
flashMovie.StopPlay();
break;
case 'stop':
flashMovie.StopPlay();
tempHtml = text.innerHTML;
text.innerHTML = '';
text.innerHTML = tempHtml;
break;
case 'close':
flashMovie.StopPlay();
text.innerHTML = '';
break;
case 'length':
return flashMovie.TotalFrames();
case 'current_time':
return flashMovie.CurrentFrame();
case 'seek':
// flashMovie.GotoFrame(variable_value);
break;
case 'isEnded':
//TODO check flash end
return false;
case 'setVisible':
text.style.visibility = variable_value;
break;
}
}
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;
}
}
function show_image(src){
var img = document.getElementById('image');
img.src = src;
if(src == '')
img.style.display = 'none';
else
img.style.display = 'block';
}
function show_blank(state){
var black = 'none';
var lyrics = '';
switch(state){
case 'theme':
lyrics = 'hidden';
break;
case 'black':
black = 'block';
break;
case 'desktop':
break;
}
document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics;
document.getElementById('image').style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics;
}
function show_footer(footertext){
document.getElementById('footer').innerHTML = footertext;
}
function show_text(new_text){
var match = /-webkit-text-fill-color:[^;"]+/gi;
if(timer != null)
clearTimeout(timer);
/*
QtWebkit bug with outlines and justify causing outline alignment
problems. (Bug 859950) Surround each word with a <span> to workaround,
but only in this scenario.
*/
var txt = document.getElementById('lyricsmain');
if(window.getComputedStyle(txt).textAlign == 'justify'){
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
function(match) {
return '</span>' + match + '<span>';
});
new_text = '<span>' + new_text + '</span>';
}
}
text_fade('lyricsmain', new_text);
}
function text_fade(id, new_text){
/*
Show the text.
*/
var text = document.getElementById(id);
if(text == null) return;
if(!transition){
text.innerHTML = new_text;
return;
}
// Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
text.style.opacity = '0.1';
// Fade new text in after the old text has finished fading out.
timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
}
function _show_text(text, new_text) {
/*
Helper function to show the new_text delayed.
*/
text.innerHTML = new_text;
text.style.opacity = '1';
// Wait until the text is completely visible. We want to save the timer id, to be able to call
// clearTimeout(timer) when the text has changed before finishing fading.
timer = window.setTimeout(function(){timer = null;}, 400);
}
function show_text_completed(){
return (timer == null);
}
</script>
</head>
<body>
<img id="bgimage" class="size" style="display:none;" />
<img id="image" class="size" style="display:none;" />
<div id="videobackboard" class="size" style="visibility:hidden"></div>
<video id="video" class="size" style="visibility:hidden" autobuffer preload></video>
<div id="flash" class="size" style="visibility:hidden"></div>
<div id="alert" style="visibility:hidden"></div>
<div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
<div id="footer" class="footer"></div>
<div id="black" class="size"></div>
</body>
</html>
"""
import logging import logging
from PyQt4 import QtWebKit from PyQt4 import QtWebKit
@ -114,12 +479,6 @@ sup {
document.getElementById('black').style.display = black; document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics; document.getElementById('lyricsmain').style.visibility = lyrics;
document.getElementById('image').style.visibility = lyrics; document.getElementById('image').style.visibility = lyrics;
outline = document.getElementById('lyricsoutline')
if(outline != null)
outline.style.visibility = lyrics;
shadow = document.getElementById('lyricsshadow')
if(shadow != null)
shadow.style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics; document.getElementById('footer').style.visibility = lyrics;
} }
@ -138,9 +497,6 @@ sup {
*/ */
var txt = document.getElementById('lyricsmain'); var txt = document.getElementById('lyricsmain');
if(window.getComputedStyle(txt).textAlign == 'justify'){ if(window.getComputedStyle(txt).textAlign == 'justify'){
var outline = document.getElementById('lyricsoutline');
if(outline != null)
txt = outline;
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){ if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g, new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
function(match) { function(match) {
@ -150,8 +506,6 @@ sup {
} }
} }
text_fade('lyricsmain', new_text); text_fade('lyricsmain', new_text);
text_fade('lyricsoutline', new_text);
text_fade('lyricsshadow', new_text.replace(match, ''));
} }
function text_fade(id, new_text){ function text_fade(id, new_text){
@ -190,7 +544,7 @@ sup {
<img id="bgimage" class="size" %s /> <img id="bgimage" class="size" %s />
<img id="image" class="size" %s /> <img id="image" class="size" %s />
%s %s
%s <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
<div id="footer" class="footer"></div> <div id="footer" class="footer"></div>
<div id="black" class="size"></div> <div id="black" class="size"></div>
</body> </body>
@ -222,8 +576,7 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
""" """
width = screen['size'].width() width = screen['size'].width()
height = screen['size'].height() height = screen['size'].height()
theme = item.themedata theme_data = item.themedata
webkit_ver = webkit_version()
# Image generated and poked in # Image generated and poked in
if background: if background:
bgimage_src = 'src="data:image/png;base64,%s"' % background bgimage_src = 'src="data:image/png;base64,%s"' % background
@ -247,12 +600,12 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
build_background_css(item, width), build_background_css(item, width),
css_additions, css_additions,
build_footer_css(item, height), build_footer_css(item, height),
build_lyrics_css(item, webkit_ver), build_lyrics_css(item),
'true' if theme and theme.display_slide_transition and is_live else 'false', 'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
js_additions, js_additions,
bgimage_src, image_src, bgimage_src,
html_additions, image_src,
build_lyrics_html(item, webkit_ver) html_additions
) )
return html return html
@ -303,16 +656,13 @@ def build_background_css(item, width):
return background return background
def build_lyrics_css(item, webkit_ver): def build_lyrics_css(item):
""" """
Build the lyrics display css Build the lyrics display css
``item`` ``item``
Service Item containing theme and location information Service Item containing theme and location information
``webkitvers``
The version of qtwebkit we're using
""" """
style = """ style = """
.lyricstable { .lyricstable {
@ -328,81 +678,44 @@ def build_lyrics_css(item, webkit_ver):
%s %s
} }
.lyricsmain { .lyricsmain {
%s %s
} }
.lyricsoutline { """
%s theme_data = item.themedata
}
.lyricsshadow {
%s
}
"""
theme = item.themedata
lyricstable = '' lyricstable = ''
lyrics = '' lyrics = ''
lyricsmain = '' lyricsmain = ''
outline = '' if theme_data and item.main:
shadow = ''
if theme and item.main:
lyricstable = 'left: %spx; top: %spx;' % (item.main.x(), item.main.y()) lyricstable = 'left: %spx; top: %spx;' % (item.main.x(), item.main.y())
lyrics = build_lyrics_format_css(theme, item.main.width(), item.main.height()) lyrics = build_lyrics_format_css(theme_data, item.main.width(), item.main.height())
# For performance reasons we want to show as few DIV's as possible, especially when animating/transitions. lyricsmain += build_lyrics_outline_css(theme_data)
# However some bugs in older versions of qtwebkit mean we need to perform workarounds and add extra divs. Only if theme_data.font_main_shadow:
# do these when needed. lyricsmain += ' text-shadow: %s %spx %spx;' % \
# (theme_data.font_main_shadow_color, theme_data.font_main_shadow_size, theme_data.font_main_shadow_size)
# Before 533.3 the webkit-text-fill colour wasn't displayed, only the stroke (outline) color. So put stroke lyrics_css = style % (lyricstable, lyrics, lyricsmain)
# layer underneath the main text.
#
# Up to 534.3 the webkit-text-stroke was sometimes out of alignment with the fill, or normal text.
# letter-spacing=1 is workaround https://bugs.webkit.org/show_bug.cgi?id=44403
#
# Up to 534.3 the text-shadow didn't get displayed when webkit-text-stroke was used. So use an offset text
# layer underneath. https://bugs.webkit.org/show_bug.cgi?id=19728
if webkit_ver >= 533.3:
lyricsmain += build_lyrics_outline_css(theme)
else:
outline = build_lyrics_outline_css(theme)
if theme.font_main_shadow:
if theme.font_main_outline and webkit_ver <= 534.3:
shadow = 'padding-left: %spx; padding-top: %spx;' % \
(int(theme.font_main_shadow_size) + (int(theme.font_main_outline_size) * 2),
theme.font_main_shadow_size)
shadow += build_lyrics_outline_css(theme, True)
else:
lyricsmain += ' text-shadow: %s %spx %spx;' % \
(theme.font_main_shadow_color, theme.font_main_shadow_size, theme.font_main_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
return lyrics_css return lyrics_css
def build_lyrics_outline_css(theme, is_shadow=False): def build_lyrics_outline_css(theme_data):
""" """
Build the css which controls the theme outline. Also used by renderer for splitting verses Build the css which controls the theme outline. Also used by renderer for splitting verses
``theme`` ``theme_data``
Object containing theme information Object containing theme information
``is_shadow``
If true, use the shadow colors instead
""" """
if theme.font_main_outline: if theme_data.font_main_outline:
size = float(theme.font_main_outline_size) / 16 size = float(theme_data.font_main_outline_size) / 16
if is_shadow: fill_color = theme_data.font_main_color
fill_color = theme.font_main_shadow_color outline_color = theme_data.font_main_outline_color
outline_color = theme.font_main_shadow_color
else:
fill_color = theme.font_main_color
outline_color = theme.font_main_outline_color
return ' -webkit-text-stroke: %sem %s; -webkit-text-fill-color: %s; ' % (size, outline_color, fill_color) return ' -webkit-text-stroke: %sem %s; -webkit-text-fill-color: %s; ' % (size, outline_color, fill_color)
else: return ''
return ''
def build_lyrics_format_css(theme, width, height): def build_lyrics_format_css(theme_data, width, height):
""" """
Build the css which controls the theme format. Also used by renderer for splitting verses Build the css which controls the theme format. Also used by renderer for splitting verses
``theme`` ``theme_data``
Object containing theme information Object containing theme information
``width`` ``width``
@ -411,17 +724,17 @@ def build_lyrics_format_css(theme, width, height):
``height`` ``height``
Height of the lyrics block Height of the lyrics block
""" """
align = HorizontalType.Names[theme.display_horizontal_align] align = HorizontalType.Names[theme_data.display_horizontal_align]
valign = VerticalType.Names[theme.display_vertical_align] valign = VerticalType.Names[theme_data.display_vertical_align]
if theme.font_main_outline: if theme_data.font_main_outline:
left_margin = int(theme.font_main_outline_size) * 2 left_margin = int(theme_data.font_main_outline_size) * 2
else: else:
left_margin = 0 left_margin = 0
justify = 'white-space:pre-wrap;' justify = 'white-space:pre-wrap;'
# fix tag incompatibilities # fix tag incompatibilities
if theme.display_horizontal_align == HorizontalType.Justify: if theme_data.display_horizontal_align == HorizontalType.Justify:
justify = '' justify = ''
if theme.display_vertical_align == VerticalType.Bottom: if theme_data.display_vertical_align == VerticalType.Bottom:
padding_bottom = '0.5em' padding_bottom = '0.5em'
else: else:
padding_bottom = '0' padding_bottom = '0'
@ -429,41 +742,13 @@ def build_lyrics_format_css(theme, width, height):
'text-align: %s; vertical-align: %s; font-family: %s; ' \ 'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \ 'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx; height: %spx; ' % \ 'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx; height: %spx; ' % \
(justify, align, valign, theme.font_main_name, theme.font_main_size, (justify, align, valign, theme_data.font_main_name, theme_data.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment), padding_bottom, left_margin, width, height) theme_data.font_main_color, 100 + int(theme_data.font_main_line_adjustment), padding_bottom,
if theme.font_main_outline: left_margin, width, height)
if webkit_version() <= 534.3: if theme_data.font_main_italics:
lyrics += ' letter-spacing: 1px;' lyrics += 'font-style:italic; '
if theme.font_main_italics: if theme_data.font_main_bold:
lyrics += ' font-style:italic; ' lyrics += 'font-weight:bold; '
if theme.font_main_bold:
lyrics += ' font-weight:bold; '
return lyrics
def build_lyrics_html(item, webkitvers):
"""
Build the HTML required to show the lyrics
``item``
Service Item containing theme and location information
``webkitvers``
The version of qtwebkit we're using
"""
# Bugs in some versions of QtWebKit mean we sometimes need additional divs for outline and shadow, since the CSS
# doesn't work. To support vertical alignment middle and bottom, nested div's using display:table/display:table-cell
# are required for each lyric block.
lyrics = ''
theme = item.themedata
if webkitvers <= 534.3 and theme and theme.font_main_outline:
lyrics += '<div class="lyricstable"><div id="lyricsshadow" style="opacity:1" ' \
'class="lyricscell lyricsshadow"></div></div>'
if webkitvers < 533.3:
lyrics += '<div class="lyricstable"><div id="lyricsoutline" style="opacity:1" ' \
'class="lyricscell lyricsoutline"></div></div>'
lyrics += '<div class="lyricstable"><div id="lyricsmain" style="opacity:1" ' \
'class="lyricscell lyricsmain"></div></div>'
return lyrics return lyrics

View File

@ -0,0 +1,59 @@
{
"background" : {
"border_color": "#000000",
"color": "#000000",
"direction": "vertical",
"end_color": "#000000",
"filename": "",
"start_color": "#000000",
"type": "solid"
},
"display" :{
"horizontal_align": 0,
"slide_transition": false,
"vertical_align": 0
},
"font": {
"footer": {
"bold": false,
"color": "#FFFFFF",
"height": 78,
"italics": false,
"line_adjustment": 0,
"location": "",
"name": "Arial",
"outline": false,
"outline_color": "#000000",
"outline_size": 2,
"override": false,
"shadow": true,
"shadow_color": "#000000",
"shadow_size": 5,
"size": 12,
"width": 1004,
"x": 10,
"y": 690
},
"main": {
"bold": false,
"color": "#FFFFFF",
"height": 690,
"italics": false,
"line_adjustment": 0,
"location": "",
"name": "Arial",
"outline": false,
"outline_color": "#000000",
"outline_size": 2,
"override": false,
"shadow": true,
"shadow_color": "#000000",
"shadow_size": 5,
"size": 40,
"width": 1004,
"x": 10,
"y": 10
}
},
"theme_name": ""
}

View File

@ -35,8 +35,9 @@ import re
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, ListWidgetWithDnD, \ from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, ListWidgetWithDnD, \
ServiceItemContext, Settings, Registry, UiStrings, translate ServiceItemContext, Registry
from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import create_widget_action, critical_error_message_box from openlp.core.lib.ui import create_widget_action, critical_error_message_box
@ -82,10 +83,17 @@ class MediaManagerItem(QtGui.QWidget):
""" """
Constructor to create the media manager item. Constructor to create the media manager item.
""" """
super(MediaManagerItem, self).__init__() super(MediaManagerItem, self).__init__(parent)
self.plugin = plugin
self._setup()
self.setup_item()
def _setup(self):
"""
Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
"""
self.hide() self.hide()
self.whitespace = re.compile(r'[\W_]+', re.UNICODE) self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin
visible_title = self.plugin.get_string(StringContent.VisibleName) visible_title = self.plugin.get_string(StringContent.VisibleName)
self.title = str(visible_title['title']) self.title = str(visible_title['title'])
Registry().register(self.plugin.name, self) Registry().register(self.plugin.name, self)
@ -106,6 +114,12 @@ class MediaManagerItem(QtGui.QWidget):
QtCore.QObject.connect(self, QtCore.SIGNAL('%s_go_live' % self.plugin.name), self.go_live_remote) QtCore.QObject.connect(self, QtCore.SIGNAL('%s_go_live' % self.plugin.name), self.go_live_remote)
QtCore.QObject.connect(self, QtCore.SIGNAL('%s_add_to_service' % self.plugin.name), self.add_to_service_remote) QtCore.QObject.connect(self, QtCore.SIGNAL('%s_add_to_service' % self.plugin.name), self.add_to_service_remote)
def setup_item(self):
"""
Override this for additional Plugin setup
"""
pass
def required_icons(self): def required_icons(self):
""" """
This method is called to define the icons for the plugin. It provides a default set and the plugin is able to This method is called to define the icons for the plugin. It provides a default set and the plugin is able to

View File

@ -34,7 +34,8 @@ import os
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Settings, Registry, UiStrings from openlp.core.common import Settings, UiStrings
from openlp.core.lib import Registry
from openlp.core.utils import get_application_version from openlp.core.utils import get_application_version
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -35,7 +35,7 @@ import logging
import imp import imp
from openlp.core.lib import Plugin, PluginStatus, Registry from openlp.core.lib import Plugin, PluginStatus, Registry
from openlp.core.utils import AppLocation from openlp.core.common import AppLocation
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,9 +31,10 @@ import logging
from PyQt4 import QtGui, QtCore, QtWebKit from PyQt4 import QtGui, QtCore, QtWebKit
from openlp.core.lib import Settings, FormattingTags, ImageSource, ItemCapabilities, Registry, ScreenList, \ from openlp.core.common import Settings
from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Registry, ScreenList, \
ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css
from openlp.core.lib.theme import ThemeLevel from openlp.core.common import ThemeLevel
from openlp.core.ui import MainDisplay from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -36,7 +36,8 @@ import copy
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Registry, translate from openlp.core.common import Settings, translate
from openlp.core.lib import Registry
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -244,7 +245,6 @@ class ScreenList(object):
""" """
Loads the screen size and the monitor number from the settings. Loads the screen size and the monitor number from the settings.
""" """
from openlp.core.lib import Settings
# Add the screen settings to the settings dict. This has to be done here due to cyclic dependency. # Add the screen settings to the settings dict. This has to be done here due to cyclic dependency.
# Do not do this anywhere else. # Do not do this anywhere else.
screen_settings = { screen_settings = {

View File

@ -39,7 +39,8 @@ import uuid
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import ImageSource, Settings, Registry, build_icon, clean_tags, expand_tags, translate from openlp.core.common import Settings, translate
from openlp.core.lib import ImageSource, Registry, build_icon, clean_tags, expand_tags
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -32,69 +32,16 @@ Provide the theme XML and handling functions for OpenLP v2 themes.
import os import os
import re import re
import logging import logging
import json
from xml.dom.minidom import Document from xml.dom.minidom import Document
from lxml import etree, objectify from lxml import etree, objectify
from openlp.core.common import AppLocation
from openlp.core.lib import str_to_bool, ScreenList from openlp.core.lib import str_to_bool, ScreenList, get_text_file_string
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
BLANK_THEME_XML = \
'''<?xml version="1.0" encoding="utf-8"?>
<theme version="1.0">
<name> </name>
<background type="image">
<filename></filename>
<borderColor>#000000</borderColor>
</background>
<background type="gradient">
<startColor>#000000</startColor>
<endColor>#000000</endColor>
<direction>vertical</direction>
</background>
<background type="solid">
<color>#000000</color>
</background>
<font type="main">
<name>Arial</name>
<color>#FFFFFF</color>
<size>40</size>
<bold>False</bold>
<italics>False</italics>
<line_adjustment>0</line_adjustment>
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
<outline outlineColor="#000000" outlineSize="2">False</outline>
<location override="False" x="10" y="10" width="1004" height="690"/>
</font>
<font type="footer">
<name>Arial</name>
<color>#FFFFFF</color>
<size>12</size>
<bold>False</bold>
<italics>False</italics>
<line_adjustment>0</line_adjustment>
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
<outline outlineColor="#000000" outlineSize="2">False</outline>
<location override="False" x="10" y="690" width="1004" height="78"/>
</font>
<display>
<horizontalAlign>0</horizontalAlign>
<verticalAlign>0</verticalAlign>
<slideTransition>False</slideTransition>
</display>
</theme>
'''
class ThemeLevel(object):
"""
Provides an enumeration for the level a theme applies to
"""
Global = 1
Service = 2
Song = 3
class BackgroundType(object): class BackgroundType(object):
""" """
@ -217,9 +164,32 @@ class ThemeXML(object):
""" """
Initialise the theme object. Initialise the theme object.
""" """
# Create the minidom document # basic theme object with defaults
self.theme_xml = Document() json_dir = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'core', 'lib', 'json')
self.parse_xml(BLANK_THEME_XML) json_file = os.path.join(json_dir, 'theme.json')
jsn = get_text_file_string(json_file)
jsn = json.loads(jsn)
self.expand_json(jsn)
def expand_json(self, var, prev=None):
"""
Expand the json objects and make into variables.
``var``
The array list to be processed.
``prev``
The preceding string to add to the key to make the variable.
"""
for key, value in var.items():
if prev:
key = prev + "_" + key
else:
key = key
if isinstance(value, dict):
self.expand_json(value, key)
else:
setattr(self, key, value)
def extend_image_filename(self, path): def extend_image_filename(self, path):
""" """

View File

@ -33,7 +33,8 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, UiStrings, build_icon, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import Registry, build_icon
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList

View File

@ -1,252 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
OpenLP version 1 theme handling
Provides reference data, a default v1 XML theme and class wrapper for
processing version 1 themes in OpenLP version 2.
"""
from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtGui
DELPHI_COLORS = {
'clAqua': 0x00FFFF,
'clBlack': 0x000000,
'clBlue': 0x0000FF,
'clFuchsia': 0xFF00FF,
'clGray': 0x808080,
'clGreen': 0x008000,
'clLime': 0x00FF00,
'clMaroon': 0x800000,
'clNavy': 0x000080,
'clOlive': 0x808000,
'clPurple': 0x800080,
'clRed': 0xFF0000,
'clSilver': 0xC0C0C0,
'clTeal': 0x008080,
'clWhite': 0xFFFFFF,
'clYellow': 0xFFFF00
}
BLANK_STYLE_XML = \
'''<?xml version="1.0" encoding="iso-8859-1"?>
<Theme>
<Name>BlankStyle</Name>
<BackgroundMode>1</BackgroundMode>
<BackgroundType>0</BackgroundType>
<BackgroundParameter1>$000000</BackgroundParameter1>
<BackgroundParameter2/>
<BackgroundParameter3/>
<FontName>Arial</FontName>
<FontColor>clWhite</FontColor>
<FontProportion>30</FontProportion>
<FontUnits>pixels</FontUnits>
<Shadow>0</Shadow>
<Outline>0</Outline>
<HorizontalAlign>0</HorizontalAlign>
<VerticalAlign>0</VerticalAlign>
<WrapStyle>0</WrapStyle>
</Theme>
'''
class Theme(object):
"""
Provide a class wrapper storing data from an XML theme
``name``
Theme name
``BackgroundMode``
The behaviour of the background. Valid modes are:
* ``0`` - Transparent
* ``1`` - Opaque
``BackgroundType``
The content of the background. Valid types are:
* ``0`` - solid color
* ``1`` - gradient color
* ``2`` - image
``BackgroundParameter1``
Extra information about the background. The contents of this attribute
depend on the BackgroundType:
* ``image`` - image filename
* ``gradient`` - start color
* ``solid`` - color
``BackgroundParameter2``
Extra information about the background. The contents of this attribute
depend on the BackgroundType:
* ``image`` - border color
* ``gradient`` - end color
* ``solid`` - N/A
``BackgroundParameter3``
Extra information about the background. The contents of this attribute
depend on the BackgroundType:
* ``image`` - N/A
* ``gradient`` - The direction of the gradient. Valid entries are:
* ``0`` - vertical
* ``1`` - horizontal
* ``solid`` - N/A
``FontName``
Name of the font to use for the main font.
``FontColor``
The color for the main font
``FontProportion``
The size of the main font
``FontUnits``
The units for FontProportion, either <pixels> or <points>
``Shadow``
The shadow type to apply to the main font.
* ``0`` - no shadow
* non-zero - use shadow
``ShadowColor``
Color for the shadow
``Outline``
The outline to apply to the main font
* ``0`` - no outline
* non-zero - use outline
``OutlineColor``
Color for the outline (or None if Outline is 0)
``HorizontalAlign``
The horizontal alignment to apply to text. Valid alignments are:
* ``0`` - left align
* ``1`` - right align
* ``2`` - centre align
``VerticalAlign``
The vertical alignment to apply to the text. Valid alignments are:
* ``0`` - top align
* ``1`` - bottom align
* ``2`` - centre align
``WrapStyle``
The wrap style to apply to the text. Valid styles are:
* ``0`` - normal
* ``1`` - lyrics
"""
def __init__(self, xml):
"""
Initialise a theme with data from xml
``xml``
The data to initialise the theme with
"""
# init to defaults
self._set_from_xml(BLANK_STYLE_XML)
self._set_from_xml(xml)
def _get_as_string(self):
"""
Return single line string representation of a theme
"""
theme_strings = []
keys = dir(self)
keys.sort()
for key in keys:
if key[0:1] != '_':
theme_strings.append('_%s_' % (getattr(self, key)))
return ''.join(theme_strings)
def _set_from_xml(self, xml):
"""
Set theme class attributes with data from XML
``xml``
The data to apply to the theme
"""
root = ElementTree(element=XML(xml.encode('ascii', 'xmlcharrefreplace')))
xml_iter = root.getiterator()
for element in xml_iter:
delphi_color_change = False
if element.tag != 'Theme':
element_text = element.text
val = 0
if element_text is None:
val = element_text
# strings need special handling to sort the colours out
if isinstance(element_text, str):
if element_text[0] == '$':
# might be a hex number
try:
val = int(element_text[1:], 16)
except ValueError:
# nope
pass
elif element_text in DELPHI_COLORS:
val = DELPHI_COLORS[element_text]
delphi_color_change = True
else:
try:
val = int(element_text)
except ValueError:
val = element_text
if (element.tag.find('Color') > 0 or (element.tag.find('BackgroundParameter') == 0 and
isinstance(val, int))):
# convert to a wx.Colour
if not delphi_color_change:
val = QtGui.QColor(val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF)
else:
val = QtGui.QColor((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)
setattr(self, element.tag, val)
def __str__(self):
"""
Provide Python string representation for the class (multiline output)
"""
theme_strings = []
for key in dir(self):
if key[0:1] != '_':
theme_strings.append('%30s : %s' % (key, getattr(self, key)))
return '\n'.join(theme_strings)

View File

@ -95,13 +95,15 @@ from .aboutform import AboutForm
from .pluginform import PluginForm from .pluginform import PluginForm
from .settingsform import SettingsForm from .settingsform import SettingsForm
from .formattingtagform import FormattingTagForm from .formattingtagform import FormattingTagForm
from .formattingtagcontroller import FormattingTagController
from .shortcutlistform import ShortcutListForm from .shortcutlistform import ShortcutListForm
from .mediadockmanager import MediaDockManager from .mediadockmanager import MediaDockManager
from .servicemanager import ServiceManager from .servicemanager import ServiceManager
from .thememanagerhelper import ThemeManagerHelper
from .thememanager import ThemeManager from .thememanager import ThemeManager
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager',
'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm', 'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm',
'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm', 'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm',
'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm', 'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm',
'FormattingTagForm', 'ShortcutListForm'] 'FormattingTagForm', 'ShortcutListForm', 'FormattingTagController', 'ThemeManagerHelper']

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import UiStrings, build_icon, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box from openlp.core.lib.ui import create_button, create_button_box

View File

@ -36,9 +36,9 @@ import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Settings, UiStrings, translate, build_icon from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate
from openlp.core.utils import AppLocation, format_time, get_images_filter from openlp.core.lib import SettingsTab, build_icon
from openlp.core.lib import SlideLimits from openlp.core.utils import format_time, get_images_filter
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -75,12 +75,6 @@ try:
ICU_VERSION = 'OK' ICU_VERSION = 'OK'
except ImportError: except ImportError:
ICU_VERSION = '-' ICU_VERSION = '-'
try:
import cherrypy
CHERRYPY_VERSION = cherrypy.__version__
except ImportError:
CHERRYPY_VERSION = '-'
try: try:
WEBKIT_VERSION = QtWebKit.qWebKitVersion() WEBKIT_VERSION = QtWebKit.qWebKitVersion()
except AttributeError: except AttributeError:
@ -91,7 +85,7 @@ try:
except ImportError: except ImportError:
VLC_VERSION = '-' VLC_VERSION = '-'
from openlp.core.lib import UiStrings, Settings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.utils import get_application_version from openlp.core.utils import get_application_version
from .exceptiondialog import Ui_ExceptionDialog from .exceptiondialog import Ui_ExceptionDialog
@ -140,7 +134,6 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
'Chardet: %s\n' % CHARDET_VERSION + \ 'Chardet: %s\n' % CHARDET_VERSION + \
'PyEnchant: %s\n' % ENCHANT_VERSION + \ 'PyEnchant: %s\n' % ENCHANT_VERSION + \
'Mako: %s\n' % MAKO_VERSION + \ 'Mako: %s\n' % MAKO_VERSION + \
'CherryPy: %s\n' % CHERRYPY_VERSION + \
'pyICU: %s\n' % ICU_VERSION + \ 'pyICU: %s\n' % ICU_VERSION + \
'pyUNO bridge: %s\n' % self._pyuno_import() + \ 'pyUNO bridge: %s\n' % self._pyuno_import() + \
'VLC: %s\n' % VLC_VERSION 'VLC: %s\n' % VLC_VERSION

View File

@ -34,7 +34,8 @@ from PyQt4 import QtGui
from .filerenamedialog import Ui_FileRenameDialog from .filerenamedialog import Ui_FileRenameDialog
from openlp.core.lib import translate, Registry from openlp.core.common import translate
from openlp.core.lib import Registry
class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):

View File

@ -41,8 +41,9 @@ from configparser import SafeConfigParser
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import PluginStatus, Settings, Registry, build_icon, check_directory_exists, translate from openlp.core.common import AppLocation, Settings, check_directory_exists, translate
from openlp.core.utils import AppLocation, get_web_page from openlp.core.lib import PluginStatus, Registry, build_icon
from openlp.core.utils import get_web_page
from .firsttimewizard import Ui_FirstTimeWizard, FirstTimePage from .firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,7 +31,7 @@ The UI widgets of the language selection dialog.
""" """
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
import sys import sys
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import add_welcome_page from openlp.core.lib.ui import add_welcome_page

View File

@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are protected and included each time loaded.
Custom tags can be defined and saved. The Custom Tag arrays are saved in a pickle so QSettings works on them. Base Tags
cannot be changed.
"""
import re
from openlp.core.common import translate
from openlp.core.lib import FormattingTags
class FormattingTagController(object):
"""
The :class:`FormattingTagController` manages the non UI functions .
"""
def __init__(self):
"""
Initiator
"""
self.html_tag_regex = re.compile(r'<(?:(?P<close>/(?=[^\s/>]+>))?'
r'(?P<tag>[^\s/!\?>]+)(?:\s+[^\s=]+="[^"]*")*\s*(?P<empty>/)?'
r'|(?P<cdata>!\[CDATA\[(?:(?!\]\]>).)*\]\])'
r'|(?P<procinst>\?(?:(?!\?>).)*\?)'
r'|(?P<comment>!--(?:(?!-->).)*--))>', re.UNICODE)
self.html_regex = re.compile(r'^(?:[^<>]*%s)*[^<>]*$' % self.html_tag_regex.pattern)
def pre_save(self):
"""
Cleanup the array before save validation runs
"""
self.protected_tags = [tag for tag in FormattingTags.html_expands if tag.get('protected')]
self.custom_tags = []
def validate_for_save(self, desc, tag, start_html, end_html):
"""
Validate a custom tag and add to the tags array if valid..
`desc`
Explanation of the tag.
`tag`
The tag in the song used to mark the text.
`start_html`
The start html tag.
`end_html`
The end html tag.
"""
for linenumber, html1 in enumerate(self.protected_tags):
if self._strip(html1['start tag']) == tag:
return translate('OpenLP.FormattingTagForm', 'Tag %s already defined.') % tag
if self._strip(html1['desc']) == desc:
return translate('OpenLP.FormattingTagForm', 'Description %s already defined.') % tag
for linenumber, html1 in enumerate(self.custom_tags):
if self._strip(html1['start tag']) == tag:
return translate('OpenLP.FormattingTagForm', 'Tag %s already defined.') % tag
if self._strip(html1['desc']) == desc:
return translate('OpenLP.FormattingTagForm', 'Description %s already defined.') % tag
tag = {
'desc': desc,
'start tag': '{%s}' % tag,
'start html': start_html,
'end tag': '{/%s}' % tag,
'end html': end_html,
'protected': False,
'temporary': False
}
self.custom_tags.append(tag)
def save_tags(self):
"""
Save the new tags if they are valid.
"""
FormattingTags.save_html_tags(self.custom_tags)
FormattingTags.load_tags()
def _strip(self, tag):
"""
Remove tag wrappers for editing.
`tag`
Tag to be stripped
"""
tag = tag.replace('{', '')
tag = tag.replace('}', '')
return tag
def start_html_to_end_html(self, start_html):
"""
Return the end HTML for a given start HTML or None if invalid.
`start_html`
The start html tag.
"""
end_tags = []
match = self.html_regex.match(start_html)
if match:
match = self.html_tag_regex.search(start_html)
while match:
if match.group('tag'):
tag = match.group('tag').lower()
if match.group('close'):
if match.group('empty') or not end_tags or end_tags.pop() != tag:
return
elif not match.group('empty'):
end_tags.append(tag)
match = self.html_tag_regex.search(start_html, match.end())
return ''.join(map(lambda tag: '</%s>' % tag, reversed(end_tags)))
def start_tag_changed(self, start_html, end_html):
"""
Validate the HTML tags when the start tag has been changed.
`start_html`
The start html tag.
`end_html`
The end html tag.
"""
end = self.start_html_to_end_html(start_html)
if not end_html:
if not end:
return translate('OpenLP.FormattingTagForm', 'Start tag %s is not valid HTML' % start_html), None
return None, end
return None, None
def end_tag_changed(self, start_html, end_html):
"""
Validate the HTML tags when the end tag has been changed.
`start_html`
The start html tag.
`end_html`
The end html tag.
"""
end = self.start_html_to_end_html(start_html)
if not end_html:
return None, end
if end and end != end_html:
return translate('OpenLP.FormattingTagForm',
'End tag %s does not match end tag for start tag %s' % (end, start_html)), None
return None, None

View File

@ -31,7 +31,8 @@ The UI widgets for the formatting tags window.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import UiStrings, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box
@ -45,12 +46,34 @@ class Ui_FormattingTagDialog(object):
""" """
formatting_tag_dialog.setObjectName('formatting_tag_dialog') formatting_tag_dialog.setObjectName('formatting_tag_dialog')
formatting_tag_dialog.resize(725, 548) formatting_tag_dialog.resize(725, 548)
self.list_data_grid_layout = QtGui.QGridLayout(formatting_tag_dialog) self.list_data_grid_layout = QtGui.QVBoxLayout(formatting_tag_dialog)
self.list_data_grid_layout.setMargin(8) self.list_data_grid_layout.setMargin(8)
self.list_data_grid_layout.setObjectName('list_data_grid_layout') self.list_data_grid_layout.setObjectName('list_data_grid_layout')
self.tag_table_widget_read_label = QtGui.QLabel()
self.list_data_grid_layout.addWidget(self.tag_table_widget_read_label)
self.tag_table_widget_read = QtGui.QTableWidget(formatting_tag_dialog)
self.tag_table_widget_read.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.tag_table_widget_read.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.tag_table_widget_read.setAlternatingRowColors(True)
self.tag_table_widget_read.setCornerButtonEnabled(False)
self.tag_table_widget_read.setObjectName('tag_table_widget_read')
self.tag_table_widget_read.setColumnCount(4)
self.tag_table_widget_read.setRowCount(0)
self.tag_table_widget_read.horizontalHeader().setStretchLastSection(True)
item = QtGui.QTableWidgetItem()
self.tag_table_widget_read.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tag_table_widget_read.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tag_table_widget_read.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tag_table_widget_read.setHorizontalHeaderItem(3, item)
self.list_data_grid_layout.addWidget(self.tag_table_widget_read)
self.tag_table_widget_label = QtGui.QLabel()
self.list_data_grid_layout.addWidget(self.tag_table_widget_label)
self.tag_table_widget = QtGui.QTableWidget(formatting_tag_dialog) self.tag_table_widget = QtGui.QTableWidget(formatting_tag_dialog)
self.tag_table_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.tag_table_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.tag_table_widget.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.tag_table_widget.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers)
self.tag_table_widget.setAlternatingRowColors(True) self.tag_table_widget.setAlternatingRowColors(True)
self.tag_table_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.tag_table_widget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.tag_table_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.tag_table_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
@ -67,59 +90,26 @@ class Ui_FormattingTagDialog(object):
self.tag_table_widget.setHorizontalHeaderItem(2, item) self.tag_table_widget.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem() item = QtGui.QTableWidgetItem()
self.tag_table_widget.setHorizontalHeaderItem(3, item) self.tag_table_widget.setHorizontalHeaderItem(3, item)
self.list_data_grid_layout.addWidget(self.tag_table_widget, 0, 0, 1, 1) self.list_data_grid_layout.addWidget(self.tag_table_widget)
self.horizontal_layout = QtGui.QHBoxLayout() self.edit_button_layout = QtGui.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout') self.new_button = QtGui.QPushButton(formatting_tag_dialog)
spacer_item = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.new_button.setIcon(build_icon(':/general/general_new.png'))
self.horizontal_layout.addItem(spacer_item) self.new_button.setObjectName('new_button')
self.delete_push_button = QtGui.QPushButton(formatting_tag_dialog) self.edit_button_layout.addWidget(self.new_button)
self.delete_push_button.setObjectName('delete_push_button') self.delete_button = QtGui.QPushButton(formatting_tag_dialog)
self.horizontal_layout.addWidget(self.delete_push_button) self.delete_button.setIcon(build_icon(':/general/general_delete.png'))
self.list_data_grid_layout.addLayout(self.horizontal_layout, 1, 0, 1, 1) self.delete_button.setObjectName('delete_button')
self.edit_group_box = QtGui.QGroupBox(formatting_tag_dialog) self.edit_button_layout.addWidget(self.delete_button)
self.edit_group_box.setObjectName('edit_group_box') self.edit_button_layout.addStretch()
self.data_grid_layout = QtGui.QGridLayout(self.edit_group_box) self.list_data_grid_layout.addLayout(self.edit_button_layout)
self.data_grid_layout.setObjectName('data_grid_layout') self.button_box = create_button_box(formatting_tag_dialog, 'button_box',
self.description_label = QtGui.QLabel(self.edit_group_box) ['cancel', 'save', 'defaults'])
self.description_label.setAlignment(QtCore.Qt.AlignCenter) self.save_button = self.button_box.button(QtGui.QDialogButtonBox.Save)
self.description_label.setObjectName('description_label') self.save_button.setObjectName('save_button')
self.data_grid_layout.addWidget(self.description_label, 0, 0, 1, 1) self.restore_button = self.button_box.button(QtGui.QDialogButtonBox.RestoreDefaults)
self.description_line_edit = QtGui.QLineEdit(self.edit_group_box) self.restore_button.setIcon(build_icon(':/general/general_revert.png'))
self.description_line_edit.setObjectName('description_line_edit') self.restore_button.setObjectName('restore_button')
self.data_grid_layout.addWidget(self.description_line_edit, 0, 1, 2, 1) self.list_data_grid_layout.addWidget(self.button_box)
self.new_push_button = QtGui.QPushButton(self.edit_group_box)
self.new_push_button.setObjectName('new_push_button')
self.data_grid_layout.addWidget(self.new_push_button, 0, 2, 2, 1)
self.tag_label = QtGui.QLabel(self.edit_group_box)
self.tag_label.setAlignment(QtCore.Qt.AlignCenter)
self.tag_label.setObjectName('tag_label')
self.data_grid_layout.addWidget(self.tag_label, 2, 0, 1, 1)
self.tag_line_edit = QtGui.QLineEdit(self.edit_group_box)
self.tag_line_edit.setMaximumSize(QtCore.QSize(50, 16777215))
self.tag_line_edit.setMaxLength(5)
self.tag_line_edit.setObjectName('tag_line_edit')
self.data_grid_layout.addWidget(self.tag_line_edit, 2, 1, 1, 1)
self.start_tag_label = QtGui.QLabel(self.edit_group_box)
self.start_tag_label.setAlignment(QtCore.Qt.AlignCenter)
self.start_tag_label.setObjectName('start_tag_label')
self.data_grid_layout.addWidget(self.start_tag_label, 3, 0, 1, 1)
self.start_tag_line_edit = QtGui.QLineEdit(self.edit_group_box)
self.start_tag_line_edit.setObjectName('start_tag_line_edit')
self.data_grid_layout.addWidget(self.start_tag_line_edit, 3, 1, 1, 1)
self.end_tag_label = QtGui.QLabel(self.edit_group_box)
self.end_tag_label.setAlignment(QtCore.Qt.AlignCenter)
self.end_tag_label.setObjectName('end_tag_label')
self.data_grid_layout.addWidget(self.end_tag_label, 4, 0, 1, 1)
self.end_tag_line_edit = QtGui.QLineEdit(self.edit_group_box)
self.end_tag_line_edit.setObjectName('end_tag_line_edit')
self.data_grid_layout.addWidget(self.end_tag_line_edit, 4, 1, 1, 1)
self.save_push_button = QtGui.QPushButton(self.edit_group_box)
self.save_push_button.setObjectName('save_push_button')
self.data_grid_layout.addWidget(self.save_push_button, 4, 2, 1, 1)
self.list_data_grid_layout.addWidget(self.edit_group_box, 2, 0, 1, 1)
self.button_box = create_button_box(formatting_tag_dialog, 'button_box', ['close'])
self.list_data_grid_layout.addWidget(self.button_box, 3, 0, 1, 1)
self.retranslateUi(formatting_tag_dialog) self.retranslateUi(formatting_tag_dialog)
def retranslateUi(self, formatting_tag_dialog): def retranslateUi(self, formatting_tag_dialog):
@ -127,14 +117,19 @@ class Ui_FormattingTagDialog(object):
Translate the UI on the fly Translate the UI on the fly
""" """
formatting_tag_dialog.setWindowTitle(translate('OpenLP.FormattingTagDialog', 'Configure Formatting Tags')) formatting_tag_dialog.setWindowTitle(translate('OpenLP.FormattingTagDialog', 'Configure Formatting Tags'))
self.edit_group_box.setTitle(translate('OpenLP.FormattingTagDialog', 'Edit Selection')) self.delete_button.setText(UiStrings().Delete)
self.save_push_button.setText(translate('OpenLP.FormattingTagDialog', 'Save')) self.new_button.setText(UiStrings().New)
self.description_label.setText(translate('OpenLP.FormattingTagDialog', 'Description')) self.tag_table_widget_read_label.setText(translate('OpenLP.FormattingTagDialog', 'Default Formatting'))
self.tag_label.setText(translate('OpenLP.FormattingTagDialog', 'Tag')) self.tag_table_widget_read.horizontalHeaderItem(0).\
self.start_tag_label.setText(translate('OpenLP.FormattingTagDialog', 'Start HTML')) setText(translate('OpenLP.FormattingTagDialog', 'Description'))
self.end_tag_label.setText(translate('OpenLP.FormattingTagDialog', 'End HTML')) self.tag_table_widget_read.horizontalHeaderItem(1).setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
self.delete_push_button.setText(UiStrings().Delete) self.tag_table_widget_read.horizontalHeaderItem(2).\
self.new_push_button.setText(UiStrings().New) setText(translate('OpenLP.FormattingTagDialog', 'Start HTML'))
self.tag_table_widget_read.horizontalHeaderItem(3).setText(translate('OpenLP.FormattingTagDialog', 'End HTML'))
self.tag_table_widget_read.setColumnWidth(0, 120)
self.tag_table_widget_read.setColumnWidth(1, 80)
self.tag_table_widget_read.setColumnWidth(2, 330)
self.tag_table_widget_label.setText(translate('OpenLP.FormattingTagDialog', 'Custom Formatting'))
self.tag_table_widget.horizontalHeaderItem(0).setText(translate('OpenLP.FormattingTagDialog', 'Description')) self.tag_table_widget.horizontalHeaderItem(0).setText(translate('OpenLP.FormattingTagDialog', 'Description'))
self.tag_table_widget.horizontalHeaderItem(1).setText(translate('OpenLP.FormattingTagDialog', 'Tag')) self.tag_table_widget.horizontalHeaderItem(1).setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
self.tag_table_widget.horizontalHeaderItem(2).setText(translate('OpenLP.FormattingTagDialog', 'Start HTML')) self.tag_table_widget.horizontalHeaderItem(2).setText(translate('OpenLP.FormattingTagDialog', 'Start HTML'))

View File

@ -31,14 +31,26 @@ The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are pro
Custom tags can be defined and saved. The Custom Tag arrays are saved in a json string so QSettings works on them. Custom tags can be defined and saved. The Custom Tag arrays are saved in a json string so QSettings works on them.
Base Tags cannot be changed. Base Tags cannot be changed.
""" """
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import FormattingTags, translate from openlp.core.common import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib import FormattingTags
from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog
from openlp.core.ui.formattingtagcontroller import FormattingTagController
class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog): class EditColumn(object):
"""
Hides the magic numbers for the table columns
"""
Description = 0
Tag = 1
StartHtml = 2
EndHtml = 3
class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog, FormattingTagController):
""" """
The :class:`FormattingTagForm` manages the settings tab . The :class:`FormattingTagForm` manages the settings tab .
""" """
@ -48,17 +60,17 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
""" """
super(FormattingTagForm, self).__init__(parent) super(FormattingTagForm, self).__init__(parent)
self.setupUi(self) self.setupUi(self)
self.services = FormattingTagController()
self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected) self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
self.new_push_button.clicked.connect(self.on_new_clicked) self.new_button.clicked.connect(self.on_new_clicked)
self.save_push_button.clicked.connect(self.on_saved_clicked) #self.save_button.clicked.connect(self.on_saved_clicked)
self.delete_push_button.clicked.connect(self.on_delete_clicked) self.delete_button.clicked.connect(self.on_delete_clicked)
self.tag_table_widget.currentCellChanged.connect(self.on_current_cell_changed)
self.button_box.rejected.connect(self.close) self.button_box.rejected.connect(self.close)
self.description_line_edit.textEdited.connect(self.on_text_edited)
self.tag_line_edit.textEdited.connect(self.on_text_edited)
self.start_tag_line_edit.textEdited.connect(self.on_text_edited)
self.end_tag_line_edit.textEdited.connect(self.on_text_edited)
# Forces reloading of tags from openlp configuration. # Forces reloading of tags from openlp configuration.
FormattingTags.load_tags() FormattingTags.load_tags()
self.is_deleting = False
self.reloading = False
def exec_(self): def exec_(self):
""" """
@ -66,138 +78,128 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
""" """
# Create initial copy from master # Create initial copy from master
self._reloadTable() self._reloadTable()
self.selected = -1
return QtGui.QDialog.exec_(self) return QtGui.QDialog.exec_(self)
def on_row_selected(self): def on_row_selected(self):
""" """
Table Row selected so display items and set field state. Table Row selected so display items and set field state.
""" """
self.save_push_button.setEnabled(False) self.delete_button.setEnabled(True)
self.selected = self.tag_table_widget.currentRow()
html = FormattingTags.get_html_tags()[self.selected]
self.description_line_edit.setText(html['desc'])
self.tag_line_edit.setText(self._strip(html['start tag']))
self.start_tag_line_edit.setText(html['start html'])
self.end_tag_line_edit.setText(html['end html'])
if html['protected']:
self.description_line_edit.setEnabled(False)
self.tag_line_edit.setEnabled(False)
self.start_tag_line_edit.setEnabled(False)
self.end_tag_line_edit.setEnabled(False)
self.delete_push_button.setEnabled(False)
else:
self.description_line_edit.setEnabled(True)
self.tag_line_edit.setEnabled(True)
self.start_tag_line_edit.setEnabled(True)
self.end_tag_line_edit.setEnabled(True)
self.delete_push_button.setEnabled(True)
def on_text_edited(self, text):
"""
Enable the ``save_push_button`` when any of the selected tag's properties
has been changed.
"""
self.save_push_button.setEnabled(True)
def on_new_clicked(self): def on_new_clicked(self):
""" """
Add a new tag to list only if it is not a duplicate. Add a new tag to edit list and select it for editing.
""" """
for html in FormattingTags.get_html_tags(): new_row = self.tag_table_widget.rowCount()
if self._strip(html['start tag']) == 'n': self.tag_table_widget.insertRow(new_row)
critical_error_message_box( self.tag_table_widget.setItem(new_row, 0,
translate('OpenLP.FormattingTagForm', 'Update Error'), QtGui.QTableWidgetItem(translate('OpenLP.FormattingTagForm', 'New Tag%s') % str(new_row)))
translate('OpenLP.FormattingTagForm', 'Tag "n" already defined.')) self.tag_table_widget.setItem(new_row, 1, QtGui.QTableWidgetItem('n%s' % str(new_row)))
return self.tag_table_widget.setItem(new_row, 2,
# Add new tag to list QtGui.QTableWidgetItem(translate('OpenLP.FormattingTagForm', '<HTML here>')))
tag = { self.tag_table_widget.setItem(new_row, 3, QtGui.QTableWidgetItem(''))
'desc': translate('OpenLP.FormattingTagForm', 'New Tag'), self.tag_table_widget.resizeRowsToContents()
'start tag': '{n}',
'start html': translate('OpenLP.FormattingTagForm', '<HTML here>'),
'end tag': '{/n}',
'end html': translate('OpenLP.FormattingTagForm', '</and here>'),
'protected': False,
'temporary': False
}
FormattingTags.add_html_tags([tag])
FormattingTags.save_html_tags()
self._reloadTable()
# Highlight new row
self.tag_table_widget.selectRow(self.tag_table_widget.rowCount() - 1)
self.on_row_selected()
self.tag_table_widget.scrollToBottom() self.tag_table_widget.scrollToBottom()
self.tag_table_widget.selectRow(new_row)
def on_delete_clicked(self): def on_delete_clicked(self):
""" """
Delete selected custom tag. Delete selected custom row.
""" """
if self.selected != -1: selected = self.tag_table_widget.currentRow()
FormattingTags.remove_html_tag(self.selected) if selected != -1:
# As the first items are protected we should not have to take care self.is_deleting = True
# of negative indexes causing tracebacks. self.tag_table_widget.removeRow(selected)
self.tag_table_widget.selectRow(self.selected - 1)
self.selected = -1
FormattingTags.save_html_tags()
self._reloadTable()
def on_saved_clicked(self): def accept(self):
""" """
Update Custom Tag details if not duplicate and save the data. Update Custom Tag details if not duplicate and save the data.
""" """
html_expands = FormattingTags.get_html_tags() count = 0
if self.selected != -1: self.services.pre_save()
html = html_expands[self.selected] while count < self.tag_table_widget.rowCount():
tag = self.tag_line_edit.text() error = self.services.validate_for_save(self.tag_table_widget.item(count, 0).text(),
for linenumber, html1 in enumerate(html_expands): self.tag_table_widget.item(count, 1).text(), self.tag_table_widget.item(count, 2).text(),
if self._strip(html1['start tag']) == tag and linenumber != self.selected: self.tag_table_widget.item(count, 3).text())
critical_error_message_box( if error:
translate('OpenLP.FormattingTagForm', 'Update Error'), QtGui.QMessageBox.warning(self,
translate('OpenLP.FormattingTagForm', 'Tag %s already defined.') % tag) translate('OpenLP.FormattingTagForm', 'Validation Error'), error, QtGui.QMessageBox.Ok)
return self.tag_table_widget.selectRow(count)
html['desc'] = self.description_line_edit.text() return
html['start html'] = self.start_tag_line_edit.text() count += 1
html['end html'] = self.end_tag_line_edit.text() self.services.save_tags()
html['start tag'] = '{%s}' % tag QtGui.QDialog.accept(self)
html['end tag'] = '{/%s}' % tag
# Keep temporary tags when the user changes one.
html['temporary'] = False
self.selected = -1
FormattingTags.save_html_tags()
self._reloadTable()
def _reloadTable(self): def _reloadTable(self):
""" """
Reset List for loading. Reset List for loading.
""" """
self.reloading = True
self.tag_table_widget_read.clearContents()
self.tag_table_widget_read.setRowCount(0)
self.tag_table_widget.clearContents() self.tag_table_widget.clearContents()
self.tag_table_widget.setRowCount(0) self.tag_table_widget.setRowCount(0)
self.new_push_button.setEnabled(True) self.new_button.setEnabled(True)
self.save_push_button.setEnabled(False) self.delete_button.setEnabled(False)
self.delete_push_button.setEnabled(False)
for linenumber, html in enumerate(FormattingTags.get_html_tags()): for linenumber, html in enumerate(FormattingTags.get_html_tags()):
self.tag_table_widget.setRowCount(self.tag_table_widget.rowCount() + 1) if html['protected']:
self.tag_table_widget.setItem(linenumber, 0, QtGui.QTableWidgetItem(html['desc'])) line = self.tag_table_widget_read.rowCount()
self.tag_table_widget.setItem(linenumber, 1, QtGui.QTableWidgetItem(self._strip(html['start tag']))) self.tag_table_widget_read.setRowCount(line + 1)
self.tag_table_widget.setItem(linenumber, 2, QtGui.QTableWidgetItem(html['start html'])) self.tag_table_widget_read.setItem(line, 0, QtGui.QTableWidgetItem(html['desc']))
self.tag_table_widget.setItem(linenumber, 3, QtGui.QTableWidgetItem(html['end html'])) self.tag_table_widget_read.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html['start tag'])))
# Permanent (persistent) tags do not have this key. self.tag_table_widget_read.setItem(line, 2, QtGui.QTableWidgetItem(html['start html']))
if 'temporary' not in html: self.tag_table_widget_read.setItem(line, 3, QtGui.QTableWidgetItem(html['end html']))
self.tag_table_widget_read.resizeRowsToContents()
else:
line = self.tag_table_widget.rowCount()
self.tag_table_widget.setRowCount(line + 1)
self.tag_table_widget.setItem(line, 0, QtGui.QTableWidgetItem(html['desc']))
self.tag_table_widget.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html['start tag'])))
self.tag_table_widget.setItem(line, 2, QtGui.QTableWidgetItem(html['start html']))
self.tag_table_widget.setItem(line, 3, QtGui.QTableWidgetItem(html['end html']))
self.tag_table_widget.resizeRowsToContents()
# Permanent (persistent) tags do not have this key
html['temporary'] = False html['temporary'] = False
self.tag_table_widget.resizeRowsToContents() self.reloading = False
self.description_line_edit.setText('')
self.tag_line_edit.setText('')
self.start_tag_line_edit.setText('')
self.end_tag_line_edit.setText('')
self.description_line_edit.setEnabled(False)
self.tag_line_edit.setEnabled(False)
self.start_tag_line_edit.setEnabled(False)
self.end_tag_line_edit.setEnabled(False)
def _strip(self, tag): def on_current_cell_changed(self, cur_row, cur_col, pre_row, pre_col):
""" """
Remove tag wrappers for editing. This function processes all user edits in the table. It is called on each cell change.
""" """
tag = tag.replace('{', '') if self.is_deleting:
tag = tag.replace('}', '') self.is_deleting = False
return tag return
if self.reloading:
return
# only process for editable rows
if self.tag_table_widget.item(pre_row, 0):
item = self.tag_table_widget.item(pre_row, pre_col)
text = item.text()
errors = None
if pre_col is EditColumn.Description:
if not text:
errors = translate('OpenLP.FormattingTagForm', 'Description is missing')
elif pre_col is EditColumn.Tag:
if not text:
errors = translate('OpenLP.FormattingTagForm', 'Tag is missing')
elif pre_col is EditColumn.StartHtml:
# HTML edited
item = self.tag_table_widget.item(pre_row, 3)
end_html = item.text()
errors, tag = self.services.start_tag_changed(text, end_html)
if tag:
self.tag_table_widget.setItem(pre_row, 3, QtGui.QTableWidgetItem(tag))
self.tag_table_widget.resizeRowsToContents()
elif pre_col is EditColumn.EndHtml:
# HTML edited
item = self.tag_table_widget.item(pre_row, 2)
start_html = item.text()
errors, tag = self.services.end_tag_changed(start_html, text)
if tag:
self.tag_table_widget.setItem(pre_row, 3, QtGui.QTableWidgetItem(tag))
if errors:
QtGui.QMessageBox.warning(self,
translate('OpenLP.FormattingTagForm', 'Validation Error'), errors, QtGui.QMessageBox.Ok)
#self.tag_table_widget.selectRow(pre_row - 1)
self.tag_table_widget.resizeRowsToContents()

View File

@ -33,7 +33,8 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, Settings, SettingsTab, ScreenList, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, SettingsTab, ScreenList
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -44,8 +44,8 @@ import sys
from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import ServiceItem, Settings, ImageSource, Registry, build_html, expand_tags, \ from openlp.core.common import Settings, translate
image_to_byte, translate from openlp.core.lib import ServiceItem, ImageSource, Registry, build_html, expand_tags, image_to_byte
from openlp.core.lib.theme import BackgroundType from openlp.core.lib.theme import BackgroundType
from openlp.core.lib import ScreenList from openlp.core.lib import ScreenList
@ -245,8 +245,6 @@ class MainDisplay(Display):
# Windows if there are many items in the service to re-render. # Windows if there are many items in the service to re-render.
# Setting the div elements direct seems to solve the issue # Setting the div elements direct seems to solve the issue
self.frame.findFirstElement("#lyricsmain").setInnerXml(slide) self.frame.findFirstElement("#lyricsmain").setInnerXml(slide)
self.frame.findFirstElement("#lyricsoutline").setInnerXml(slide)
self.frame.findFirstElement("#lyricsshadow").setInnerXml(slide)
def alert(self, text, location): def alert(self, text, location):
""" """

View File

@ -42,12 +42,14 @@ from datetime import datetime
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, Registry, \ from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, Registry, \
Settings, ScreenList, build_icon, check_directory_exists, translate ScreenList, build_icon
from openlp.core.lib.ui import UiStrings, create_action from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \ from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
MediaDockManager, ShortcutListForm, FormattingTagForm MediaDockManager, ShortcutListForm, FormattingTagForm
from openlp.core.common import AppLocation, Settings, check_directory_exists, translate
from openlp.core.ui.media import MediaController from openlp.core.ui.media import MediaController
from openlp.core.utils import AppLocation, LanguageManager, add_actions, get_application_version from openlp.core.utils import LanguageManager, add_actions, get_application_version
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimeform import FirstTimeForm

View File

@ -31,7 +31,7 @@ The :mod:`~openlp.core.ui.media` module contains classes and objects for media p
""" """
import logging import logging
from openlp.core.lib import Settings from openlp.core.common import Settings
from PyQt4 import QtCore from PyQt4 import QtCore

View File

@ -35,11 +35,12 @@ import os
import datetime import datetime
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Settings, Registry, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import OpenLPToolbar, Registry
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.ui.media.mediaplayer import MediaPlayer
from openlp.core.utils import AppLocation from openlp.core.common import AppLocation
from openlp.core.ui import DisplayControllerType from openlp.core.ui import DisplayControllerType
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -36,7 +36,8 @@ from datetime import datetime
from PyQt4 import QtGui from PyQt4 import QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import Settings, translate from openlp.core.common import Settings
from openlp.core.lib import translate
from openlp.core.ui.media import MediaState from openlp.core.ui.media import MediaState
from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.ui.media.mediaplayer import MediaPlayer
@ -45,36 +46,22 @@ from openlp.core.ui.media.mediaplayer import MediaPlayer
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
ADDITIONAL_EXT = { ADDITIONAL_EXT = {
'audio/ac3': ['.ac3'], 'audio/ac3': ['.ac3'],
'audio/flac': ['.flac'], 'audio/flac': ['.flac'],
'audio/x-m4a': ['.m4a'], 'audio/x-m4a': ['.m4a'],
'audio/midi': ['.mid', '.midi'], 'audio/midi': ['.mid', '.midi'],
'audio/x-mp3': ['.mp3'], 'audio/x-mp3': ['.mp3'],
'audio/mpeg': ['.mp3', '.mp2', '.mpga', '.mpega', '.m4a'], 'audio/mpeg': ['.mp3', '.mp2', '.mpga', '.mpega', '.m4a'],
'audio/qcelp': ['.qcp'], 'audio/qcelp': ['.qcp'],
'audio/x-wma': ['.wma'], 'audio/x-wma': ['.wma'],
'audio/x-ms-wma': ['.wma'], 'audio/x-ms-wma': ['.wma'],
'video/x-flv': ['.flv'], 'video/x-flv': ['.flv'],
'video/x-matroska': ['.mpv', '.mkv'], 'video/x-matroska': ['.mpv', '.mkv'],
'video/x-wmv': ['.wmv'], 'video/x-wmv': ['.wmv'],
'video/x-mpg': ['.mpg'], 'video/x-mpg': ['.mpg'],
'video/mpeg': ['.mp4', '.mts', '.mov'], 'video/mpeg': ['.mp4', '.mts', '.mov'],
'video/x-ms-wmv': ['.wmv']} 'video/x-ms-wmv': ['.wmv']
VIDEO_CSS = """
#videobackboard {
z-index:3;
background-color: %(bgcolor)s;
} }
#video1 {
background-color: %(bgcolor)s;
z-index:4;
}
#video2 {
background-color: %(bgcolor)s;
z-index:4;
}
"""
class PhononPlayer(MediaPlayer): class PhononPlayer(MediaPlayer):
@ -268,8 +255,7 @@ class PhononPlayer(MediaPlayer):
""" """
Add css style sheets to htmlbuilder Add css style sheets to htmlbuilder
""" """
background = QtGui.QColor(Settings().value('players/background color')).name() return ''
return VIDEO_CSS % {'bgcolor': background}
def get_info(self): def get_info(self):
""" """

View File

@ -31,7 +31,8 @@ The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab fo
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, SettingsTab
from openlp.core.lib.ui import create_button from openlp.core.lib.ui import create_button
from openlp.core.ui.media import get_media_players, set_media_players from openlp.core.ui.media import get_media_players, set_media_players

View File

@ -37,7 +37,8 @@ import sys
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Settings, translate from openlp.core.common import Settings
from openlp.core.lib import translate
from openlp.core.ui.media import MediaState from openlp.core.ui.media import MediaState
from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.ui.media.mediaplayer import MediaPlayer

View File

@ -33,7 +33,8 @@ from PyQt4 import QtGui
import logging import logging
from openlp.core.lib import Settings, translate from openlp.core.common import Settings
from openlp.core.lib import translate
from openlp.core.ui.media import MediaState from openlp.core.ui.media import MediaState
from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.ui.media.mediaplayer import MediaPlayer

View File

@ -31,7 +31,7 @@ The UI widgets of the plugin view dialog
#""" #"""
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import UiStrings, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -34,7 +34,8 @@ import os
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import PluginStatus, Registry, translate from openlp.core.common import translate
from openlp.core.lib import PluginStatus, Registry
from .plugindialog import Ui_PluginViewDialog from .plugindialog import Ui_PluginViewDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,7 +31,8 @@ The UI widgets of the print service dialog.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SpellTextEdit, UiStrings, build_icon, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import SpellTextEdit, build_icon
class ZoomSize(object): class ZoomSize(object):

View File

@ -36,9 +36,10 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from lxml import html from lxml import html
from openlp.core.lib import Settings, UiStrings, Registry, translate, get_text_file_string from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, get_text_file_string
from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
from openlp.core.utils import AppLocation from openlp.core.common import AppLocation
DEFAULT_CSS = """/* DEFAULT_CSS = """/*
Edit this file to customize the service order print. Note, that not all CSS Edit this file to customize the service order print. Note, that not all CSS

View File

@ -31,7 +31,7 @@ The UI widgets for the service item edit dialog
""" """
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box, create_button from openlp.core.lib.ui import create_button_box, create_button

View File

@ -29,7 +29,7 @@
""" """
The service item edit dialog The service item edit dialog
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import Registry from openlp.core.lib import Registry
from .serviceitemeditdialog import Ui_ServiceItemEditDialog from .serviceitemeditdialog import Ui_ServiceItemEditDialog

View File

@ -42,13 +42,12 @@ log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, Settings, PluginStatus, Registry, \ from openlp.core.common import AppLocation, Settings, ThemeLevel, check_directory_exists, UiStrings, translate
UiStrings, build_icon, translate, str_to_bool, check_directory_exists from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, Registry, build_icon
from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.utils import AppLocation, delete_file, split_filename, format_time from openlp.core.utils import delete_file, split_filename, format_time
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder

View File

@ -31,7 +31,8 @@ The :mod:`~openlp.core.ui.servicenoteform` module contains the `ServiceNoteForm`
""" """
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import SpellTextEdit, Registry, translate from openlp.core.common import translate
from openlp.core.lib import SpellTextEdit, Registry
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -31,7 +31,8 @@ The UI widgets of the settings dialog.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon from openlp.core.common import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -31,7 +31,8 @@ The list of shortcuts within a dialog.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon from openlp.core.common import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -33,8 +33,8 @@ import re
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, Settings from openlp.core.lib import Registry
from openlp.core.utils import translate from openlp.core.common import Settings, translate
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from .shortcutlistdialog import Ui_ShortcutListDialog from .shortcutlistdialog import Ui_ShortcutListDialog

View File

@ -37,8 +37,9 @@ from collections import deque
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \ from openlp.core.common import Settings, SlideLimits, UiStrings, translate
ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, ServiceItemAction, Registry, \
ScreenList, build_icon, build_html
from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
from openlp.core.lib.ui import create_action from openlp.core.lib.ui import create_action
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder

View File

@ -31,7 +31,7 @@ The UI widgets for the time dialog
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import UiStrings, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -33,7 +33,8 @@ from PyQt4 import QtGui
from .starttimedialog import Ui_StartTimeDialog from .starttimedialog import Ui_StartTimeDialog
from openlp.core.lib import UiStrings, Registry, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import Registry
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box

View File

@ -34,7 +34,8 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import UiStrings, Registry, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import Registry
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm from openlp.core.ui import ThemeLayoutForm

View File

@ -31,7 +31,7 @@ The layout of the theme
""" """
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -38,18 +38,18 @@ import re
from xml.etree.ElementTree import ElementTree, XML from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, Settings, UiStrings, get_text_file_string, \ from openlp.core.common import AppLocation, Settings, check_directory_exists, UiStrings, translate
build_icon, translate, check_item_selected, check_directory_exists, create_thumb, validate_thumb from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, get_text_file_string, build_icon, \
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.theme import ThemeXML, BackgroundType
from openlp.core.lib.ui import critical_error_message_box, create_widget_action from openlp.core.lib.ui import critical_error_message_box, create_widget_action
from openlp.core.theme import Theme from openlp.core.ui import FileRenameForm, ThemeForm, ThemeManagerHelper
from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding
from openlp.core.utils import AppLocation, delete_file, get_locale_key, get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class ThemeManager(QtGui.QWidget): class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
""" """
Manages the orders of Theme. Manages the orders of Theme.
""" """
@ -328,8 +328,8 @@ class ThemeManager(QtGui.QWidget):
try: try:
encoding = get_filesystem_encoding() encoding = get_filesystem_encoding()
shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
except OSError as xxx_todo_changeme1: except OSError as os_error:
shutil.Error = xxx_todo_changeme1 shutil.Error = os_error
log.exception('Error deleting theme %s', theme) log.exception('Error deleting theme %s', theme)
def on_export_theme(self): def on_export_theme(self):
@ -469,7 +469,7 @@ class ThemeManager(QtGui.QWidget):
log.debug('No theme data - using default theme') log.debug('No theme data - using default theme')
return ThemeXML() return ThemeXML()
else: else:
return self._create_theme_fom_Xml(xml, self.path) return self._create_theme_from_Xml(xml, self.path)
def over_write_message_box(self, theme_name): def over_write_message_box(self, theme_name):
""" """
@ -501,35 +501,30 @@ class ThemeManager(QtGui.QWidget):
log.exception('Theme contains "%s" XML files' % len(xml_file)) log.exception('Theme contains "%s" XML files' % len(xml_file))
raise Exception('validation') raise Exception('validation')
xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot() xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot()
v1_background = xml_tree.find('BackgroundType') theme_name = xml_tree.find('name').text.strip()
if v1_background is not None: theme_folder = os.path.join(directory, theme_name)
theme_name, file_xml, out_file, abort_import = \ theme_exists = os.path.exists(theme_folder)
self.unzip_version_122(directory, theme_zip, xml_file[0], xml_tree, v1_background, out_file) if theme_exists and not self.over_write_message_box(theme_name):
abort_import = True
return
else: else:
theme_name = xml_tree.find('name').text.strip() abort_import = False
theme_folder = os.path.join(directory, theme_name) for name in theme_zip.namelist():
theme_exists = os.path.exists(theme_folder) name = name.replace('/', os.path.sep)
if theme_exists and not self.over_write_message_box(theme_name): split_name = name.split(os.path.sep)
abort_import = True if split_name[-1] == '' or len(split_name) == 1:
return # is directory or preview file
continue
full_name = os.path.join(directory, name)
check_directory_exists(os.path.dirname(full_name))
if os.path.splitext(name)[1].lower() == '.xml':
file_xml = str(theme_zip.read(name), 'utf-8')
out_file = open(full_name, 'w')
out_file.write(file_xml)
else: else:
abort_import = False out_file = open(full_name, 'wb')
for name in theme_zip.namelist(): out_file.write(theme_zip.read(name))
name = name.replace('/', os.path.sep) out_file.close()
split_name = name.split(os.path.sep)
if split_name[-1] == '' or len(split_name) == 1:
# is directory or preview file
continue
full_name = os.path.join(directory, name)
check_directory_exists(os.path.dirname(full_name))
if os.path.splitext(name)[1].lower() == '.xml':
file_xml = str(theme_zip.read(name), 'utf-8')
out_file = open(full_name, 'w')
out_file.write(file_xml)
else:
out_file = open(full_name, 'wb')
out_file.write(theme_zip.read(name))
out_file.close()
except (IOError, zipfile.BadZipfile): except (IOError, zipfile.BadZipfile):
log.exception('Importing theme from zip failed %s' % file_name) log.exception('Importing theme from zip failed %s' % file_name)
raise Exception('validation') raise Exception('validation')
@ -548,7 +543,7 @@ class ThemeManager(QtGui.QWidget):
if not abort_import: if not abort_import:
# As all files are closed, we can create the Theme. # As all files are closed, we can create the Theme.
if file_xml: if file_xml:
theme = self._create_theme_fom_Xml(file_xml, self.path) theme = self._create_theme_from_Xml(file_xml, self.path)
self.generate_and_save_image(directory, theme_name, theme) self.generate_and_save_image(directory, theme_name, theme)
# Only show the error message, when IOError was not raised (in # Only show the error message, when IOError was not raised (in
# this case the error message has already been shown). # this case the error message has already been shown).
@ -558,38 +553,6 @@ class ThemeManager(QtGui.QWidget):
translate('OpenLP.ThemeManager', 'File is not a valid theme.')) translate('OpenLP.ThemeManager', 'File is not a valid theme.'))
log.exception('Theme file does not contain XML data %s' % file_name) log.exception('Theme file does not contain XML data %s' % file_name)
def unzip_version_122(self, dir_name, zip_file, xml_file, xml_tree, background, out_file):
"""
Unzip openlp.org 1.2x theme file and upgrade the theme xml. When calling
this method, please keep in mind, that some parameters are redundant.
"""
theme_name = xml_tree.find('Name').text.strip()
theme_name = self.bad_v1_name_chars.sub('', theme_name)
theme_folder = os.path.join(dir_name, theme_name)
theme_exists = os.path.exists(theme_folder)
if theme_exists and not self.over_write_message_box(theme_name):
return '', '', '', True
themedir = os.path.join(dir_name, theme_name)
check_directory_exists(themedir)
file_xml = str(zip_file.read(xml_file), 'utf-8')
file_xml = self._migrate_version_122(file_xml)
out_file = open(os.path.join(themedir, theme_name + '.xml'), 'w')
out_file.write(file_xml.encode('utf-8'))
out_file.close()
if background.text.strip() == '2':
image_name = xml_tree.find('BackgroundParameter1').text.strip()
# image file has same extension and is in subfolder
image_file = [name for name in zip_file.namelist() if os.path.splitext(name)[1].lower()
== os.path.splitext(image_name)[1].lower() and name.find(r'/')]
if len(image_file) >= 1:
out_file = open(os.path.join(themedir, image_name), 'wb')
out_file.write(zip_file.read(image_file[0]))
out_file.close()
else:
log.exception('Theme file does not contain image file "%s"' % image_name.decode('utf-8', 'replace'))
raise Exception('validation')
return theme_name, file_xml, out_file, False
def check_if_theme_exists(self, theme_name): def check_if_theme_exists(self, theme_name):
""" """
Check if theme already exists and displays error message Check if theme already exists and displays error message
@ -697,7 +660,7 @@ class ThemeManager(QtGui.QWidget):
image = os.path.join(self.path, theme + '.png') image = os.path.join(self.path, theme + '.png')
return image return image
def _create_theme_fom_Xml(self, theme_xml, path): def _create_theme_from_Xml(self, theme_xml, path):
""" """
Return a theme object using information parsed from XML Return a theme object using information parsed from XML
@ -741,55 +704,6 @@ class ThemeManager(QtGui.QWidget):
return True return True
return False return False
def _migrate_version_122(self, xml_data):
"""
Convert the xml data from version 1 format to the current format.
New fields are loaded with defaults to provide a complete, working
theme containing all compatible customisations from the old theme.
``xml_data``
Version 1 theme to convert
"""
theme = Theme(xml_data)
new_theme = ThemeXML()
new_theme.theme_name = self.bad_v1_name_chars.sub('', theme.Name)
if theme.BackgroundType == BackgroundType.Solid:
new_theme.background_type = BackgroundType.to_string(BackgroundType.Solid)
new_theme.background_color = str(theme.BackgroundParameter1.name())
elif theme.BackgroundType == BackgroundType.Horizontal:
new_theme.background_type = BackgroundType.to_string(BackgroundType.Gradient)
new_theme.background_direction = BackgroundGradientType.to_string(BackgroundGradientType.Horizontal)
if theme.BackgroundParameter3.name() == 1:
new_theme.background_direction = BackgroundGradientType.to_string(BackgroundGradientType.Horizontal)
new_theme.background_start_color = str(theme.BackgroundParameter1.name())
new_theme.background_end_color = str(theme.BackgroundParameter2.name())
elif theme.BackgroundType == BackgroundType.Image:
new_theme.background_type = BackgroundType.to_string(BackgroundType.Image)
new_theme.background_filename = str(theme.BackgroundParameter1)
elif theme.BackgroundType == BackgroundType.Transparent:
new_theme.background_type = BackgroundType.to_string(BackgroundType.Transparent)
new_theme.font_main_name = theme.FontName
new_theme.font_main_color = str(theme.FontColor.name())
new_theme.font_main_size = theme.FontProportion * 3
new_theme.font_footer_name = theme.FontName
new_theme.font_footer_color = str(theme.FontColor.name())
new_theme.font_main_shadow = False
if theme.Shadow == 1:
new_theme.font_main_shadow = True
new_theme.font_main_shadow_color = str(theme.ShadowColor.name())
if theme.Outline == 1:
new_theme.font_main_outline = True
new_theme.font_main_outline_color = str(theme.OutlineColor.name())
vAlignCorrection = VerticalType.Top
if theme.VerticalAlign == 2:
vAlignCorrection = VerticalType.Middle
elif theme.VerticalAlign == 1:
vAlignCorrection = VerticalType.Bottom
new_theme.display_horizontal_align = theme.HorizontalAlign
new_theme.display_vertical_align = vAlignCorrection
return new_theme.extract_xml()
def _get_renderer(self): def _get_renderer(self):
""" """
Adds the Renderer to the class dynamically Adds the Renderer to the class dynamically

View File

@ -27,10 +27,12 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
""" """
The :mod:`~openlp.core.theme` module contains all the themeing functions used by The Theme Controller helps manages adding, deleteing and modifying of themes.
OpenLP when displaying a song or a scripture.
""" """
from openlp.core.theme.theme import Theme
__all__ = ['Theme'] class ThemeManagerHelper(object):
"""
Manages the non ui theme functions.
"""
pass

View File

@ -33,8 +33,8 @@ The Themes configuration tab
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, Settings, SettingsTab, UiStrings, translate from openlp.core.common import Settings, ThemeLevel, UiStrings, translate
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib import Registry, SettingsTab
from openlp.core.lib.ui import find_and_set_in_combo_box from openlp.core.lib.ui import find_and_set_in_combo_box

View File

@ -31,7 +31,8 @@ The Create/Edit theme wizard
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import UiStrings, build_icon, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets

View File

@ -32,9 +32,10 @@ The :mod:``wizard`` module provides generic wizard tools for OpenLP.
import logging import logging
import os import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import Registry, Settings, UiStrings, build_icon, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, build_icon
from openlp.core.lib.ui import add_welcome_page from openlp.core.lib.ui import add_welcome_page
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -37,11 +37,14 @@ import os
import re import re
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import sys import sys
import urllib.request, urllib.error, urllib.parse import urllib.request
import urllib.error
import urllib.parse
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from openlp.core.lib import Registry, Settings from openlp.core.common import AppLocation, Settings
from openlp.core.lib import Registry
if sys.platform != 'win32' and sys.platform != 'darwin': if sys.platform != 'win32' and sys.platform != 'darwin':
@ -51,7 +54,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
except ImportError: except ImportError:
XDG_BASE_AVAILABLE = False XDG_BASE_AVAILABLE = False
from openlp.core.lib import translate from openlp.core.common import translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
APPLICATION_VERSION = {} APPLICATION_VERSION = {}
@ -81,15 +84,6 @@ class VersionThread(QtCore.QThread):
Registry().execute('openlp_version_check', '%s' % version) Registry().execute('openlp_version_check', '%s' % version)
def _get_frozen_path(frozen_option, non_frozen_option):
"""
Return a path based on the system status.
"""
if hasattr(sys, 'frozen') and sys.frozen == 1:
return frozen_option
return non_frozen_option
def get_application_version(): def get_application_version():
""" """
Returns the application version of the running instance of OpenLP:: Returns the application version of the running instance of OpenLP::
@ -418,18 +412,17 @@ def get_natural_key(string):
""" """
key = DIGITS_OR_NONDIGITS.findall(string) key = DIGITS_OR_NONDIGITS.findall(string)
key = [int(part) if part.isdigit() else get_locale_key(part) for part in key] key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
# Python 3 does not support comparision of different types anymore. So make sure, that we do not compare str # Python 3 does not support comparison of different types anymore. So make sure, that we do not compare str
# and int. # and int.
if string[0].isdigit(): if string[0].isdigit():
return [b''] + key return [b''] + key
return key return key
from .applocation import AppLocation
from .languagemanager import LanguageManager from .languagemanager import LanguageManager
from .actions import ActionList from .actions import ActionList
__all__ = ['AppLocation', 'ActionList', 'LanguageManager', 'get_application_version', 'check_latest_version', __all__ = ['ActionList', 'LanguageManager', 'get_application_version', 'check_latest_version',
'add_actions', 'get_filesystem_encoding', 'get_web_page', 'get_uno_command', 'get_uno_instance', 'add_actions', 'get_filesystem_encoding', 'get_web_page', 'get_uno_command', 'get_uno_instance',
'delete_file', 'clean_filename', 'format_time', 'get_locale_key', 'get_natural_key'] 'delete_file', 'clean_filename', 'format_time', 'get_locale_key', 'get_natural_key']

View File

@ -34,7 +34,7 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Settings from openlp.core.common import Settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -35,8 +35,7 @@ import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.utils import AppLocation from openlp.core.common import AppLocation, Settings, translate
from openlp.core.lib import Settings, translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,7 +31,8 @@ import logging
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Plugin, Settings, StringContent, build_icon, translate from openlp.core.common import Settings, translate
from openlp.core.lib import Plugin, StringContent, build_icon
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import create_action, UiStrings from openlp.core.lib.ui import create_action, UiStrings
from openlp.core.lib.theme import VerticalType from openlp.core.lib.theme import VerticalType

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import build_icon, translate from openlp.core.common import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button, create_button_box from openlp.core.lib.ui import create_button, create_button_box

View File

@ -29,7 +29,7 @@
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.plugins.alerts.lib.db import AlertItem from openlp.plugins.alerts.lib.db import AlertItem
from .alertdialog import Ui_AlertDialog from .alertdialog import Ui_AlertDialog

View File

@ -35,7 +35,8 @@ import logging
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Registry, translate from openlp.core.common import translate
from openlp.core.lib import Registry
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import SettingsTab, Settings, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import SettingsTab
from openlp.core.lib.ui import create_valign_selection_widgets from openlp.core.lib.ui import create_valign_selection_widgets

View File

@ -48,6 +48,7 @@ __default_settings__ = {
'bibles/verse layout style': LayoutStyle.VersePerSlide, 'bibles/verse layout style': LayoutStyle.VersePerSlide,
'bibles/book name language': LanguageSelection.Bible, 'bibles/book name language': LanguageSelection.Bible,
'bibles/display brackets': DisplayStyle.NoBrackets, 'bibles/display brackets': DisplayStyle.NoBrackets,
'bibles/is verse number visible': True,
'bibles/display new chapter': False, 'bibles/display new chapter': False,
'bibles/second bibles': True, 'bibles/second bibles': True,
'bibles/advanced bible': '', 'bibles/advanced bible': '',
@ -66,6 +67,9 @@ __default_settings__ = {
class BiblePlugin(Plugin): class BiblePlugin(Plugin):
"""
The Bible plugin provides a plugin for managing and displaying Bibles.
"""
log.info('Bible Plugin loaded') log.info('Bible Plugin loaded')
def __init__(self): def __init__(self):
@ -73,13 +77,14 @@ class BiblePlugin(Plugin):
self.weight = -9 self.weight = -9
self.icon_path = ':/plugins/plugin_bibles.png' self.icon_path = ':/plugins/plugin_bibles.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)
self.manager = None self.manager = BibleManager(self)
def initialise(self): def initialise(self):
"""
Initialise the Bible plugin.
"""
log.info('bibles Initialising') log.info('bibles Initialising')
if self.manager is None: super(BiblePlugin, self).initialise()
self.manager = BibleManager(self)
Plugin.initialise(self)
self.import_bible_item.setVisible(True) self.import_bible_item.setVisible(True)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(self.import_bible_item, UiStrings().Import) action_list.add_action(self.import_bible_item, UiStrings().Import)
@ -106,7 +111,7 @@ class BiblePlugin(Plugin):
""" """
Perform tasks on application startup Perform tasks on application startup
""" """
Plugin.app_startup(self) super(BiblePlugin, self).app_startup()
if self.manager.old_bible_databases: if self.manager.old_bible_databases:
if QtGui.QMessageBox.information(self.main_window, if QtGui.QMessageBox.information(self.main_window,
translate('OpenLP', 'Information'), translate('OpenLP', 'Information'),

View File

@ -32,13 +32,13 @@ The bible import functions for OpenLP
import logging import logging
import os import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import Settings, UiStrings, translate from openlp.core.common import AppLocation, Settings, UiStrings, translate
from openlp.core.lib.db import delete_database from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, get_locale_key from openlp.core.utils import get_locale_key
from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.manager import BibleFormat
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename

View File

@ -36,10 +36,11 @@ from tempfile import gettempdir
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, Settings, UiStrings, translate, check_directory_exists from openlp.core.common import AppLocation, UiStrings, Settings, check_directory_exists, translate
from openlp.core.lib import Registry
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, delete_file from openlp.core.utils import delete_file
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract

View File

@ -29,7 +29,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box
class Ui_BookNameDialog(object): class Ui_BookNameDialog(object):

View File

@ -36,7 +36,7 @@ import re
from PyQt4.QtGui import QDialog from PyQt4.QtGui import QDialog
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.booknamedialog import Ui_BookNameDialog from openlp.plugins.bibles.forms.booknamedialog import Ui_BookNameDialog
from openlp.plugins.bibles.lib import BibleStrings from openlp.plugins.bibles.lib import BibleStrings

View File

@ -29,7 +29,8 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate from openlp.core.common import translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box
from openlp.plugins.bibles.lib import LanguageSelection, BibleStrings from openlp.plugins.bibles.lib import LanguageSelection, BibleStrings
from openlp.plugins.bibles.lib.db import BiblesResourcesDB from openlp.plugins.bibles.lib.db import BiblesResourcesDB

View File

@ -33,7 +33,8 @@ import re
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Registry, UiStrings, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import Registry
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from .editbibledialog import Ui_EditBibleDialog from .editbibledialog import Ui_EditBibleDialog
from openlp.plugins.bibles.lib import BibleStrings from openlp.plugins.bibles.lib import BibleStrings

View File

@ -29,7 +29,7 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box
class Ui_LanguageDialog(object): class Ui_LanguageDialog(object):

View File

@ -34,7 +34,7 @@ import logging
from PyQt4.QtGui import QDialog from PyQt4.QtGui import QDialog
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.languagedialog import \ from openlp.plugins.bibles.forms.languagedialog import \
Ui_LanguageDialog Ui_LanguageDialog

View File

@ -33,7 +33,8 @@ plugin.
import logging import logging
import re import re
from openlp.core.lib import Settings, translate from openlp.core.common import Settings
from openlp.core.lib import translate
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -31,7 +31,8 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, SettingsTab
from openlp.core.lib.ui import find_and_set_in_combo_box from openlp.core.lib.ui import find_and_set_in_combo_box
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \ from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \
get_reference_separator, LanguageSelection get_reference_separator, LanguageSelection
@ -58,6 +59,9 @@ class BiblesTab(SettingsTab):
self.verse_display_group_box.setObjectName('verse_display_group_box') self.verse_display_group_box.setObjectName('verse_display_group_box')
self.verse_display_layout = QtGui.QFormLayout(self.verse_display_group_box) self.verse_display_layout = QtGui.QFormLayout(self.verse_display_group_box)
self.verse_display_layout.setObjectName('verse_display_layout') self.verse_display_layout.setObjectName('verse_display_layout')
self.is_verse_number_visible_check_box = QtGui.QCheckBox(self.verse_display_group_box)
self.is_verse_number_visible_check_box.setObjectName('is_verse_number_visible_check_box')
self.verse_display_layout.addRow(self.is_verse_number_visible_check_box)
self.new_chapters_check_box = QtGui.QCheckBox(self.verse_display_group_box) self.new_chapters_check_box = QtGui.QCheckBox(self.verse_display_group_box)
self.new_chapters_check_box.setObjectName('new_chapters_check_box') self.new_chapters_check_box.setObjectName('new_chapters_check_box')
self.verse_display_layout.addRow(self.new_chapters_check_box) self.verse_display_layout.addRow(self.new_chapters_check_box)
@ -134,6 +138,7 @@ class BiblesTab(SettingsTab):
self.left_layout.addStretch() self.left_layout.addStretch()
self.right_layout.addStretch() self.right_layout.addStretch()
# Signals and slots # Signals and slots
self.is_verse_number_visible_check_box.stateChanged.connect(self.on_is_verse_number_visible_check_box_changed)
self.new_chapters_check_box.stateChanged.connect(self.on_new_chapters_check_box_changed) self.new_chapters_check_box.stateChanged.connect(self.on_new_chapters_check_box_changed)
self.display_style_combo_box.activated.connect(self.on_display_style_combo_box_changed) self.display_style_combo_box.activated.connect(self.on_display_style_combo_box_changed)
self.bible_theme_combo_box.activated.connect(self.on_bible_theme_combo_box_changed) self.bible_theme_combo_box.activated.connect(self.on_bible_theme_combo_box_changed)
@ -156,6 +161,7 @@ class BiblesTab(SettingsTab):
def retranslateUi(self): def retranslateUi(self):
self.verse_display_group_box.setTitle(translate('BiblesPlugin.BiblesTab', 'Verse Display')) self.verse_display_group_box.setTitle(translate('BiblesPlugin.BiblesTab', 'Verse Display'))
self.is_verse_number_visible_check_box.setText(translate('BiblesPlugin.BiblesTab', 'Show verse numbers'))
self.new_chapters_check_box.setText(translate('BiblesPlugin.BiblesTab', 'Only show new chapter numbers')) self.new_chapters_check_box.setText(translate('BiblesPlugin.BiblesTab', 'Only show new chapter numbers'))
self.layout_style_label.setText(UiStrings().LayoutStyle) self.layout_style_label.setText(UiStrings().LayoutStyle)
self.display_style_label.setText(UiStrings().DisplayStyle) self.display_style_label.setText(UiStrings().DisplayStyle)
@ -208,6 +214,13 @@ class BiblesTab(SettingsTab):
def on_language_selection_combo_box_changed(self): def on_language_selection_combo_box_changed(self):
self.language_selection = self.language_selection_combo_box.currentIndex() self.language_selection = self.language_selection_combo_box.currentIndex()
def on_is_verse_number_visible_check_box_changed(self, check_state):
"""
Event handler for the 'verse number visible' check box
"""
self.is_verse_number_visible = (check_state == QtCore.Qt.Checked)
self.check_is_verse_number_visible()
def on_new_chapters_check_box_changed(self, check_state): def on_new_chapters_check_box_changed(self, check_state):
self.show_new_chapters = False self.show_new_chapters = False
# We have a set value convert to True/False. # We have a set value convert to True/False.
@ -299,11 +312,14 @@ class BiblesTab(SettingsTab):
def load(self): def load(self):
settings = Settings() settings = Settings()
settings.beginGroup(self.settings_section) settings.beginGroup(self.settings_section)
self.is_verse_number_visible = settings.value('is verse number visible')
self.show_new_chapters = settings.value('display new chapter') self.show_new_chapters = settings.value('display new chapter')
self.display_style = settings.value('display brackets') self.display_style = settings.value('display brackets')
self.layout_style = settings.value('verse layout style') self.layout_style = settings.value('verse layout style')
self.bible_theme = settings.value('bible theme') self.bible_theme = settings.value('bible theme')
self.second_bibles = settings.value('second bibles') self.second_bibles = settings.value('second bibles')
self.is_verse_number_visible_check_box.setChecked(self.is_verse_number_visible)
self.check_is_verse_number_visible()
self.new_chapters_check_box.setChecked(self.show_new_chapters) self.new_chapters_check_box.setChecked(self.show_new_chapters)
self.display_style_combo_box.setCurrentIndex(self.display_style) self.display_style_combo_box.setCurrentIndex(self.display_style)
self.layout_style_combo_box.setCurrentIndex(self.layout_style) self.layout_style_combo_box.setCurrentIndex(self.layout_style)
@ -351,6 +367,7 @@ class BiblesTab(SettingsTab):
def save(self): def save(self):
settings = Settings() settings = Settings()
settings.beginGroup(self.settings_section) settings.beginGroup(self.settings_section)
settings.setValue('is verse number visible', self.is_verse_number_visible)
settings.setValue('display new chapter', self.show_new_chapters) settings.setValue('display new chapter', self.show_new_chapters)
settings.setValue('display brackets', self.display_style) settings.setValue('display brackets', self.display_style)
settings.setValue('verse layout style', self.layout_style) settings.setValue('verse layout style', self.layout_style)
@ -405,3 +422,12 @@ class BiblesTab(SettingsTab):
color.setAlpha(128) color.setAlpha(128)
palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color) palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
return palette return palette
def check_is_verse_number_visible(self):
"""
Enables / Disables verse settings dependent on is_verse_number_visible
"""
self.new_chapters_check_box.setEnabled(self.is_verse_number_visible)
self.display_style_label.setEnabled(self.is_verse_number_visible)
self.display_style_combo_box.setEnabled(self.is_verse_number_visible)

View File

@ -60,7 +60,7 @@ import logging
import chardet import chardet
import csv import csv
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB

View File

@ -38,10 +38,11 @@ from sqlalchemy import Column, ForeignKey, Table, or_, types, func
from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import Registry, translate from openlp.core.common import AppLocation, translate
from openlp.core.lib import Registry
from openlp.core.lib.db import BaseModel, init_db, Manager from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, clean_filename from openlp.core.utils import clean_filename
from . import upgrade from . import upgrade
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -38,7 +38,8 @@ from html.parser import HTMLParseError
from bs4 import BeautifulSoup, NavigableString, Tag from bs4 import BeautifulSoup, NavigableString, Tag
from openlp.core.lib import Registry, translate from openlp.core.common import translate
from openlp.core.lib import Registry
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import get_web_page from openlp.core.utils import get_web_page
from openlp.plugins.bibles.lib import SearchResults from openlp.plugins.bibles.lib import SearchResults

View File

@ -30,8 +30,9 @@
import logging import logging
import os import os
from openlp.core.lib import Registry, Settings, translate from openlp.core.common import AppLocation, Settings, translate
from openlp.core.utils import AppLocation, delete_file from openlp.core.lib import Registry
from openlp.core.utils import delete_file
from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
from .csvbible import CSVBible from .csvbible import CSVBible

View File

@ -31,8 +31,8 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \ from openlp.core.common import Settings, UiStrings, translate
create_separated_list, translate from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, create_separated_list
from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import set_case_insensitive_completer, create_horizontal_adjusting_combo_box, \ from openlp.core.lib.ui import set_case_insensitive_completer, create_horizontal_adjusting_combo_box, \
critical_error_message_box, find_and_set_in_combo_box, build_icon critical_error_message_box, find_and_set_in_combo_box, build_icon
@ -64,6 +64,11 @@ class BibleMediaItem(MediaManagerItem):
self.lock_icon = build_icon(':/bibles/bibles_search_lock.png') self.lock_icon = build_icon(':/bibles/bibles_search_lock.png')
self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png') self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png')
MediaManagerItem.__init__(self, parent, plugin) MediaManagerItem.__init__(self, parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
# Place to store the search results for both bibles. # Place to store the search results for both bibles.
self.settings = self.plugin.settings_tab self.settings = self.plugin.settings_tab
self.quick_preview_allowed = True self.quick_preview_allowed = True
@ -803,20 +808,20 @@ class BibleMediaItem(MediaManagerItem):
verses.add(book, chapter, verse, version, copyright, permissions) verses.add(book, chapter, verse, version, copyright, permissions)
verse_text = self.formatVerse(old_chapter, chapter, verse) verse_text = self.formatVerse(old_chapter, chapter, verse)
if second_bible: if second_bible:
bible_text = '%s&nbsp;%s\n\n%s&nbsp;%s' % (verse_text, text, verse_text, second_text) bible_text = '%s%s\n\n%s&nbsp;%s' % (verse_text, text, verse_text, second_text)
raw_slides.append(bible_text.rstrip()) raw_slides.append(bible_text.rstrip())
bible_text = '' bible_text = ''
# If we are 'Verse Per Slide' then create a new slide. # If we are 'Verse Per Slide' then create a new slide.
elif self.settings.layout_style == LayoutStyle.VersePerSlide: elif self.settings.layout_style == LayoutStyle.VersePerSlide:
bible_text = '%s&nbsp;%s' % (verse_text, text) bible_text = '%s%s' % (verse_text, text)
raw_slides.append(bible_text.rstrip()) raw_slides.append(bible_text.rstrip())
bible_text = '' bible_text = ''
# If we are 'Verse Per Line' then force a new line. # If we are 'Verse Per Line' then force a new line.
elif self.settings.layout_style == LayoutStyle.VersePerLine: elif self.settings.layout_style == LayoutStyle.VersePerLine:
bible_text = '%s%s&nbsp;%s\n' % (bible_text, verse_text, text) bible_text = '%s%s%s\n' % (bible_text, verse_text, text)
# We have to be 'Continuous'. # We have to be 'Continuous'.
else: else:
bible_text = '%s %s&nbsp;%s\n' % (bible_text, verse_text, text) bible_text = '%s %s%s\n' % (bible_text, verse_text, text)
bible_text = bible_text.strip(' ') bible_text = bible_text.strip(' ')
if not old_item: if not old_item:
start_item = bitem start_item = bitem
@ -943,17 +948,19 @@ class BibleMediaItem(MediaManagerItem):
The verse number (int). The verse number (int).
""" """
verse_separator = get_reference_separator('sep_v_display') verse_separator = get_reference_separator('sep_v_display')
if not self.settings.is_verse_number_visible:
return ''
if not self.settings.show_new_chapters or old_chapter != chapter: if not self.settings.show_new_chapters or old_chapter != chapter:
verse_text = str(chapter) + verse_separator + str(verse) verse_text = str(chapter) + verse_separator + str(verse)
else: else:
verse_text = str(verse) verse_text = str(verse)
if self.settings.display_style == DisplayStyle.Round: if self.settings.display_style == DisplayStyle.Round:
return '{su}(%s){/su}' % verse_text return '{su}(%s){/su}&nbsp;' % verse_text
if self.settings.display_style == DisplayStyle.Curly: if self.settings.display_style == DisplayStyle.Curly:
return '{su}{%s}{/su}' % verse_text return '{su}{%s}{/su}&nbsp;' % verse_text
if self.settings.display_style == DisplayStyle.Square: if self.settings.display_style == DisplayStyle.Square:
return '{su}[%s]{/su}' % verse_text return '{su}[%s]{/su}&nbsp;' % verse_text
return '{su}%s{/su}' % verse_text return '{su}%s{/su}&nbsp;' % verse_text
def search(self, string, showError): def search(self, string, showError):
""" """

View File

@ -30,7 +30,7 @@
import logging import logging
from lxml import etree, objectify from lxml import etree, objectify
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB

View File

@ -33,8 +33,7 @@ import chardet
import codecs import codecs
import re import re
from openlp.core.lib import translate from openlp.core.common import AppLocation, translate
from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -27,6 +27,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
class VerseReferenceList(object): class VerseReferenceList(object):
""" """
The VerseReferenceList class encapsulates a list of verse references, but maintains the order in which they were The VerseReferenceList class encapsulates a list of verse references, but maintains the order in which they were

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import UiStrings, build_icon, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import build_icon
from openlp.core.lib.ui import create_button_box, create_button from openlp.core.lib.ui import create_button_box, create_button

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import SpellTextEdit, UiStrings, translate from openlp.core.common import UiStrings, translate
from openlp.core.lib import SpellTextEdit
from openlp.core.lib.ui import create_button, create_button_box from openlp.core.lib.ui import create_button, create_button_box
class Ui_CustomSlideEditDialog(object): class Ui_CustomSlideEditDialog(object):

View File

@ -30,7 +30,7 @@
import logging import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from .editcustomslidedialog import Ui_CustomSlideEditDialog from .editcustomslidedialog import Ui_CustomSlideEditDialog

View File

@ -33,7 +33,8 @@ for the Custom Slides plugin, which is inserted into the configuration dialog.
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Settings, translate from openlp.core.common import Settings, translate
from openlp.core.lib import SettingsTab
class CustomTab(SettingsTab): class CustomTab(SettingsTab):

View File

@ -32,8 +32,9 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_, func, and_ from sqlalchemy.sql import or_, func, and_
from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, Settings, PluginStatus,\ from openlp.core.common import Settings, UiStrings, translate
UiStrings, check_item_selected, translate from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, PluginStatus,\
check_item_selected
from openlp.plugins.custom.forms.editcustomform import EditCustomForm from openlp.plugins.custom.forms.editcustomform import EditCustomForm
from openlp.plugins.custom.lib import CustomXMLParser, CustomXMLBuilder from openlp.plugins.custom.lib import CustomXMLParser, CustomXMLBuilder
from openlp.plugins.custom.lib.db import CustomSlide from openlp.plugins.custom.lib.db import CustomSlide
@ -58,6 +59,11 @@ class CustomMediaItem(MediaManagerItem):
def __init__(self, parent, plugin): def __init__(self, parent, plugin):
self.icon_path = 'custom/custom' self.icon_path = 'custom/custom'
super(CustomMediaItem, self).__init__(parent, plugin) super(CustomMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager) self.edit_custom_form = EditCustomForm(self, self.main_window, self.plugin.manager)
self.single_service_item = False self.single_service_item = False
self.quick_preview_allowed = True self.quick_preview_allowed = True
@ -65,7 +71,7 @@ class CustomMediaItem(MediaManagerItem):
# Holds information about whether the edit is remotely triggered and # Holds information about whether the edit is remotely triggered and
# which Custom is required. # which Custom is required.
self.remote_custom = -1 self.remote_custom = -1
self.manager = plugin.manager self.manager = self.plugin.manager
def add_end_header_bar(self): def add_end_header_bar(self):
self.toolbar.addSeparator() self.toolbar.addSeparator()

View File

@ -29,7 +29,7 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -29,7 +29,7 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.images.forms.addgroupdialog import Ui_AddGroupDialog from openlp.plugins.images.forms.addgroupdialog import Ui_AddGroupDialog

View File

@ -29,7 +29,7 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box from openlp.core.lib.ui import create_button_box

View File

@ -31,10 +31,11 @@ from PyQt4 import QtGui
import logging import logging
from openlp.core.lib import Plugin, StringContent, Registry, ImageSource, Settings, build_icon, translate from openlp.core.common import Settings, translate
from openlp.core.lib import Plugin, StringContent, Registry, ImageSource, build_icon
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.plugins.images.lib import ImageMediaItem, ImageTab from openlp.plugins.images.lib import ImageMediaItem, ImageTab
from openlp.plugins.images.lib.db import init_schema, ImageFilenames from openlp.plugins.images.lib.db import init_schema
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Registry, SettingsTab, Settings, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import SettingsTab
class ImageTab(SettingsTab): class ImageTab(SettingsTab):

View File

@ -32,11 +32,11 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import ItemCapabilities, MediaManagerItem, Registry, ServiceItemContext, Settings, \ from openlp.core.common import AppLocation, Settings, UiStrings, check_directory_exists, translate
StringContent, TreeWidgetWithDnD, UiStrings, build_icon, check_directory_exists, check_item_selected, \ from openlp.core.lib import ItemCapabilities, MediaManagerItem, Registry, ServiceItemContext, \
create_thumb, translate, validate_thumb StringContent, TreeWidgetWithDnD, build_icon, check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.ui import create_widget_action, critical_error_message_box from openlp.core.lib.ui import create_widget_action, critical_error_message_box
from openlp.core.utils import AppLocation, delete_file, get_locale_key, get_images_filter from openlp.core.utils import delete_file, get_locale_key, get_images_filter
from openlp.plugins.images.forms import AddGroupForm, ChooseGroupForm from openlp.plugins.images.forms import AddGroupForm, ChooseGroupForm
from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups
@ -52,10 +52,18 @@ class ImageMediaItem(MediaManagerItem):
def __init__(self, parent, plugin): def __init__(self, parent, plugin):
self.icon_path = 'images/image' self.icon_path = 'images/image'
self.manager = None
self.choose_group_form = None
self.add_group_form = None
super(ImageMediaItem, self).__init__(parent, plugin) super(ImageMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.quick_preview_allowed = True self.quick_preview_allowed = True
self.has_search = True self.has_search = True
self.manager = plugin.manager self.manager = self.plugin.manager
self.choose_group_form = ChooseGroupForm(self) self.choose_group_form = ChooseGroupForm(self)
self.add_group_form = AddGroupForm(self) self.add_group_form = AddGroupForm(self)
self.fill_groups_combobox(self.choose_group_form.group_combobox) self.fill_groups_combobox(self.choose_group_form.group_combobox)
@ -91,8 +99,8 @@ class ImageMediaItem(MediaManagerItem):
self.list_view.setIconSize(QtCore.QSize(88, 50)) self.list_view.setIconSize(QtCore.QSize(88, 50))
self.list_view.setIndentation(self.list_view.default_indentation) self.list_view.setIndentation(self.list_view.default_indentation)
self.list_view.allow_internal_dnd = True self.list_view.allow_internal_dnd = True
self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails')
check_directory_exists(self.servicePath) check_directory_exists(self.service_path)
# Load images from the database # Load images from the database
self.load_full_list( self.load_full_list(
self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), initial_load=True) self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), initial_load=True)
@ -193,7 +201,7 @@ class ImageMediaItem(MediaManagerItem):
""" """
images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id) images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
for image in images: for image in images:
delete_file(os.path.join(self.servicePath, os.path.split(image.filename)[1])) delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
self.manager.delete_object(ImageFilenames, image.id) self.manager.delete_object(ImageFilenames, image.id)
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id) image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
for group in image_groups: for group in image_groups:
@ -215,7 +223,7 @@ class ImageMediaItem(MediaManagerItem):
if row_item: if row_item:
item_data = row_item.data(0, QtCore.Qt.UserRole) item_data = row_item.data(0, QtCore.Qt.UserRole)
if isinstance(item_data, ImageFilenames): if isinstance(item_data, ImageFilenames):
delete_file(os.path.join(self.servicePath, row_item.text(0))) delete_file(os.path.join(self.service_path, row_item.text(0)))
if item_data.group_id == 0: if item_data.group_id == 0:
self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item)) self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
else: else:
@ -339,7 +347,7 @@ class ImageMediaItem(MediaManagerItem):
for imageFile in images: for imageFile in images:
log.debug('Loading image: %s', imageFile.filename) log.debug('Loading image: %s', imageFile.filename)
filename = os.path.split(imageFile.filename)[1] filename = os.path.split(imageFile.filename)[1]
thumb = os.path.join(self.servicePath, filename) thumb = os.path.join(self.service_path, filename)
if not os.path.exists(imageFile.filename): if not os.path.exists(imageFile.filename):
icon = build_icon(':/general/general_delete.png') icon = build_icon(':/general/general_delete.png')
else: else:
@ -672,7 +680,16 @@ class ImageMediaItem(MediaManagerItem):
translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, ' translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, '
'the image file "%s" no longer exists.') % filename) 'the image file "%s" no longer exists.') % filename)
def search(self, string, showError): def search(self, string, show_error=True):
"""
Perform a search on the image file names.
``string``
The glob to search for
``show_error``
Unused.
"""
files = self.manager.get_all_objects(ImageFilenames, filter_clause=ImageFilenames.filename.contains(string), files = self.manager.get_all_objects(ImageFilenames, filter_clause=ImageFilenames.filename.contains(string),
order_by_ref=ImageFilenames.filename) order_by_ref=ImageFilenames.filename)
results = [] results = []

View File

@ -32,12 +32,13 @@ import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.common import AppLocation, Settings, check_directory_exists, UiStrings, translate
from openlp.core.lib import ItemCapabilities, MediaManagerItem,MediaType, Registry, ServiceItem, ServiceItemContext, \ from openlp.core.lib import ItemCapabilities, MediaManagerItem,MediaType, Registry, ServiceItem, ServiceItemContext, \
Settings, UiStrings, build_icon, check_item_selected, check_directory_exists, translate build_icon, check_item_selected
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
from openlp.core.ui import DisplayController, Display, DisplayControllerType from openlp.core.ui import DisplayController, Display, DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players from openlp.core.ui.media import get_media_players, set_media_players
from openlp.core.utils import AppLocation, get_locale_key from openlp.core.utils import get_locale_key
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -61,10 +62,15 @@ class MediaMediaItem(MediaManagerItem):
self.background = False self.background = False
self.automatic = '' self.automatic = ''
super(MediaMediaItem, self).__init__(parent, plugin) super(MediaMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.single_service_item = False self.single_service_item = False
self.has_search = True self.has_search = True
self.media_object = None self.media_object = None
self.display_controller = DisplayController(parent) self.display_controller = DisplayController(self.parent())
self.display_controller.controller_layout = QtGui.QVBoxLayout() self.display_controller.controller_layout = QtGui.QVBoxLayout()
self.media_controller.register_controller(self.display_controller) self.media_controller.register_controller(self.display_controller)
self.media_controller.set_controls_visible(self.display_controller, False) self.media_controller.set_controls_visible(self.display_controller, False)

View File

@ -29,7 +29,8 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Settings, SettingsTab, UiStrings, translate from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import SettingsTab
class MediaQ_check_box(QtGui.QCheckBox): class MediaQ_check_box(QtGui.QCheckBox):

Some files were not shown because too many files have changed in this diff Show More