This commit is contained in:
rimach 2010-09-21 21:22:49 +02:00
commit 32544d1556
13 changed files with 396 additions and 50 deletions

View File

@ -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

View File

@ -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 {
</script>
</head>
<body>
<img id="image" class="size" src="%s" />
<img id="image" class="size" %s />
<video id="video" class="size"></video>
%s
<div id="footer" class="footer"></div>
@ -301,10 +299,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),

View File

@ -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):
"""
@ -88,7 +87,23 @@ 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._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

View File

@ -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):

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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(''))

View File

@ -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

View File

@ -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(

View 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

View File

@ -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

View File

@ -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."