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 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.ui.mainwindow import MainWindow
from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
from openlp.core.ui.firsttimeform import FirstTimeForm
from openlp.core.ui.exceptionform import ExceptionForm
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']

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 #
###############################################################################
"""
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 os
import sys
from openlp.core.lib import Settings
from openlp.core.utils import _get_frozen_path
from openlp.core.common import Settings
if sys.platform != 'win32' and sys.platform != 'darwin':
@ -45,7 +44,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
XDG_BASE_AVAILABLE = False
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__)
@ -74,15 +73,15 @@ class AppLocation(object):
The directory type you want, for instance the data directory. Default *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:
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'))
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:
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')
elif dir_type == AppLocation.DataDir and AppLocation.BaseDir:
return os.path.join(AppLocation.BaseDir, 'data')
@ -171,4 +170,3 @@ def _get_os_dir_path(dir_type):
if dir_type == AppLocation.DataDir:
return os.path.join(str(os.getenv('HOME')), '.openlp', 'data')
return os.path.join(str(os.getenv('HOME')), '.openlp')

View File

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

View File

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

View File

@ -37,6 +37,8 @@ import os
from PyQt4 import QtCore, QtGui, Qt
from openlp.core.common import translate
log = logging.getLogger(__name__)
@ -72,16 +74,6 @@ class MediaType(object):
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):
"""
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
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):
"""
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
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 create_separated_list(stringlist):
def create_separated_list(string_list):
"""
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
http://www.unicode.org/reports/tr35/#ListPatterns
``stringlist``
``string_list``
List of unicode strings
"""
if LooseVersion(Qt.PYQT_VERSION_STR) >= LooseVersion('4.9') and \
LooseVersion(Qt.qVersion()) >= LooseVersion('4.8'):
return QtCore.QLocale().createSeparatedList(stringlist)
if not stringlist:
return QtCore.QLocale().createSeparatedList(string_list)
if not string_list:
return ''
elif len(stringlist) == 1:
return stringlist[0]
elif len(stringlist) == 2:
elif len(string_list) == 1:
return string_list[0]
elif len(string_list) == 2:
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:
merged = translate('OpenLP.core.lib', '%s, and %s',
'Locale list separator: end') % (stringlist[-2], stringlist[-1])
for index in reversed(list(range(1, len(stringlist) - 2))):
'Locale list separator: end') % (string_list[-2], string_list[-1])
for index in reversed(list(range(1, len(string_list) - 2))):
merged = translate('OpenLP.core.lib', '%s, %s',
'Locale list separator: middle') % (stringlist[index], merged)
return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (stringlist[0], merged)
'Locale list separator: middle') % (string_list[index], merged)
return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (string_list[0], merged)
from .registry import Registry
from .uistrings import UiStrings
from .screen import ScreenList
from .settings import Settings
from .listwidgetwithdnd import ListWidgetWithDnD
from .treewidgetwithdnd import TreeWidgetWithDnD
from .formattingtags import FormattingTags

View File

@ -41,9 +41,9 @@ from sqlalchemy.pool import NullPool
from alembic.migration import MigrationContext
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.utils import AppLocation, delete_file
from openlp.core.utils import delete_file
log = logging.getLogger(__name__)

View File

@ -31,12 +31,13 @@ Provide HTML Tag management and Formatting Tag access class
"""
import json
from openlp.core.lib import Settings, translate
from openlp.core.common import Settings
from openlp.core.lib import translate
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 = []
@ -48,22 +49,15 @@ class FormattingTags(object):
return FormattingTags.html_expands
@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.
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
def load_tags():

View File

