diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index b325f0c6c..ade4bc019 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -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
diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py
index 906ebb987..ef8fb286a 100644
--- a/openlp/core/lib/htmlbuilder.py
+++ b/openlp/core/lib/htmlbuilder.py
@@ -27,8 +27,6 @@
import logging
from PyQt4 import QtWebKit
-from openlp.core.lib import image_to_byte
-
log = logging.getLogger(__name__)
HTMLSRC = u"""
@@ -274,7 +272,7 @@ body {
-' % \
+ (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'' \
- u'
' % \
- (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'
'
- web.setHtml(html)
+ html = self.page_shell + styled_text + u'
'
+ 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
diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py
index a6e494b01..e98ab4f01 100644
--- a/openlp/core/lib/rendermanager.py
+++ b/openlp/core/lib/rendermanager.py
@@ -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):
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index b0d453af5..e7ec9c2af 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -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()
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index a2b9dd81a..7e4a31b83 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -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,
@@ -306,6 +313,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 +326,8 @@ class MainDisplay(DisplayWidget):
# Important otherwise first preview will miss the background !
while not self.loaded:
Receiver.send_message(u'openlp_process_events')
+ if self.isLive:
+ self.setVisible(True)
preview = QtGui.QImage(self.screen[u'size'].width(),
self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
@@ -326,8 +336,6 @@ class MainDisplay(DisplayWidget):
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 +349,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
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 7a2e3ccf0..0a3e0c91b 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -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)
diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py
index 84f0f41ee..43df48d5b 100644
--- a/openlp/plugins/bibles/forms/importwizardform.py
+++ b/openlp/plugins/bibles/forms/importwizardform.py
@@ -290,6 +290,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(''))
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index 29cc42ec5..c62fa058e 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -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
diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py
index 37ee10612..0fb36cfe7 100644
--- a/openlp/plugins/songs/forms/songimportwizard.py
+++ b/openlp/plugins/songs/forms/songimportwizard.py
@@ -96,6 +96,7 @@ class Ui_SongImportWizard(object):
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,
@@ -413,6 +414,30 @@ class Ui_SongImportWizard(object):
self.genericImportLayout.addLayout(self.genericButtonLayout)
self.genericLayout.addWidget(self.genericImportWidget)
self.formatStackedWidget.addWidget(self.genericPage)
+ # EasyWorship
+ self.ewPage = QtGui.QWidget()
+ self.ewPage.setObjectName(u'ewPage')
+ self.ewLayout = QtGui.QFormLayout(self.ewPage)
+ self.ewLayout.setMargin(0)
+ self.ewLayout.setSpacing(8)
+ self.ewLayout.setObjectName(u'ewLayout')
+ self.ewFilenameLabel = QtGui.QLabel(self.ewPage)
+ self.ewFilenameLabel.setObjectName(u'ewFilenameLabel')
+ self.ewLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
+ self.ewFilenameLabel)
+ self.ewFileLayout = QtGui.QHBoxLayout()
+ self.ewFileLayout.setSpacing(8)
+ self.ewFileLayout.setObjectName(u'ewFileLayout')
+ self.ewFilenameEdit = QtGui.QLineEdit(self.ewPage)
+ self.ewFilenameEdit.setObjectName(u'ewFilenameEdit')
+ self.ewFileLayout.addWidget(self.ewFilenameEdit)
+ self.ewBrowseButton = QtGui.QToolButton(self.ewPage)
+ self.ewBrowseButton.setIcon(openIcon)
+ self.ewBrowseButton.setObjectName(u'ewBrowseButton')
+ self.ewFileLayout.addWidget(self.ewBrowseButton)
+ self.ewLayout.setLayout(0, QtGui.QFormLayout.FieldRole,
+ self.ewFileLayout)
+ self.formatStackedWidget.addWidget(self.ewPage)
# Commented out for future use.
# self.csvPage = QtGui.QWidget()
# self.csvPage.setObjectName(u'CSVPage')
@@ -497,7 +522,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 +576,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(
diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py
new file mode 100644
index 000000000..16db36b20
--- /dev/null
+++ b/openlp/plugins/songs/lib/ewimport.py
@@ -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('