forked from openlp/openlp
r1058
This commit is contained in:
commit
ba576f6426
22
openlp.pyw
22
openlp.pyw
@ -162,18 +162,18 @@ def main():
|
||||
the PyQt4 Application.
|
||||
"""
|
||||
# Set up command line options.
|
||||
usage = u'Usage: %prog [options] [qt-options]'
|
||||
usage = 'Usage: %prog [options] [qt-options]'
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option(u'-e', u'--no-error-form', dest=u'no_error_form',
|
||||
action=u'store_true', help=u'Disable the error notification form.')
|
||||
parser.add_option(u'-l', u'--log-level', dest=u'loglevel',
|
||||
default=u'warning', metavar=u'LEVEL', help=u'Set logging to LEVEL '
|
||||
u'level. Valid values are "debug", "info", "warning".')
|
||||
parser.add_option(u'-p', u'--portable', dest=u'portable',
|
||||
action=u'store_true', help=u'Specify if this should be run as a '
|
||||
u'portable app, off a USB flash drive (not implemented).')
|
||||
parser.add_option(u'-s', u'--style', dest=u'style',
|
||||
help=u'Set the Qt4 style (passed directly to Qt4).')
|
||||
parser.add_option('-e', '--no-error-form', dest='no_error_form',
|
||||
action='store_true', help='Disable the error notification form.')
|
||||
parser.add_option('-l', '--log-level', dest='loglevel',
|
||||
default='warning', metavar='LEVEL', help='Set logging to LEVEL '
|
||||
'level. Valid values are "debug", "info", "warning".')
|
||||
parser.add_option('-p', '--portable', dest='portable',
|
||||
action='store_true', help='Specify if this should be run as a '
|
||||
'portable app, off a USB flash drive (not implemented).')
|
||||
parser.add_option('-s', '--style', dest='style',
|
||||
help='Set the Qt4 style (passed directly to Qt4).')
|
||||
# Set up logging
|
||||
log_path = AppLocation.get_directory(AppLocation.CacheDir)
|
||||
if not os.path.exists(log_path):
|
||||
|
@ -220,6 +220,7 @@ def image_to_byte(image):
|
||||
``image``
|
||||
The image to converted.
|
||||
"""
|
||||
log.debug(u'image_to_byte')
|
||||
byte_array = QtCore.QByteArray()
|
||||
# use buffer to store pixmap into byteArray
|
||||
buffie = QtCore.QBuffer(byte_array)
|
||||
@ -249,6 +250,7 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
|
||||
The background colour defaults to black.
|
||||
|
||||
"""
|
||||
log.debug(u'resize_image')
|
||||
preview = QtGui.QImage(image)
|
||||
if not preview.isNull():
|
||||
# Only resize if different size
|
||||
|
@ -27,8 +27,6 @@
|
||||
import logging
|
||||
from PyQt4 import QtWebKit
|
||||
|
||||
from openlp.core.lib import image_to_byte
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
HTMLSRC = u"""
|
||||
@ -60,7 +58,10 @@ body {
|
||||
#image {
|
||||
z-index:1;
|
||||
}
|
||||
#video {
|
||||
#video1 {
|
||||
z-index:2;
|
||||
}
|
||||
#video2 {
|
||||
z-index:2;
|
||||
}
|
||||
#alert {
|
||||
@ -82,54 +83,12 @@ body {
|
||||
<script language="javascript">
|
||||
var timer = null;
|
||||
var video_timer = null;
|
||||
var current_video = '1';
|
||||
var transition = %s;
|
||||
|
||||
function show_video(state, path, volume, loop){
|
||||
var vid = document.getElementById('video');
|
||||
if(path != null){
|
||||
vid.src = path;
|
||||
vid.load();
|
||||
}
|
||||
if(volume != null){
|
||||
vid.volume = volume;
|
||||
}
|
||||
switch(state){
|
||||
case 'play':
|
||||
vid.play();
|
||||
vid.style.display = 'block';
|
||||
if(loop)
|
||||
video_timer = setInterval('video_loop()', 200);
|
||||
break;
|
||||
case 'pause':
|
||||
if(video_timer!=null){
|
||||
clearInterval(video_timer);
|
||||
video_timer = null;
|
||||
}
|
||||
vid.pause();
|
||||
vid.style.display = 'block';
|
||||
break;
|
||||
case 'stop':
|
||||
if(video_timer!=null){
|
||||
clearInterval(video_timer);
|
||||
video_timer = null;
|
||||
}
|
||||
vid.pause();
|
||||
vid.style.display = 'none';
|
||||
vid.load();
|
||||
break;
|
||||
case 'close':
|
||||
if(video_timer!=null){
|
||||
clearInterval(video_timer);
|
||||
video_timer = null;
|
||||
}
|
||||
vid.pause();
|
||||
vid.style.display = 'none';
|
||||
vid.src = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
function video_loop(){
|
||||
// The preferred method would be to use the video tag loop attribute
|
||||
// Note, the preferred method for looping would be to use the
|
||||
// video tag loop attribute.
|
||||
// But QtWebKit doesn't support this. Neither does it support the
|
||||
// onended event, hence the setInterval()
|
||||
// In addition, setting the currentTime attribute to zero to restart
|
||||
@ -140,12 +99,73 @@ body {
|
||||
// Note, currently the background may go black between loops. Not
|
||||
// desirable. Need to investigate using two <video>'s, and hiding/
|
||||
// preloading one, and toggle between the two when looping.
|
||||
var vid = document.getElementById('video');
|
||||
if(vid.ended||vid.currentTime+0.2>=vid.duration){
|
||||
vid.load();
|
||||
vid.play();
|
||||
}
|
||||
|
||||
if(current_video=='1'){
|
||||
var vid = document.getElementById('video1');
|
||||
var vid2 = document.getElementById('video2');
|
||||
} else {
|
||||
var vid = document.getElementById('video2');
|
||||
var vid2 = document.getElementById('video1');
|
||||
}
|
||||
if(volume != null){
|
||||
vid.volume = volume;
|
||||
vid2.volume = volume;
|
||||
}
|
||||
switch(state){
|
||||
case 'init':
|
||||
vid.src = path;
|
||||
vid2.src = path;
|
||||
if(loop == null) loop = false;
|
||||
vid.looping = loop;
|
||||
vid2.looping = loop;
|
||||
vid.load();
|
||||
break;
|
||||
case 'load':
|
||||
vid2.style.visibility = 'hidden';
|
||||
vid2.load();
|
||||
break;
|
||||
case 'play':
|
||||
vid.play();
|
||||
vid.style.visibility = 'visible';
|
||||
if(vid.looping){
|
||||
video_timer = setInterval(
|
||||
function() {
|
||||
show_video('poll');
|
||||
}, 200);
|
||||
}
|
||||
break;
|
||||
case 'pause':
|
||||
if(video_timer!=null){
|
||||
clearInterval(video_timer);
|
||||
video_timer = null;
|
||||
}
|
||||
vid.pause();
|
||||
break;
|
||||
case 'stop':
|
||||
show_video('pause');
|
||||
vid.style.visibility = 'hidden';
|
||||
break;
|
||||
case 'poll':
|
||||
if(vid.ended||vid.currentTime+0.2>vid.duration)
|
||||
show_video('swap');
|
||||
break;
|
||||
case 'swap':
|
||||
show_video('pause');
|
||||
if(current_video=='1')
|
||||
current_video = '2';
|
||||
else
|
||||
current_video = '1';
|
||||
show_video('play');
|
||||
show_video('load');
|
||||
break;
|
||||
case 'close':
|
||||
show_video('stop');
|
||||
vid.src = '';
|
||||
vid2.src = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function show_image(src){
|
||||
var img = document.getElementById('image');
|
||||
img.src = src;
|
||||
@ -274,8 +294,11 @@ body {
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<img id="image" class="size" src="%s" />
|
||||
<video id="video" class="size"></video>
|
||||
<img id="image" class="size" %s />
|
||||
<video id="video1" class="size" style="visibility:hidden" autobuffer preload>
|
||||
</video>
|
||||
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
|
||||
</video>
|
||||
%s
|
||||
<div id="footer" class="footer"></div>
|
||||
<div id="black" class="size"></div>
|
||||
@ -301,10 +324,10 @@ def build_html(item, screen, alert, islive):
|
||||
height = screen[u'size'].height()
|
||||
theme = item.themedata
|
||||
webkitvers = webkit_version()
|
||||
if item.bg_frame:
|
||||
image = u'data:image/png;base64,%s' % image_to_byte(item.bg_frame)
|
||||
if item.bg_image_bytes:
|
||||
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
|
||||
else:
|
||||
image = u''
|
||||
image = u'style="display:none;"'
|
||||
html = HTMLSRC % (build_background_css(item, width, height),
|
||||
width, height,
|
||||
build_alert_css(alert, width),
|
||||
@ -426,8 +449,10 @@ def build_lyrics_css(item, webkitvers):
|
||||
outline = build_lyrics_outline_css(theme)
|
||||
if theme.display_shadow:
|
||||
if theme.display_outline and webkitvers < 534.3:
|
||||
shadow = u'padding-left: %spx; padding-top: %spx ' % \
|
||||
(theme.display_shadow_size, theme.display_shadow_size)
|
||||
shadow = u'padding-left: %spx; padding-top: %spx;' % \
|
||||
(int(theme.display_shadow_size) +
|
||||
(int(theme.display_outline_size) * 2),
|
||||
theme.display_shadow_size)
|
||||
shadow += build_lyrics_outline_css(theme, True)
|
||||
else:
|
||||
lyricsmain += u' text-shadow: %s %spx %spx;' % \
|
||||
@ -487,13 +512,17 @@ def build_lyrics_format_css(theme, width, height):
|
||||
valign = u'middle'
|
||||
else:
|
||||
valign = u'top'
|
||||
if theme.display_outline:
|
||||
left_margin = int(theme.display_outline_size) * 2
|
||||
else:
|
||||
left_margin = 0
|
||||
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
|
||||
'text-align: %s; vertical-align: %s; font-family: %s; ' \
|
||||
'font-size: %spt; color: %s; line-height: %d%%; ' \
|
||||
'margin:0; padding:0; width: %spx; height: %spx; ' % \
|
||||
'font-size: %spt; color: %s; line-height: %d%%; margin:0;' \
|
||||
'padding:0; padding-left:%spx; width: %spx; height: %spx; ' % \
|
||||
(align, valign, theme.font_main_name, theme.font_main_proportion,
|
||||
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
|
||||
width, height)
|
||||
left_margin, width, height)
|
||||
if theme.display_outline:
|
||||
if webkit_version() < 534.3:
|
||||
lyrics += u' letter-spacing: 1px;'
|
||||
|
@ -32,7 +32,8 @@ import logging
|
||||
from PyQt4 import QtGui, QtCore, QtWebKit
|
||||
|
||||
from openlp.core.lib import resize_image, expand_tags, \
|
||||
build_lyrics_format_css, build_lyrics_outline_css
|
||||
build_lyrics_format_css, build_lyrics_outline_css, image_to_byte
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -54,6 +55,7 @@ class Renderer(object):
|
||||
self.frame = None
|
||||
self.bg_frame = None
|
||||
self.bg_image = None
|
||||
self.bg_image_bytes = None
|
||||
|
||||
def set_theme(self, theme):
|
||||
"""
|
||||
@ -66,15 +68,12 @@ class Renderer(object):
|
||||
self._theme = theme
|
||||
self.bg_frame = None
|
||||
self.bg_image = None
|
||||
self.bg_image_bytes = None
|
||||
self._bg_image_filename = None
|
||||
self.theme_name = theme.theme_name
|
||||
if theme.background_type == u'image':
|
||||
if theme.background_filename:
|
||||
self._bg_image_filename = unicode(theme.background_filename)
|
||||
if self.frame:
|
||||
self.bg_image = resize_image(self._bg_image_filename,
|
||||
self.frame.width(),
|
||||
self.frame.height())
|
||||
|
||||
def set_text_rectangle(self, rect_main, rect_footer):
|
||||
"""
|
||||
@ -89,6 +88,22 @@ class Renderer(object):
|
||||
log.debug(u'set_text_rectangle %s , %s' % (rect_main, rect_footer))
|
||||
self._rect = rect_main
|
||||
self._rect_footer = rect_footer
|
||||
self.page_width = self._rect.width()
|
||||
self.page_height = self._rect.height()
|
||||
if self._theme.display_shadow:
|
||||
self.page_width -= int(self._theme.display_shadow_size)
|
||||
self.page_height -= int(self._theme.display_shadow_size)
|
||||
self.web = QtWebKit.QWebView()
|
||||
self.web.setVisible(False)
|
||||
self.web.resize(self.page_width, self.page_height)
|
||||
self.web_frame = self.web.page().mainFrame()
|
||||
# Adjust width and height to account for shadow. outline done in css
|
||||
self.page_shell = u'<html><head><style>' \
|
||||
u'*{margin: 0; padding: 0; border: 0;} '\
|
||||
u'#main {position:absolute; top:0px; %s %s}</style><body>' \
|
||||
u'<div id="main">' % \
|
||||
(build_lyrics_format_css(self._theme, self.page_width,
|
||||
self.page_height), build_lyrics_outline_css(self._theme))
|
||||
|
||||
def set_frame_dest(self, frame_width, frame_height):
|
||||
"""
|
||||
@ -110,15 +125,18 @@ class Renderer(object):
|
||||
self.frame.width(), self.frame.height())
|
||||
if self._theme.background_type == u'image':
|
||||
self.bg_frame = QtGui.QImage(self.frame.width(),
|
||||
self.frame.height(), QtGui.QImage.Format_ARGB32_Premultiplied)
|
||||
self.frame.height(),
|
||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
||||
painter = QtGui.QPainter()
|
||||
painter.begin(self.bg_frame)
|
||||
painter.fillRect(self.frame.rect(), QtCore.Qt.black)
|
||||
if self.bg_image:
|
||||
painter.drawImage(0, 0, self.bg_image)
|
||||
painter.end()
|
||||
self.bg_image_bytes = image_to_byte(self.bg_frame)
|
||||
else:
|
||||
self.bg_frame = None
|
||||
self.bg_image_bytes = None
|
||||
|
||||
def format_slide(self, words, line_break):
|
||||
"""
|
||||
@ -139,29 +157,16 @@ class Renderer(object):
|
||||
lines = verse.split(u'\n')
|
||||
for line in lines:
|
||||
text.append(line)
|
||||
web = QtWebKit.QWebView()
|
||||
web.resize(self._rect.width(), self._rect.height())
|
||||
web.setVisible(False)
|
||||
frame = web.page().mainFrame()
|
||||
# Adjust width and height to account for shadow. outline done in css
|
||||
width = self._rect.width() - int(self._theme.display_shadow_size)
|
||||
height = self._rect.height() - int(self._theme.display_shadow_size)
|
||||
shell = u'<html><head><style>#main {%s %s}</style><body>' \
|
||||
u'<div id="main">' % \
|
||||
(build_lyrics_format_css(self._theme, width, height),
|
||||
build_lyrics_outline_css(self._theme))
|
||||
formatted = []
|
||||
html_text = u''
|
||||
styled_text = u''
|
||||
js_height = 'document.getElementById("main").scrollHeight'
|
||||
for line in text:
|
||||
styled_line = expand_tags(line) + line_end
|
||||
styled_text += styled_line
|
||||
html = shell + styled_text + u'</div></body></html>'
|
||||
web.setHtml(html)
|
||||
html = self.page_shell + styled_text + u'</div></body></html>'
|
||||
self.web.setHtml(html)
|
||||
# Text too long so go to next page
|
||||
text_height = int(frame.evaluateJavaScript(js_height).toString())
|
||||
if text_height > height:
|
||||
if self.web_frame.contentsSize().height() > self.page_height:
|
||||
formatted.append(html_text)
|
||||
html_text = u''
|
||||
styled_text = styled_line
|
||||
|
@ -223,7 +223,6 @@ class RenderManager(object):
|
||||
The words to go on the slides.
|
||||
"""
|
||||
log.debug(u'format slide')
|
||||
self.build_text_rectangle(self.themedata)
|
||||
return self.renderer.format_slide(words, line_break)
|
||||
|
||||
def calculate_default(self, screen):
|
||||
|
@ -97,7 +97,7 @@ class ServiceItem(object):
|
||||
self.themedata = None
|
||||
self.main = None
|
||||
self.footer = None
|
||||
self.bg_frame = None
|
||||
self.bg_image_bytes = None
|
||||
|
||||
def _new_item(self):
|
||||
"""
|
||||
@ -145,7 +145,7 @@ class ServiceItem(object):
|
||||
"""
|
||||
log.debug(u'Render called')
|
||||
self._display_frames = []
|
||||
self.bg_frame = None
|
||||
self.bg_image_bytes = None
|
||||
line_break = True
|
||||
if self.is_capable(ItemCapabilities.NoLineBreaks):
|
||||
line_break = False
|
||||
@ -156,7 +156,7 @@ class ServiceItem(object):
|
||||
theme = self.theme
|
||||
self.main, self.footer = \
|
||||
self.render_manager.set_override_theme(theme, useOverride)
|
||||
self.bg_frame = self.render_manager.renderer.bg_frame
|
||||
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
|
||||
self.themedata = self.render_manager.renderer._theme
|
||||
for slide in self._raw_frames:
|
||||
before = time.time()
|
||||
|
@ -28,6 +28,7 @@ import re
|
||||
import sys
|
||||
try:
|
||||
import enchant
|
||||
from enchant import DictNotFoundError
|
||||
enchant_available = True
|
||||
except ImportError:
|
||||
enchant_available = False
|
||||
@ -43,7 +44,10 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
|
||||
QtGui.QPlainTextEdit.__init__(self, *args)
|
||||
# Default dictionary based on the current locale.
|
||||
if enchant_available:
|
||||
self.dict = enchant.Dict()
|
||||
try:
|
||||
self.dict = enchant.Dict()
|
||||
except DictNotFoundError:
|
||||
self.dict = enchant.Dict(u'en_US')
|
||||
self.highlighter = Highlighter(self.document())
|
||||
self.highlighter.setDict(self.dict)
|
||||
|
||||
|
@ -99,6 +99,7 @@ class MainDisplay(DisplayWidget):
|
||||
self.alertTab = None
|
||||
self.hide_mode = None
|
||||
self.setWindowTitle(u'OpenLP Display')
|
||||
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
|
||||
self.setWindowFlags(QtCore.Qt.FramelessWindowHint |
|
||||
QtCore.Qt.WindowStaysOnTopHint)
|
||||
if self.isLive:
|
||||
@ -116,12 +117,18 @@ class MainDisplay(DisplayWidget):
|
||||
self.screen = self.screens.current
|
||||
self.setVisible(False)
|
||||
self.setGeometry(self.screen[u'size'])
|
||||
self.scene = QtGui.QGraphicsScene()
|
||||
self.setScene(self.scene)
|
||||
self.webView = QtWebKit.QGraphicsWebView()
|
||||
self.scene.addItem(self.webView)
|
||||
self.webView.resize(self.screen[u'size'].width(),
|
||||
self.screen[u'size'].height())
|
||||
try:
|
||||
self.webView = QtWebKit.QGraphicsWebView()
|
||||
self.scene = QtGui.QGraphicsScene(self)
|
||||
self.setScene(self.scene)
|
||||
self.scene.addItem(self.webView)
|
||||
self.webView.setGeometry(QtCore.QRectF(0, 0,
|
||||
self.screen[u'size'].width(), self.screen[u'size'].height()))
|
||||
except AttributeError:
|
||||
# QGraphicsWebView a recent addition, so fall back to QWebView
|
||||
self.webView = QtWebKit.QWebView(self)
|
||||
self.webView.setGeometry(0, 0,
|
||||
self.screen[u'size'].width(), self.screen[u'size'].height())
|
||||
self.page = self.webView.page()
|
||||
self.frame = self.page.mainFrame()
|
||||
QtCore.QObject.connect(self.webView,
|
||||
@ -157,7 +164,7 @@ class MainDisplay(DisplayWidget):
|
||||
- splash_image.height()) / 2,
|
||||
splash_image)
|
||||
serviceItem = ServiceItem()
|
||||
serviceItem.bg_frame = initialFrame
|
||||
serviceItem.bg_image_bytes = image_to_byte(initialFrame)
|
||||
self.webView.setHtml(build_html(serviceItem, self.screen,
|
||||
self.parent.alertTab, self.isLive))
|
||||
self.initialFrame = True
|
||||
@ -176,6 +183,9 @@ class MainDisplay(DisplayWidget):
|
||||
The slide text to be displayed
|
||||
"""
|
||||
log.debug(u'text')
|
||||
# Wait for the webview to update before displayiong text.
|
||||
while not self.loaded:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.frame.evaluateJavaScript(u'show_text("%s")' % \
|
||||
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||
return self.preview()
|
||||
@ -227,8 +237,11 @@ class MainDisplay(DisplayWidget):
|
||||
Display an image, as is.
|
||||
"""
|
||||
if image:
|
||||
js = u'show_image("data:image/png;base64,%s");' % \
|
||||
image_to_byte(image)
|
||||
if isinstance(image, QtGui.QImage):
|
||||
js = u'show_image("data:image/png;base64,%s");' % \
|
||||
image_to_byte(image)
|
||||
else:
|
||||
js = u'show_image("data:image/png;base64,%s");' % image
|
||||
else:
|
||||
js = u'show_image("");'
|
||||
self.frame.evaluateJavaScript(js)
|
||||
@ -239,7 +252,7 @@ class MainDisplay(DisplayWidget):
|
||||
Used after Image plugin has changed the background
|
||||
"""
|
||||
log.debug(u'resetImage')
|
||||
self.displayImage(self.serviceItem.bg_frame)
|
||||
self.displayImage(self.serviceItem.bg_image_bytes)
|
||||
|
||||
def resetVideo(self):
|
||||
"""
|
||||
@ -286,7 +299,7 @@ class MainDisplay(DisplayWidget):
|
||||
"""
|
||||
log.debug(u'video')
|
||||
self.loaded = True
|
||||
js = u'show_video("play", "%s", %s, true);' % \
|
||||
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
|
||||
(videoPath.replace(u'\\', u'\\\\'), str(float(volume)/float(10)))
|
||||
self.frame.evaluateJavaScript(js)
|
||||
return self.preview()
|
||||
@ -306,6 +319,7 @@ class MainDisplay(DisplayWidget):
|
||||
# We must have a service item to preview
|
||||
if not hasattr(self, u'serviceItem'):
|
||||
return
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
if self.isLive:
|
||||
# Wait for the fade to finish before geting the preview.
|
||||
# Important otherwise preview will have incorrect text if at all !
|
||||
@ -318,6 +332,12 @@ class MainDisplay(DisplayWidget):
|
||||
# Important otherwise first preview will miss the background !
|
||||
while not self.loaded:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
# if was hidden keep it hidden
|
||||
if self.isLive:
|
||||
self.setVisible(True)
|
||||
# if was hidden keep it hidden
|
||||
if self.hide_mode and self.isLive:
|
||||
self.hideDisplay(self.hide_mode)
|
||||
preview = QtGui.QImage(self.screen[u'size'].width(),
|
||||
self.screen[u'size'].height(),
|
||||
QtGui.QImage.Format_ARGB32_Premultiplied)
|
||||
@ -325,9 +345,6 @@ class MainDisplay(DisplayWidget):
|
||||
painter.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
self.frame.render(painter)
|
||||
painter.end()
|
||||
# Make display show up if in single screen mode
|
||||
if self.isLive:
|
||||
self.setVisible(True)
|
||||
return preview
|
||||
|
||||
def buildHtml(self, serviceItem):
|
||||
@ -341,7 +358,9 @@ class MainDisplay(DisplayWidget):
|
||||
self.serviceItem = serviceItem
|
||||
html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
|
||||
self.isLive)
|
||||
log.debug(u'buildHtml - pre setHtml')
|
||||
self.webView.setHtml(html)
|
||||
log.debug(u'buildHtml - post setHtml')
|
||||
if serviceItem.foot_text and serviceItem.foot_text:
|
||||
self.footer(serviceItem.foot_text)
|
||||
# if was hidden keep it hidden
|
||||
|
@ -343,7 +343,7 @@ class Ui_MainWindow(object):
|
||||
Set up the translation system
|
||||
"""
|
||||
MainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0')
|
||||
MainWindow.language = translate('OpenLP.MainWindow', 'English')
|
||||
# MainWindow.language = translate('OpenLP.MainWindow', 'English')
|
||||
MainWindow.setWindowTitle(MainWindow.mainTitle)
|
||||
self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
|
||||
self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
|
||||
@ -575,7 +575,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage)
|
||||
self.LanguageGroup.triggered.connect(LanguageManager.set_language)
|
||||
QtCore.QObject.connect(self.ModeDefaultItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.setViewMode)
|
||||
QtCore.SIGNAL(u'triggered()'), self.onModeDefaultItemClicked)
|
||||
QtCore.QObject.connect(self.ModeSetupItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onModeSetupItemClicked)
|
||||
QtCore.QObject.connect(self.ModeLiveItem,
|
||||
@ -670,6 +670,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.generalSettingsSection + u'/auto open',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
self.ServiceManagerContents.onLoadService(True)
|
||||
view_mode = QtCore.QSettings().value(u'%s/view mode' % \
|
||||
self.generalSettingsSection, u'default')
|
||||
if view_mode == u'default':
|
||||
self.ModeDefaultItem.setChecked(True)
|
||||
elif view_mode == u'setup':
|
||||
self.setViewMode(True, True, False, True, False)
|
||||
self.ModeSetupItem.setChecked(True)
|
||||
elif view_mode == u'live':
|
||||
self.setViewMode(False, True, False, False, True)
|
||||
self.ModeLiveItem.setChecked(True)
|
||||
|
||||
def blankCheck(self):
|
||||
"""
|
||||
@ -677,8 +687,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
Triggered by delay thread.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.generalSettingsSection)
|
||||
if settings.value(u'screen blank', QtCore.QVariant(False)).toBool():
|
||||
if settings.value(u'%s/screen blank' % self.generalSettingsSection,
|
||||
QtCore.QVariant(False)).toBool():
|
||||
self.LiveController.mainDisplaySetBackground()
|
||||
if settings.value(u'blank warning',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
@ -687,7 +697,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
'OpenLP Main Display Blanked'),
|
||||
translate('OpenLP.MainWindow',
|
||||
'The Main Display has been blanked out'))
|
||||
settings.endGroup()
|
||||
|
||||
def onHelpWebSiteClicked(self):
|
||||
"""
|
||||
@ -716,16 +725,31 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
self.settingsForm.exec_()
|
||||
|
||||
def onModeDefaultItemClicked(self):
|
||||
"""
|
||||
Put OpenLP into "Default" view mode.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
|
||||
u'default')
|
||||
self.setViewMode(True, True, True, True, True)
|
||||
|
||||
def onModeSetupItemClicked(self):
|
||||
"""
|
||||
Put OpenLP into "Setup" view mode.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
|
||||
u'setup')
|
||||
self.setViewMode(True, True, False, True, False)
|
||||
|
||||
def onModeLiveItemClicked(self):
|
||||
"""
|
||||
Put OpenLP into "Live" view mode.
|
||||
"""
|
||||
settings = QtCore.QSettings()
|
||||
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
|
||||
u'live')
|
||||
self.setViewMode(False, True, False, False, True)
|
||||
|
||||
def setViewMode(self, media=True, service=True, theme=True, preview=True,
|
||||
|
@ -383,20 +383,20 @@ class ServiceManager(QtGui.QWidget):
|
||||
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
|
||||
tempItem = None
|
||||
setLastItem = False
|
||||
while serviceIterator:
|
||||
if serviceIterator.isSelected() and tempItem is None:
|
||||
while serviceIterator.value():
|
||||
if serviceIterator.value().isSelected() and tempItem is None:
|
||||
setLastItem = True
|
||||
serviceIterator.setSelected(False)
|
||||
if serviceIterator.isSelected():
|
||||
#We are on the first record
|
||||
serviceIterator.value().setSelected(False)
|
||||
if serviceIterator.value().isSelected():
|
||||
# We are on the first record
|
||||
if tempItem:
|
||||
tempItem.setSelected(True)
|
||||
serviceIterator.setSelected(False)
|
||||
serviceIterator.value().setSelected(False)
|
||||
else:
|
||||
tempItem = serviceIterator
|
||||
lastItem = serviceIterator
|
||||
++serviceIterator
|
||||
#Top Item was selected so set the last one
|
||||
tempItem = serviceIterator.value()
|
||||
lastItem = serviceIterator.value()
|
||||
serviceIterator += 1
|
||||
# Top Item was selected so set the last one
|
||||
if setLastItem:
|
||||
lastItem.setSelected(True)
|
||||
|
||||
@ -406,16 +406,18 @@ class ServiceManager(QtGui.QWidget):
|
||||
Called by the down arrow
|
||||
"""
|
||||
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
|
||||
firstItem = serviceIterator
|
||||
firstItem = None
|
||||
setSelected = False
|
||||
while serviceIterator:
|
||||
while serviceIterator.value():
|
||||
if not firstItem:
|
||||
firstItem = serviceIterator.value()
|
||||
if setSelected:
|
||||
setSelected = False
|
||||
serviceIterator.setSelected(True)
|
||||
elif serviceIterator.isSelected():
|
||||
serviceIterator.setSelected(False)
|
||||
serviceIterator.value().setSelected(True)
|
||||
elif serviceIterator.value() and serviceIterator.value().isSelected():
|
||||
serviceIterator.value().setSelected(False)
|
||||
setSelected = True
|
||||
++serviceIterator
|
||||
serviceIterator += 1
|
||||
if setSelected:
|
||||
firstItem.setSelected(True)
|
||||
|
||||
@ -557,7 +559,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
QtCore.QVariant(item[u'order']))
|
||||
for count, frame in enumerate(serviceitem.get_frames()):
|
||||
treewidgetitem1 = QtGui.QTreeWidgetItem(treewidgetitem)
|
||||
text = frame[u'title']
|
||||
text = frame[u'title'].replace(u'\n', u' ')
|
||||
treewidgetitem1.setText(0, text[:40])
|
||||
treewidgetitem1.setData(0, QtCore.Qt.UserRole,
|
||||
QtCore.QVariant(count))
|
||||
|
@ -637,9 +637,9 @@ class SlideController(QtGui.QWidget):
|
||||
"""
|
||||
if not self.serviceItem:
|
||||
return
|
||||
Receiver.send_message(u'%s_first' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
if self.serviceItem.is_command():
|
||||
Receiver.send_message(u'%s_first' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
self.updatePreview()
|
||||
else:
|
||||
self.PreviewListWidget.selectRow(0)
|
||||
@ -652,9 +652,9 @@ class SlideController(QtGui.QWidget):
|
||||
index = int(message[0])
|
||||
if not self.serviceItem:
|
||||
return
|
||||
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive, index])
|
||||
if self.serviceItem.is_command():
|
||||
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive, index])
|
||||
self.updatePreview()
|
||||
else:
|
||||
self.PreviewListWidget.selectRow(index)
|
||||
@ -769,9 +769,9 @@ class SlideController(QtGui.QWidget):
|
||||
row = self.PreviewListWidget.currentRow()
|
||||
self.selectedRow = 0
|
||||
if row > -1 and row < self.PreviewListWidget.rowCount():
|
||||
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive, row])
|
||||
if self.serviceItem.is_command() and self.isLive:
|
||||
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive, row])
|
||||
self.updatePreview()
|
||||
else:
|
||||
frame, raw_html = self.serviceItem.get_rendered_frame(row)
|
||||
|
@ -82,7 +82,8 @@ class LanguageManager(object):
|
||||
"""
|
||||
translator = QtCore.QTranslator()
|
||||
translator.load(qm_file)
|
||||
return translator.translate('OpenLP.MainWindow', 'English')
|
||||
return translator.translate('OpenLP.MainWindow', 'English',
|
||||
'Please add the name of your language here')
|
||||
|
||||
@staticmethod
|
||||
def get_language():
|
||||
@ -107,12 +108,13 @@ class LanguageManager(object):
|
||||
``action``
|
||||
The language menu option
|
||||
"""
|
||||
action_name = u'%s' % action.objectName()
|
||||
qm_list = LanguageManager.get_qm_list()
|
||||
if LanguageManager.auto_language:
|
||||
language = u'[%s]' % qm_list[action_name]
|
||||
else:
|
||||
language = u'en'
|
||||
if action:
|
||||
action_name = u'%s' % action.objectName()
|
||||
qm_list = LanguageManager.get_qm_list()
|
||||
language = u'%s' % qm_list[action_name]
|
||||
if LanguageManager.auto_language:
|
||||
language = u'[%s]' % language
|
||||
QtCore.QSettings().setValue(
|
||||
u'general/language', QtCore.QVariant(language))
|
||||
log.info(u'Language file: \'%s\' written to conf file' % language)
|
||||
@ -129,9 +131,11 @@ class LanguageManager(object):
|
||||
LanguageManager.__qm_list__ = {}
|
||||
qm_files = LanguageManager.find_qm_files()
|
||||
for counter, qmf in enumerate(qm_files):
|
||||
name = unicode(qmf).split(u'.')[0]
|
||||
LanguageManager.__qm_list__[u'%#2i %s' % (counter + 1,
|
||||
LanguageManager.language_name(qmf))] = name
|
||||
reg_ex = QtCore.QRegExp("^.*i18n/(.*).qm")
|
||||
if reg_ex.exactMatch(qmf):
|
||||
name = u'%s' % reg_ex.cap(1)
|
||||
LanguageManager.__qm_list__[u'%#2i %s' % (counter + 1,
|
||||
LanguageManager.language_name(qmf))] = name
|
||||
|
||||
@staticmethod
|
||||
def get_qm_list():
|
||||
|
@ -40,7 +40,7 @@ class AlertsPlugin(Plugin):
|
||||
log.info(u'Alerts Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'Alerts', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Alerts', u'1.9.3', plugin_helpers)
|
||||
self.weight = -3
|
||||
self.icon = build_icon(u':/plugins/plugin_alerts.png')
|
||||
self.alertsmanager = AlertsManager(self)
|
||||
|
@ -37,7 +37,7 @@ class BiblePlugin(Plugin):
|
||||
log.info(u'Bible Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'Bibles', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Bibles', u'1.9.3', plugin_helpers)
|
||||
self.weight = -9
|
||||
self.icon_path = u':/plugins/plugin_bibles.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
@ -126,29 +126,29 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
if self.field(u'osis_location').toString() == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Invalid Bible Location'),
|
||||
'Invalid Bible Location'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to specify a file to import your '
|
||||
'Bible from.'))
|
||||
'You need to specify a file to import your '
|
||||
'Bible from.'))
|
||||
self.OSISLocationEdit.setFocus()
|
||||
return False
|
||||
elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV:
|
||||
if self.field(u'csv_booksfile').toString() == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Invalid Books File'),
|
||||
'Invalid Books File'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to specify a file with books of '
|
||||
'the Bible to use in the import.'))
|
||||
'You need to specify a file with books of '
|
||||
'the Bible to use in the import.'))
|
||||
self.BooksLocationEdit.setFocus()
|
||||
return False
|
||||
elif self.field(u'csv_versefile').toString() == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Invalid Verse File'),
|
||||
'Invalid Verse File'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to specify a file of Bible '
|
||||
'verses to import.'))
|
||||
'You need to specify a file of Bible '
|
||||
'verses to import.'))
|
||||
self.CsvVerseLocationEdit.setFocus()
|
||||
return False
|
||||
elif self.field(u'source_format').toInt()[0] == \
|
||||
@ -156,10 +156,10 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
if self.field(u'opensong_file').toString() == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Invalid OpenSong Bible'),
|
||||
'Invalid OpenSong Bible'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to specify an OpenSong Bible '
|
||||
'file to import.'))
|
||||
'You need to specify an OpenSong Bible '
|
||||
'file to import.'))
|
||||
self.OpenSongFileEdit.setFocus()
|
||||
return False
|
||||
return True
|
||||
@ -171,29 +171,26 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
if license_version == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Empty Version Name'),
|
||||
'Empty Version Name'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to specify a version name for your '
|
||||
'Bible.'))
|
||||
'You need to specify a version name for your Bible.'))
|
||||
self.VersionNameEdit.setFocus()
|
||||
return False
|
||||
elif license_copyright == u'':
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Empty Copyright'),
|
||||
'Empty Copyright'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'You need to set a copyright for your Bible. '
|
||||
'Bibles in the Public Domain need to be marked as '
|
||||
'such.'))
|
||||
'You need to set a copyright for your Bible. '
|
||||
'Bibles in the Public Domain need to be marked as such.'))
|
||||
self.CopyrightEdit.setFocus()
|
||||
return False
|
||||
elif self.manager.exists(license_version):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Bible Exists'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Bible Exists'),
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'This Bible already exists. Please import '
|
||||
'a different Bible or first delete the existing one.'))
|
||||
'This Bible already exists. Please import '
|
||||
'a different Bible or first delete the existing one.'))
|
||||
self.VersionNameEdit.setFocus()
|
||||
return False
|
||||
return True
|
||||
@ -290,6 +287,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
def setDefaults(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.bibleplugin.settingsSection)
|
||||
self.restart()
|
||||
self.finishButton.setVisible(False)
|
||||
self.cancelButton.setVisible(True)
|
||||
self.setField(u'source_format', QtCore.QVariant(0))
|
||||
self.setField(u'osis_location', QtCore.QVariant(''))
|
||||
self.setField(u'csv_booksfile', QtCore.QVariant(''))
|
||||
@ -434,18 +434,16 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
unicode(self.field(u'proxy_username').toString()),
|
||||
proxy_password=unicode(self.field(u'proxy_password').toString())
|
||||
)
|
||||
success = importer.do_import()
|
||||
if success:
|
||||
if importer.do_import():
|
||||
self.manager.save_meta_data(license_version, license_version,
|
||||
license_copyright, license_permission)
|
||||
self.manager.reload_bibles()
|
||||
self.ImportProgressLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Finished import.'))
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Finished import.'))
|
||||
else:
|
||||
self.ImportProgressLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Your Bible import failed.'))
|
||||
'Your Bible import failed.'))
|
||||
delete_database(self.bibleplugin.settingsSection, importer.file)
|
||||
|
||||
def postImport(self):
|
||||
|
@ -65,12 +65,6 @@ class BibleMediaItem(MediaManagerItem):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles)
|
||||
|
||||
def _decodeQtObject(self, listobj, key):
|
||||
obj = listobj[QtCore.QString(key)]
|
||||
if isinstance(obj, QtCore.QVariant):
|
||||
obj = obj.toPyObject()
|
||||
return unicode(obj)
|
||||
|
||||
def requiredIcons(self):
|
||||
MediaManagerItem.requiredIcons(self)
|
||||
self.hasImportIcon = True
|
||||
@ -376,9 +370,6 @@ class BibleMediaItem(MediaManagerItem):
|
||||
def onSearchProgressShow(self):
|
||||
self.SearchProgress.setVisible(True)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
#self.SearchProgress.setMinimum(0)
|
||||
#self.SearchProgress.setMaximum(2)
|
||||
#self.SearchProgress.setValue(1)
|
||||
|
||||
def onSearchProgressHide(self):
|
||||
self.SearchProgress.setVisible(False)
|
||||
@ -408,18 +399,28 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.reloadBibles()
|
||||
|
||||
def onAdvancedFromVerse(self):
|
||||
frm = self.AdvancedFromVerse.currentText()
|
||||
self.adjustComboBox(frm, self.verses, self.AdvancedToVerse)
|
||||
|
||||
def onAdvancedToChapter(self):
|
||||
frm = unicode(self.AdvancedFromChapter.currentText())
|
||||
to = unicode(self.AdvancedToChapter.currentText())
|
||||
if frm != to:
|
||||
frm = int(self.AdvancedFromVerse.currentText())
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
if chapter_frm == chapter_to:
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
# get the verse count for new chapter
|
||||
verses = self.parent.manager.get_verse_count(bible, book, int(to))
|
||||
verses = self.parent.manager.get_verse_count(bible, book, chapter_to)
|
||||
self.adjustComboBox(frm, verses, self.AdvancedToVerse)
|
||||
|
||||
def onAdvancedToChapter(self):
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
verses = self.parent.manager.get_verse_count(bible, book, chapter_to)
|
||||
if chapter_frm != chapter_to:
|
||||
self.adjustComboBox(1, verses, self.AdvancedToVerse)
|
||||
else:
|
||||
frm = int(self.AdvancedFromVerse.currentText())
|
||||
to = int(self.AdvancedToVerse.currentText())
|
||||
if to < frm:
|
||||
self.adjustComboBox(frm, verses, self.AdvancedToVerse)
|
||||
|
||||
def onAdvancedSearchButton(self):
|
||||
log.debug(u'Advanced Search Button pressed')
|
||||
@ -438,32 +439,72 @@ class BibleMediaItem(MediaManagerItem):
|
||||
dual_bible, versetext)
|
||||
if self.ClearAdvancedSearchComboBox.currentIndex() == 0:
|
||||
self.listView.clear()
|
||||
self.displayResults(bible, dual_bible)
|
||||
if self.listView.count() != 0:
|
||||
bitem = self.listView.item(0)
|
||||
item_dual_bible = self._decodeQtObject(bitem, 'dual_bible')
|
||||
if item_dual_bible and dual_bible or not item_dual_bible and \
|
||||
not dual_bible:
|
||||
self.displayResults(bible, dual_bible)
|
||||
elif QtGui.QMessageBox.critical(self,
|
||||
translate('BiblePlugin.MediaItem', 'Error'),
|
||||
translate('BiblePlugin.MediaItem', 'You cannot combine single '
|
||||
'and dual bible verses. Do you want to delete your search '
|
||||
'results and start a new search?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes:
|
||||
self.listView.clear()
|
||||
self.displayResults(bible, dual_bible)
|
||||
else:
|
||||
self.displayResults(bible, dual_bible)
|
||||
|
||||
def onAdvancedFromChapter(self):
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
cf = int(self.AdvancedFromChapter.currentText())
|
||||
self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter)
|
||||
# get the verse count for new chapter
|
||||
vse = self.parent.manager.get_verse_count(bible, book, cf)
|
||||
self.adjustComboBox(1, vse, self.AdvancedFromVerse)
|
||||
self.adjustComboBox(1, vse, self.AdvancedToVerse)
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
self.adjustComboBox(chapter_frm, self.chapters_from,
|
||||
self.AdvancedToChapter)
|
||||
verse = self.parent.manager.get_verse_count(bible, book, chapter_frm)
|
||||
self.adjustComboBox(1, verse, self.AdvancedToVerse)
|
||||
self.adjustComboBox(1, verse, self.AdvancedFromVerse)
|
||||
|
||||
def onQuickSearchButton(self):
|
||||
log.debug(u'Quick Search Button pressed')
|
||||
bible = unicode(self.QuickVersionComboBox.currentText())
|
||||
dual_bible = unicode(self.QuickSecondBibleComboBox.currentText())
|
||||
text = unicode(self.QuickSearchEdit.text())
|
||||
if self.ClearQuickSearchComboBox.currentIndex() == 0:
|
||||
self.listView.clear()
|
||||
self.search_results = self.parent.manager.get_verses(bible, text)
|
||||
if dual_bible:
|
||||
self.dual_search_results = self.parent.manager.get_verses(
|
||||
dual_bible, text)
|
||||
if self.search_results:
|
||||
if self.ClearQuickSearchComboBox.currentIndex() == 0:
|
||||
self.listView.clear()
|
||||
if self.listView.count() != 0 and self.search_results:
|
||||
bitem = self.listView.item(0)
|
||||
item_dual_bible = self._decodeQtObject(bitem, 'dual_bible')
|
||||
if item_dual_bible and dual_bible or not item_dual_bible and \
|
||||
not dual_bible:
|
||||
self.displayResults(bible, dual_bible)
|
||||
elif QtGui.QMessageBox.critical(self,
|
||||
translate('BiblePlugin.MediaItem', 'Error'),
|
||||
translate('BiblePlugin.MediaItem', 'You cannot combine single '
|
||||
'and dual bible verses. Do you want to delete your search '
|
||||
'results and start a new search?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.Yes:
|
||||
self.listView.clear()
|
||||
self.displayResults(bible, dual_bible)
|
||||
elif self.search_results:
|
||||
self.displayResults(bible, dual_bible)
|
||||
|
||||
def _decodeQtObject(self, bitem, key):
|
||||
reference = bitem.data(QtCore.Qt.UserRole)
|
||||
if isinstance(reference, QtCore.QVariant):
|
||||
reference = reference.toPyObject()
|
||||
obj = reference[QtCore.QString(key)]
|
||||
if isinstance(obj, QtCore.QVariant):
|
||||
obj = obj.toPyObject()
|
||||
return unicode(obj)
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
"""
|
||||
Generates and formats the slides for the service item as well as the
|
||||
@ -473,67 +514,40 @@ class BibleMediaItem(MediaManagerItem):
|
||||
items = self.listView.selectedIndexes()
|
||||
if len(items) == 0:
|
||||
return False
|
||||
has_dual_bible = False
|
||||
bible_text = u''
|
||||
old_chapter = u''
|
||||
raw_footer = []
|
||||
raw_slides = []
|
||||
raw_title = []
|
||||
first_item = True
|
||||
for item in items:
|
||||
bitem = self.listView.item(item.row())
|
||||
reference = bitem.data(QtCore.Qt.UserRole)
|
||||
if isinstance(reference, QtCore.QVariant):
|
||||
reference = reference.toPyObject()
|
||||
dual_bible = self._decodeQtObject(reference, 'dual_bible')
|
||||
if dual_bible:
|
||||
has_dual_bible = True
|
||||
break
|
||||
# Let's loop through the main lot, and assemble our verses.
|
||||
for item in items:
|
||||
bitem = self.listView.item(item.row())
|
||||
reference = bitem.data(QtCore.Qt.UserRole)
|
||||
if isinstance(reference, QtCore.QVariant):
|
||||
reference = reference.toPyObject()
|
||||
book = self._decodeQtObject(reference, 'book')
|
||||
chapter = self._decodeQtObject(reference, 'chapter')
|
||||
verse = self._decodeQtObject(reference, 'verse')
|
||||
bible = self._decodeQtObject(reference, 'bible')
|
||||
version = self._decodeQtObject(reference, 'version')
|
||||
copyright = self._decodeQtObject(reference, 'copyright')
|
||||
permission = self._decodeQtObject(reference, 'permission')
|
||||
text = self._decodeQtObject(reference, 'text')
|
||||
dual_bible = self._decodeQtObject(reference, 'dual_bible')
|
||||
if dual_bible:
|
||||
dual_version = self._decodeQtObject(reference,
|
||||
'dual_version')
|
||||
dual_copyright = self._decodeQtObject(reference,
|
||||
'dual_copyright')
|
||||
dual_permission = self._decodeQtObject(reference,
|
||||
'dual_permission')
|
||||
dual_text = self._decodeQtObject(reference, 'dual_text')
|
||||
book = self._decodeQtObject(bitem, 'book')
|
||||
chapter = int(self._decodeQtObject(bitem, 'chapter'))
|
||||
verse = int(self._decodeQtObject(bitem, 'verse'))
|
||||
bible = self._decodeQtObject(bitem, 'bible')
|
||||
version = self._decodeQtObject(bitem, 'version')
|
||||
copyright = self._decodeQtObject(bitem, 'copyright')
|
||||
permission = self._decodeQtObject(bitem, 'permission')
|
||||
text = self._decodeQtObject(bitem, 'text')
|
||||
dual_bible = self._decodeQtObject(bitem, 'dual_bible')
|
||||
dual_version = self._decodeQtObject(bitem, 'dual_version')
|
||||
dual_copyright = self._decodeQtObject(bitem, 'dual_copyright')
|
||||
dual_permission = self._decodeQtObject(bitem, 'dual_permission')
|
||||
dual_text = self._decodeQtObject(bitem, 'dual_text')
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse)
|
||||
footer = u'%s (%s %s %s)' % (book, version, copyright, permission)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
if has_dual_bible:
|
||||
if dual_bible:
|
||||
footer = u'%s (%s %s %s)' % (book, dual_version,
|
||||
dual_copyright, dual_permission)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
# If there is an old bible_text we have to add it.
|
||||
if bible_text:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
bible_text = u'%s %s\n\n%s %s' % (verse_text, text,
|
||||
verse_text, dual_text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
elif self.parent.settings_tab.layout_style == 0:
|
||||
bible_text = u'%s %s' % (verse_text, text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
else:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
if dual_bible:
|
||||
footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright,
|
||||
dual_permission)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text,
|
||||
dual_text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# If we are 'Verse Per Slide' then create a new slide.
|
||||
elif self.parent.settings_tab.layout_style == 0:
|
||||
bible_text = u'%s %s' % (verse_text, text)
|
||||
@ -545,29 +559,31 @@ class BibleMediaItem(MediaManagerItem):
|
||||
# We have to be 'Continuous'.
|
||||
else:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
if first_item:
|
||||
start_item = item
|
||||
first_item = False
|
||||
elif self.checkTitle(item, old_item):
|
||||
raw_title.append(self.formatTitle(start_item, old_item))
|
||||
start_item = item
|
||||
old_item = item
|
||||
old_chapter = chapter
|
||||
raw_title.append(self.formatTitle(start_item, item))
|
||||
# If there are no more items we check whether we have to add bible_text.
|
||||
if bible_text:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# Service Item: Capabilities
|
||||
if self.parent.settings_tab.layout_style == 2 and not has_dual_bible:
|
||||
# split the line but do not replace line breaks in renderer
|
||||
if self.parent.settings_tab.layout_style == 2 and not dual_bible:
|
||||
# Split the line but do not replace line breaks in renderer.
|
||||
service_item.add_capability(ItemCapabilities.NoLineBreaks)
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
service_item.add_capability(ItemCapabilities.AllowsAdditions)
|
||||
# Service Item: Title
|
||||
if not service_item.title:
|
||||
if dual_bible:
|
||||
service_item.title = u'%s (%s, %s) %s' % (book, version,
|
||||
dual_version, verse_text)
|
||||
for title in raw_title:
|
||||
if not service_item.title:
|
||||
service_item.title = title
|
||||
else:
|
||||
service_item.title = u'%s (%s) %s' % (book, version, verse_text)
|
||||
elif service_item.title.find(
|
||||
translate('BiblesPlugin.MediaItem', 'etc')) == -1:
|
||||
service_item.title = u'%s, %s' % (service_item.title,
|
||||
translate('BiblesPlugin.MediaItem', 'etc'))
|
||||
service_item.title += u', ' + title
|
||||
# Service Item: Theme
|
||||
if len(self.parent.settings_tab.bible_theme) == 0:
|
||||
service_item.theme = None
|
||||
@ -582,12 +598,80 @@ class BibleMediaItem(MediaManagerItem):
|
||||
service_item.raw_footer = raw_footer
|
||||
return True
|
||||
|
||||
def formatTitle(self, start_item, old_item):
|
||||
"""
|
||||
This methode is called, when we have to change the title, because
|
||||
we are at the end of a verse range. E. g. if we want to add
|
||||
Genesis 1:1-6 as well as Daniel 2:14.
|
||||
"""
|
||||
old_bitem = self.listView.item(old_item.row())
|
||||
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter'))
|
||||
old_verse = int(self._decodeQtObject(old_bitem, 'verse'))
|
||||
start_bitem = self.listView.item(start_item.row())
|
||||
start_book = self._decodeQtObject(start_bitem, 'book')
|
||||
start_chapter = int(self._decodeQtObject(start_bitem, 'chapter'))
|
||||
start_verse = int(self._decodeQtObject(start_bitem, 'verse'))
|
||||
start_bible = self._decodeQtObject(start_bitem, 'bible')
|
||||
start_dual_bible = self._decodeQtObject(start_bitem, 'dual_bible')
|
||||
if start_dual_bible:
|
||||
if start_verse == old_verse and start_chapter == old_chapter:
|
||||
title = u'%s %s:%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, start_bible, start_dual_bible)
|
||||
elif start_chapter == old_chapter:
|
||||
title = u'%s %s:%s-%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, old_verse, start_bible, start_dual_bible)
|
||||
else:
|
||||
title = u'%s %s:%s-%s:%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, old_chapter, old_verse, start_bible,
|
||||
start_dual_bible)
|
||||
else:
|
||||
if start_verse == old_verse and start_chapter == old_chapter:
|
||||
title = u'%s %s:%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, start_bible)
|
||||
elif start_chapter == old_chapter:
|
||||
title = u'%s %s:%s-%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, old_verse, start_bible)
|
||||
else:
|
||||
title = u'%s %s:%s-%s:%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, old_chapter, old_verse, start_bible)
|
||||
return title
|
||||
|
||||
def checkTitle(self, item, old_item):
|
||||
"""
|
||||
This methode checks if we are at the end of an verse range. If that is
|
||||
the case, we return True, else False. E. g. if we added Genesis 1:1-6,
|
||||
but the next verse is Daniel 2:14.
|
||||
"""
|
||||
bitem = self.listView.item(item.row())
|
||||
book = self._decodeQtObject(bitem, 'book')
|
||||
chapter = int(self._decodeQtObject(bitem, 'chapter'))
|
||||
verse = int(self._decodeQtObject(bitem, 'verse'))
|
||||
bible = self._decodeQtObject(bitem, 'bible')
|
||||
dual_bible = self._decodeQtObject(bitem, 'dual_bible')
|
||||
old_bitem = self.listView.item(old_item.row())
|
||||
old_book = self._decodeQtObject(old_bitem, 'book')
|
||||
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter'))
|
||||
old_verse = int(self._decodeQtObject(old_bitem, 'verse'))
|
||||
old_bible = self._decodeQtObject(old_bitem, 'bible')
|
||||
old_dual_bible = self._decodeQtObject(old_bitem, 'dual_bible')
|
||||
if old_bible != bible or old_dual_bible != dual_bible or \
|
||||
old_book != book:
|
||||
return True
|
||||
elif old_verse + 1 != verse and old_chapter == chapter:
|
||||
return True
|
||||
elif old_chapter + 1 == chapter and (verse != 1 or
|
||||
old_verse != self.parent.manager.get_verse_count(
|
||||
old_bible, old_book, old_chapter)):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def formatVerse(self, old_chapter, chapter, verse):
|
||||
if not self.parent.settings_tab.show_new_chapters or \
|
||||
old_chapter != chapter:
|
||||
verse_text = chapter + u':' + verse
|
||||
verse_text = u'%s:%s' % (chapter, verse)
|
||||
else:
|
||||
verse_text = verse
|
||||
verse_text = u'%s' % verse
|
||||
if self.parent.settings_tab.display_style == 1:
|
||||
verse_text = u'{su}(' + verse_text + u'){/su}'
|
||||
elif self.parent.settings_tab.display_style == 2:
|
||||
@ -690,14 +774,15 @@ class BibleMediaItem(MediaManagerItem):
|
||||
'copyright': QtCore.QVariant(copyright.value),
|
||||
'permission': QtCore.QVariant(permission.value),
|
||||
'text': QtCore.QVariant(verse.text),
|
||||
'dual_bible': QtCore.QVariant(dual_bible)
|
||||
'dual_bible': QtCore.QVariant(u''),
|
||||
'dual_version': QtCore.QVariant(u''),
|
||||
'dual_copyright': QtCore.QVariant(u''),
|
||||
'dual_permission': QtCore.QVariant(u''),
|
||||
'dual_text': QtCore.QVariant(u'')
|
||||
}
|
||||
bible_text = u' %s %d:%d (%s)' % (verse.book.name,
|
||||
verse.chapter, verse.verse, version.value)
|
||||
# set the row title
|
||||
bible_verse = QtGui.QListWidgetItem(bible_text)
|
||||
#bible_verse.setData(QtCore.Qt.UserRole,
|
||||
# QtCore.QVariant(bible_text))
|
||||
bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(vdict))
|
||||
self.listView.addItem(bible_verse)
|
||||
row = self.listView.setCurrentRow(count + start_count)
|
||||
|
@ -47,7 +47,7 @@ class CustomPlugin(Plugin):
|
||||
log.info(u'Custom Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'Custom', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Custom', u'1.9.3', plugin_helpers)
|
||||
self.weight = -5
|
||||
self.custommanager = Manager(u'custom', init_schema)
|
||||
self.edit_custom_form = EditCustomForm(self.custommanager)
|
||||
|
@ -35,7 +35,7 @@ class ImagePlugin(Plugin):
|
||||
log.info(u'Image Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'Images', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Images', u'1.9.3', plugin_helpers)
|
||||
self.weight = -7
|
||||
self.icon_path = u':/plugins/plugin_images.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
@ -37,7 +37,7 @@ class MediaPlugin(Plugin):
|
||||
log.info(u'%s MediaPlugin loaded', __name__)
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'Media', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Media', u'1.9.3', plugin_helpers)
|
||||
self.weight = -6
|
||||
self.icon_path = u':/plugins/plugin_media.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
@ -74,6 +74,7 @@ class ImpressController(PresentationController):
|
||||
self.process = None
|
||||
self.desktop = None
|
||||
self.manager = None
|
||||
self.uno_connection_type = u'pipe' #u'socket'
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
@ -98,7 +99,14 @@ class ImpressController(PresentationController):
|
||||
self.manager._FlagAsMethod(u'Bridge_GetValueObject')
|
||||
else:
|
||||
# -headless
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized -invisible -nofirststartwizard -accept="socket,host=localhost,port=2002;urp;"'
|
||||
if self.uno_connection_type == u'pipe':
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized ' \
|
||||
+ u'-invisible -nofirststartwizard ' \
|
||||
+ u'-accept=pipe,name=openlp_pipe;urp;'
|
||||
else:
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized ' \
|
||||
+ u'-invisible -nofirststartwizard ' \
|
||||
+ u'-accept=socket,host=localhost,port=2002;urp;'
|
||||
self.process = QtCore.QProcess()
|
||||
self.process.startDetached(cmd)
|
||||
self.process.waitForStarted()
|
||||
@ -120,8 +128,14 @@ class ImpressController(PresentationController):
|
||||
while ctx is None and loop < 3:
|
||||
try:
|
||||
log.debug(u'get UNO Desktop Openoffice - resolve')
|
||||
ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;'
|
||||
u'urp;StarOffice.ComponentContext')
|
||||
if self.uno_connection_type == u'pipe':
|
||||
ctx = resolver.resolve(u'uno:' \
|
||||
+ u'pipe,name=openlp_pipe;' \
|
||||
+ u'urp;StarOffice.ComponentContext')
|
||||
else:
|
||||
ctx = resolver.resolve(u'uno:' \
|
||||
+ u'socket,host=localhost,port=2002;' \
|
||||
+ u'urp;StarOffice.ComponentContext')
|
||||
except:
|
||||
log.exception(u'Unable to find running instance ')
|
||||
self.start_process()
|
||||
|
@ -51,7 +51,7 @@ class PresentationPlugin(Plugin):
|
||||
"""
|
||||
log.debug(u'Initialised')
|
||||
self.controllers = {}
|
||||
Plugin.__init__(self, u'Presentations', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Presentations', u'1.9.3', plugin_helpers)
|
||||
self.weight = -8
|
||||
self.icon_path = u':/plugins/plugin_presentations.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
@ -38,7 +38,7 @@ class RemotesPlugin(Plugin):
|
||||
"""
|
||||
remotes constructor
|
||||
"""
|
||||
Plugin.__init__(self, u'Remotes', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Remotes', u'1.9.3', plugin_helpers)
|
||||
self.icon = build_icon(u':/plugins/plugin_remote.png')
|
||||
self.weight = -1
|
||||
self.server = None
|
||||
|
@ -629,7 +629,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.song.alternate_title = unicode(self.AlternativeEdit.text())
|
||||
self.song.copyright = unicode(self.CopyrightEditItem.text())
|
||||
self.song.search_title = self.song.title + u'@' + \
|
||||
unicode(self.AlternativeEdit.text())
|
||||
self.song.alternate_title
|
||||
self.song.comments = unicode(self.CommentsEdit.toPlainText())
|
||||
self.song.verse_order = unicode(self.VerseOrderEdit.text())
|
||||
self.song.ccli_number = unicode(self.CCLNumberEdit.text())
|
||||
@ -669,7 +669,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
unicode(self.VerseListWidget.item(i, 0).text())) + u' '
|
||||
if (bits[1] > u'1') and (bits[0][0] not in multiple):
|
||||
multiple.append(bits[0][0])
|
||||
self.song.search_lyrics = text
|
||||
self.song.search_lyrics = text.lower()
|
||||
self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||
for verse in multiple:
|
||||
self.song.verse_order = re.sub(u'([' + verse.upper() +
|
||||
@ -682,4 +682,4 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
def processTitle(self):
|
||||
log.debug(u'processTitle')
|
||||
self.song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'',
|
||||
unicode(self.song.search_title))
|
||||
unicode(self.song.search_title)).lower()
|
||||
|
@ -109,6 +109,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
QtCore.QObject.connect(self.genericRemoveButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onGenericRemoveButtonClicked)
|
||||
QtCore.QObject.connect(self.ewBrowseButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onEWBrowseButtonClicked)
|
||||
QtCore.QObject.connect(self.cancelButton,
|
||||
QtCore.SIGNAL(u'clicked(bool)'),
|
||||
self.onCancelButtonClicked)
|
||||
@ -214,6 +217,16 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
'presentation file to import from.'))
|
||||
self.genericAddButton.setFocus()
|
||||
return False
|
||||
elif source_format == SongFormat.EasyWorship:
|
||||
if self.ewFilenameEdit.text().isEmpty():
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'No EasyWorship Song Database Selected'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'You need to select an EasyWorship song database '
|
||||
'file to import from.'))
|
||||
self.ewBrowseButton.setFocus()
|
||||
return False
|
||||
return True
|
||||
elif self.currentId() == 2:
|
||||
# Progress page
|
||||
@ -322,6 +335,13 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
def onGenericRemoveButtonClicked(self):
|
||||
self.removeSelectedItems(self.genericFileListWidget)
|
||||
|
||||
def onEWBrowseButtonClicked(self):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select EasyWorship Database File'),
|
||||
self.ewFilenameEdit
|
||||
)
|
||||
|
||||
def onCancelButtonClicked(self, checked):
|
||||
"""
|
||||
Stop the import on pressing the cancel button.
|
||||
@ -341,6 +361,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
|
||||
def setDefaults(self):
|
||||
self.restart()
|
||||
self.finishButton.setVisible(False)
|
||||
self.cancelButton.setVisible(True)
|
||||
self.formatComboBox.setCurrentIndex(0)
|
||||
self.openLP2FilenameEdit.setText(u'')
|
||||
self.openLP1FilenameEdit.setText(u'')
|
||||
@ -350,6 +372,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.ccliFileListWidget.clear()
|
||||
self.songsOfFellowshipFileListWidget.clear()
|
||||
self.genericFileListWidget.clear()
|
||||
self.ewFilenameEdit.setText(u'')
|
||||
#self.csvFilenameEdit.setText(u'')
|
||||
|
||||
def incrementProgressBar(self, status_text, increment=1):
|
||||
@ -420,6 +443,11 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
importer = self.plugin.importSongs(SongFormat.Generic,
|
||||
filenames=self.getListOfFiles(self.genericFileListWidget)
|
||||
)
|
||||
elif source_format == SongFormat.EasyWorship:
|
||||
# Import an OpenLP 2.0 database
|
||||
importer = self.plugin.importSongs(SongFormat.EasyWorship,
|
||||
filename=unicode(self.ewFilenameEdit.text())
|
||||
)
|
||||
success = importer.do_import()
|
||||
if success:
|
||||
# reload songs
|
||||
|
@ -30,8 +30,8 @@ from openlp.core.lib import build_icon, translate
|
||||
|
||||
class Ui_SongImportWizard(object):
|
||||
def setupUi(self, songImportWizard):
|
||||
openIcon = build_icon(u':/general/general_open.png')
|
||||
deleteIcon = build_icon(u':/general/general_delete.png')
|
||||
self.openIcon = build_icon(u':/general/general_open.png')
|
||||
self.deleteIcon = build_icon(u':/general/general_delete.png')
|
||||
songImportWizard.setObjectName(u'songImportWizard')
|
||||
songImportWizard.resize(550, 386)
|
||||
songImportWizard.setModal(True)
|
||||
@ -88,15 +88,6 @@ class Ui_SongImportWizard(object):
|
||||
self.formatComboBox.sizePolicy().hasHeightForWidth())
|
||||
self.formatComboBox.setSizePolicy(sizePolicy)
|
||||
self.formatComboBox.setObjectName(u'formatComboBox')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
self.formatComboBox.addItem(u'')
|
||||
# self.formatComboBox.addItem(u'')
|
||||
self.formatLayout.addWidget(self.formatComboBox)
|
||||
self.formatSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
@ -105,338 +96,28 @@ class Ui_SongImportWizard(object):
|
||||
self.formatStackedWidget = QtGui.QStackedWidget(self.sourcePage)
|
||||
self.formatStackedWidget.setObjectName(u'FormatStackedWidget')
|
||||
# OpenLP 2.0
|
||||
self.openLP2Page = QtGui.QWidget()
|
||||
self.openLP2Page.setObjectName(u'openLP2Page')
|
||||
self.openLP2Layout = QtGui.QFormLayout(self.openLP2Page)
|
||||
self.openLP2Layout.setMargin(0)
|
||||
self.openLP2Layout.setSpacing(8)
|
||||
self.openLP2Layout.setObjectName(u'openLP2Layout')
|
||||
self.openLP2FilenameLabel = QtGui.QLabel(self.openLP2Page)
|
||||
self.openLP2FilenameLabel.setObjectName(u'openLP2FilenameLabel')
|
||||
self.openLP2Layout.setWidget(0, QtGui.QFormLayout.LabelRole,
|
||||
self.openLP2FilenameLabel)
|
||||
self.openLP2FileLayout = QtGui.QHBoxLayout()
|
||||
self.openLP2FileLayout.setSpacing(8)
|
||||
self.openLP2FileLayout.setObjectName(u'openLP2FileLayout')
|
||||
self.openLP2FilenameEdit = QtGui.QLineEdit(self.openLP2Page)
|
||||
self.openLP2FilenameEdit.setObjectName(u'openLP2FilenameEdit')
|
||||
self.openLP2FileLayout.addWidget(self.openLP2FilenameEdit)
|
||||
self.openLP2BrowseButton = QtGui.QToolButton(self.openLP2Page)
|
||||
self.openLP2BrowseButton.setIcon(openIcon)
|
||||
self.openLP2BrowseButton.setObjectName(u'openLP2BrowseButton')
|
||||
self.openLP2FileLayout.addWidget(self.openLP2BrowseButton)
|
||||
self.openLP2Layout.setLayout(0, QtGui.QFormLayout.FieldRole,
|
||||
self.openLP2FileLayout)
|
||||
self.formatStackedWidget.addWidget(self.openLP2Page)
|
||||
self.addSingleFileSelectItem(u'openLP2')
|
||||
# openlp.org 1.x
|
||||
self.openLP1Page = QtGui.QWidget()
|
||||
self.openLP1Page.setObjectName(u'openLP1Page')
|
||||
self.openLP1Layout = QtGui.QVBoxLayout(self.openLP1Page)
|
||||
self.openLP1Layout.setMargin(0)
|
||||
self.openLP1Layout.setSpacing(0)
|
||||
self.openLP1Layout.setObjectName(u'openLP1Layout')
|
||||
self.openLP1DisabledWidget = QtGui.QWidget(self.openLP1Page)
|
||||
self.openLP1DisabledLayout = QtGui.QVBoxLayout(self.openLP1DisabledWidget)
|
||||
self.openLP1DisabledLayout.setMargin(0)
|
||||
self.openLP1DisabledLayout.setSpacing(8)
|
||||
self.openLP1DisabledLayout.setObjectName(u'openLP1DisabledLayout')
|
||||
self.openLP1DisabledLabel = QtGui.QLabel(self.openLP1DisabledWidget)
|
||||
self.openLP1DisabledLabel.setWordWrap(True)
|
||||
self.openLP1DisabledLabel.setObjectName(u'openLP1DisabledLabel')
|
||||
self.openLP1DisabledLayout.addWidget(self.openLP1DisabledLabel)
|
||||
self.openLP1DisabledWidget.setVisible(False)
|
||||
self.openLP1Layout.addWidget(self.openLP1DisabledWidget)
|
||||
self.openLP1ImportWidget = QtGui.QWidget(self.openLP1Page)
|
||||
self.openLP1ImportLayout = QtGui.QFormLayout(self.openLP1ImportWidget)
|
||||
self.openLP1ImportLayout.setMargin(0)
|
||||
self.openLP1ImportLayout.setSpacing(8)
|
||||
self.openLP1ImportLayout.setObjectName(u'openLP1ImportLayout')
|
||||
self.openLP1FilenameLabel = QtGui.QLabel(self.openLP1ImportWidget)
|
||||
self.openLP1FilenameLabel.setObjectName(u'openLP1FilenameLabel')
|
||||
self.openLP1ImportLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
|
||||
self.openLP1FilenameLabel)
|
||||
self.openLP1FileLayout = QtGui.QHBoxLayout()
|
||||
self.openLP1FileLayout.setSpacing(8)
|
||||
self.openLP1FileLayout.setObjectName(u'openLP1FileLayout')
|
||||
self.openLP1FilenameEdit = QtGui.QLineEdit(self.openLP1ImportWidget)
|
||||
self.openLP1FilenameEdit.setObjectName(u'openLP1FilenameEdit')
|
||||
self.openLP1FileLayout.addWidget(self.openLP1FilenameEdit)
|
||||
self.openLP1BrowseButton = QtGui.QToolButton(self.openLP1ImportWidget)
|
||||
self.openLP1BrowseButton.setIcon(openIcon)
|
||||
self.openLP1BrowseButton.setObjectName(u'openLP1BrowseButton')
|
||||
self.openLP1FileLayout.addWidget(self.openLP1BrowseButton)
|
||||
self.openLP1ImportLayout.setLayout(0, QtGui.QFormLayout.FieldRole,
|
||||
self.openLP1FileLayout)
|
||||
self.openLP1Layout.addWidget(self.openLP1ImportWidget)
|
||||
self.formatStackedWidget.addWidget(self.openLP1Page)
|
||||
self.addSingleFileSelectItem(u'openLP1', None, True)
|
||||
# OpenLyrics
|
||||
self.openLyricsPage = QtGui.QWidget()
|
||||
self.openLyricsPage.setObjectName(u'OpenLyricsPage')
|
||||
self.openLyricsLayout = QtGui.QVBoxLayout(self.openLyricsPage)
|
||||
self.openLyricsLayout.setSpacing(8)
|
||||
self.openLyricsLayout.setMargin(0)
|
||||
self.openLyricsLayout.setObjectName(u'OpenLyricsLayout')
|
||||
self.openLyricsDisabledLabel = QtGui.QLabel(self.openLyricsPage)
|
||||
self.openLyricsDisabledLabel.setWordWrap(True)
|
||||
self.openLyricsDisabledLabel.setObjectName(u'openLyricsDisabledLabel')
|
||||
self.openLyricsLayout.addWidget(self.openLyricsDisabledLabel)
|
||||
# Commented out for future use.
|
||||
#self.openLyricsFileListWidget = QtGui.QListWidget(self.openLyricsPage)
|
||||
#self.openLyricsFileListWidget.setSelectionMode(
|
||||
# QtGui.QAbstractItemView.ExtendedSelection)
|
||||
#self.openLyricsFileListWidget.setObjectName(u'OpenLyricsFileListWidget')
|
||||
#self.openLyricsLayout.addWidget(self.openLyricsFileListWidget)
|
||||
#self.openLyricsButtonLayout = QtGui.QHBoxLayout()
|
||||
#self.openLyricsButtonLayout.setSpacing(8)
|
||||
#self.openLyricsButtonLayout.setObjectName(u'OpenLyricsButtonLayout')
|
||||
#self.openLyricsAddButton = QtGui.QPushButton(self.openLyricsPage)
|
||||
#self.openLyricsAddButton.setIcon(openIcon)
|
||||
#self.openLyricsAddButton.setObjectName(u'OpenLyricsAddButton')
|
||||
#self.openLyricsButtonLayout.addWidget(self.openLyricsAddButton)
|
||||
#self.openLyricsButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
# QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
#self.openLyricsButtonLayout.addItem(self.openLyricsButtonSpacer)
|
||||
#self.openLyricsRemoveButton = QtGui.QPushButton(self.openLyricsPage)
|
||||
#self.openLyricsRemoveButton.setIcon(deleteIcon)
|
||||
#self.openLyricsRemoveButton.setObjectName(u'OpenLyricsRemoveButton')
|
||||
#self.openLyricsButtonLayout.addWidget(self.openLyricsRemoveButton)
|
||||
#self.openLyricsLayout.addLayout(self.openLyricsButtonLayout)
|
||||
self.formatStackedWidget.addWidget(self.openLyricsPage)
|
||||
self.addMultiFileSelectItem(u'openLyrics', u'OpenLyrics', True)
|
||||
# set OpenLyrics to disabled by default
|
||||
self.openLyricsDisabledWidget.setVisible(True)
|
||||
self.openLyricsImportWidget.setVisible(False)
|
||||
# Open Song
|
||||
self.openSongPage = QtGui.QWidget()
|
||||
self.openSongPage.setObjectName(u'OpenSongPage')
|
||||
self.openSongLayout = QtGui.QVBoxLayout(self.openSongPage)
|
||||
self.openSongLayout.setSpacing(8)
|
||||
self.openSongLayout.setMargin(0)
|
||||
self.openSongLayout.setObjectName(u'OpenSongLayout')
|
||||
self.openSongFileListWidget = QtGui.QListWidget(self.openSongPage)
|
||||
self.openSongFileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.openSongFileListWidget.setObjectName(u'OpenSongFileListWidget')
|
||||
self.openSongLayout.addWidget(self.openSongFileListWidget)
|
||||
self.openSongButtonLayout = QtGui.QHBoxLayout()
|
||||
self.openSongButtonLayout.setSpacing(8)
|
||||
self.openSongButtonLayout.setObjectName(u'OpenSongButtonLayout')
|
||||
self.openSongAddButton = QtGui.QPushButton(self.openSongPage)
|
||||
self.openSongAddButton.setIcon(openIcon)
|
||||
self.openSongAddButton.setObjectName(u'OpenSongAddButton')
|
||||
self.openSongButtonLayout.addWidget(self.openSongAddButton)
|
||||
self.openSongButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.openSongButtonLayout.addItem(self.openSongButtonSpacer)
|
||||
self.openSongRemoveButton = QtGui.QPushButton(self.openSongPage)
|
||||
self.openSongRemoveButton.setIcon(deleteIcon)
|
||||
self.openSongRemoveButton.setObjectName(u'OpenSongRemoveButton')
|
||||
self.openSongButtonLayout.addWidget(self.openSongRemoveButton)
|
||||
self.openSongLayout.addLayout(self.openSongButtonLayout)
|
||||
self.formatStackedWidget.addWidget(self.openSongPage)
|
||||
self.addMultiFileSelectItem(u'openSong', u'OpenSong')
|
||||
# Words of Worship
|
||||
self.wordsOfWorshipPage = QtGui.QWidget()
|
||||
self.wordsOfWorshipPage.setObjectName(u'wordsOfWorshipPage')
|
||||
self.wordsOfWorshipLayout = QtGui.QVBoxLayout(self.wordsOfWorshipPage)
|
||||
self.wordsOfWorshipLayout.setSpacing(8)
|
||||
self.wordsOfWorshipLayout.setMargin(0)
|
||||
self.wordsOfWorshipLayout.setObjectName(u'wordsOfWorshipLayout')
|
||||
self.wordsOfWorshipFileListWidget = QtGui.QListWidget(
|
||||
self.wordsOfWorshipPage)
|
||||
self.wordsOfWorshipFileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.wordsOfWorshipFileListWidget.setObjectName(
|
||||
u'wordsOfWorshipFileListWidget')
|
||||
self.wordsOfWorshipLayout.addWidget(self.wordsOfWorshipFileListWidget)
|
||||
self.wordsOfWorshipButtonLayout = QtGui.QHBoxLayout()
|
||||
self.wordsOfWorshipButtonLayout.setSpacing(8)
|
||||
self.wordsOfWorshipButtonLayout.setObjectName(
|
||||
u'wordsOfWorshipButtonLayout')
|
||||
self.wordsOfWorshipAddButton = QtGui.QPushButton(
|
||||
self.wordsOfWorshipPage)
|
||||
self.wordsOfWorshipAddButton.setIcon(openIcon)
|
||||
self.wordsOfWorshipAddButton.setObjectName(u'wordsOfWorshipAddButton')
|
||||
self.wordsOfWorshipButtonLayout.addWidget(self.wordsOfWorshipAddButton)
|
||||
self.wordsOfWorshipButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.wordsOfWorshipButtonLayout.addItem(self.wordsOfWorshipButtonSpacer)
|
||||
self.wordsOfWorshipRemoveButton = QtGui.QPushButton(
|
||||
self.wordsOfWorshipPage)
|
||||
self.wordsOfWorshipRemoveButton.setIcon(deleteIcon)
|
||||
self.wordsOfWorshipRemoveButton.setObjectName(
|
||||
u'wordsOfWorshipRemoveButton')
|
||||
self.wordsOfWorshipButtonLayout.addWidget(
|
||||
self.wordsOfWorshipRemoveButton)
|
||||
self.wordsOfWorshipLayout.addLayout(self.wordsOfWorshipButtonLayout)
|
||||
self.formatStackedWidget.addWidget(self.wordsOfWorshipPage)
|
||||
self.addMultiFileSelectItem(u'wordsOfWorship')
|
||||
# CCLI File import
|
||||
self.ccliPage = QtGui.QWidget()
|
||||
self.ccliPage.setObjectName(u'ccliPage')
|
||||
self.ccliLayout = QtGui.QVBoxLayout(self.ccliPage)
|
||||
self.ccliLayout.setSpacing(8)
|
||||
self.ccliLayout.setMargin(0)
|
||||
self.ccliLayout.setObjectName(u'ccliLayout')
|
||||
self.ccliFileListWidget = QtGui.QListWidget(self.ccliPage)
|
||||
self.ccliFileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.ccliFileListWidget.setObjectName(u'ccliFileListWidget')
|
||||
self.ccliLayout.addWidget(self.ccliFileListWidget)
|
||||
self.ccliButtonLayout = QtGui.QHBoxLayout()
|
||||
self.ccliButtonLayout.setSpacing(8)
|
||||
self.ccliButtonLayout.setObjectName(u'ccliButtonLayout')
|
||||
self.ccliAddButton = QtGui.QPushButton(self.ccliPage)
|
||||
self.ccliAddButton.setIcon(openIcon)
|
||||
self.ccliAddButton.setObjectName(u'ccliAddButton')
|
||||
self.ccliButtonLayout.addWidget(self.ccliAddButton)
|
||||
self.ccliButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.ccliButtonLayout.addItem(self.ccliButtonSpacer)
|
||||
self.ccliRemoveButton = QtGui.QPushButton(self.ccliPage)
|
||||
self.ccliRemoveButton.setIcon(deleteIcon)
|
||||
self.ccliRemoveButton.setObjectName(u'ccliRemoveButton')
|
||||
self.ccliButtonLayout.addWidget(self.ccliRemoveButton)
|
||||
self.ccliLayout.addLayout(self.ccliButtonLayout)
|
||||
self.formatStackedWidget.addWidget(self.ccliPage)
|
||||
self.addMultiFileSelectItem(u'ccli')
|
||||
# Songs of Fellowship
|
||||
self.songsOfFellowshipPage = QtGui.QWidget()
|
||||
self.songsOfFellowshipPage.setObjectName(u'songsOfFellowshipPage')
|
||||
self.songsOfFellowshipLayout = QtGui.QVBoxLayout(
|
||||
self.songsOfFellowshipPage)
|
||||
self.songsOfFellowshipLayout.setMargin(0)
|
||||
self.songsOfFellowshipLayout.setSpacing(0)
|
||||
self.songsOfFellowshipLayout.setObjectName(u'songsOfFellowshipLayout')
|
||||
self.songsOfFellowshipDisabledWidget = QtGui.QWidget(
|
||||
self.songsOfFellowshipPage)
|
||||
self.songsOfFellowshipDisabledWidget.setVisible(False)
|
||||
self.songsOfFellowshipDisabledWidget.setObjectName(
|
||||
u'songsOfFellowshipDisabledWidget')
|
||||
self.songsOfFellowshipDisabledLayout = QtGui.QVBoxLayout(
|
||||
self.songsOfFellowshipDisabledWidget)
|
||||
self.songsOfFellowshipDisabledLayout.setMargin(0)
|
||||
self.songsOfFellowshipDisabledLayout.setSpacing(8)
|
||||
self.songsOfFellowshipDisabledLayout.setObjectName(
|
||||
u'songsOfFellowshipDisabledLayout')
|
||||
self.songsOfFellowshipDisabledLabel = QtGui.QLabel(
|
||||
self.songsOfFellowshipDisabledWidget)
|
||||
self.songsOfFellowshipDisabledLabel.setWordWrap(True)
|
||||
self.songsOfFellowshipDisabledLabel.setObjectName(
|
||||
u'songsOfFellowshipDisabledLabel')
|
||||
self.songsOfFellowshipDisabledLayout.addWidget(
|
||||
self.songsOfFellowshipDisabledLabel)
|
||||
self.songsOfFellowshipLayout.addWidget(
|
||||
self.songsOfFellowshipDisabledWidget)
|
||||
self.songsOfFellowshipImportWidget = QtGui.QWidget(
|
||||
self.songsOfFellowshipPage)
|
||||
self.songsOfFellowshipImportWidget.setObjectName(
|
||||
u'songsOfFellowshipImportWidget')
|
||||
self.songsOfFellowshipImportLayout = QtGui.QVBoxLayout(
|
||||
self.songsOfFellowshipImportWidget)
|
||||
self.songsOfFellowshipImportLayout.setMargin(0)
|
||||
self.songsOfFellowshipImportLayout.setSpacing(8)
|
||||
self.songsOfFellowshipImportLayout.setObjectName(
|
||||
u'songsOfFellowshipImportLayout')
|
||||
self.songsOfFellowshipFileListWidget = QtGui.QListWidget(
|
||||
self.songsOfFellowshipImportWidget)
|
||||
self.songsOfFellowshipFileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.songsOfFellowshipFileListWidget.setObjectName(
|
||||
u'songsOfFellowshipFileListWidget')
|
||||
self.songsOfFellowshipImportLayout.addWidget(
|
||||
self.songsOfFellowshipFileListWidget)
|
||||
self.songsOfFellowshipButtonLayout = QtGui.QHBoxLayout()
|
||||
self.songsOfFellowshipButtonLayout.setSpacing(8)
|
||||
self.songsOfFellowshipButtonLayout.setObjectName(
|
||||
u'songsOfFellowshipButtonLayout')
|
||||
self.songsOfFellowshipAddButton = QtGui.QPushButton(
|
||||
self.songsOfFellowshipImportWidget)
|
||||
self.songsOfFellowshipAddButton.setIcon(openIcon)
|
||||
self.songsOfFellowshipAddButton.setObjectName(
|
||||
u'songsOfFellowshipAddButton')
|
||||
self.songsOfFellowshipButtonLayout.addWidget(
|
||||
self.songsOfFellowshipAddButton)
|
||||
self.songsOfFellowshipButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.songsOfFellowshipButtonLayout.addItem(
|
||||
self.songsOfFellowshipButtonSpacer)
|
||||
self.songsOfFellowshipRemoveButton = QtGui.QPushButton(
|
||||
self.songsOfFellowshipImportWidget)
|
||||
self.songsOfFellowshipRemoveButton.setIcon(deleteIcon)
|
||||
self.songsOfFellowshipRemoveButton.setObjectName(
|
||||
u'songsOfFellowshipRemoveButton')
|
||||
self.songsOfFellowshipButtonLayout.addWidget(
|
||||
self.songsOfFellowshipRemoveButton)
|
||||
self.songsOfFellowshipImportLayout.addLayout(
|
||||
self.songsOfFellowshipButtonLayout)
|
||||
self.songsOfFellowshipLayout.addWidget(
|
||||
self.songsOfFellowshipImportWidget)
|
||||
self.formatStackedWidget.addWidget(self.songsOfFellowshipPage)
|
||||
self.addMultiFileSelectItem(u'songsOfFellowship', None, True)
|
||||
# Generic Document/Presentation import
|
||||
self.genericPage = QtGui.QWidget()
|
||||
self.genericPage.setObjectName(u'genericPage')
|
||||
self.genericLayout = QtGui.QVBoxLayout(self.genericPage)
|
||||
self.genericLayout.setMargin(0)
|
||||
self.genericLayout.setSpacing(0)
|
||||
self.genericLayout.setObjectName(u'genericLayout')
|
||||
self.genericDisabledWidget = QtGui.QWidget(self.genericPage)
|
||||
self.genericDisabledWidget.setObjectName(u'genericDisabledWidget')
|
||||
self.genericDisabledLayout = QtGui.QVBoxLayout(self.genericDisabledWidget)
|
||||
self.genericDisabledLayout.setMargin(0)
|
||||
self.genericDisabledLayout.setSpacing(8)
|
||||
self.genericDisabledLayout.setObjectName(u'genericDisabledLayout')
|
||||
self.genericDisabledLabel = QtGui.QLabel(self.genericDisabledWidget)
|
||||
self.genericDisabledLabel.setWordWrap(True)
|
||||
self.genericDisabledLabel.setObjectName(u'genericDisabledLabel')
|
||||
self.genericDisabledWidget.setVisible(False)
|
||||
self.genericDisabledLayout.addWidget(self.genericDisabledLabel)
|
||||
self.genericLayout.addWidget(self.genericDisabledWidget)
|
||||
self.genericImportWidget = QtGui.QWidget(self.genericPage)
|
||||
self.genericImportWidget.setObjectName(u'genericImportWidget')
|
||||
self.genericImportLayout = QtGui.QVBoxLayout(self.genericImportWidget)
|
||||
self.genericImportLayout.setMargin(0)
|
||||
self.genericImportLayout.setSpacing(8)
|
||||
self.genericImportLayout.setObjectName(u'genericImportLayout')
|
||||
self.genericFileListWidget = QtGui.QListWidget(self.genericImportWidget)
|
||||
self.genericFileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.genericFileListWidget.setObjectName(u'genericFileListWidget')
|
||||
self.genericImportLayout.addWidget(self.genericFileListWidget)
|
||||
self.genericButtonLayout = QtGui.QHBoxLayout()
|
||||
self.genericButtonLayout.setSpacing(8)
|
||||
self.genericButtonLayout.setObjectName(u'genericButtonLayout')
|
||||
self.genericAddButton = QtGui.QPushButton(self.genericImportWidget)
|
||||
self.genericAddButton.setIcon(openIcon)
|
||||
self.genericAddButton.setObjectName(u'genericAddButton')
|
||||
self.genericButtonLayout.addWidget(self.genericAddButton)
|
||||
self.genericButtonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.genericButtonLayout.addItem(self.genericButtonSpacer)
|
||||
self.genericRemoveButton = QtGui.QPushButton(self.genericImportWidget)
|
||||
self.genericRemoveButton.setIcon(deleteIcon)
|
||||
self.genericRemoveButton.setObjectName(u'genericRemoveButton')
|
||||
self.genericButtonLayout.addWidget(self.genericRemoveButton)
|
||||
self.genericImportLayout.addLayout(self.genericButtonLayout)
|
||||
self.genericLayout.addWidget(self.genericImportWidget)
|
||||
self.formatStackedWidget.addWidget(self.genericPage)
|
||||
self.addMultiFileSelectItem(u'generic', None, True)
|
||||
# EasyWorship
|
||||
self.addSingleFileSelectItem(u'ew')
|
||||
# Commented out for future use.
|
||||
# self.csvPage = QtGui.QWidget()
|
||||
# self.csvPage.setObjectName(u'CSVPage')
|
||||
# self.csvLayout = QtGui.QFormLayout(self.csvPage)
|
||||
# self.csvLayout.setMargin(0)
|
||||
# self.csvLayout.setSpacing(8)
|
||||
# self.csvLayout.setObjectName(u'CSVLayout')
|
||||
# self.csvFilenameLabel = QtGui.QLabel(self.csvPage)
|
||||
# self.csvFilenameLabel.setObjectName(u'CSVFilenameLabel')
|
||||
# self.csvLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
|
||||
# self.csvFilenameLabel)
|
||||
# self.csvFileLayout = QtGui.QHBoxLayout()
|
||||
# self.csvFileLayout.setSpacing(8)
|
||||
# self.csvFileLayout.setObjectName(u'CSVFileLayout')
|
||||
# self.csvFilenameEdit = QtGui.QLineEdit(self.csvPage)
|
||||
# self.csvFilenameEdit.setObjectName(u'CSVFilenameEdit')
|
||||
# self.csvFileLayout.addWidget(self.csvFilenameEdit)
|
||||
# self.csvBrowseButton = QtGui.QToolButton(self.csvPage)
|
||||
# self.csvBrowseButton.setIcon(openIcon)
|
||||
# self.csvBrowseButton.setObjectName(u'CSVBrowseButton')
|
||||
# self.csvFileLayout.addWidget(self.csvBrowseButton)
|
||||
# self.csvLayout.setLayout(0, QtGui.QFormLayout.FieldRole,
|
||||
# self.csvFileLayout)
|
||||
# self.formatStackedWidget.addWidget(self.csvPage)
|
||||
# self.addSingleFileSelectItem(u'csv', u'CSV')
|
||||
self.sourceLayout.addWidget(self.formatStackedWidget)
|
||||
songImportWizard.addPage(self.sourcePage)
|
||||
self.importPage = QtGui.QWizardPage()
|
||||
@ -497,7 +178,9 @@ class Ui_SongImportWizard(object):
|
||||
self.formatComboBox.setItemText(7,
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Generic Document/Presentation'))
|
||||
# self.formatComboBox.setItemText(8,
|
||||
self.formatComboBox.setItemText(8,
|
||||
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
|
||||
# self.formatComboBox.setItemText(9,
|
||||
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
|
||||
self.openLP2FilenameLabel.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
@ -549,6 +232,10 @@ class Ui_SongImportWizard(object):
|
||||
translate('SongsPlugin.ImportWizardForm', 'The generic document/'
|
||||
'presentation importer has been disabled because OpenLP cannot '
|
||||
'find OpenOffice.org on your computer.'))
|
||||
self.ewFilenameLabel.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
self.ewBrowseButton.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Browse...'))
|
||||
# self.csvFilenameLabel.setText(
|
||||
# translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
# self.csvBrowseButton.setText(
|
||||
@ -562,3 +249,123 @@ class Ui_SongImportWizard(object):
|
||||
translate('SongsPlugin.ImportWizardForm', 'Ready.'))
|
||||
self.importProgressBar.setFormat(
|
||||
translate('SongsPlugin.ImportWizardForm', '%p%'))
|
||||
|
||||
def addSingleFileSelectItem(self, prefix, obj_prefix=None,
|
||||
can_disable=False):
|
||||
if not obj_prefix:
|
||||
obj_prefix = prefix
|
||||
page = QtGui.QWidget()
|
||||
page.setObjectName(obj_prefix + u'Page')
|
||||
if can_disable:
|
||||
importWidget = self.disablableWidget(page, prefix, obj_prefix)
|
||||
else:
|
||||
importWidget = page
|
||||
importLayout = QtGui.QFormLayout(importWidget)
|
||||
importLayout.setMargin(0)
|
||||
importLayout.setSpacing(8)
|
||||
if can_disable:
|
||||
importLayout.setObjectName(obj_prefix + u'ImportLayout')
|
||||
else:
|
||||
importLayout.setObjectName(obj_prefix + u'Layout')
|
||||
filenameLabel = QtGui.QLabel(importWidget)
|
||||
filenameLabel.setObjectName(obj_prefix + u'FilenameLabel')
|
||||
importLayout.setWidget(0, QtGui.QFormLayout.LabelRole, filenameLabel)
|
||||
fileLayout = QtGui.QHBoxLayout()
|
||||
fileLayout.setSpacing(8)
|
||||
fileLayout.setObjectName(obj_prefix + u'FileLayout')
|
||||
filenameEdit = QtGui.QLineEdit(importWidget)
|
||||
filenameEdit.setObjectName(obj_prefix + u'FilenameEdit')
|
||||
fileLayout.addWidget(filenameEdit)
|
||||
browseButton = QtGui.QToolButton(importWidget)
|
||||
browseButton.setIcon(self.openIcon)
|
||||
browseButton.setObjectName(obj_prefix + u'BrowseButton')
|
||||
fileLayout.addWidget(browseButton)
|
||||
importLayout.setLayout(0, QtGui.QFormLayout.FieldRole, fileLayout)
|
||||
self.formatStackedWidget.addWidget(page)
|
||||
setattr(self, prefix + u'Page', page)
|
||||
setattr(self, prefix + u'FilenameLabel', filenameLabel)
|
||||
setattr(self, prefix + u'FileLayout', fileLayout)
|
||||
setattr(self, prefix + u'FilenameEdit', filenameEdit)
|
||||
setattr(self, prefix + u'BrowseButton', browseButton)
|
||||
if can_disable:
|
||||
setattr(self, prefix + u'ImportLayout', importLayout)
|
||||
else:
|
||||
setattr(self, prefix + u'Layout', importLayout)
|
||||
self.formatComboBox.addItem(u'')
|
||||
|
||||
def addMultiFileSelectItem(self, prefix, obj_prefix=None,
|
||||
can_disable=False):
|
||||
if not obj_prefix:
|
||||
obj_prefix = prefix
|
||||
page = QtGui.QWidget()
|
||||
page.setObjectName(obj_prefix + u'Page')
|
||||
if can_disable:
|
||||
importWidget = self.disablableWidget(page, prefix, obj_prefix)
|
||||
else:
|
||||
importWidget = page
|
||||
importLayout = QtGui.QVBoxLayout(importWidget)
|
||||
importLayout.setMargin(0)
|
||||
importLayout.setSpacing(8)
|
||||
if can_disable:
|
||||
importLayout.setObjectName(obj_prefix + u'ImportLayout')
|
||||
else:
|
||||
importLayout.setObjectName(obj_prefix + u'Layout')
|
||||
fileListWidget = QtGui.QListWidget(importWidget)
|
||||
fileListWidget.setSelectionMode(
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
fileListWidget.setObjectName(obj_prefix + u'FileListWidget')
|
||||
importLayout.addWidget(fileListWidget)
|
||||
buttonLayout = QtGui.QHBoxLayout()
|
||||
buttonLayout.setSpacing(8)
|
||||
buttonLayout.setObjectName(obj_prefix + u'ButtonLayout')
|
||||
addButton = QtGui.QPushButton(importWidget)
|
||||
addButton.setIcon(self.openIcon)
|
||||
addButton.setObjectName(obj_prefix + u'AddButton')
|
||||
buttonLayout.addWidget(addButton)
|
||||
buttonSpacer = QtGui.QSpacerItem(40, 20,
|
||||
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
buttonLayout.addItem(buttonSpacer)
|
||||
removeButton = QtGui.QPushButton(importWidget)
|
||||
removeButton.setIcon(self.deleteIcon)
|
||||
removeButton.setObjectName(obj_prefix + u'RemoveButton')
|
||||
buttonLayout.addWidget(removeButton)
|
||||
importLayout.addLayout(buttonLayout)
|
||||
self.formatStackedWidget.addWidget(page)
|
||||
setattr(self, prefix + u'Page', page)
|
||||
setattr(self, prefix + u'FileListWidget', fileListWidget)
|
||||
setattr(self, prefix + u'ButtonLayout', buttonLayout)
|
||||
setattr(self, prefix + u'ButtonSpacer', buttonSpacer)
|
||||
setattr(self, prefix + u'AddButton', addButton)
|
||||
setattr(self, prefix + u'RemoveButton', removeButton)
|
||||
if can_disable:
|
||||
setattr(self, prefix + u'ImportLayout', importLayout)
|
||||
else:
|
||||
setattr(self, prefix + u'Layout', importLayout)
|
||||
self.formatComboBox.addItem(u'')
|
||||
|
||||
def disablableWidget(self, page, prefix, obj_prefix):
|
||||
layout = QtGui.QVBoxLayout(page)
|
||||
layout.setMargin(0)
|
||||
layout.setSpacing(0)
|
||||
layout.setObjectName(obj_prefix + u'Layout')
|
||||
disabledWidget = QtGui.QWidget(page)
|
||||
disabledWidget.setVisible(False)
|
||||
disabledWidget.setObjectName(obj_prefix + u'DisabledWidget')
|
||||
disabledLayout = QtGui.QVBoxLayout(disabledWidget)
|
||||
disabledLayout.setMargin(0)
|
||||
disabledLayout.setSpacing(8)
|
||||
disabledLayout.setObjectName(obj_prefix + u'DisabledLayout')
|
||||
disabledLabel = QtGui.QLabel(disabledWidget)
|
||||
disabledLabel.setWordWrap(True)
|
||||
disabledLabel.setObjectName(obj_prefix + u'DisabledLabel')
|
||||
disabledLayout.addWidget(disabledLabel)
|
||||
layout.addWidget(disabledWidget)
|
||||
importWidget = QtGui.QWidget(page)
|
||||
importWidget.setObjectName(obj_prefix + u'ImportWidget')
|
||||
layout.addWidget(importWidget)
|
||||
setattr(self, prefix + u'Layout', layout)
|
||||
setattr(self, prefix + u'DisabledWidget', disabledWidget)
|
||||
setattr(self, prefix + u'DisabledLayout', disabledLayout)
|
||||
setattr(self, prefix + u'DisabledLabel', disabledLabel)
|
||||
setattr(self, prefix + u'ImportWidget', importWidget)
|
||||
return importWidget
|
||||
|
255
openlp/plugins/songs/lib/ewimport.py
Normal file
255
openlp/plugins/songs/lib/ewimport.py
Normal file
@ -0,0 +1,255 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
"""
|
||||
The :mod:`ewimport` module provides the functionality for importing
|
||||
EasyWorship song databases into the current installation database.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import struct
|
||||
|
||||
from songimport import SongImport
|
||||
|
||||
def strip_rtf(blob):
|
||||
depth = 0
|
||||
control = False
|
||||
clear_text = []
|
||||
control_word = []
|
||||
for c in blob:
|
||||
if control:
|
||||
# for delimiters, set control to False
|
||||
if c == '{':
|
||||
if len(control_word) > 0:
|
||||
depth += 1
|
||||
control = False
|
||||
elif c == '}':
|
||||
if len(control_word) > 0:
|
||||
depth -= 1
|
||||
control = False
|
||||
elif c == '\\':
|
||||
new_control = (len(control_word) > 0)
|
||||
control = False
|
||||
elif c.isspace():
|
||||
control = False
|
||||
else:
|
||||
control_word.append(c)
|
||||
if len(control_word) == 3 and control_word[0] == '\'':
|
||||
control = False
|
||||
if not control:
|
||||
if len(control_word) == 0:
|
||||
if c == '{' or c == '}' or c == '\\':
|
||||
clear_text.append(c)
|
||||
else:
|
||||
control_str = ''.join(control_word)
|
||||
if control_str == 'par' or control_str == 'line':
|
||||
clear_text.append(u'\n')
|
||||
elif control_str == 'tab':
|
||||
clear_text.append(u'\n')
|
||||
elif control_str[0] == '\'':
|
||||
# Really should take RTF character set into account but
|
||||
# for now assume ANSI (Windows-1252) and call it good
|
||||
s = chr(int(control_str[1:3], 16))
|
||||
clear_text.append(s.decode(u'windows-1252'))
|
||||
del control_word[:]
|
||||
if c == '\\' and new_control:
|
||||
control = True
|
||||
elif c == '{':
|
||||
depth += 1
|
||||
elif c == '}':
|
||||
depth -= 1
|
||||
elif depth > 2:
|
||||
continue
|
||||
elif c == '\n' or c == '\r':
|
||||
continue
|
||||
elif c == '\\':
|
||||
control = True
|
||||
else:
|
||||
clear_text.append(c)
|
||||
return u''.join(clear_text)
|
||||
|
||||
class FieldDescEntry:
|
||||
def __init__(self, name, type, size):
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.size = size
|
||||
|
||||
class EasyWorshipSongImport(SongImport):
|
||||
"""
|
||||
The :class:`EasyWorshipSongImport` class provides OpenLP with the
|
||||
ability to import EasyWorship song files.
|
||||
"""
|
||||
def __init__(self, manager, **kwargs):
|
||||
self.import_source = kwargs[u'filename']
|
||||
SongImport.__init__(self, manager)
|
||||
|
||||
def do_import(self):
|
||||
# Open the DB and MB files if they exist
|
||||
import_source_mb = self.import_source.replace('.DB', '.MB')
|
||||
if not os.path.isfile(self.import_source):
|
||||
return False
|
||||
if not os.path.isfile(import_source_mb):
|
||||
return False
|
||||
db_size = os.path.getsize(self.import_source)
|
||||
if db_size < 0x800:
|
||||
return False
|
||||
db_file = open(self.import_source, 'rb')
|
||||
self.memo_file = open(import_source_mb, 'rb')
|
||||
# Don't accept files that are clearly not paradox files
|
||||
record_size, header_size, block_size, first_block, num_fields \
|
||||
= struct.unpack('<hhxb8xh17xh', db_file.read(35))
|
||||
if header_size != 0x800 or block_size < 1 or block_size > 4:
|
||||
db_file.close()
|
||||
self.memo_file.close()
|
||||
return False
|
||||
# There does not appear to be a _reliable_ way of getting the number
|
||||
# of songs/records, so let's use file blocks for measuring progress.
|
||||
total_blocks = (db_size - header_size) / (block_size * 1024)
|
||||
self.import_wizard.importProgressBar.setMaximum(total_blocks)
|
||||
# Read the field description information
|
||||
db_file.seek(120)
|
||||
field_info = db_file.read(num_fields * 2)
|
||||
db_file.seek(4 + (num_fields * 4) + 261, os.SEEK_CUR)
|
||||
field_names = db_file.read(header_size - db_file.tell()).split('\0',
|
||||
num_fields)
|
||||
field_names.pop()
|
||||
field_descs = []
|
||||
for i,field_name in enumerate(field_names):
|
||||
field_type, field_size = struct.unpack_from('BB', field_info, i * 2)
|
||||
field_descs.append(FieldDescEntry(field_name, field_type,
|
||||
field_size))
|
||||
self.set_record_struct(field_descs)
|
||||
# Pick out the field description indexes we will need
|
||||
success = True
|
||||
try:
|
||||
fi_title = self.find_field(u'Title')
|
||||
fi_author = self.find_field(u'Author')
|
||||
fi_copy = self.find_field(u'Copyright')
|
||||
fi_admin = self.find_field(u'Administrator')
|
||||
fi_words = self.find_field(u'Words')
|
||||
fi_ccli = self.find_field(u'Song Number')
|
||||
except IndexError:
|
||||
# This is the wrong table
|
||||
success = False
|
||||
# Loop through each block of the file
|
||||
cur_block = first_block
|
||||
while cur_block != 0 and success:
|
||||
db_file.seek(header_size + ((cur_block - 1) * 1024 * block_size))
|
||||
cur_block, rec_count = struct.unpack('<h2xh', db_file.read(6))
|
||||
rec_count = (rec_count + record_size) / record_size
|
||||
# Loop through each record within the current block
|
||||
for i in range(rec_count):
|
||||
if self.stop_import_flag:
|
||||
success = False
|
||||
break
|
||||
raw_record = db_file.read(record_size)
|
||||
self.fields = self.record_struct.unpack(raw_record)
|
||||
self.set_defaults()
|
||||
self.title = self.get_field(fi_title)
|
||||
self.import_wizard.incrementProgressBar(
|
||||
u'Importing "%s"...' % self.title, 0)
|
||||
self.copyright = self.get_field(fi_copy) + \
|
||||
u', Administered by ' + self.get_field(fi_admin)
|
||||
self.ccli_number = self.get_field(fi_ccli)
|
||||
# Format the lyrics
|
||||
if self.stop_import_flag:
|
||||
success = False
|
||||
break
|
||||
words = self.get_field(fi_words)
|
||||
words = strip_rtf(words)
|
||||
for verse in words.split(u'\n\n'):
|
||||
self.add_verse(verse.strip(), u'V')
|
||||
# Split up the authors
|
||||
authors = self.get_field(fi_author)
|
||||
author_list = authors.split(u'/')
|
||||
if len(author_list) < 2:
|
||||
author_list = authors.split(u',')
|
||||
for author_name in author_list:
|
||||
self.add_author(author_name.strip())
|
||||
if self.stop_import_flag:
|
||||
success = False
|
||||
break
|
||||
self.finish()
|
||||
if not self.stop_import_flag:
|
||||
self.import_wizard.incrementProgressBar(u'')
|
||||
db_file.close()
|
||||
self.memo_file.close()
|
||||
return success
|
||||
|
||||
def find_field(self, field_name):
|
||||
return [i for i,x in enumerate(self.field_descs) \
|
||||
if x.name == field_name][0]
|
||||
|
||||
def set_record_struct(self, field_descs):
|
||||
# Begin with empty field struct list
|
||||
fsl = ['>']
|
||||
for field_desc in field_descs:
|
||||
if field_desc.type == 1:
|
||||
# string
|
||||
fsl.append('%ds' % field_desc.size)
|
||||
elif field_desc.type == 3:
|
||||
# 16-bit int
|
||||
fsl.append('H')
|
||||
elif field_desc.type == 4:
|
||||
# 32-bit int
|
||||
fsl.append('I')
|
||||
elif field_desc.type == 9:
|
||||
# Logical
|
||||
fsl.append('B')
|
||||
elif field_desc.type == 0x0c:
|
||||
# Memo
|
||||
fsl.append('%ds' % field_desc.size)
|
||||
elif field_desc.type == 0x0d:
|
||||
# Blob
|
||||
fsl.append('%ds' % field_desc.size)
|
||||
elif field_desc.type == 0x15:
|
||||
# Timestamp
|
||||
fsl.append('Q')
|
||||
else:
|
||||
fsl.append('%ds' % field_desc.size)
|
||||
self.record_struct = struct.Struct(''.join(fsl))
|
||||
self.field_descs = field_descs
|
||||
|
||||
def get_field(self, field_desc_index):
|
||||
field = self.fields[field_desc_index]
|
||||
field_desc = self.field_descs[field_desc_index]
|
||||
# Check for 'blank' entries
|
||||
if isinstance(field, str):
|
||||
if len(field.rstrip('\0')) == 0:
|
||||
return u''
|
||||
elif field == 0:
|
||||
return 0
|
||||
# Format the field depending on the field type
|
||||
if field_desc.type == 1:
|
||||
# string
|
||||
return field.rstrip('\0').decode(u'windows-1252')
|
||||
elif field_desc.type == 3:
|
||||
# 16-bit int
|
||||
return field ^ 0x8000
|
||||
elif field_desc.type == 4:
|
||||
# 32-bit int
|
||||
return field ^ 0x80000000
|
||||
elif field_desc.type == 9:
|
||||
# Logical
|
||||
return (field ^ 0x80 == 1)
|
||||
elif field_desc.type == 0x0c or field_desc.type == 0x0d:
|
||||
# Memo or Blob
|
||||
sub_block, block_start, blob_size = \
|
||||
struct.unpack_from('<bhxi', field, len(field)-10)
|
||||
self.memo_file.seek(block_start * 256)
|
||||
memo_block_type, = struct.unpack('b', self.memo_file.read(1))
|
||||
if memo_block_type == 2:
|
||||
self.memo_file.seek(8, os.SEEK_CUR)
|
||||
elif memo_block_type == 3:
|
||||
if sub_block < 0 or sub_block > 63:
|
||||
return u'';
|
||||
self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR)
|
||||
sub_block_start, = struct.unpack('B', self.memo_file.read(1))
|
||||
self.memo_file.seek((block_start * 256) +
|
||||
(sub_block_start * 16))
|
||||
else:
|
||||
return u'';
|
||||
return self.memo_file.read(blob_size)
|
||||
else:
|
||||
return 0
|
@ -28,6 +28,7 @@ from opensongimport import OpenSongImport
|
||||
from olpimport import OpenLPSongImport
|
||||
from wowimport import WowImport
|
||||
from cclifileimport import CCLIFileImport
|
||||
from ewimport import EasyWorshipSongImport
|
||||
# Imports that might fail
|
||||
try:
|
||||
from olp1import import OpenLP1SongImport
|
||||
@ -61,7 +62,8 @@ class SongFormat(object):
|
||||
CCLI = 5
|
||||
SongsOfFellowship = 6
|
||||
Generic = 7
|
||||
CSV = 8
|
||||
#CSV = 8
|
||||
EasyWorship = 8
|
||||
|
||||
@staticmethod
|
||||
def get_class(format):
|
||||
@ -85,6 +87,8 @@ class SongFormat(object):
|
||||
return OooImport
|
||||
elif format == SongFormat.CCLI:
|
||||
return CCLIFileImport
|
||||
elif format == SongFormat.EasyWorship:
|
||||
return EasyWorshipSongImport
|
||||
# else:
|
||||
return None
|
||||
|
||||
@ -101,7 +105,8 @@ class SongFormat(object):
|
||||
SongFormat.WordsOfWorship,
|
||||
SongFormat.CCLI,
|
||||
SongFormat.SongsOfFellowship,
|
||||
SongFormat.Generic
|
||||
SongFormat.Generic,
|
||||
SongFormat.EasyWorship
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
|
@ -166,13 +166,13 @@ class SongMediaItem(MediaManagerItem):
|
||||
if search_type == 0:
|
||||
log.debug(u'Titles Search')
|
||||
search_results = self.parent.manager.get_all_objects(Song,
|
||||
Song.search_title.like(u'%' + search_keywords + u'%'),
|
||||
Song.search_title.like(u'%' + search_keywords.lower() + u'%'),
|
||||
Song.search_title.asc())
|
||||
self.displayResultsSong(search_results)
|
||||
elif search_type == 1:
|
||||
log.debug(u'Lyrics Search')
|
||||
search_results = self.parent.manager.get_all_objects(Song,
|
||||
Song.search_lyrics.like(u'%' + search_keywords + u'%'),
|
||||
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'),
|
||||
Song.search_lyrics.asc())
|
||||
self.displayResultsSong(search_results)
|
||||
elif search_type == 2:
|
||||
|
@ -59,6 +59,7 @@ class OooImport(SongImport):
|
||||
self.document = None
|
||||
self.process_started = False
|
||||
self.filenames = kwargs[u'filenames']
|
||||
self.uno_connection_type = u'pipe' #u'socket'
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'song_stop_import'), self.stop_import)
|
||||
|
||||
@ -106,8 +107,14 @@ class OooImport(SongImport):
|
||||
loop = 0
|
||||
while ctx is None and loop < 5:
|
||||
try:
|
||||
ctx = resolver.resolve(u'uno:socket,host=localhost,' \
|
||||
+ 'port=2002;urp;StarOffice.ComponentContext')
|
||||
if self.uno_connection_type == u'pipe':
|
||||
ctx = resolver.resolve(u'uno:' \
|
||||
+ u'pipe,name=openlp_pipe;' \
|
||||
+ u'urp;StarOffice.ComponentContext')
|
||||
else:
|
||||
ctx = resolver.resolve(u'uno:' \
|
||||
+ u'socket,host=localhost,port=2002;' \
|
||||
+ u'urp;StarOffice.ComponentContext')
|
||||
except:
|
||||
pass
|
||||
self.start_ooo_process()
|
||||
@ -123,9 +130,14 @@ class OooImport(SongImport):
|
||||
self.manager._FlagAsMethod(u'Bridge_GetStruct')
|
||||
self.manager._FlagAsMethod(u'Bridge_GetValueObject')
|
||||
else:
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized ' \
|
||||
+ u'-invisible -nofirststartwizard ' \
|
||||
+ '-accept="socket,host=localhost,port=2002;urp;"'
|
||||
if self.uno_connection_type == u'pipe':
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized ' \
|
||||
+ u'-invisible -nofirststartwizard ' \
|
||||
+ u'-accept=pipe,name=openlp_pipe;urp;'
|
||||
else:
|
||||
cmd = u'openoffice.org -nologo -norestore -minimized ' \
|
||||
+ u'-invisible -nofirststartwizard ' \
|
||||
+ u'-accept=socket,host=localhost,port=2002;urp;'
|
||||
process = QtCore.QProcess()
|
||||
process.startDetached(cmd)
|
||||
process.waitForStarted()
|
||||
|
@ -55,6 +55,7 @@ class SongImport(QtCore.QObject):
|
||||
self.set_defaults()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'songs_stop_import'), self.stop_import)
|
||||
|
||||
def set_defaults(self):
|
||||
"""
|
||||
Create defaults for properties - call this before each song
|
||||
@ -262,8 +263,8 @@ class SongImport(QtCore.QObject):
|
||||
log.info(u'commiting song %s to database', self.title)
|
||||
song = Song()
|
||||
song.title = self.title
|
||||
song.search_title = self.remove_punctuation(self.title) \
|
||||
+ '@' + self.alternate_title
|
||||
song.search_title = self.remove_punctuation(self.title).lower() \
|
||||
+ '@' + self.remove_punctuation(self.alternate_title).lower()
|
||||
song.song_number = self.song_number
|
||||
song.search_lyrics = u''
|
||||
verses_changed_to_other = {}
|
||||
@ -291,6 +292,7 @@ class SongImport(QtCore.QObject):
|
||||
versetag = newversetag
|
||||
sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext)
|
||||
song.search_lyrics += u' ' + self.remove_punctuation(versetext)
|
||||
song.search_lyrics = song.search_lyrics.lower()
|
||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||
for i, current_verse_tag in enumerate(self.verse_order_list):
|
||||
if verses_changed_to_other.has_key(current_verse_tag):
|
||||
|
0
openlp/plugins/songs/lib/test/test3.opensong
Executable file → Normal file
0
openlp/plugins/songs/lib/test/test3.opensong
Executable file → Normal file
@ -50,7 +50,7 @@ class SongsPlugin(Plugin):
|
||||
"""
|
||||
Create and set up the Songs plugin.
|
||||
"""
|
||||
Plugin.__init__(self, u'Songs', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'Songs', u'1.9.3', plugin_helpers)
|
||||
self.weight = -10
|
||||
self.manager = Manager(u'songs', init_schema)
|
||||
self.icon_path = u':/plugins/plugin_songs.png'
|
||||
@ -63,7 +63,7 @@ class SongsPlugin(Plugin):
|
||||
log.info(u'Songs Initialising')
|
||||
Plugin.initialise(self)
|
||||
self.mediaItem.displayResultsSong(
|
||||
self.manager.get_all_objects(Song, order_by_ref=Song.title))
|
||||
self.manager.get_all_objects(Song, order_by_ref=Song.search_title))
|
||||
|
||||
def getMediaManagerItem(self):
|
||||
"""
|
||||
|
@ -41,7 +41,7 @@ class SongUsagePlugin(Plugin):
|
||||
log.info(u'SongUsage Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'SongUsage', u'1.9.2', plugin_helpers)
|
||||
Plugin.__init__(self, u'SongUsage', u'1.9.3', plugin_helpers)
|
||||
self.weight = -4
|
||||
self.icon = build_icon(u':/plugins/plugin_songusage.png')
|
||||
self.songusagemanager = None
|
||||
|
1379
resources/i18n/af.ts
1379
resources/i18n/af.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2080
resources/i18n/hu.ts
2080
resources/i18n/hu.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
0
resources/images/about-new.bmp
Executable file → Normal file
0
resources/images/about-new.bmp
Executable file → Normal file
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
17
resources/openlp.desktop
Normal file → Executable file
17
resources/openlp.desktop
Normal file → Executable file
@ -1,10 +1,21 @@
|
||||
[Desktop Entry]
|
||||
Categories=AudioVideo;
|
||||
Comment[de]=
|
||||
Comment=
|
||||
Encoding=UTF-8
|
||||
Name=OpenLP
|
||||
GenericName=Church lyrics projection
|
||||
Exec=openlp
|
||||
GenericName[de]=Church lyrics projection
|
||||
GenericName=Church lyrics projection
|
||||
Icon=openlp
|
||||
MimeType=
|
||||
Name[de]=OpenLP
|
||||
Name=OpenLP
|
||||
Path=
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
TerminalOptions=
|
||||
Type=Application
|
||||
Categories=AudioVideo;
|
||||
X-DBUS-ServiceName=
|
||||
X-DBUS-StartupType=
|
||||
X-KDE-SubstituteUID=false
|
||||
X-KDE-Username=
|
||||
|
@ -127,6 +127,8 @@ def import_bible():
|
||||
for row in rows:
|
||||
key = unicode(row[0], u'cp1252')
|
||||
value = unicode(row[1], u'cp1252')
|
||||
if key == u'Permission':
|
||||
key = u'Permissions'
|
||||
sql_insert = u'INSERT INTO metadata '\
|
||||
'("key", "value") '\
|
||||
'VALUES (?, ?)'
|
||||
|
@ -52,6 +52,7 @@ This is done easily via the ``-d``, ``-p`` and ``-u`` options::
|
||||
import os
|
||||
import urllib
|
||||
import re
|
||||
from shutil import copy
|
||||
|
||||
from optparse import OptionParser
|
||||
from PyQt4 import QtCore
|
||||
@ -85,7 +86,9 @@ class CommandStack(object):
|
||||
return len(self.data)
|
||||
|
||||
def __getitem__(self, index):
|
||||
if self.data[index].get(u'arguments'):
|
||||
if not index in self.data:
|
||||
return None
|
||||
elif self.data[index].get(u'arguments'):
|
||||
return self.data[index][u'command'], self.data[index][u'arguments']
|
||||
else:
|
||||
return self.data[index][u'command']
|
||||
@ -110,6 +113,21 @@ class CommandStack(object):
|
||||
def reset(self):
|
||||
self.current_index = 0
|
||||
|
||||
def arguments(self):
|
||||
if self.data[self.current_index - 1].get(u'arguments'):
|
||||
return self.data[self.current_index - 1][u'arguments']
|
||||
else:
|
||||
return []
|
||||
|
||||
def __repr__(self):
|
||||
results = []
|
||||
for item in self.data:
|
||||
if item.get(u'arguments'):
|
||||
results.append(str((item[u'command'], item[u'arguments'])))
|
||||
else:
|
||||
results.append(str((item[u'command'], )))
|
||||
return u'[%s]' % u', '.join(results)
|
||||
|
||||
|
||||
def print_verbose(text):
|
||||
"""
|
||||
@ -139,6 +157,21 @@ def run(command):
|
||||
print_verbose(u'Output:\n%s' % process.readAllStandardOutput())
|
||||
print u' Done.'
|
||||
|
||||
def update_export_at_pootle(source_filename):
|
||||
"""
|
||||
This is needed because of database and exported *.ts file can be out of sync
|
||||
|
||||
``source_filename``
|
||||
The file to sync.
|
||||
|
||||
"""
|
||||
language = source_filename[:-3]
|
||||
REVIEW_URL = u'http://pootle.projecthq.biz/%s/openlp/review.html' % language
|
||||
print_verbose(u'Accessing: %s' % (REVIEW_URL))
|
||||
page = urllib.urlopen(REVIEW_URL)
|
||||
page.close()
|
||||
|
||||
|
||||
def download_file(source_filename, dest_filename):
|
||||
"""
|
||||
Download a file and save it to disk.
|
||||
@ -165,11 +198,13 @@ def download_translations():
|
||||
page = urllib.urlopen(SERVER_URL)
|
||||
soup = BeautifulSoup(page)
|
||||
languages = soup.findAll(text=re.compile(r'.*\.ts'))
|
||||
for language in languages:
|
||||
for language_file in languages:
|
||||
update_export_at_pootle(language_file)
|
||||
for language_file in languages:
|
||||
filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n',
|
||||
language)
|
||||
language_file)
|
||||
print_verbose(u'Get Translation File: %s' % filename)
|
||||
download_file(language, filename)
|
||||
download_file(language_file, filename)
|
||||
print u' Done.'
|
||||
|
||||
def prepare_project():
|
||||
@ -227,11 +262,12 @@ def update_translations():
|
||||
else:
|
||||
os.chdir(os.path.abspath(u'..'))
|
||||
run(u'pylupdate4 -verbose -noobsolete openlp.pro')
|
||||
os.chdir(os.path.abspath(u'scripts'))
|
||||
|
||||
def generate_binaries():
|
||||
print u'Generate the related *.qm files'
|
||||
if not os.path.exists(os.path.join(os.path.abspath(u'..'), u'openlp.pro')):
|
||||
print u'You have no generated a project file yet, please run this ' + \
|
||||
print u'You have not generated a project file yet, please run this ' + \
|
||||
u'script with the -p option. It is also recommended that you ' + \
|
||||
u'this script with the -u option to update the translation ' + \
|
||||
u'files as well.'
|
||||
@ -239,6 +275,17 @@ def generate_binaries():
|
||||
else:
|
||||
os.chdir(os.path.abspath(u'..'))
|
||||
run(u'lrelease openlp.pro')
|
||||
os.chdir(os.path.abspath(u'scripts'))
|
||||
src_path = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n')
|
||||
dest_path = os.path.join(os.path.abspath(u'..'), u'openlp', u'i18n')
|
||||
if not os.path.exists(dest_path):
|
||||
os.makedirs(dest_path)
|
||||
src_list = os.listdir(src_path)
|
||||
for file in src_list:
|
||||
if re.search('.qm$', file):
|
||||
copy(os.path.join(src_path, u'%s' % file),
|
||||
os.path.join(dest_path, u'%s' % file))
|
||||
|
||||
|
||||
def create_translation(language):
|
||||
"""
|
||||
@ -248,13 +295,15 @@ def create_translation(language):
|
||||
The language file to create.
|
||||
"""
|
||||
print "Create new Translation File"
|
||||
if not language.endswith(u'.ts'):
|
||||
language += u'.ts'
|
||||
filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n', language)
|
||||
download_file(u'en.ts', filename)
|
||||
print u'\n** Please Note **\n'
|
||||
print u'In order to get this file into OpenLP and onto the Pootle ' + \
|
||||
print u' ** Please Note **'
|
||||
print u' In order to get this file into OpenLP and onto the Pootle ' + \
|
||||
u'translation server you will need to subscribe to the OpenLP' + \
|
||||
u'Translators mailing list, and request that your language file ' + \
|
||||
u'be added to the project.\n'
|
||||
u'be added to the project.'
|
||||
print u' Done'
|
||||
|
||||
def process_stack(command_stack):
|
||||
@ -278,7 +327,7 @@ def process_stack(command_stack):
|
||||
elif command == Command.Generate:
|
||||
generate_binaries()
|
||||
elif command == Command.Create:
|
||||
command, arguments = command_stack[command_stack.current_index]
|
||||
arguments = command_stack.arguments()
|
||||
create_translation(*arguments)
|
||||
print u'Finished processing commands.'
|
||||
else:
|
||||
@ -293,7 +342,7 @@ def main():
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option('-d', '--download-ts', dest='download',
|
||||
action='store_true', help='download language files from Pootle')
|
||||
parser.add_option('-c', '--create', dest=u'create', metavar='LANG',
|
||||
parser.add_option('-c', '--create', dest='create', metavar='LANG',
|
||||
help='create a new translation file for language LANG, e.g. "en_GB"')
|
||||
parser.add_option('-p', '--prepare', dest='prepare', action='store_true',
|
||||
help='generate a project file, used to update the translations')
|
||||
@ -330,4 +379,3 @@ if __name__ == u'__main__':
|
||||
print u'You need to run this script from the scripts directory.'
|
||||
else:
|
||||
main()
|
||||
|
||||
|
@ -179,7 +179,16 @@ def copy_windows_files():
|
||||
copy(os.path.join(iss_path, u'OpenLP.ico'), os.path.join(dist_path, u'OpenLP.ico'))
|
||||
copy(os.path.join(iss_path, u'LICENSE.txt'), os.path.join(dist_path, u'LICENSE.txt'))
|
||||
|
||||
def update_translations():
|
||||
print u'Updating translations...'
|
||||
os.chdir(script_path)
|
||||
translation_utils = Popen(u'python translation_utils.py -dpu')
|
||||
code = translation_utils.wait()
|
||||
if code != 0:
|
||||
print u'Error running translation_utils.py'
|
||||
|
||||
def compile_translations():
|
||||
print u'Compiling translations...'
|
||||
files = os.listdir(i18n_path)
|
||||
if not os.path.exists(os.path.join(dist_path, u'i18n')):
|
||||
os.makedirs(os.path.join(dist_path, u'i18n'))
|
||||
@ -221,6 +230,7 @@ def main():
|
||||
copy_enchant()
|
||||
copy_plugins()
|
||||
copy_windows_files()
|
||||
update_translations()
|
||||
compile_translations()
|
||||
run_innosetup()
|
||||
print "Done."
|
||||
|
Loading…
Reference in New Issue
Block a user