@ -26,7 +26,372 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# 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
from PyQt4 import QtWebKit
@ -114,12 +479,6 @@ sup {
document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').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;
}
@ -138,9 +497,6 @@ sup {
*/
var txt = document.getElementById('lyricsmain');
if(window.getComputedStyle(txt).textAlign == 'justify'){
var outline = document.getElementById('lyricsoutline');
if(outline != null)
txt = outline;
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
function(match) {
@ -150,8 +506,6 @@ sup {
}
}
text_fade('lyricsmain', new_text);
text_fade('lyricsoutline', new_text);
text_fade('lyricsshadow', new_text.replace(match, ''));
}
function text_fade(id, new_text){
@ -190,7 +544,7 @@ sup {
<img id="bgimage" class="size" %s />
<img id="image" class="size" %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="black" class="size"></div>
</body>
@ -222,8 +576,7 @@ def build_html(item, screen, is_live, background, image=None, plugins=None):
"""
width = screen['size'].width()
height = screen['size'].height()
theme = item.themedata
webkit_ver = webkit_version()
theme_data = item.themedata
# Image generated and poked in
if 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),
css_additions,
build_footer_css(item, height),
build_lyrics_css(item, webkit_ver),
'true' if theme and theme.display_slide_transition and is_live else 'false',
build_lyrics_css(item),
'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
js_additions,
bgimage_src, image_src,
html_additions,
build_lyrics_html(item, webkit_ver)
bgimage_src,
image_src,
html_additions
)
return html
@ -303,16 +656,13 @@ def build_background_css(item, width):
return background
def build_lyrics_css(item, webkit_ver):
def build_lyrics_css(item):
"""
Build the lyrics display css
``item``
Service Item containing theme and location information
``webkitvers``
The version of qtwebkit we're using
"""
style = """
.lyricstable {
@ -328,81 +678,44 @@ def build_lyrics_css(item, webkit_ver):
%s
}
.lyricsmain {
%s
%s
}
.lyricsoutline {
%s
}
.lyricsshadow {
%s
}
"""
theme = item.themedata
"""
theme_data = item.themedata
lyricstable = ''
lyrics = ''
lyricsmain = ''
outline = ''
shadow = ''
if theme and item.main:
if theme_data and item.main:
lyricstable = 'left: %spx; top: %spx;' % (item.main.x(), item.main.y())
lyrics = build_lyrics_format_css(theme, item.main.width(), item.main.height())
# For performance reasons we want to show as few DIV's as possible, especially when animating/transitions.
# However some bugs in older versions of qtwebkit mean we need to perform workarounds and add extra divs. Only
# do these when needed.
#
# Before 533.3 the webkit-text-fill colour wasn't displayed, only the stroke (outline) color. So put stroke
# 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)
lyrics = build_lyrics_format_css(theme_data, item.main.width(), item.main.height())
lyricsmain += build_lyrics_outline_css(theme_data)
if theme_data.font_main_shadow:
lyricsmain += ' text-shadow: %s %spx %spx;' % \
(theme_data.font_main_shadow_color, theme_data.font_main_shadow_size, theme_data.font_main_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain)
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
``theme``
``theme_data``
Object containing theme information
``is_shadow``
If true, use the shadow colors instead
"""
if theme.font_main_outline:
size = float(theme.font_main_outline_size) / 16
if is_shadow:
fill_color = theme.font_main_shadow_color
outline_color = theme.font_main_shadow_color
else:
fill_color = theme.font_main_color
outline_color = theme.font_main_outline_color
if theme_data.font_main_outline:
size = float(theme_data.font_main_outline_size) / 16
fill_color = theme_data.font_main_color
outline_color = theme_data.font_main_outline_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
``theme``
``theme_data``
Object containing theme information
``width``
@ -411,17 +724,17 @@ def build_lyrics_format_css(theme, width, height):
``height``
Height of the lyrics block
"""
align = HorizontalType.Names[theme.display_horizontal_align]
valign = VerticalType.Names[theme.display_vertical_align]
if theme.font_main_outline:
left_margin = int(theme.font_main_outline_size) * 2
align = HorizontalType.Names[theme_data.display_horizontal_align]
valign = VerticalType.Names[theme_data.display_vertical_align]
if theme_data.font_main_outline:
left_margin = int(theme_data.font_main_outline_size) * 2
else:
left_margin = 0
justify = 'white-space:pre-wrap;'
# fix tag incompatibilities
if theme.display_horizontal_align == HorizontalType.Justify:
if theme_data.display_horizontal_align == HorizontalType.Justify:
justify = ''
if theme.display_vertical_align == VerticalType.Bottom:
if theme_data.display_vertical_align == VerticalType.Bottom:
padding_bottom = '0.5em'
else:
padding_bottom = '0'
@ -429,41 +742,13 @@ def build_lyrics_format_css(theme, width, height):
'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx; height: %spx; ' % \
(justify, align, valign, theme.font_main_name, theme.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment), padding_bottom, left_margin, width, height)
if theme.font_main_outline:
if webkit_version() <= 534.3:
lyrics += ' letter-spacing: 1px;'
if theme.font_main_italics:
lyrics += ' font-style:italic; '
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>'
(justify, align, valign, theme_data.font_main_name, theme_data.font_main_size,
theme_data.font_main_color, 100 + int(theme_data.font_main_line_adjustment), padding_bottom,
left_margin, width, height)
if theme_data.font_main_italics:
lyrics += 'font-style:italic; '
if theme_data.font_main_bold:
lyrics += 'font-weight:bold; '
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 openlp.core.common import Settings, UiStrings, translate
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.ui import create_widget_action, critical_error_message_box
@ -82,10 +83,17 @@ class MediaManagerItem(QtGui.QWidget):
"""
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.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin
visible_title = self.plugin.get_string(StringContent.VisibleName)
self.title = str(visible_title['title'])
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_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):
"""
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 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
log = logging.getLogger(__name__)

View File

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

View File

@ -31,9 +31,10 @@ import logging
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
from openlp.core.lib.theme import ThemeLevel
from openlp.core.common import ThemeLevel
from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__)

View File

@ -36,7 +36,8 @@ import copy
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__)
@ -244,7 +245,6 @@ class ScreenList(object):
"""
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.
# Do not do this anywhere else.
screen_settings = {

View File

@ -39,7 +39,8 @@ import uuid
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__)

View File

@ -32,69 +32,16 @@ Provide the theme XML and handling functions for OpenLP v2 themes.
import os
import re
import logging
import json
from xml.dom.minidom import Document
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__)
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):
"""
@ -217,9 +164,32 @@ class ThemeXML(object):
"""
Initialise the theme object.
"""
# Create the minidom document
self.theme_xml = Document()
self.parse_xml(BLANK_THEME_XML)
# basic theme object with defaults
json_dir = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'core', 'lib', 'json')
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):
"""

View File

@ -33,7 +33,8 @@ import logging
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

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 .settingsform import SettingsForm
from .formattingtagform import FormattingTagForm
from .formattingtagcontroller import FormattingTagController
from .shortcutlistform import ShortcutListForm
from .mediadockmanager import MediaDockManager
from .servicemanager import ServiceManager
from .thememanagerhelper import ThemeManagerHelper
from .thememanager import ThemeManager
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager',
'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm',
'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm',
'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm',
'FormattingTagForm', 'ShortcutListForm']
'FormattingTagForm', 'ShortcutListForm', 'FormattingTagController', 'ThemeManagerHelper']

View File

@ -29,7 +29,8 @@
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

View File

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

View File

@ -75,12 +75,6 @@ try:
ICU_VERSION = 'OK'
except ImportError:
ICU_VERSION = '-'
try:
import cherrypy
CHERRYPY_VERSION = cherrypy.__version__
except ImportError:
CHERRYPY_VERSION = '-'
try:
WEBKIT_VERSION = QtWebKit.qWebKitVersion()
except AttributeError:
@ -91,7 +85,7 @@ try:
except ImportError:
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 .exceptiondialog import Ui_ExceptionDialog
@ -140,7 +134,6 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
'Chardet: %s\n' % CHARDET_VERSION + \
'PyEnchant: %s\n' % ENCHANT_VERSION + \
'Mako: %s\n' % MAKO_VERSION + \
'CherryPy: %s\n' % CHERRYPY_VERSION + \
'pyICU: %s\n' % ICU_VERSION + \
'pyUNO bridge: %s\n' % self._pyuno_import() + \
'VLC: %s\n' % VLC_VERSION

View File

@ -34,7 +34,8 @@ from PyQt4 import QtGui
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):

View File

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

View File

@ -31,7 +31,7 @@ The UI widgets of the language selection dialog.
"""
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

View File

@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
import sys
from openlp.core.lib import translate
from openlp.core.common import translate
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 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
@ -45,12 +46,34 @@ class Ui_FormattingTagDialog(object):
"""
formatting_tag_dialog.setObjectName('formatting_tag_dialog')
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.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.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.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.tag_table_widget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
@ -67,59 +90,26 @@ class Ui_FormattingTagDialog(object):
self.tag_table_widget.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tag_table_widget.setHorizontalHeaderItem(3, item)
self.list_data_grid_layout.addWidget(self.tag_table_widget, 0, 0, 1, 1)
self.horizontal_layout = QtGui.QHBoxLayout()
self.horizontal_layout.setObjectName('horizontal_layout')
spacer_item = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontal_layout.addItem(spacer_item)
self.delete_push_button = QtGui.QPushButton(formatting_tag_dialog)
self.delete_push_button.setObjectName('delete_push_button')
self.horizontal_layout.addWidget(self.delete_push_button)
self.list_data_grid_layout.addLayout(self.horizontal_layout, 1, 0, 1, 1)
self.edit_group_box = QtGui.QGroupBox(formatting_tag_dialog)
self.edit_group_box.setObjectName('edit_group_box')
self.data_grid_layout = QtGui.QGridLayout(self.edit_group_box)
self.data_grid_layout.setObjectName('data_grid_layout')
self.description_label = QtGui.QLabel(self.edit_group_box)
self.description_label.setAlignment(QtCore.Qt.AlignCenter)
self.description_label.setObjectName('description_label')
self.data_grid_layout.addWidget(self.description_label, 0, 0, 1, 1)
self.description_line_edit = QtGui.QLineEdit(self.edit_group_box)
self.description_line_edit.setObjectName('description_line_edit')
self.data_grid_layout.addWidget(self.description_line_edit, 0, 1, 2, 1)
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.list_data_grid_layout.addWidget(self.tag_table_widget)
self.edit_button_layout = QtGui.QHBoxLayout()
self.new_button = QtGui.QPushButton(formatting_tag_dialog)
self.new_button.setIcon(build_icon(':/general/general_new.png'))
self.new_button.setObjectName('new_button')
self.edit_button_layout.addWidget(self.new_button)
self.delete_button = QtGui.QPushButton(formatting_tag_dialog)
self.delete_button.setIcon(build_icon(':/general/general_delete.png'))
self.delete_button.setObjectName('delete_button')
self.edit_button_layout.addWidget(self.delete_button)
self.edit_button_layout.addStretch()
self.list_data_grid_layout.addLayout(self.edit_button_layout)
self.button_box = create_button_box(formatting_tag_dialog, 'button_box',
['cancel', 'save', 'defaults'])
self.save_button = self.button_box.button(QtGui.QDialogButtonBox.Save)
self.save_button.setObjectName('save_button')
self.restore_button = self.button_box.button(QtGui.QDialogButtonBox.RestoreDefaults)
self.restore_button.setIcon(build_icon(':/general/general_revert.png'))
self.restore_button.setObjectName('restore_button')
self.list_data_grid_layout.addWidget(self.button_box)
self.retranslateUi(formatting_tag_dialog)
def retranslateUi(self, formatting_tag_dialog):
@ -127,14 +117,19 @@ class Ui_FormattingTagDialog(object):
Translate the UI on the fly
"""
formatting_tag_dialog.setWindowTitle(translate('OpenLP.FormattingTagDialog', 'Configure Formatting Tags'))
self.edit_group_box.setTitle(translate('OpenLP.FormattingTagDialog', 'Edit Selection'))
self.save_push_button.setText(translate('OpenLP.FormattingTagDialog', 'Save'))
self.description_label.setText(translate('OpenLP.FormattingTagDialog', 'Description'))
self.tag_label.setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
self.start_tag_label.setText(translate('OpenLP.FormattingTagDialog', 'Start HTML'))
self.end_tag_label.setText(translate('OpenLP.FormattingTagDialog', 'End HTML'))
self.delete_push_button.setText(UiStrings().Delete)
self.new_push_button.setText(UiStrings().New)
self.delete_button.setText(UiStrings().Delete)
self.new_button.setText(UiStrings().New)
self.tag_table_widget_read_label.setText(translate('OpenLP.FormattingTagDialog', 'Default Formatting'))
self.tag_table_widget_read.horizontalHeaderItem(0).\
setText(translate('OpenLP.FormattingTagDialog', 'Description'))
self.tag_table_widget_read.horizontalHeaderItem(1).setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
self.tag_table_widget_read.horizontalHeaderItem(2).\
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(1).setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
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.
Base Tags cannot be changed.
"""
from PyQt4 import QtGui
from openlp.core.lib import FormattingTags, translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.common import translate
from openlp.core.lib import FormattingTags
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 .
"""
@ -48,17 +60,17 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
"""
super(FormattingTagForm, self).__init__(parent)
self.setupUi(self)
self.services = FormattingTagController()
self.tag_table_widget.itemSelectionChanged.connect(self.on_row_selected)
self.new_push_button.clicked.connect(self.on_new_clicked)
self.save_push_button.clicked.connect(self.on_saved_clicked)
self.delete_push_button.clicked.connect(self.on_delete_clicked)
self.new_button.clicked.connect(self.on_new_clicked)
#self.save_button.clicked.connect(self.on_saved_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.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.
FormattingTags.load_tags()
self.is_deleting = False
self.reloading = False
def exec_(self):
"""
@ -66,138 +78,128 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
"""
# Create initial copy from master
self._reloadTable()
self.selected = -1
return QtGui.QDialog.exec_(self)
def on_row_selected(self):
"""
Table Row selected so display items and set field state.
"""
self.save_push_button.setEnabled(False)
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)
self.delete_button.setEnabled(True)
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():
if self._strip(html['start tag']) == 'n':
critical_error_message_box(
translate('OpenLP.FormattingTagForm', 'Update Error'),
translate('OpenLP.FormattingTagForm', 'Tag "n" already defined.'))
return
# Add new tag to list
tag = {
'desc': translate('OpenLP.FormattingTagForm', 'New Tag'),
'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()
new_row = self.tag_table_widget.rowCount()
self.tag_table_widget.insertRow(new_row)
self.tag_table_widget.setItem(new_row, 0,
QtGui.QTableWidgetItem(translate('OpenLP.FormattingTagForm', 'New Tag%s') % str(new_row)))
self.tag_table_widget.setItem(new_row, 1, QtGui.QTableWidgetItem('n%s' % str(new_row)))
self.tag_table_widget.setItem(new_row, 2,
QtGui.QTableWidgetItem(translate('OpenLP.FormattingTagForm', '<HTML here>')))
self.tag_table_widget.setItem(new_row, 3, QtGui.QTableWidgetItem(''))
self.tag_table_widget.resizeRowsToContents()
self.tag_table_widget.scrollToBottom()
self.tag_table_widget.selectRow(new_row)
def on_delete_clicked(self):
"""
Delete selected custom tag.
Delete selected custom row.
"""
if self.selected != -1:
FormattingTags.remove_html_tag(self.selected)
# As the first items are protected we should not have to take care
# of negative indexes causing tracebacks.
self.tag_table_widget.selectRow(self.selected - 1)
self.selected = -1
FormattingTags.save_html_tags()
self._reloadTable()
selected = self.tag_table_widget.currentRow()
if selected != -1:
self.is_deleting = True
self.tag_table_widget.removeRow(selected)
def on_saved_clicked(self):
def accept(self):
"""
Update Custom Tag details if not duplicate and save the data.
"""
html_expands = FormattingTags.get_html_tags()
if self.selected != -1:
html = html_expands[self.selected]
tag = self.tag_line_edit.text()
for linenumber, html1 in enumerate(html_expands):
if self._strip(html1['start tag']) == tag and linenumber != self.selected:
critical_error_message_box(
translate('OpenLP.FormattingTagForm', 'Update Error'),
translate('OpenLP.FormattingTagForm', 'Tag %s already defined.') % tag)
return
html['desc'] = self.description_line_edit.text()
html['start html'] = self.start_tag_line_edit.text()
html['end html'] = self.end_tag_line_edit.text()
html['start tag'] = '{%s}' % tag
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()
count = 0
self.services.pre_save()
while count < self.tag_table_widget.rowCount():
error = self.services.validate_for_save(self.tag_table_widget.item(count, 0).text(),
self.tag_table_widget.item(count, 1).text(), self.tag_table_widget.item(count, 2).text(),
self.tag_table_widget.item(count, 3).text())
if error:
QtGui.QMessageBox.warning(self,
translate('OpenLP.FormattingTagForm', 'Validation Error'), error, QtGui.QMessageBox.Ok)
self.tag_table_widget.selectRow(count)
return
count += 1
self.services.save_tags()
QtGui.QDialog.accept(self)
def _reloadTable(self):
"""
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.setRowCount(0)
self.new_push_button.setEnabled(True)
self.save_push_button.setEnabled(False)
self.delete_push_button.setEnabled(False)
self.new_button.setEnabled(True)
self.delete_button.setEnabled(False)
for linenumber, html in enumerate(FormattingTags.get_html_tags()):
self.tag_table_widget.setRowCount(self.tag_table_widget.rowCount() + 1)
self.tag_table_widget.setItem(linenumber, 0, QtGui.QTableWidgetItem(html['desc']))
self.tag_table_widget.setItem(linenumber, 1, QtGui.QTableWidgetItem(self._strip(html['start tag'])))
self.tag_table_widget.setItem(linenumber, 2, QtGui.QTableWidgetItem(html['start html']))
self.tag_table_widget.setItem(linenumber, 3, QtGui.QTableWidgetItem(html['end html']))
# Permanent (persistent) tags do not have this key.
if 'temporary' not in html:
if html['protected']:
line = self.tag_table_widget_read.rowCount()
self.tag_table_widget_read.setRowCount(line + 1)
self.tag_table_widget_read.setItem(line, 0, QtGui.QTableWidgetItem(html['desc']))
self.tag_table_widget_read.setItem(line, 1, QtGui.QTableWidgetItem(self._strip(html['start tag'])))
self.tag_table_widget_read.setItem(line, 2, QtGui.QTableWidgetItem(html['start 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
self.tag_table_widget.resizeRowsToContents()
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)
self.reloading = 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('{', '')
tag = tag.replace('}', '')
return tag
if self.is_deleting:
self.is_deleting = False
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 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__)

View File

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

View File

@ -42,12 +42,14 @@ from datetime import datetime
from PyQt4 import QtCore, QtGui
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.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
MediaDockManager, ShortcutListForm, FormattingTagForm
from openlp.core.common import AppLocation, Settings, check_directory_exists, translate
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.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
from openlp.core.lib import Settings
from openlp.core.common import Settings
from PyQt4 import QtCore

View File

@ -35,11 +35,12 @@ import os
import datetime
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.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
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
log = logging.getLogger(__name__)

View File

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

View File

@ -37,7 +37,8 @@ import sys
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.mediaplayer import MediaPlayer

View File

@ -33,7 +33,8 @@ from PyQt4 import QtGui
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.mediaplayer import MediaPlayer

View File

@ -31,7 +31,7 @@ The UI widgets of the plugin view dialog
#"""
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

View File

@ -34,7 +34,8 @@ import os
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
log = logging.getLogger(__name__)

View File

@ -31,7 +31,8 @@ The UI widgets of the print service dialog.
"""
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):

View File

@ -36,9 +36,10 @@ import os
from PyQt4 import QtCore, QtGui
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.utils import AppLocation
from openlp.core.common import AppLocation
DEFAULT_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 openlp.core.lib import translate
from openlp.core.common import translate
from openlp.core.lib.ui import create_button_box, create_button

View File

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

View File

@ -42,13 +42,12 @@ log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, Settings, PluginStatus, Registry, \
UiStrings, build_icon, translate, str_to_bool, check_directory_exists
from openlp.core.lib.theme import ThemeLevel
from openlp.core.common import AppLocation, Settings, ThemeLevel, check_directory_exists, UiStrings, translate
from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, Registry, build_icon
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.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

View File

@ -31,7 +31,8 @@ The :mod:`~openlp.core.ui.servicenoteform` module contains the `ServiceNoteForm`
"""
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

View File

@ -31,7 +31,8 @@ The UI widgets of the settings dialog.
"""
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

View File

@ -31,7 +31,8 @@ The list of shortcuts within a dialog.
"""
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

View File

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

View File

@ -37,8 +37,9 @@ from collections import deque
from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \
ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate
from openlp.core.common import Settings, SlideLimits, UiStrings, 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.lib.ui import create_action
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 openlp.core.lib import UiStrings, translate
from openlp.core.common import UiStrings, translate
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 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

View File

@ -34,7 +34,8 @@ import os
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.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm

View File

@ -31,7 +31,7 @@ The layout of the theme
"""
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

View File

@ -38,18 +38,18 @@ import re
from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtCore, QtGui
from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, Settings, UiStrings, get_text_file_string, \
build_icon, translate, check_item_selected, check_directory_exists, create_thumb, validate_thumb
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType
from openlp.core.common import AppLocation, Settings, check_directory_exists, UiStrings, translate
from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, get_text_file_string, build_icon, \
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.theme import Theme
from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.utils import AppLocation, delete_file, get_locale_key, get_filesystem_encoding
from openlp.core.ui import FileRenameForm, ThemeForm, ThemeManagerHelper
from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding
log = logging.getLogger(__name__)
class ThemeManager(QtGui.QWidget):
class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
"""
Manages the orders of Theme.
"""
@ -328,8 +328,8 @@ class ThemeManager(QtGui.QWidget):
try:
encoding = get_filesystem_encoding()
shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
except OSError as xxx_todo_changeme1:
shutil.Error = xxx_todo_changeme1
except OSError as os_error:
shutil.Error = os_error
log.exception('Error deleting theme %s', theme)
def on_export_theme(self):
@ -469,7 +469,7 @@ class ThemeManager(QtGui.QWidget):
log.debug('No theme data - using default theme')
return ThemeXML()
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):
"""
@ -501,35 +501,30 @@ class ThemeManager(QtGui.QWidget):
log.exception('Theme contains "%s" XML files' % len(xml_file))
raise Exception('validation')
xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot()
v1_background = xml_tree.find('BackgroundType')
if v1_background is not None:
theme_name, file_xml, out_file, abort_import = \
self.unzip_version_122(directory, theme_zip, xml_file[0], xml_tree, v1_background, out_file)
theme_name = xml_tree.find('name').text.strip()
theme_folder = os.path.join(directory, theme_name)
theme_exists = os.path.exists(theme_folder)
if theme_exists and not self.over_write_message_box(theme_name):
abort_import = True
return
else:
theme_name = xml_tree.find('name').text.strip()
theme_folder = os.path.join(directory, theme_name)
theme_exists = os.path.exists(theme_folder)
if theme_exists and not self.over_write_message_box(theme_name):
abort_import = True
return
abort_import = False
for name in theme_zip.namelist():
name = name.replace('/', os.path.sep)
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:
abort_import = False
for name in theme_zip.namelist():
name = name.replace('/', os.path.sep)
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()
out_file = open(full_name, 'wb')
out_file.write(theme_zip.read(name))
out_file.close()
except (IOError, zipfile.BadZipfile):
log.exception('Importing theme from zip failed %s' % file_name)
raise Exception('validation')
@ -548,7 +543,7 @@ class ThemeManager(QtGui.QWidget):
if not abort_import:
# As all files are closed, we can create the Theme.
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)
# Only show the error message, when IOError was not raised (in
# 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.'))
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):
"""
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')
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
@ -741,55 +704,6 @@ class ThemeManager(QtGui.QWidget):
return True
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):
"""
Adds the Renderer to the class dynamically

View File

@ -27,10 +27,12 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`~openlp.core.theme` module contains all the themeing functions used by
OpenLP when displaying a song or a scripture.
The Theme Controller helps manages adding, deleteing and modifying of themes.
"""
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 openlp.core.lib import Registry, Settings, SettingsTab, UiStrings, translate
from openlp.core.lib.theme import ThemeLevel
from openlp.core.common import Settings, ThemeLevel, UiStrings, translate
from openlp.core.lib import Registry, SettingsTab
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 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.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 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
log = logging.getLogger(__name__)

View File

@ -37,11 +37,14 @@ import os
import re
from subprocess import Popen, PIPE
import sys
import urllib.request, urllib.error, urllib.parse
import urllib.request
import urllib.error
import urllib.parse
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':
@ -51,7 +54,7 @@ if sys.platform != 'win32' and sys.platform != 'darwin':
except ImportError:
XDG_BASE_AVAILABLE = False
from openlp.core.lib import translate
from openlp.core.common import translate
log = logging.getLogger(__name__)
APPLICATION_VERSION = {}
@ -81,15 +84,6 @@ class VersionThread(QtCore.QThread):
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():
"""
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 = [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.
if string[0].isdigit():
return [b''] + key
return key
from .applocation import AppLocation
from .languagemanager import LanguageManager
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',
'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 openlp.core.lib import Settings
from openlp.core.common import Settings
log = logging.getLogger(__name__)

View File

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

View File

@ -31,7 +31,8 @@ import logging
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.ui import create_action, UiStrings
from openlp.core.lib.theme import VerticalType

View File

@ -29,7 +29,8 @@
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

View File

@ -29,7 +29,7 @@
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 .alertdialog import Ui_AlertDialog

View File

@ -35,7 +35,8 @@ import logging
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__)

View File

@ -29,7 +29,8 @@
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

View File

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

View File

@ -32,13 +32,13 @@ The bible import functions for OpenLP
import logging
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.ui import critical_error_message_box
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.db import BiblesResourcesDB, clean_filename

View File

@ -36,10 +36,11 @@ from tempfile import gettempdir
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.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.http import BSExtract, BGExtract, CWExtract

View File

@ -29,7 +29,7 @@
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
class Ui_BookNameDialog(object):

View File

@ -36,7 +36,7 @@ import re
from PyQt4.QtGui import QDialog
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.plugins.bibles.forms.booknamedialog import Ui_BookNameDialog
from openlp.plugins.bibles.lib import BibleStrings

View File

@ -29,7 +29,8 @@
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.plugins.bibles.lib import LanguageSelection, BibleStrings
from openlp.plugins.bibles.lib.db import BiblesResourcesDB

View File

@ -33,7 +33,8 @@ import re
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 .editbibledialog import Ui_EditBibleDialog
from openlp.plugins.bibles.lib import BibleStrings

View File

@ -29,7 +29,7 @@
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
class Ui_LanguageDialog(object):

View File

@ -34,7 +34,7 @@ import logging
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.plugins.bibles.forms.languagedialog import \
Ui_LanguageDialog

View File

@ -33,7 +33,8 @@ plugin.
import logging
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__)

View File

@ -31,7 +31,8 @@ import logging
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.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \
get_reference_separator, LanguageSelection
@ -58,6 +59,9 @@ class BiblesTab(SettingsTab):
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.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.setObjectName('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.right_layout.addStretch()
# 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.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)
@ -156,6 +161,7 @@ class BiblesTab(SettingsTab):
def retranslateUi(self):
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.layout_style_label.setText(UiStrings().LayoutStyle)
self.display_style_label.setText(UiStrings().DisplayStyle)
@ -208,6 +214,13 @@ class BiblesTab(SettingsTab):
def on_language_selection_combo_box_changed(self):
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):
self.show_new_chapters = False
# We have a set value convert to True/False.
@ -299,11 +312,14 @@ class BiblesTab(SettingsTab):
def load(self):
settings = Settings()
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.display_style = settings.value('display brackets')
self.layout_style = settings.value('verse layout style')
self.bible_theme = settings.value('bible theme')
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.display_style_combo_box.setCurrentIndex(self.display_style)
self.layout_style_combo_box.setCurrentIndex(self.layout_style)
@ -351,6 +367,7 @@ class BiblesTab(SettingsTab):
def save(self):
settings = Settings()
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 brackets', self.display_style)
settings.setValue('verse layout style', self.layout_style)
@ -405,3 +422,12 @@ class BiblesTab(SettingsTab):
color.setAlpha(128)
palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
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 csv
from openlp.core.lib import translate
from openlp.core.common import translate
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.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.ui import critical_error_message_box
from openlp.core.utils import AppLocation, clean_filename
from openlp.core.utils import clean_filename
from . import upgrade
log = logging.getLogger(__name__)

View File

@ -38,7 +38,8 @@ from html.parser import HTMLParseError
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.utils import get_web_page
from openlp.plugins.bibles.lib import SearchResults

View File

@ -30,8 +30,9 @@
import logging
import os
from openlp.core.lib import Registry, Settings, translate
from openlp.core.utils import AppLocation, delete_file
from openlp.core.common import AppLocation, Settings, translate
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.db import BibleDB, BibleMeta
from .csvbible import CSVBible

View File

@ -31,8 +31,8 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, Settings, UiStrings, \
create_separated_list, translate
from openlp.core.common import Settings, UiStrings, translate
from openlp.core.lib import Registry, MediaManagerItem, ItemCapabilities, ServiceItemContext, create_separated_list
from openlp.core.lib.searchedit import SearchEdit
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
@ -64,6 +64,11 @@ class BibleMediaItem(MediaManagerItem):
self.lock_icon = build_icon(':/bibles/bibles_search_lock.png')
self.unlock_icon = build_icon(':/bibles/bibles_search_unlock.png')
MediaManagerItem.__init__(self, parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
# Place to store the search results for both bibles.
self.settings = self.plugin.settings_tab
self.quick_preview_allowed = True
@ -803,20 +808,20 @@ class BibleMediaItem(MediaManagerItem):
verses.add(book, chapter, verse, version, copyright, permissions)
verse_text = self.formatVerse(old_chapter, chapter, verse)
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())
bible_text = ''
# If we are 'Verse Per Slide' then create a new slide.
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())
bible_text = ''
# If we are 'Verse Per Line' then force a new line.
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'.
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(' ')
if not old_item:
start_item = bitem
@ -943,17 +948,19 @@ class BibleMediaItem(MediaManagerItem):
The verse number (int).
"""
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:
verse_text = str(chapter) + verse_separator + str(verse)
else:
verse_text = str(verse)
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:
return '{su}{%s}{/su}' % verse_text
return '{su}{%s}{/su}&nbsp;' % verse_text
if self.settings.display_style == DisplayStyle.Square:
return '{su}[%s]{/su}' % verse_text
return '{su}%s{/su}' % verse_text
return '{su}[%s]{/su}&nbsp;' % verse_text
return '{su}%s{/su}&nbsp;' % verse_text
def search(self, string, showError):
"""

View File

@ -30,7 +30,7 @@
import logging
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.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB

View File

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

View File

@ -27,6 +27,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
class VerseReferenceList(object):
"""
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 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

View File

@ -29,7 +29,8 @@
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
class Ui_CustomSlideEditDialog(object):

View File

@ -30,7 +30,7 @@
import logging
from PyQt4 import QtCore, QtGui
from PyQt4 import QtGui
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 openlp.core.lib import SettingsTab, Settings, translate
from openlp.core.common import Settings, translate
from openlp.core.lib import SettingsTab
class CustomTab(SettingsTab):

View File

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

View File

@ -29,7 +29,7 @@
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

View File

@ -29,7 +29,7 @@
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.plugins.images.forms.addgroupdialog import Ui_AddGroupDialog

View File

@ -29,7 +29,7 @@
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

View File

@ -31,10 +31,11 @@ from PyQt4 import QtGui
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.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__)

View File

@ -29,7 +29,8 @@
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):

View File

@ -32,11 +32,11 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import ItemCapabilities, MediaManagerItem, Registry, ServiceItemContext, Settings, \
StringContent, TreeWidgetWithDnD, UiStrings, build_icon, check_directory_exists, check_item_selected, \
create_thumb, translate, validate_thumb
from openlp.core.common import AppLocation, Settings, UiStrings, check_directory_exists, translate
from openlp.core.lib import ItemCapabilities, MediaManagerItem, Registry, ServiceItemContext, \
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.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.lib.db import ImageFilenames, ImageGroups
@ -52,10 +52,18 @@ class ImageMediaItem(MediaManagerItem):
def __init__(self, parent, plugin):
self.icon_path = 'images/image'
self.manager = None
self.choose_group_form = None
self.add_group_form = None
super(ImageMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.quick_preview_allowed = True
self.has_search = True
self.manager = plugin.manager
self.manager = self.plugin.manager
self.choose_group_form = ChooseGroupForm(self)
self.add_group_form = AddGroupForm(self)
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.setIndentation(self.list_view.default_indentation)
self.list_view.allow_internal_dnd = True
self.servicePath = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails')
check_directory_exists(self.servicePath)
self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails')
check_directory_exists(self.service_path)
# Load images from the database
self.load_full_list(
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)
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)
image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
for group in image_groups:
@ -215,7 +223,7 @@ class ImageMediaItem(MediaManagerItem):
if row_item:
item_data = row_item.data(0, QtCore.Qt.UserRole)
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:
self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
else:
@ -339,7 +347,7 @@ class ImageMediaItem(MediaManagerItem):
for imageFile in images:
log.debug('Loading image: %s', imageFile.filename)
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):
icon = build_icon(':/general/general_delete.png')
else:
@ -672,7 +680,16 @@ class ImageMediaItem(MediaManagerItem):
translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, '
'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),
order_by_ref=ImageFilenames.filename)
results = []

View File

@ -32,12 +32,13 @@ import os
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, \
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.ui import DisplayController, Display, DisplayControllerType
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__)
@ -61,10 +62,15 @@ class MediaMediaItem(MediaManagerItem):
self.background = False
self.automatic = ''
super(MediaMediaItem, self).__init__(parent, plugin)
def setup_item(self):
"""
Do some additional setup.
"""
self.single_service_item = False
self.has_search = True
self.media_object = None
self.display_controller = DisplayController(parent)
self.display_controller = DisplayController(self.parent())
self.display_controller.controller_layout = QtGui.QVBoxLayout()
self.media_controller.register_controller(self.display_controller)
self.media_controller.set_controls_visible(self.display_controller, False)

View File

@ -29,7 +29,8 @@
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):

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