configurethemes.png
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 94 KiB |
@ -637,4 +637,4 @@ class ThemeXML(object):
|
|||||||
self.font_footer_shadow_size)
|
self.font_footer_shadow_size)
|
||||||
self.add_display(self.display_horizontal_align,
|
self.add_display(self.display_horizontal_align,
|
||||||
self.display_vertical_align,
|
self.display_vertical_align,
|
||||||
self.display_slide_transition)
|
self.display_slide_transition)
|
||||||
|
@ -46,41 +46,58 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
|
|||||||
color:black;
|
color:black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
color:black;
|
||||||
|
}
|
||||||
|
|
||||||
.itemTitle {
|
.itemTitle {
|
||||||
font-weight:600;
|
font-weight:600;
|
||||||
font-size:large;
|
font-size:large;
|
||||||
color:black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemText {
|
.itemText {}
|
||||||
color:black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.itemFooter {
|
.itemFooter {
|
||||||
font-size:8px;
|
font-size:8px;
|
||||||
color:black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.itemNotes {}
|
||||||
|
|
||||||
.itemNotesTitle {
|
.itemNotesTitle {
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
font-size:12px;
|
font-size:12px;
|
||||||
color:black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemNotesText {
|
.itemNotesText {
|
||||||
font-size:11px;
|
font-size:11px;
|
||||||
color:black;
|
}
|
||||||
|
|
||||||
|
.media {}
|
||||||
|
|
||||||
|
.mediaTitle {
|
||||||
|
font-weight:bold;
|
||||||
|
font-size:11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaText {}
|
||||||
|
|
||||||
|
.imageList {}
|
||||||
|
|
||||||
|
.customNotes {
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.customNotesTitle {
|
.customNotesTitle {
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
font-size:11px;
|
font-size:11px;
|
||||||
color:black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.customNotesText {
|
.customNotesText {
|
||||||
font-size:11px;
|
font-size:11px;
|
||||||
color:black;
|
}
|
||||||
|
|
||||||
|
.newPage {
|
||||||
|
page-break-before:always;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -153,86 +170,90 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
"""
|
"""
|
||||||
Creates the html text and updates the html of *self.document*.
|
Creates the html text and updates the html of *self.document*.
|
||||||
"""
|
"""
|
||||||
html_data = html.fromstring(
|
html_data = self._addElement(u'html')
|
||||||
u'<title>%s</title>' % unicode(self.titleLineEdit.text()))
|
self._addElement(u'head', parent=html_data)
|
||||||
|
self._addElement(u'title', unicode(self.titleLineEdit.text()),
|
||||||
|
html_data.head)
|
||||||
css_path = os.path.join(
|
css_path = os.path.join(
|
||||||
AppLocation.get_data_path(), u'servicePrint.css')
|
AppLocation.get_data_path(), u'service_print.css')
|
||||||
if not os.path.isfile(css_path):
|
|
||||||
# Create default css file.
|
|
||||||
css_file = open(css_path, u'w')
|
|
||||||
css_file.write(DEFAULT_CSS)
|
|
||||||
css_file.close()
|
|
||||||
custom_css = get_text_file_string(css_path)
|
custom_css = get_text_file_string(css_path)
|
||||||
self._addChildToParent(
|
if not custom_css:
|
||||||
u'style', custom_css, html_data.head, u'type', u'text/css')
|
custom_css = DEFAULT_CSS
|
||||||
self._addChildToParent(u'body', parent=html_data)
|
self._addElement(u'style', custom_css, html_data.head,
|
||||||
self._addChildToParent(u'span', unicode(self.titleLineEdit.text()),
|
attribute=(u'type', u'text/css'))
|
||||||
html_data.body, u'class', u'serviceTitle')
|
self._addElement(u'body', parent=html_data)
|
||||||
|
self._addElement(u'h1', unicode(self.titleLineEdit.text()),
|
||||||
|
html_data.body, classId=u'serviceTitle')
|
||||||
for index, item in enumerate(self.serviceManager.serviceItems):
|
for index, item in enumerate(self.serviceManager.serviceItems):
|
||||||
item = item[u'service_item']
|
self._addPreviewItem(html_data.body, item[u'service_item'], index)
|
||||||
div = self._addChildToParent(u'div', parent=html_data.body)
|
|
||||||
# Add the title of the service item.
|
|
||||||
item_title = self._addChildToParent(
|
|
||||||
u'h2', parent=div, attribute=u'class', value=u'itemTitle')
|
|
||||||
self._addChildToParent(
|
|
||||||
u'img', parent=item_title, attribute=u'src', value=item.icon)
|
|
||||||
self._fromstring(
|
|
||||||
u'<span> %s</span>' % item.get_display_title(), item_title)
|
|
||||||
if self.slideTextCheckBox.isChecked():
|
|
||||||
# Add the text of the service item.
|
|
||||||
if item.is_text():
|
|
||||||
verse_def = None
|
|
||||||
for slide in item.get_frames():
|
|
||||||
if not verse_def or verse_def != slide[u'verseTag']:
|
|
||||||
p = self._addChildToParent(u'p', parent=div,
|
|
||||||
attribute=u'class', value=u'itemText')
|
|
||||||
else:
|
|
||||||
self._addChildToParent(u'br', parent=p)
|
|
||||||
self._fromstring(u'<span>%s</span>' % slide[u'html'], p)
|
|
||||||
verse_def = slide[u'verseTag']
|
|
||||||
# Break the page before the div element.
|
|
||||||
if index != 0 and self.pageBreakAfterText.isChecked():
|
|
||||||
div.set(u'style', u'page-break-before:always')
|
|
||||||
# Add the image names of the service item.
|
|
||||||
elif item.is_image():
|
|
||||||
ol = self._addChildToParent(u'ol', parent=div)
|
|
||||||
for slide in range(len(item.get_frames())):
|
|
||||||
self._addChildToParent(u'li', item.get_frame_title(slide), ol)
|
|
||||||
# add footer
|
|
||||||
if item.foot_text:
|
|
||||||
self._fromstring(
|
|
||||||
item.foot_text, div, u'class', u'itemFooter')
|
|
||||||
# Add service items' notes.
|
|
||||||
if self.notesCheckBox.isChecked():
|
|
||||||
if item.notes:
|
|
||||||
p = self._addChildToParent(u'p', parent=div)
|
|
||||||
self._addChildToParent(u'span', unicode(
|
|
||||||
translate('OpenLP.ServiceManager', 'Notes:')), p,
|
|
||||||
u'class', u'itemNotesTitle')
|
|
||||||
self._fromstring(u'<span> %s</span>' % item.notes.replace(
|
|
||||||
u'\n', u'<br />'), p, u'class', u'itemNotesText')
|
|
||||||
# Add play length of media files.
|
|
||||||
if item.is_media() and self.metaDataCheckBox.isChecked():
|
|
||||||
tme = item.media_length
|
|
||||||
if item.end_time > 0:
|
|
||||||
tme = item.end_time - item.start_time
|
|
||||||
title = self._fromstring(u'<p><strong>%s</strong> </p>' %
|
|
||||||
translate('OpenLP.ServiceManager', 'Playing time:'), div)
|
|
||||||
self._fromstring(u'<span>%s</span>' %
|
|
||||||
unicode(datetime.timedelta(seconds=tme)), title)
|
|
||||||
# Add the custom service notes:
|
# Add the custom service notes:
|
||||||
if self.footerTextEdit.toPlainText():
|
if self.footerTextEdit.toPlainText():
|
||||||
div = self._addChildToParent(u'div', parent=html_data.body)
|
div = self._addElement(u'div', parent=html_data.body,
|
||||||
self._addChildToParent(u'span', translate('OpenLP.ServiceManager',
|
classId=u'customNotes')
|
||||||
u'Custom Service Notes:'), div, u'class', u'customNotesTitle')
|
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
||||||
self._addChildToParent(
|
'Custom Service Notes: '), div, classId=u'customNotesTitle')
|
||||||
u'span', u' %s' % self.footerTextEdit.toPlainText(), div,
|
self._addElement(u'span', self.footerTextEdit.toPlainText(), div,
|
||||||
u'class', u'customNotesText')
|
classId=u'customNotesText')
|
||||||
self.document.setHtml(html.tostring(html_data))
|
self.document.setHtml(html.tostring(html_data))
|
||||||
self.previewWidget.updatePreview()
|
self.previewWidget.updatePreview()
|
||||||
|
|
||||||
def _addChildToParent(self, tag, text=None, parent=None, attribute=None,
|
def _addPreviewItem(self, body, item, index):
|
||||||
value=None):
|
div = self._addElement(u'div', classId=u'item', parent=body)
|
||||||
|
# Add the title of the service item.
|
||||||
|
item_title = self._addElement(u'h2', parent=div, classId=u'itemTitle')
|
||||||
|
self._addElement(u'img', parent=item_title,
|
||||||
|
attribute=(u'src', item.icon))
|
||||||
|
self._addElement(u'span', u' ' + item.get_display_title(),
|
||||||
|
item_title)
|
||||||
|
if self.slideTextCheckBox.isChecked():
|
||||||
|
# Add the text of the service item.
|
||||||
|
if item.is_text():
|
||||||
|
verse_def = None
|
||||||
|
for slide in item.get_frames():
|
||||||
|
if not verse_def or verse_def != slide[u'verseTag']:
|
||||||
|
p = self._addElement(u'div', parent=div,
|
||||||
|
classId=u'itemText')
|
||||||
|
else:
|
||||||
|
self._addElement(u'br', parent=p)
|
||||||
|
self._addElement(u'p', slide[u'html'], p)
|
||||||
|
verse_def = slide[u'verseTag']
|
||||||
|
# Break the page before the div element.
|
||||||
|
if index != 0 and self.pageBreakAfterText.isChecked():
|
||||||
|
div.set(u'class', u'item newPage')
|
||||||
|
# Add the image names of the service item.
|
||||||
|
elif item.is_image():
|
||||||
|
ol = self._addElement(u'ol', parent=div, classId=u'imageList')
|
||||||
|
for slide in range(len(item.get_frames())):
|
||||||
|
self._addElement(u'li', item.get_frame_title(slide), ol)
|
||||||
|
# add footer
|
||||||
|
foot_text = item.foot_text
|
||||||
|
foot_text = foot_text.partition(u'<br>')[2]
|
||||||
|
if foot_text:
|
||||||
|
foot = self._addElement(u'div', foot_text, parent=div,
|
||||||
|
classId=u'itemFooter')
|
||||||
|
# Add service items' notes.
|
||||||
|
if self.notesCheckBox.isChecked():
|
||||||
|
if item.notes:
|
||||||
|
p = self._addElement(u'div', classId=u'itemNotes', parent=div)
|
||||||
|
self._addElement(u'span',
|
||||||
|
translate('OpenLP.ServiceManager', 'Notes: '), p,
|
||||||
|
classId=u'itemNotesTitle')
|
||||||
|
notes = self._addElement(u'span',
|
||||||
|
item.notes.replace(u'\n', u'<br />'), p,
|
||||||
|
classId=u'itemNotesText')
|
||||||
|
# Add play length of media files.
|
||||||
|
if item.is_media() and self.metaDataCheckBox.isChecked():
|
||||||
|
tme = item.media_length
|
||||||
|
if item.end_time > 0:
|
||||||
|
tme = item.end_time - item.start_time
|
||||||
|
title = self._addElement(u'div', classId=u'media', parent=div)
|
||||||
|
self._addElement(u'span', translate('OpenLP.ServiceManager',
|
||||||
|
'Playing time: '), title, classId=u'mediaTitle')
|
||||||
|
self._addElement(u'span', unicode(datetime.timedelta(seconds=tme)),
|
||||||
|
title, classId=u'mediaText')
|
||||||
|
|
||||||
|
def _addElement(self, tag, text=None, parent=None, classId=None,
|
||||||
|
attribute=None):
|
||||||
"""
|
"""
|
||||||
Creates a html element. If ``text`` is given, the element's text will
|
Creates a html element. If ``text`` is given, the element's text will
|
||||||
set and if a ``parent`` is given, the element is appended.
|
set and if a ``parent`` is given, the element is appended.
|
||||||
@ -246,30 +267,22 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
``parent``
|
``parent``
|
||||||
The parent element. Defaults to ``None``.
|
The parent element. Defaults to ``None``.
|
||||||
|
|
||||||
``attribute``
|
``classId``
|
||||||
An optional attribute, for instance ``u'class``.
|
Value for the class attribute
|
||||||
|
|
||||||
``value``
|
``attribute``
|
||||||
The value for the given ``attribute``. It does not have a meaning,
|
Tuple name/value pair to add as an optional attribute
|
||||||
if the attribute is left to its default.
|
|
||||||
"""
|
"""
|
||||||
element = html.Element(tag)
|
|
||||||
if text is not None:
|
if text is not None:
|
||||||
element.text = unicode(text)
|
element = html.fragment_fromstring(unicode(text), create_parent=tag)
|
||||||
|
else:
|
||||||
|
element = html.Element(tag)
|
||||||
if parent is not None:
|
if parent is not None:
|
||||||
parent.append(element)
|
parent.append(element)
|
||||||
|
if classId is not None:
|
||||||
|
element.set(u'class', classId)
|
||||||
if attribute is not None:
|
if attribute is not None:
|
||||||
element.set(attribute, value if value is not None else u'')
|
element.set(attribute[0], attribute[1])
|
||||||
return element
|
|
||||||
|
|
||||||
def _fromstring(self, string, parent, attribute=None, value=None):
|
|
||||||
"""
|
|
||||||
This is used to create a child html element from a string.
|
|
||||||
"""
|
|
||||||
element = html.fromstring(string)
|
|
||||||
if attribute is not None:
|
|
||||||
element.set(attribute, value if value is not None else u'')
|
|
||||||
parent.append(element)
|
|
||||||
return element
|
return element
|
||||||
|
|
||||||
def paintRequested(self, printer):
|
def paintRequested(self, printer):
|
||||||
@ -380,4 +393,4 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
|||||||
QtCore.QVariant(self.metaDataCheckBox.isChecked()))
|
QtCore.QVariant(self.metaDataCheckBox.isChecked()))
|
||||||
settings.setValue(u'print notes',
|
settings.setValue(u'print notes',
|
||||||
QtCore.QVariant(self.notesCheckBox.isChecked()))
|
QtCore.QVariant(self.notesCheckBox.isChecked()))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
@ -686,6 +686,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems[item][u'service_item'].notes = \
|
self.serviceItems[item][u'service_item'].notes = \
|
||||||
self.serviceNoteForm.textEdit.toPlainText()
|
self.serviceNoteForm.textEdit.toPlainText()
|
||||||
self.repaintServiceList(item, -1)
|
self.repaintServiceList(item, -1)
|
||||||
|
self.setModified()
|
||||||
|
|
||||||
def onStartTimeForm(self):
|
def onStartTimeForm(self):
|
||||||
item = self.findServiceItem()[0]
|
item = self.findServiceItem()[0]
|
||||||
@ -789,7 +790,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
# Top Item was selected so set the last one
|
# Top Item was selected so set the last one
|
||||||
if setLastItem:
|
if setLastItem:
|
||||||
lastItem.setSelected(True)
|
lastItem.setSelected(True)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onMoveSelectionDown(self):
|
def onMoveSelectionDown(self):
|
||||||
"""
|
"""
|
||||||
@ -811,7 +812,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
serviceIterator += 1
|
serviceIterator += 1
|
||||||
if setSelected:
|
if setSelected:
|
||||||
firstItem.setSelected(True)
|
firstItem.setSelected(True)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onCollapseAll(self):
|
def onCollapseAll(self):
|
||||||
"""
|
"""
|
||||||
@ -855,7 +856,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(0, temp)
|
self.serviceItems.insert(0, temp)
|
||||||
self.repaintServiceList(0, child)
|
self.repaintServiceList(0, child)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onServiceUp(self):
|
def onServiceUp(self):
|
||||||
"""
|
"""
|
||||||
@ -867,7 +868,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(item - 1, temp)
|
self.serviceItems.insert(item - 1, temp)
|
||||||
self.repaintServiceList(item - 1, child)
|
self.repaintServiceList(item - 1, child)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onServiceDown(self):
|
def onServiceDown(self):
|
||||||
"""
|
"""
|
||||||
@ -879,7 +880,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(item + 1, temp)
|
self.serviceItems.insert(item + 1, temp)
|
||||||
self.repaintServiceList(item + 1, child)
|
self.repaintServiceList(item + 1, child)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onServiceEnd(self):
|
def onServiceEnd(self):
|
||||||
"""
|
"""
|
||||||
@ -891,7 +892,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.serviceItems.insert(len(self.serviceItems), temp)
|
self.serviceItems.insert(len(self.serviceItems), temp)
|
||||||
self.repaintServiceList(len(self.serviceItems) - 1, child)
|
self.repaintServiceList(len(self.serviceItems) - 1, child)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def onDeleteFromService(self):
|
def onDeleteFromService(self):
|
||||||
"""
|
"""
|
||||||
@ -901,7 +902,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
if item != -1:
|
if item != -1:
|
||||||
self.serviceItems.remove(self.serviceItems[item])
|
self.serviceItems.remove(self.serviceItems[item])
|
||||||
self.repaintServiceList(item - 1, -1)
|
self.repaintServiceList(item - 1, -1)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def repaintServiceList(self, serviceItem, serviceItemChild):
|
def repaintServiceList(self, serviceItem, serviceItemChild):
|
||||||
"""
|
"""
|
||||||
@ -1026,7 +1027,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
item[u'service_item'], False, expand=item[u'expanded'])
|
item[u'service_item'], False, expand=item[u'expanded'])
|
||||||
# Set to False as items may have changed rendering
|
# Set to False as items may have changed rendering
|
||||||
# does not impact the saved song so True may also be valid
|
# does not impact the saved song so True may also be valid
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
Receiver.send_message(u'cursor_normal')
|
Receiver.send_message(u'cursor_normal')
|
||||||
|
|
||||||
def serviceItemUpdate(self, message):
|
def serviceItemUpdate(self, message):
|
||||||
@ -1037,7 +1038,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
for item in self.serviceItems:
|
for item in self.serviceItems:
|
||||||
if item[u'service_item']._uuid == uuid:
|
if item[u'service_item']._uuid == uuid:
|
||||||
item[u'service_item'].edit_id = int(editId)
|
item[u'service_item'].edit_id = int(editId)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def replaceServiceItem(self, newItem):
|
def replaceServiceItem(self, newItem):
|
||||||
"""
|
"""
|
||||||
@ -1053,7 +1054,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.repaintServiceList(itemcount + 1, 0)
|
self.repaintServiceList(itemcount + 1, 0)
|
||||||
self.mainwindow.liveController.replaceServiceManagerItem(
|
self.mainwindow.liveController.replaceServiceManagerItem(
|
||||||
newItem)
|
newItem)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def addServiceItem(self, item, rebuild=False, expand=None, replace=False):
|
def addServiceItem(self, item, rebuild=False, expand=None, replace=False):
|
||||||
"""
|
"""
|
||||||
@ -1098,7 +1099,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
if rebuild:
|
if rebuild:
|
||||||
self.mainwindow.liveController.replaceServiceManagerItem(item)
|
self.mainwindow.liveController.replaceServiceManagerItem(item)
|
||||||
self.dropPosition = 0
|
self.dropPosition = 0
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
|
|
||||||
def makePreview(self):
|
def makePreview(self):
|
||||||
"""
|
"""
|
||||||
@ -1235,7 +1236,7 @@ class ServiceManager(QtGui.QWidget):
|
|||||||
self.serviceItems.remove(serviceItem)
|
self.serviceItems.remove(serviceItem)
|
||||||
self.serviceItems.insert(endpos, serviceItem)
|
self.serviceItems.insert(endpos, serviceItem)
|
||||||
self.repaintServiceList(endpos, child)
|
self.repaintServiceList(endpos, child)
|
||||||
self.setModified(True)
|
self.setModified()
|
||||||
else:
|
else:
|
||||||
# we are not over anything so drop
|
# we are not over anything so drop
|
||||||
replace = False
|
replace = False
|
||||||
|
@ -56,6 +56,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.registerFields()
|
self.registerFields()
|
||||||
self.updateThemeAllowed = True
|
self.updateThemeAllowed = True
|
||||||
|
self.temp_background_filename = u''
|
||||||
QtCore.QObject.connect(self.backgroundComboBox,
|
QtCore.QObject.connect(self.backgroundComboBox,
|
||||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||||
self.onBackgroundComboBoxCurrentIndexChanged)
|
self.onBackgroundComboBoxCurrentIndexChanged)
|
||||||
@ -279,6 +280,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
Run the wizard.
|
Run the wizard.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Editing theme %s' % self.theme.theme_name)
|
log.debug(u'Editing theme %s' % self.theme.theme_name)
|
||||||
|
self.temp_background_filename = u''
|
||||||
self.updateThemeAllowed = False
|
self.updateThemeAllowed = False
|
||||||
self.setDefaults()
|
self.setDefaults()
|
||||||
self.updateThemeAllowed = True
|
self.updateThemeAllowed = True
|
||||||
@ -432,6 +434,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
# do not allow updates when screen is building for the first time.
|
# do not allow updates when screen is building for the first time.
|
||||||
if self.updateThemeAllowed:
|
if self.updateThemeAllowed:
|
||||||
self.theme.background_type = BackgroundType.to_string(index)
|
self.theme.background_type = BackgroundType.to_string(index)
|
||||||
|
if self.theme.background_type != \
|
||||||
|
BackgroundType.to_string(BackgroundType.Image) and \
|
||||||
|
self.temp_background_filename == u'':
|
||||||
|
self.temp_background_filename = self.theme.background_filename
|
||||||
|
self.theme.background_filename = u''
|
||||||
|
if self.theme.background_type == \
|
||||||
|
BackgroundType.to_string(BackgroundType.Image) and \
|
||||||
|
self.temp_background_filename != u'':
|
||||||
|
self.theme.background_filename = self.temp_background_filename
|
||||||
|
self.temp_background_filename = u''
|
||||||
self.setBackgroundPageValues()
|
self.setBackgroundPageValues()
|
||||||
|
|
||||||
def onGradientComboBoxCurrentIndexChanged(self, index):
|
def onGradientComboBoxCurrentIndexChanged(self, index):
|
||||||
@ -589,4 +601,4 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
QtGui.QColor(field), self)
|
QtGui.QColor(field), self)
|
||||||
if new_color.isValid():
|
if new_color.isValid():
|
||||||
field = new_color.name()
|
field = new_color.name()
|
||||||
return field
|
return field
|
||||||
|
@ -95,6 +95,10 @@ class OpenLPWizard(QtGui.QWizard):
|
|||||||
self.customSignals()
|
self.customSignals()
|
||||||
QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'),
|
QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'),
|
||||||
self.onCurrentIdChanged)
|
self.onCurrentIdChanged)
|
||||||
|
QtCore.QObject.connect(self.errorCopyToButton,
|
||||||
|
QtCore.SIGNAL(u'clicked()'), self.onErrorCopyToButtonClicked)
|
||||||
|
QtCore.QObject.connect(self.errorSaveToButton,
|
||||||
|
QtCore.SIGNAL(u'clicked()'), self.onErrorSaveToButtonClicked)
|
||||||
|
|
||||||
def setupUi(self, image):
|
def setupUi(self, image):
|
||||||
"""
|
"""
|
||||||
@ -129,10 +133,36 @@ class OpenLPWizard(QtGui.QWizard):
|
|||||||
self.progressLayout.setObjectName(u'progressLayout')
|
self.progressLayout.setObjectName(u'progressLayout')
|
||||||
self.progressLabel = QtGui.QLabel(self.progressPage)
|
self.progressLabel = QtGui.QLabel(self.progressPage)
|
||||||
self.progressLabel.setObjectName(u'progressLabel')
|
self.progressLabel.setObjectName(u'progressLabel')
|
||||||
|
self.progressLabel.setWordWrap(True)
|
||||||
self.progressLayout.addWidget(self.progressLabel)
|
self.progressLayout.addWidget(self.progressLabel)
|
||||||
self.progressBar = QtGui.QProgressBar(self.progressPage)
|
self.progressBar = QtGui.QProgressBar(self.progressPage)
|
||||||
self.progressBar.setObjectName(u'progressBar')
|
self.progressBar.setObjectName(u'progressBar')
|
||||||
self.progressLayout.addWidget(self.progressBar)
|
self.progressLayout.addWidget(self.progressBar)
|
||||||
|
# Add a QTextEdit and a copy to file and copy to clipboard button to be
|
||||||
|
# able to provide feedback to the user. Hidden by default.
|
||||||
|
self.errorReportTextEdit = QtGui.QTextEdit(self.progressPage)
|
||||||
|
self.errorReportTextEdit.setObjectName(u'progresserrorReportTextEdit')
|
||||||
|
self.errorReportTextEdit.setHidden(True)
|
||||||
|
self.errorReportTextEdit.setReadOnly(True)
|
||||||
|
self.progressLayout.addWidget(self.errorReportTextEdit)
|
||||||
|
self.errorButtonLayout = QtGui.QHBoxLayout()
|
||||||
|
self.errorButtonLayout.setObjectName(u'errorButtonLayout')
|
||||||
|
spacer = QtGui.QSpacerItem(40, 20,
|
||||||
|
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||||
|
self.errorButtonLayout.addItem(spacer)
|
||||||
|
self.errorCopyToButton = QtGui.QPushButton(self.progressPage)
|
||||||
|
self.errorCopyToButton.setObjectName(u'errorCopyToButton')
|
||||||
|
self.errorCopyToButton.setHidden(True)
|
||||||
|
self.errorCopyToButton.setIcon(
|
||||||
|
build_icon(u':/system/system_edit_copy.png'))
|
||||||
|
self.errorButtonLayout.addWidget(self.errorCopyToButton)
|
||||||
|
self.errorSaveToButton = QtGui.QPushButton(self.progressPage)
|
||||||
|
self.errorSaveToButton.setObjectName(u'errorSaveToButton')
|
||||||
|
self.errorSaveToButton.setHidden(True)
|
||||||
|
self.errorSaveToButton.setIcon(
|
||||||
|
build_icon(u':/general/general_save.png'))
|
||||||
|
self.errorButtonLayout.addWidget(self.errorSaveToButton)
|
||||||
|
self.progressLayout.addLayout(self.errorButtonLayout)
|
||||||
self.addPage(self.progressPage)
|
self.addPage(self.progressPage)
|
||||||
|
|
||||||
def exec_(self):
|
def exec_(self):
|
||||||
@ -160,6 +190,18 @@ class OpenLPWizard(QtGui.QWizard):
|
|||||||
self.performWizard()
|
self.performWizard()
|
||||||
self.postWizard()
|
self.postWizard()
|
||||||
|
|
||||||
|
def onErrorCopyToButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Called when the ``onErrorCopyToButtonClicked`` has been clicked.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def onErrorSaveToButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Called when the ``onErrorSaveToButtonClicked`` has been clicked.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def incrementProgressBar(self, status_text, increment=1):
|
def incrementProgressBar(self, status_text, increment=1):
|
||||||
"""
|
"""
|
||||||
Update the wizard progress page.
|
Update the wizard progress page.
|
||||||
@ -219,4 +261,5 @@ class OpenLPWizard(QtGui.QWizard):
|
|||||||
if filename:
|
if filename:
|
||||||
editbox.setText(filename)
|
editbox.setText(filename)
|
||||||
SettingsManager.set_last_dir(self.plugin.settingsSection,
|
SettingsManager.set_last_dir(self.plugin.settingsSection,
|
||||||
filename, 1)
|
filename, 1)
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"""
|
"""
|
||||||
The song import functions for OpenLP.
|
The song import functions for OpenLP.
|
||||||
"""
|
"""
|
||||||
|
import codecs
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ class SongImportForm(OpenLPWizard):
|
|||||||
``plugin``
|
``plugin``
|
||||||
The songs plugin.
|
The songs plugin.
|
||||||
"""
|
"""
|
||||||
|
self.clipboard = plugin.formparent.clipboard
|
||||||
OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard',
|
OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard',
|
||||||
u':/wizards/wizard_importsong.bmp')
|
u':/wizards/wizard_importsong.bmp')
|
||||||
|
|
||||||
@ -330,6 +332,10 @@ class SongImportForm(OpenLPWizard):
|
|||||||
'Please wait while your songs are imported.'))
|
'Please wait while your songs are imported.'))
|
||||||
self.progressLabel.setText(WizardStrings.Ready)
|
self.progressLabel.setText(WizardStrings.Ready)
|
||||||
self.progressBar.setFormat(WizardStrings.PercentSymbolFormat)
|
self.progressBar.setFormat(WizardStrings.PercentSymbolFormat)
|
||||||
|
self.errorCopyToButton.setText(translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'Copy'))
|
||||||
|
self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'Save to File'))
|
||||||
# Align all QFormLayouts towards each other.
|
# Align all QFormLayouts towards each other.
|
||||||
width = max(self.formatLabel.minimumSizeHint().width(),
|
width = max(self.formatLabel.minimumSizeHint().width(),
|
||||||
self.openLP2FilenameLabel.minimumSizeHint().width())
|
self.openLP2FilenameLabel.minimumSizeHint().width())
|
||||||
@ -459,10 +465,7 @@ class SongImportForm(OpenLPWizard):
|
|||||||
"""
|
"""
|
||||||
Return a list of file from the listbox
|
Return a list of file from the listbox
|
||||||
"""
|
"""
|
||||||
files = []
|
return [unicode(listbox.item(i).text()) for i in range(listbox.count())]
|
||||||
for row in range(0, listbox.count()):
|
|
||||||
files.append(unicode(listbox.item(row).text()))
|
|
||||||
return files
|
|
||||||
|
|
||||||
def removeSelectedItems(self, listbox):
|
def removeSelectedItems(self, listbox):
|
||||||
"""
|
"""
|
||||||
@ -659,6 +662,10 @@ class SongImportForm(OpenLPWizard):
|
|||||||
self.songShowPlusFileListWidget.clear()
|
self.songShowPlusFileListWidget.clear()
|
||||||
self.foilPresenterFileListWidget.clear()
|
self.foilPresenterFileListWidget.clear()
|
||||||
#self.csvFilenameEdit.setText(u'')
|
#self.csvFilenameEdit.setText(u'')
|
||||||
|
self.errorReportTextEdit.clear()
|
||||||
|
self.errorReportTextEdit.setHidden(True)
|
||||||
|
self.errorCopyToButton.setHidden(True)
|
||||||
|
self.errorSaveToButton.setHidden(True)
|
||||||
|
|
||||||
def preWizard(self):
|
def preWizard(self):
|
||||||
"""
|
"""
|
||||||
@ -743,12 +750,30 @@ class SongImportForm(OpenLPWizard):
|
|||||||
importer = self.plugin.importSongs(SongFormat.FoilPresenter,
|
importer = self.plugin.importSongs(SongFormat.FoilPresenter,
|
||||||
filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
|
filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
|
||||||
)
|
)
|
||||||
if importer.do_import():
|
importer.do_import()
|
||||||
self.progressLabel.setText(WizardStrings.FinishedImport)
|
if importer.error_log:
|
||||||
|
self.progressLabel.setText(translate(
|
||||||
|
'SongsPlugin.SongImportForm', 'Your song import failed.'))
|
||||||
else:
|
else:
|
||||||
self.progressLabel.setText(
|
self.progressLabel.setText(WizardStrings.FinishedImport)
|
||||||
translate('SongsPlugin.SongImportForm',
|
|
||||||
'Your song import failed.'))
|
def onErrorCopyToButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Copy the error report to the clipboard.
|
||||||
|
"""
|
||||||
|
self.clipboard.setText(self.errorReportTextEdit.toPlainText())
|
||||||
|
|
||||||
|
def onErrorSaveToButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Save the error report to a file.
|
||||||
|
"""
|
||||||
|
filename = QtGui.QFileDialog.getSaveFileName(self,
|
||||||
|
SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
|
||||||
|
if not filename:
|
||||||
|
return
|
||||||
|
file = codecs.open(filename, u'w', u'utf-8')
|
||||||
|
file.write(self.errorReportTextEdit.toPlainText())
|
||||||
|
file.close()
|
||||||
|
|
||||||
def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
|
def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
|
||||||
single_select=False):
|
single_select=False):
|
||||||
@ -836,4 +861,4 @@ class SongImportForm(OpenLPWizard):
|
|||||||
setattr(self, prefix + u'DisabledLayout', disabledLayout)
|
setattr(self, prefix + u'DisabledLayout', disabledLayout)
|
||||||
setattr(self, prefix + u'DisabledLabel', disabledLabel)
|
setattr(self, prefix + u'DisabledLabel', disabledLabel)
|
||||||
setattr(self, prefix + u'ImportWidget', importWidget)
|
setattr(self, prefix + u'ImportWidget', importWidget)
|
||||||
return importWidget
|
return importWidget
|
||||||
|
@ -278,24 +278,29 @@ def clean_song(manager, song):
|
|||||||
# List for later comparison.
|
# List for later comparison.
|
||||||
compare_order = []
|
compare_order = []
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
type = VerseType.Tags[VerseType.from_loose_input(verse[0][u'type'])]
|
verse_type = VerseType.Tags[VerseType.from_loose_input(
|
||||||
|
verse[0][u'type'])]
|
||||||
sxml.add_verse_to_lyrics(
|
sxml.add_verse_to_lyrics(
|
||||||
type,
|
verse_type,
|
||||||
verse[0][u'label'],
|
verse[0][u'label'],
|
||||||
verse[1],
|
verse[1],
|
||||||
verse[0][u'lang'] if verse[0].has_key(u'lang') else None
|
verse[0][u'lang'] if verse[0].has_key(u'lang') else None
|
||||||
)
|
)
|
||||||
compare_order.append((u'%s%s' % (type, verse[0][u'label'])).upper())
|
compare_order.append((u'%s%s' % (verse_type, verse[0][u'label'])
|
||||||
|
).upper())
|
||||||
|
if verse[0][u'label'] == u'1':
|
||||||
|
compare_order.append(verse_type.upper())
|
||||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
# Rebuild the verse order, to convert translated verse tags, which might
|
# Rebuild the verse order, to convert translated verse tags, which might
|
||||||
# have been added prior to 1.9.5.
|
# have been added prior to 1.9.5.
|
||||||
order = song.verse_order.strip().split()
|
order = song.verse_order.strip().split()
|
||||||
new_order = []
|
new_order = []
|
||||||
for verse_def in order:
|
for verse_def in order:
|
||||||
new_order.append((u'%s%s' % (
|
verse_type = VerseType.Tags[VerseType.from_loose_input(verse_def[0])]
|
||||||
VerseType.Tags[VerseType.from_loose_input(verse_def[0])],
|
if len(verse_def) > 1:
|
||||||
verse_def[1:])).upper()
|
new_order.append((u'%s%s' % (verse_type, verse_def[1:])).upper())
|
||||||
)
|
else:
|
||||||
|
new_order.append(verse_type.upper())
|
||||||
song.verse_order = u' '.join(new_order)
|
song.verse_order = u' '.join(new_order)
|
||||||
# Check if the verse order contains tags for verses which do not exist.
|
# Check if the verse order contains tags for verses which do not exist.
|
||||||
for order in new_order:
|
for order in new_order:
|
||||||
|
@ -59,16 +59,10 @@ class CCLIFileImport(SongImport):
|
|||||||
Import either a ``.usr`` or a ``.txt`` SongSelect file.
|
Import either a ``.usr`` or a ``.txt`` SongSelect file.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Starting CCLI File Import')
|
log.debug(u'Starting CCLI File Import')
|
||||||
song_total = len(self.import_source)
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
self.import_wizard.progressBar.setMaximum(song_total)
|
|
||||||
song_count = 1
|
|
||||||
for filename in self.import_source:
|
for filename in self.import_source:
|
||||||
self.import_wizard.incrementProgressBar(unicode(translate(
|
|
||||||
'SongsPlugin.CCLIFileImport', 'Importing song %d of %d')) %
|
|
||||||
(song_count, song_total))
|
|
||||||
filename = unicode(filename)
|
filename = unicode(filename)
|
||||||
log.debug(u'Importing CCLI File: %s', filename)
|
log.debug(u'Importing CCLI File: %s', filename)
|
||||||
self.set_defaults()
|
|
||||||
lines = []
|
lines = []
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
detect_file = open(filename, u'r')
|
detect_file = open(filename, u'r')
|
||||||
@ -81,19 +75,23 @@ class CCLIFileImport(SongImport):
|
|||||||
detect_file.close()
|
detect_file.close()
|
||||||
infile = codecs.open(filename, u'r', details['encoding'])
|
infile = codecs.open(filename, u'r', details['encoding'])
|
||||||
lines = infile.readlines()
|
lines = infile.readlines()
|
||||||
|
infile.close()
|
||||||
ext = os.path.splitext(filename)[1]
|
ext = os.path.splitext(filename)[1]
|
||||||
if ext.lower() == u'.usr':
|
if ext.lower() == u'.usr':
|
||||||
log.info(u'SongSelect .usr format file found: %s', filename)
|
log.info(u'SongSelect .usr format file found: %s', filename)
|
||||||
self.do_import_usr_file(lines)
|
if not self.do_import_usr_file(lines):
|
||||||
|
self.log_error(filename)
|
||||||
elif ext.lower() == u'.txt':
|
elif ext.lower() == u'.txt':
|
||||||
log.info(u'SongSelect .txt format file found: %s', filename)
|
log.info(u'SongSelect .txt format file found: %s', filename)
|
||||||
self.do_import_txt_file(lines)
|
if not self.do_import_txt_file(lines):
|
||||||
|
self.log_error(filename)
|
||||||
else:
|
else:
|
||||||
|
self.log_error(filename,
|
||||||
|
translate('SongsPlugin.CCLIFileImport',
|
||||||
|
'The file does not have a valid extension.'))
|
||||||
log.info(u'Extension %s is not valid', filename)
|
log.info(u'Extension %s is not valid', filename)
|
||||||
song_count += 1
|
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return False
|
return
|
||||||
return True
|
|
||||||
|
|
||||||
def do_import_usr_file(self, textList):
|
def do_import_usr_file(self, textList):
|
||||||
"""
|
"""
|
||||||
@ -218,7 +216,7 @@ class CCLIFileImport(SongImport):
|
|||||||
else:
|
else:
|
||||||
self.add_author(author)
|
self.add_author(author)
|
||||||
self.topics = [topic.strip() for topic in song_topics.split(u'/t')]
|
self.topics = [topic.strip() for topic in song_topics.split(u'/t')]
|
||||||
self.finish()
|
return self.finish()
|
||||||
|
|
||||||
def do_import_txt_file(self, textList):
|
def do_import_txt_file(self, textList):
|
||||||
"""
|
"""
|
||||||
@ -334,6 +332,5 @@ class CCLIFileImport(SongImport):
|
|||||||
if len(author_list) < 2:
|
if len(author_list) < 2:
|
||||||
author_list = song_author.split(u'|')
|
author_list = song_author.split(u'|')
|
||||||
# Clean spaces before and after author names.
|
# Clean spaces before and after author names.
|
||||||
for author_name in author_list:
|
[self.add_author(author_name.strip()) for author_name in author_list]
|
||||||
self.add_author(author_name.strip())
|
return self.finish()
|
||||||
self.finish()
|
|
||||||
|
@ -26,11 +26,13 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from lxml import etree, objectify
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from lxml import etree, objectify
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -56,26 +58,16 @@ class EasiSlidesImport(SongImport):
|
|||||||
multiple opensong files. If `self.commit` is set False, the
|
multiple opensong files. If `self.commit` is set False, the
|
||||||
import will not be committed to the database (useful for test scripts).
|
import will not be committed to the database (useful for test scripts).
|
||||||
"""
|
"""
|
||||||
self.import_wizard.progressBar.setMaximum(1)
|
|
||||||
log.info(u'Importing EasiSlides XML file %s', self.import_source)
|
log.info(u'Importing EasiSlides XML file %s', self.import_source)
|
||||||
parser = etree.XMLParser(remove_blank_text=True)
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
file = etree.parse(self.import_source, parser)
|
file = etree.parse(self.import_source, parser)
|
||||||
xml = unicode(etree.tostring(file))
|
xml = unicode(etree.tostring(file))
|
||||||
song_xml = objectify.fromstring(xml)
|
song_xml = objectify.fromstring(xml)
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % os.path.split(self.import_source)[-1])
|
|
||||||
self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
|
self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
|
||||||
for song in song_xml.Item:
|
for song in song_xml.Item:
|
||||||
self.import_wizard.incrementProgressBar(
|
if self.stop_import_flag:
|
||||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
return
|
||||||
u'Importing %s, song %s...')) %
|
self._parse_song(song)
|
||||||
(os.path.split(self.import_source)[-1], song.Title1))
|
|
||||||
success = self._parse_song(song)
|
|
||||||
if not success or self.stop_import_flag:
|
|
||||||
return False
|
|
||||||
elif self.commit:
|
|
||||||
self.finish()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _parse_song(self, song):
|
def _parse_song(self, song):
|
||||||
self._success = True
|
self._success = True
|
||||||
@ -90,7 +82,11 @@ class EasiSlidesImport(SongImport):
|
|||||||
self._add_copyright(song.LicenceAdmin2)
|
self._add_copyright(song.LicenceAdmin2)
|
||||||
self._add_unicode_attribute(u'song_book_name', song.BookReference)
|
self._add_unicode_attribute(u'song_book_name', song.BookReference)
|
||||||
self._parse_and_add_lyrics(song)
|
self._parse_and_add_lyrics(song)
|
||||||
return self._success
|
if self._success:
|
||||||
|
if not self.finish():
|
||||||
|
self.log_error(song.Title1 if song.Title1 else u'')
|
||||||
|
else:
|
||||||
|
self.set_defaults()
|
||||||
|
|
||||||
def _add_unicode_attribute(self, self_attribute, import_attribute,
|
def _add_unicode_attribute(self, self_attribute, import_attribute,
|
||||||
mandatory=False):
|
mandatory=False):
|
||||||
@ -122,10 +118,8 @@ class EasiSlidesImport(SongImport):
|
|||||||
def _add_authors(self, song):
|
def _add_authors(self, song):
|
||||||
try:
|
try:
|
||||||
authors = unicode(song.Writer).split(u',')
|
authors = unicode(song.Writer).split(u',')
|
||||||
for author in authors:
|
self.authors = \
|
||||||
author = author.strip()
|
[author.strip() for author in authors if author.strip()]
|
||||||
if len(author):
|
|
||||||
self.authors.append(author)
|
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
log.exception(u'Unicode decode error while decoding Writer')
|
log.exception(u'Unicode decode error while decoding Writer')
|
||||||
self._success = False
|
self._success = False
|
||||||
@ -188,12 +182,13 @@ class EasiSlidesImport(SongImport):
|
|||||||
# if the regions are inside verses
|
# if the regions are inside verses
|
||||||
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
|
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
|
||||||
MarkTypes = {
|
MarkTypes = {
|
||||||
u'CHORUS': u'C',
|
u'CHORUS': VerseType.Tags[VerseType.Chorus],
|
||||||
u'VERSE': u'V',
|
u'VERSE': VerseType.Tags[VerseType.Verse],
|
||||||
u'INTRO': u'I',
|
u'INTRO': VerseType.Tags[VerseType.Intro],
|
||||||
u'ENDING': u'E',
|
u'ENDING': VerseType.Tags[VerseType.Ending],
|
||||||
u'BRIDGE': u'B',
|
u'BRIDGE': VerseType.Tags[VerseType.Bridge],
|
||||||
u'PRECHORUS': u'P'}
|
u'PRECHORUS': VerseType.Tags[VerseType.PreChorus]
|
||||||
|
}
|
||||||
verses = {}
|
verses = {}
|
||||||
# list as [region, versetype, versenum, instance]
|
# list as [region, versetype, versenum, instance]
|
||||||
our_verse_order = []
|
our_verse_order = []
|
||||||
|
@ -33,6 +33,7 @@ import struct
|
|||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
||||||
from songimport import SongImport
|
from songimport import SongImport
|
||||||
|
|
||||||
@ -142,12 +143,12 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
# Open the DB and MB files if they exist
|
# Open the DB and MB files if they exist
|
||||||
import_source_mb = self.import_source.replace('.DB', '.MB')
|
import_source_mb = self.import_source.replace('.DB', '.MB')
|
||||||
if not os.path.isfile(self.import_source):
|
if not os.path.isfile(self.import_source):
|
||||||
return False
|
return
|
||||||
if not os.path.isfile(import_source_mb):
|
if not os.path.isfile(import_source_mb):
|
||||||
return False
|
return
|
||||||
db_size = os.path.getsize(self.import_source)
|
db_size = os.path.getsize(self.import_source)
|
||||||
if db_size < 0x800:
|
if db_size < 0x800:
|
||||||
return False
|
return
|
||||||
db_file = open(self.import_source, 'rb')
|
db_file = open(self.import_source, 'rb')
|
||||||
self.memo_file = open(import_source_mb, 'rb')
|
self.memo_file = open(import_source_mb, 'rb')
|
||||||
# Don't accept files that are clearly not paradox files
|
# Don't accept files that are clearly not paradox files
|
||||||
@ -156,7 +157,7 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
if header_size != 0x800 or block_size < 1 or block_size > 4:
|
if header_size != 0x800 or block_size < 1 or block_size > 4:
|
||||||
db_file.close()
|
db_file.close()
|
||||||
self.memo_file.close()
|
self.memo_file.close()
|
||||||
return False
|
return
|
||||||
# Take a stab at how text is encoded
|
# Take a stab at how text is encoded
|
||||||
self.encoding = u'cp1252'
|
self.encoding = u'cp1252'
|
||||||
db_file.seek(106)
|
db_file.seek(106)
|
||||||
@ -183,7 +184,7 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
self.encoding = u'cp874'
|
self.encoding = u'cp874'
|
||||||
self.encoding = retrieve_windows_encoding(self.encoding)
|
self.encoding = retrieve_windows_encoding(self.encoding)
|
||||||
if not self.encoding:
|
if not self.encoding:
|
||||||
return False
|
return
|
||||||
# There does not appear to be a _reliable_ way of getting the number
|
# 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.
|
# of songs/records, so let's use file blocks for measuring progress.
|
||||||
total_blocks = (db_size - header_size) / (block_size * 1024)
|
total_blocks = (db_size - header_size) / (block_size * 1024)
|
||||||
@ -203,8 +204,8 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
field_size))
|
field_size))
|
||||||
self.set_record_struct(field_descs)
|
self.set_record_struct(field_descs)
|
||||||
# Pick out the field description indexes we will need
|
# Pick out the field description indexes we will need
|
||||||
success = True
|
|
||||||
try:
|
try:
|
||||||
|
success = True
|
||||||
fi_title = self.find_field(u'Title')
|
fi_title = self.find_field(u'Title')
|
||||||
fi_author = self.find_field(u'Author')
|
fi_author = self.find_field(u'Author')
|
||||||
fi_copy = self.find_field(u'Copyright')
|
fi_copy = self.find_field(u'Copyright')
|
||||||
@ -223,31 +224,25 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
# Loop through each record within the current block
|
# Loop through each record within the current block
|
||||||
for i in range(rec_count):
|
for i in range(rec_count):
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
raw_record = db_file.read(record_size)
|
raw_record = db_file.read(record_size)
|
||||||
self.fields = self.record_struct.unpack(raw_record)
|
self.fields = self.record_struct.unpack(raw_record)
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
# Get title and update progress bar message
|
self.title = self.get_field(fi_title)
|
||||||
title = self.get_field(fi_title)
|
# Get remaining fields.
|
||||||
if title:
|
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % title, 0)
|
|
||||||
self.title = title
|
|
||||||
# Get remaining fields
|
|
||||||
copy = self.get_field(fi_copy)
|
copy = self.get_field(fi_copy)
|
||||||
admin = self.get_field(fi_admin)
|
admin = self.get_field(fi_admin)
|
||||||
ccli = self.get_field(fi_ccli)
|
ccli = self.get_field(fi_ccli)
|
||||||
authors = self.get_field(fi_author)
|
authors = self.get_field(fi_author)
|
||||||
words = self.get_field(fi_words)
|
words = self.get_field(fi_words)
|
||||||
# Set the SongImport object members
|
# Set the SongImport object members.
|
||||||
if copy:
|
if copy:
|
||||||
self.copyright = copy
|
self.copyright = copy
|
||||||
if admin:
|
if admin:
|
||||||
if copy:
|
if copy:
|
||||||
self.copyright += u', '
|
self.copyright += u', '
|
||||||
self.copyright += \
|
self.copyright += \
|
||||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
unicode(translate('SongsPlugin.EasyWorshipSongImport',
|
||||||
'Administered by %s')) % admin
|
'Administered by %s')) % admin
|
||||||
if ccli:
|
if ccli:
|
||||||
self.ccli_number = ccli
|
self.ccli_number = ccli
|
||||||
@ -264,19 +259,17 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
# Format the lyrics
|
# Format the lyrics
|
||||||
words = strip_rtf(words, self.encoding)
|
words = strip_rtf(words, self.encoding)
|
||||||
for verse in words.split(u'\n\n'):
|
for verse in words.split(u'\n\n'):
|
||||||
self.add_verse(verse.strip(), u'V')
|
self.add_verse(
|
||||||
|
verse.strip(), VerseType.Tags[VerseType.Verse])
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
self.finish()
|
if not self.finish():
|
||||||
if not self.stop_import_flag:
|
self.log_error(self.import_source)
|
||||||
self.import_wizard.incrementProgressBar(u'')
|
|
||||||
db_file.close()
|
db_file.close()
|
||||||
self.memo_file.close()
|
self.memo_file.close()
|
||||||
return success
|
|
||||||
|
|
||||||
def find_field(self, field_name):
|
def find_field(self, field_name):
|
||||||
return [i for i, x in enumerate(self.field_descs) \
|
return [i for i, x in enumerate(self.field_descs)
|
||||||
if x.name == field_name][0]
|
if x.name == field_name][0]
|
||||||
|
|
||||||
def set_record_struct(self, field_descs):
|
def set_record_struct(self, field_descs):
|
||||||
|
@ -97,6 +97,7 @@ from openlp.core.ui.wizard import WizardStrings
|
|||||||
from openlp.plugins.songs.lib import clean_song, VerseType
|
from openlp.plugins.songs.lib import clean_song, VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
|
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
|
||||||
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
from openlp.plugins.songs.lib.xml import SongXML
|
from openlp.plugins.songs.lib.xml import SongXML
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -121,17 +122,16 @@ class FoilPresenterImport(SongImport):
|
|||||||
parser = etree.XMLParser(remove_blank_text=True)
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
for file_path in self.import_source:
|
for file_path in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return False
|
return
|
||||||
self.import_wizard.incrementProgressBar(
|
self.import_wizard.incrementProgressBar(
|
||||||
WizardStrings.ImportingType % os.path.basename(file_path))
|
WizardStrings.ImportingType % os.path.basename(file_path))
|
||||||
try:
|
try:
|
||||||
parsed_file = etree.parse(file_path, parser)
|
parsed_file = etree.parse(file_path, parser)
|
||||||
xml = unicode(etree.tostring(parsed_file))
|
xml = unicode(etree.tostring(parsed_file))
|
||||||
if self.FoilPresenter.xml_to_song(xml) is None:
|
self.FoilPresenter.xml_to_song(xml)
|
||||||
log.debug(u'File could not be imported: %s' % file_path)
|
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
|
self.log_error(file_path, SongStrings.XMLSyntaxError)
|
||||||
log.exception(u'XML syntax error in file %s' % file_path)
|
log.exception(u'XML syntax error in file %s' % file_path)
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class FoilPresenter(object):
|
class FoilPresenter(object):
|
||||||
@ -211,7 +211,7 @@ class FoilPresenter(object):
|
|||||||
"""
|
"""
|
||||||
# No xml get out of here.
|
# No xml get out of here.
|
||||||
if not xml:
|
if not xml:
|
||||||
return None
|
return
|
||||||
if xml[:5] == u'<?xml':
|
if xml[:5] == u'<?xml':
|
||||||
xml = xml[38:]
|
xml = xml[38:]
|
||||||
song = Song()
|
song = Song()
|
||||||
@ -235,7 +235,6 @@ class FoilPresenter(object):
|
|||||||
self._process_topics(foilpresenterfolie, song)
|
self._process_topics(foilpresenterfolie, song)
|
||||||
clean_song(self.manager, song)
|
clean_song(self.manager, song)
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
return song.id
|
|
||||||
|
|
||||||
def _child(self, element):
|
def _child(self, element):
|
||||||
"""
|
"""
|
||||||
@ -305,9 +304,8 @@ class FoilPresenter(object):
|
|||||||
for marker in markers:
|
for marker in markers:
|
||||||
copyright = re.compile(marker).sub(u'<marker>', copyright, re.U)
|
copyright = re.compile(marker).sub(u'<marker>', copyright, re.U)
|
||||||
copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright)
|
copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright)
|
||||||
i = 0
|
|
||||||
x = 0
|
x = 0
|
||||||
while i != 1:
|
while True:
|
||||||
if copyright.find(u'<marker>') != -1:
|
if copyright.find(u'<marker>') != -1:
|
||||||
temp = copyright.partition(u'<marker>')
|
temp = copyright.partition(u'<marker>')
|
||||||
if temp[0].strip() and x > 0:
|
if temp[0].strip() and x > 0:
|
||||||
@ -316,9 +314,9 @@ class FoilPresenter(object):
|
|||||||
x += 1
|
x += 1
|
||||||
elif x > 0:
|
elif x > 0:
|
||||||
strings.append(copyright)
|
strings.append(copyright)
|
||||||
i = 1
|
break
|
||||||
else:
|
else:
|
||||||
i = 1
|
break
|
||||||
author_temp = []
|
author_temp = []
|
||||||
for author in strings:
|
for author in strings:
|
||||||
temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);',
|
temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);',
|
||||||
@ -349,8 +347,8 @@ class FoilPresenter(object):
|
|||||||
if author is None:
|
if author is None:
|
||||||
# We need to create a new author, as the author does not exist.
|
# We need to create a new author, as the author does not exist.
|
||||||
author = Author.populate(display_name=display_name,
|
author = Author.populate(display_name=display_name,
|
||||||
last_name = display_name.split(u' ')[-1],
|
last_name=display_name.split(u' ')[-1],
|
||||||
first_name = u' '.join(display_name.split(u' ')[:-1]))
|
first_name=u' '.join(display_name.split(u' ')[:-1]))
|
||||||
self.manager.save_object(author)
|
self.manager.save_object(author)
|
||||||
song.authors.append(author)
|
song.authors.append(author)
|
||||||
|
|
||||||
@ -414,8 +412,15 @@ class FoilPresenter(object):
|
|||||||
temp_verse_order_backup = []
|
temp_verse_order_backup = []
|
||||||
temp_sortnr_backup = 1
|
temp_sortnr_backup = 1
|
||||||
temp_sortnr_liste = []
|
temp_sortnr_liste = []
|
||||||
versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1,
|
versenumber = {
|
||||||
u'P': 1}
|
VerseType.Tags[VerseType.Verse]: 1,
|
||||||
|
VerseType.Tags[VerseType.Chorus]: 1,
|
||||||
|
VerseType.Tags[VerseType.Bridge]: 1,
|
||||||
|
VerseType.Tags[VerseType.Ending]: 1,
|
||||||
|
VerseType.Tags[VerseType.Other]: 1,
|
||||||
|
VerseType.Tags[VerseType.Intro]: 1,
|
||||||
|
VerseType.Tags[VerseType.PreChorus]: 1
|
||||||
|
}
|
||||||
for strophe in foilpresenterfolie.strophen.strophe:
|
for strophe in foilpresenterfolie.strophen.strophe:
|
||||||
text = self._child(strophe.text_)
|
text = self._child(strophe.text_)
|
||||||
verse_name = self._child(strophe.key)
|
verse_name = self._child(strophe.key)
|
||||||
@ -434,25 +439,25 @@ class FoilPresenter(object):
|
|||||||
temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name)
|
temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name)
|
||||||
temp_verse_name = temp_verse_name[:3].lower()
|
temp_verse_name = temp_verse_name[:3].lower()
|
||||||
if temp_verse_name == u'ref':
|
if temp_verse_name == u'ref':
|
||||||
verse_type = u'C'
|
verse_type = VerseType.Tags[VerseType.Chorus]
|
||||||
elif temp_verse_name == u'r':
|
elif temp_verse_name == u'r':
|
||||||
verse_type = u'C'
|
verse_type = VerseType.Tags[VerseType.Chorus]
|
||||||
elif temp_verse_name == u'':
|
elif temp_verse_name == u'':
|
||||||
verse_type = u'V'
|
verse_type = VerseType.Tags[VerseType.Verse]
|
||||||
elif temp_verse_name == u'v':
|
elif temp_verse_name == u'v':
|
||||||
verse_type = u'V'
|
verse_type = VerseType.Tags[VerseType.Verse]
|
||||||
elif temp_verse_name == u'bri':
|
elif temp_verse_name == u'bri':
|
||||||
verse_type = u'B'
|
verse_type = VerseType.Tags[VerseType.Bridge]
|
||||||
elif temp_verse_name == u'cod':
|
elif temp_verse_name == u'cod':
|
||||||
verse_type = u'E'
|
verse_type = VerseType.Tags[VerseType.Ending]
|
||||||
elif temp_verse_name == u'sch':
|
elif temp_verse_name == u'sch':
|
||||||
verse_type = u'E'
|
verse_type = VerseType.Tags[VerseType.Ending]
|
||||||
elif temp_verse_name == u'pre':
|
elif temp_verse_name == u'pre':
|
||||||
verse_type = u'P'
|
verse_type = VerseType.Tags[VerseType.PreChorus]
|
||||||
elif temp_verse_name == u'int':
|
elif temp_verse_name == u'int':
|
||||||
verse_type = u'I'
|
verse_type = VerseType.Tags[VerseType.Intro]
|
||||||
else:
|
else:
|
||||||
verse_type = u'O'
|
verse_type = VerseType.Tags[VerseType.Other]
|
||||||
verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name)
|
verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name)
|
||||||
# Foilpresenter allows e. g. "C", but we need "C1".
|
# Foilpresenter allows e. g. "C", but we need "C1".
|
||||||
if not verse_number:
|
if not verse_number:
|
||||||
@ -466,8 +471,8 @@ class FoilPresenter(object):
|
|||||||
verse_number = unicode(int(verse_number) + 1)
|
verse_number = unicode(int(verse_number) + 1)
|
||||||
verse_type_index = VerseType.from_tag(verse_type[0])
|
verse_type_index = VerseType.from_tag(verse_type[0])
|
||||||
verse_type = VerseType.Names[verse_type_index]
|
verse_type = VerseType.Names[verse_type_index]
|
||||||
temp_verse_order[verse_sortnr] = (u''.join((verse_type[0],
|
temp_verse_order[verse_sortnr] = u''.join((verse_type[0],
|
||||||
verse_number)))
|
verse_number))
|
||||||
temp_verse_order_backup.append(u''.join((verse_type[0],
|
temp_verse_order_backup.append(u''.join((verse_type[0],
|
||||||
verse_number)))
|
verse_number)))
|
||||||
sxml.add_verse_to_lyrics(verse_type, verse_number, text)
|
sxml.add_verse_to_lyrics(verse_type, verse_number, text)
|
||||||
|
@ -32,7 +32,7 @@ import logging
|
|||||||
from chardet.universaldetector import UniversalDetector
|
from chardet.universaldetector import UniversalDetector
|
||||||
import sqlite
|
import sqlite
|
||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.lib import translate
|
||||||
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
from openlp.plugins.songs.lib import retrieve_windows_encoding
|
||||||
from songimport import SongImport
|
from songimport import SongImport
|
||||||
|
|
||||||
@ -61,10 +61,15 @@ class OpenLP1SongImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Run the import for an openlp.org 1.x song database.
|
Run the import for an openlp.org 1.x song database.
|
||||||
"""
|
"""
|
||||||
# Connect to the database
|
if not self.import_source.endswith(u'.olp'):
|
||||||
|
self.log_error(self.import_source,
|
||||||
|
translate('SongsPlugin.OpenLP1SongImport',
|
||||||
|
'Not a valid openlp.org 1.x song database.'))
|
||||||
|
return
|
||||||
encoding = self.get_encoding()
|
encoding = self.get_encoding()
|
||||||
if not encoding:
|
if not encoding:
|
||||||
return False
|
return
|
||||||
|
# Connect to the database
|
||||||
connection = sqlite.connect(self.import_source, mode=0444,
|
connection = sqlite.connect(self.import_source, mode=0444,
|
||||||
encoding=(encoding, 'replace'))
|
encoding=(encoding, 'replace'))
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
@ -72,12 +77,6 @@ class OpenLP1SongImport(SongImport):
|
|||||||
cursor.execute(u'SELECT name FROM sqlite_master '
|
cursor.execute(u'SELECT name FROM sqlite_master '
|
||||||
u'WHERE type = \'table\' AND name = \'tracks\'')
|
u'WHERE type = \'table\' AND name = \'tracks\'')
|
||||||
new_db = len(cursor.fetchall()) > 0
|
new_db = len(cursor.fetchall()) > 0
|
||||||
# Count the number of records we need to import, for the progress bar
|
|
||||||
cursor.execute(u'-- types int')
|
|
||||||
cursor.execute(u'SELECT COUNT(songid) FROM songs')
|
|
||||||
count = cursor.fetchone()[0]
|
|
||||||
success = True
|
|
||||||
self.import_wizard.progressBar.setMaximum(count)
|
|
||||||
# "cache" our list of authors
|
# "cache" our list of authors
|
||||||
cursor.execute(u'-- types int, unicode')
|
cursor.execute(u'-- types int, unicode')
|
||||||
cursor.execute(u'SELECT authorid, authorname FROM authors')
|
cursor.execute(u'SELECT authorid, authorname FROM authors')
|
||||||
@ -92,37 +91,29 @@ class OpenLP1SongImport(SongImport):
|
|||||||
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
|
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
|
||||||
u'copyrightinfo FROM songs')
|
u'copyrightinfo FROM songs')
|
||||||
songs = cursor.fetchall()
|
songs = cursor.fetchall()
|
||||||
|
self.import_wizard.progressBar.setMaximum(len(songs))
|
||||||
for song in songs:
|
for song in songs:
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
song_id = song[0]
|
song_id = song[0]
|
||||||
title = song[1]
|
self.title = song[1]
|
||||||
lyrics = song[2].replace(u'\r\n', u'\n')
|
lyrics = song[2].replace(u'\r\n', u'\n')
|
||||||
copyright = song[3]
|
self.add_copyright(song[3])
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % title)
|
|
||||||
self.title = title
|
|
||||||
verses = lyrics.split(u'\n\n')
|
verses = lyrics.split(u'\n\n')
|
||||||
for verse in verses:
|
[self.add_verse(verse.strip()) for verse in verses if verse.strip()]
|
||||||
if verse.strip() != u'':
|
|
||||||
self.add_verse(verse.strip())
|
|
||||||
self.add_copyright(copyright)
|
|
||||||
cursor.execute(u'-- types int')
|
cursor.execute(u'-- types int')
|
||||||
cursor.execute(u'SELECT authorid FROM songauthors '
|
cursor.execute(u'SELECT authorid FROM songauthors '
|
||||||
u'WHERE songid = %s' % song_id)
|
u'WHERE songid = %s' % song_id)
|
||||||
author_ids = cursor.fetchall()
|
author_ids = cursor.fetchall()
|
||||||
for author_id in author_ids:
|
for author_id in author_ids:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
for author in authors:
|
for author in authors:
|
||||||
if author[0] == author_id[0]:
|
if author[0] == author_id[0]:
|
||||||
self.parse_author(author[1])
|
self.parse_author(author[1])
|
||||||
break
|
break
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
if new_db:
|
if new_db:
|
||||||
cursor.execute(u'-- types int')
|
cursor.execute(u'-- types int')
|
||||||
@ -131,17 +122,15 @@ class OpenLP1SongImport(SongImport):
|
|||||||
track_ids = cursor.fetchall()
|
track_ids = cursor.fetchall()
|
||||||
for track_id in track_ids:
|
for track_id in track_ids:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
if track[0] == track_id[0]:
|
if track[0] == track_id[0]:
|
||||||
self.add_media_file(track[1])
|
self.add_media_file(track[1])
|
||||||
break
|
break
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
|
||||||
break
|
break
|
||||||
self.finish()
|
if not self.finish():
|
||||||
return success
|
self.log_error(self.import_source)
|
||||||
|
|
||||||
def get_encoding(self):
|
def get_encoding(self):
|
||||||
"""
|
"""
|
||||||
|
@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError
|
|||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.lib.db import BaseModel
|
from openlp.core.lib.db import BaseModel
|
||||||
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
from openlp.plugins.songs.lib import clean_song
|
from openlp.plugins.songs.lib import clean_song
|
||||||
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
|
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
|
||||||
from songimport import SongImport
|
from songimport import SongImport
|
||||||
@ -93,13 +94,18 @@ class OpenLPSongImport(SongImport):
|
|||||||
The database providing the data to import.
|
The database providing the data to import.
|
||||||
"""
|
"""
|
||||||
SongImport.__init__(self, manager, **kwargs)
|
SongImport.__init__(self, manager, **kwargs)
|
||||||
self.import_source = u'sqlite:///%s' % self.import_source
|
|
||||||
self.source_session = None
|
self.source_session = None
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
"""
|
"""
|
||||||
Run the import for an OpenLP version 2 song database.
|
Run the import for an OpenLP version 2 song database.
|
||||||
"""
|
"""
|
||||||
|
if not self.import_source.endswith(u'.sqlite'):
|
||||||
|
self.log_error(self.import_source,
|
||||||
|
translate('SongsPlugin.OpenLPSongImport',
|
||||||
|
'Not a valid OpenLP 2.0 song database.'))
|
||||||
|
return
|
||||||
|
self.import_source = u'sqlite:///%s' % self.import_source
|
||||||
engine = create_engine(self.import_source)
|
engine = create_engine(self.import_source)
|
||||||
source_meta = MetaData()
|
source_meta = MetaData()
|
||||||
source_meta.reflect(engine)
|
source_meta.reflect(engine)
|
||||||
@ -124,10 +130,10 @@ class OpenLPSongImport(SongImport):
|
|||||||
mapper(OldMediaFile, source_media_files_table)
|
mapper(OldMediaFile, source_media_files_table)
|
||||||
song_props = {
|
song_props = {
|
||||||
'authors': relation(OldAuthor, backref='songs',
|
'authors': relation(OldAuthor, backref='songs',
|
||||||
secondary=source_authors_songs_table),
|
secondary=source_authors_songs_table),
|
||||||
'book': relation(OldBook, backref='songs'),
|
'book': relation(OldBook, backref='songs'),
|
||||||
'topics': relation(OldTopic, backref='songs',
|
'topics': relation(OldTopic, backref='songs',
|
||||||
secondary=source_songs_topics_table)
|
secondary=source_songs_topics_table)
|
||||||
}
|
}
|
||||||
if has_media_files:
|
if has_media_files:
|
||||||
song_props['media_files'] = relation(OldMediaFile, backref='songs',
|
song_props['media_files'] = relation(OldMediaFile, backref='songs',
|
||||||
@ -150,15 +156,9 @@ class OpenLPSongImport(SongImport):
|
|||||||
mapper(OldTopic, source_topics_table)
|
mapper(OldTopic, source_topics_table)
|
||||||
|
|
||||||
source_songs = self.source_session.query(OldSong).all()
|
source_songs = self.source_session.query(OldSong).all()
|
||||||
song_total = len(source_songs)
|
|
||||||
if self.import_wizard:
|
if self.import_wizard:
|
||||||
self.import_wizard.progressBar.setMaximum(song_total)
|
self.import_wizard.progressBar.setMaximum(len(source_songs))
|
||||||
song_count = 1
|
|
||||||
for song in source_songs:
|
for song in source_songs:
|
||||||
if self.import_wizard:
|
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
unicode(translate('SongsPlugin.OpenLPSongImport',
|
|
||||||
'Importing song %d of %d.')) % (song_count, song_total))
|
|
||||||
new_song = Song()
|
new_song = Song()
|
||||||
new_song.title = song.title
|
new_song.title = song.title
|
||||||
if has_media_files and hasattr(song, 'alternate_title'):
|
if has_media_files and hasattr(song, 'alternate_title'):
|
||||||
@ -213,8 +213,9 @@ class OpenLPSongImport(SongImport):
|
|||||||
# file_name=media_file.file_name))
|
# file_name=media_file.file_name))
|
||||||
clean_song(self.manager, new_song)
|
clean_song(self.manager, new_song)
|
||||||
self.manager.save_object(new_song)
|
self.manager.save_object(new_song)
|
||||||
song_count += 1
|
if self.import_wizard:
|
||||||
|
self.import_wizard.incrementProgressBar(
|
||||||
|
WizardStrings.ImportingType % new_song.title)
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return False
|
break
|
||||||
engine.dispose()
|
engine.dispose()
|
||||||
return True
|
|
||||||
|
@ -56,13 +56,11 @@ class OooImport(SongImport):
|
|||||||
self.process_started = False
|
self.process_started = False
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
self.stop_import_flag = False
|
|
||||||
self.import_wizard.progressBar.setMaximum(0)
|
|
||||||
self.start_ooo()
|
self.start_ooo()
|
||||||
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
for filename in self.import_source:
|
for filename in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
self.import_wizard.incrementProgressBar(u'Import cancelled', 0)
|
break
|
||||||
return
|
|
||||||
filename = unicode(filename)
|
filename = unicode(filename)
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
self.open_ooo_file(filename)
|
self.open_ooo_file(filename)
|
||||||
@ -70,9 +68,6 @@ class OooImport(SongImport):
|
|||||||
self.process_ooo_document()
|
self.process_ooo_document()
|
||||||
self.close_ooo_file()
|
self.close_ooo_file()
|
||||||
self.close_ooo()
|
self.close_ooo()
|
||||||
self.import_wizard.progressBar.setMaximum(1)
|
|
||||||
self.import_wizard.incrementProgressBar(u'', 1)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def process_ooo_document(self):
|
def process_ooo_document(self):
|
||||||
"""
|
"""
|
||||||
|
@ -35,6 +35,7 @@ from lxml import etree
|
|||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
from openlp.plugins.songs.lib import OpenLyrics
|
from openlp.plugins.songs.lib import OpenLyrics
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -59,7 +60,7 @@ class OpenLyricsImport(SongImport):
|
|||||||
parser = etree.XMLParser(remove_blank_text=True)
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
for file_path in self.import_source:
|
for file_path in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return False
|
return
|
||||||
self.import_wizard.incrementProgressBar(
|
self.import_wizard.incrementProgressBar(
|
||||||
WizardStrings.ImportingType % os.path.basename(file_path))
|
WizardStrings.ImportingType % os.path.basename(file_path))
|
||||||
try:
|
try:
|
||||||
@ -67,8 +68,7 @@ class OpenLyricsImport(SongImport):
|
|||||||
# special characters in the path (see lp:757673 and lp:744337).
|
# special characters in the path (see lp:757673 and lp:744337).
|
||||||
parsed_file = etree.parse(open(file_path, u'r'), parser)
|
parsed_file = etree.parse(open(file_path, u'r'), parser)
|
||||||
xml = unicode(etree.tostring(parsed_file))
|
xml = unicode(etree.tostring(parsed_file))
|
||||||
if self.openLyrics.xml_to_song(xml) is None:
|
self.openLyrics.xml_to_song(xml)
|
||||||
log.debug(u'File could not be imported: %s' % file_path)
|
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
log.exception(u'XML syntax error in file %s' % file_path)
|
log.exception(u'XML syntax error in file %s' % file_path)
|
||||||
return True
|
self.log_error(file_path, SongStrings.XMLSyntaxError)
|
||||||
|
@ -26,13 +26,15 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from lxml import objectify
|
from lxml import objectify
|
||||||
from lxml.etree import Error, LxmlError
|
from lxml.etree import Error, LxmlError
|
||||||
import re
|
|
||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -105,77 +107,62 @@ class OpenSongImport(SongImport):
|
|||||||
Initialise the class.
|
Initialise the class.
|
||||||
"""
|
"""
|
||||||
SongImport.__init__(self, manager, **kwargs)
|
SongImport.__init__(self, manager, **kwargs)
|
||||||
self.commit = True
|
|
||||||
|
|
||||||
def do_import(self):
|
def do_import(self):
|
||||||
"""
|
"""
|
||||||
Import either each of the files in self.import_source - each element of
|
Import either each of the files in self.import_source - each element of
|
||||||
which can be either a single opensong file, or a zipfile containing
|
which can be either a single opensong file, or a zipfile containing
|
||||||
multiple opensong files. If `self.commit` is set False, the
|
multiple opensong files.
|
||||||
import will not be committed to the database (useful for test scripts).
|
|
||||||
"""
|
"""
|
||||||
success = True
|
|
||||||
numfiles = 0
|
numfiles = 0
|
||||||
for filename in self.import_source:
|
for filename in self.import_source:
|
||||||
ext = os.path.splitext(filename)[1]
|
ext = os.path.splitext(filename)[1]
|
||||||
if ext.lower() == u'.zip':
|
if ext.lower() == u'.zip':
|
||||||
z = ZipFile(filename, u'r')
|
z = ZipFile(filename, u'r')
|
||||||
numfiles += len(z.infolist())
|
numfiles += len(z.infolist())
|
||||||
|
z.close()
|
||||||
else:
|
else:
|
||||||
numfiles += 1
|
numfiles += 1
|
||||||
log.debug(u'Total number of files: %d', numfiles)
|
log.debug(u'Total number of files: %d', numfiles)
|
||||||
self.import_wizard.progressBar.setMaximum(numfiles)
|
self.import_wizard.progressBar.setMaximum(numfiles)
|
||||||
for filename in self.import_source:
|
for filename in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
return
|
||||||
break
|
|
||||||
ext = os.path.splitext(filename)[1]
|
ext = os.path.splitext(filename)[1]
|
||||||
if ext.lower() == u'.zip':
|
if ext.lower() == u'.zip':
|
||||||
log.debug(u'Zipfile found %s', filename)
|
log.debug(u'Zipfile found %s', filename)
|
||||||
z = ZipFile(filename, u'r')
|
z = ZipFile(filename, u'r')
|
||||||
for song in z.infolist():
|
for song in z.infolist():
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
success = False
|
z.close()
|
||||||
break
|
return
|
||||||
parts = os.path.split(song.filename)
|
parts = os.path.split(song.filename)
|
||||||
if parts[-1] == u'':
|
if parts[-1] == u'':
|
||||||
#No final part => directory
|
# No final part => directory
|
||||||
continue
|
continue
|
||||||
log.info(u'Zip importing %s', parts[-1])
|
log.info(u'Zip importing %s', parts[-1])
|
||||||
self.import_wizard.incrementProgressBar(
|
song_file = z.open(song)
|
||||||
WizardStrings.ImportingType % parts[-1])
|
self.do_import_file(song_file)
|
||||||
songfile = z.open(song)
|
song_file.close()
|
||||||
if self.do_import_file(songfile) and self.commit and \
|
z.close()
|
||||||
not self.stop_import_flag:
|
|
||||||
self.finish()
|
|
||||||
else:
|
|
||||||
success = False
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
# not a zipfile
|
# not a zipfile
|
||||||
log.info(u'Direct import %s', filename)
|
log.info(u'Direct import %s', filename)
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % os.path.split(filename)[-1])
|
|
||||||
song_file = open(filename)
|
song_file = open(filename)
|
||||||
if self.do_import_file(song_file) and self.commit and \
|
self.do_import_file(song_file)
|
||||||
not self.stop_import_flag:
|
song_file.close()
|
||||||
self.finish()
|
|
||||||
else:
|
|
||||||
success = False
|
|
||||||
break
|
|
||||||
return success
|
|
||||||
|
|
||||||
def do_import_file(self, file):
|
def do_import_file(self, file):
|
||||||
"""
|
"""
|
||||||
Process the OpenSong file - pass in a file-like object,
|
Process the OpenSong file - pass in a file-like object, not a file path.
|
||||||
not a filename
|
|
||||||
"""
|
"""
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
try:
|
try:
|
||||||
tree = objectify.parse(file)
|
tree = objectify.parse(file)
|
||||||
except (Error, LxmlError):
|
except (Error, LxmlError):
|
||||||
|
self.log_error(file.name, SongStrings.XMLSyntaxError)
|
||||||
log.exception(u'Error parsing XML')
|
log.exception(u'Error parsing XML')
|
||||||
return False
|
return
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
fields = dir(root)
|
fields = dir(root)
|
||||||
decode = {
|
decode = {
|
||||||
@ -193,9 +180,6 @@ class OpenSongImport(SongImport):
|
|||||||
setattr(self, fn_or_string, ustring)
|
setattr(self, fn_or_string, ustring)
|
||||||
else:
|
else:
|
||||||
fn_or_string(ustring)
|
fn_or_string(ustring)
|
||||||
if not len(self.title):
|
|
||||||
# to prevent creation of empty songs from wrong files
|
|
||||||
return False
|
|
||||||
if u'theme' in fields and unicode(root.theme) not in self.topics:
|
if u'theme' in fields and unicode(root.theme) not in self.topics:
|
||||||
self.topics.append(unicode(root.theme))
|
self.topics.append(unicode(root.theme))
|
||||||
if u'alttheme' in fields and unicode(root.alttheme) not in self.topics:
|
if u'alttheme' in fields and unicode(root.alttheme) not in self.topics:
|
||||||
@ -205,11 +189,14 @@ class OpenSongImport(SongImport):
|
|||||||
# keep track of verses appearance order
|
# keep track of verses appearance order
|
||||||
our_verse_order = []
|
our_verse_order = []
|
||||||
# default verse
|
# default verse
|
||||||
verse_tag = u'v'
|
verse_tag = VerseType.Tags[VerseType.Verse]
|
||||||
verse_num = u'1'
|
verse_num = u'1'
|
||||||
# for the case where song has several sections with same marker
|
# for the case where song has several sections with same marker
|
||||||
inst = 1
|
inst = 1
|
||||||
lyrics = unicode(root.lyrics)
|
if u'lyrics' in fields:
|
||||||
|
lyrics = unicode(root.lyrics)
|
||||||
|
else:
|
||||||
|
lyrics = u''
|
||||||
for this_line in lyrics.split(u'\n'):
|
for this_line in lyrics.split(u'\n'):
|
||||||
# remove comments
|
# remove comments
|
||||||
semicolon = this_line.find(u';')
|
semicolon = this_line.find(u';')
|
||||||
@ -230,7 +217,7 @@ class OpenSongImport(SongImport):
|
|||||||
# have we got any digits?
|
# have we got any digits?
|
||||||
# If so, verse number is everything from the digits
|
# If so, verse number is everything from the digits
|
||||||
# to the end (even if there are some alpha chars on the end)
|
# to the end (even if there are some alpha chars on the end)
|
||||||
match = re.match(u'(.*)(\d+.*)', content)
|
match = re.match(u'(\D*)(\d+.*)', content)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
verse_tag = match.group(1)
|
verse_tag = match.group(1)
|
||||||
verse_num = match.group(2)
|
verse_num = match.group(2)
|
||||||
@ -239,12 +226,13 @@ class OpenSongImport(SongImport):
|
|||||||
# the verse tag
|
# the verse tag
|
||||||
verse_tag = content
|
verse_tag = content
|
||||||
verse_num = u'1'
|
verse_num = u'1'
|
||||||
|
verse_index = VerseType.from_loose_input(verse_tag)
|
||||||
|
verse_tag = VerseType.Tags[verse_index]
|
||||||
inst = 1
|
inst = 1
|
||||||
if [verse_tag, verse_num, inst] in our_verse_order \
|
if [verse_tag, verse_num, inst] in our_verse_order \
|
||||||
and verses.has_key(verse_tag) \
|
and verses.has_key(verse_tag) \
|
||||||
and verses[verse_tag].has_key(verse_num):
|
and verses[verse_tag].has_key(verse_num):
|
||||||
inst = len(verses[verse_tag][verse_num])+1
|
inst = len(verses[verse_tag][verse_num]) + 1
|
||||||
our_verse_order.append([verse_tag, verse_num, inst])
|
|
||||||
continue
|
continue
|
||||||
# number at start of line.. it's verse number
|
# number at start of line.. it's verse number
|
||||||
if this_line[0].isdigit():
|
if this_line[0].isdigit():
|
||||||
@ -257,6 +245,7 @@ class OpenSongImport(SongImport):
|
|||||||
verses[verse_tag][verse_num] = {}
|
verses[verse_tag][verse_num] = {}
|
||||||
if not verses[verse_tag][verse_num].has_key(inst):
|
if not verses[verse_tag][verse_num].has_key(inst):
|
||||||
verses[verse_tag][verse_num][inst] = []
|
verses[verse_tag][verse_num][inst] = []
|
||||||
|
our_verse_order.append([verse_tag, verse_num, inst])
|
||||||
# Tidy text and remove the ____s from extended words
|
# Tidy text and remove the ____s from extended words
|
||||||
this_line = self.tidy_text(this_line)
|
this_line = self.tidy_text(this_line)
|
||||||
this_line = this_line.replace(u'_', u'')
|
this_line = this_line.replace(u'_', u'')
|
||||||
@ -268,28 +257,31 @@ class OpenSongImport(SongImport):
|
|||||||
verse_def = u'%s%s' % (verse_tag, verse_num)
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
lines = u'\n'.join(verses[verse_tag][verse_num][inst])
|
lines = u'\n'.join(verses[verse_tag][verse_num][inst])
|
||||||
self.add_verse(lines, verse_def)
|
self.add_verse(lines, verse_def)
|
||||||
|
if not self.verses:
|
||||||
|
self.add_verse('')
|
||||||
# figure out the presentation order, if present
|
# figure out the presentation order, if present
|
||||||
if u'presentation' in fields and root.presentation != u'':
|
if u'presentation' in fields and root.presentation:
|
||||||
order = unicode(root.presentation)
|
order = unicode(root.presentation)
|
||||||
# We make all the tags in the lyrics lower case, so match that here
|
# We make all the tags in the lyrics lower case, so match that here
|
||||||
# and then split into a list on the whitespace
|
# and then split into a list on the whitespace
|
||||||
order = order.lower().split()
|
order = order.lower().split()
|
||||||
for verse_def in order:
|
for verse_def in order:
|
||||||
match = re.match(u'(.*)(\d+.*)', verse_def)
|
match = re.match(u'(\D*)(\d+.*)', verse_def)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
verse_tag = match.group(1)
|
verse_tag = match.group(1)
|
||||||
verse_num = match.group(2)
|
verse_num = match.group(2)
|
||||||
if not len(verse_tag):
|
if not len(verse_tag):
|
||||||
verse_tag = u'v'
|
verse_tag = VerseType.Tags[VerseType.Verse]
|
||||||
else:
|
else:
|
||||||
# Assume it's no.1 if there are no digits
|
# Assume it's no.1 if there are no digits
|
||||||
verse_tag = verse_def
|
verse_tag = verse_def
|
||||||
verse_num = u'1'
|
verse_num = u'1'
|
||||||
verse_def = u'%s%s' % (verse_tag, verse_num)
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
if verses.has_key(verse_tag) \
|
if verses.has_key(verse_tag) and \
|
||||||
and verses[verse_tag].has_key(verse_num):
|
verses[verse_tag].has_key(verse_num):
|
||||||
self.verse_order_list.append(verse_def)
|
self.verse_order_list.append(verse_def)
|
||||||
else:
|
else:
|
||||||
log.info(u'Got order %s but not in verse tags, dropping'
|
log.info(u'Got order %s but not in verse tags, dropping'
|
||||||
u'this item from presentation order', verse_def)
|
u'this item from presentation order', verse_def)
|
||||||
return True
|
if not self.finish():
|
||||||
|
self.log_error(file.name)
|
||||||
|
@ -88,7 +88,6 @@ class SofImport(OooImport):
|
|||||||
paragraphs = self.document.getText().createEnumeration()
|
paragraphs = self.document.getText().createEnumeration()
|
||||||
while paragraphs.hasMoreElements():
|
while paragraphs.hasMoreElements():
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
self.import_wizard.incrementProgressBar(u'Import cancelled', 0)
|
|
||||||
return
|
return
|
||||||
paragraph = paragraphs.nextElement()
|
paragraph = paragraphs.nextElement()
|
||||||
if paragraph.supportsService("com.sun.star.text.Paragraph"):
|
if paragraph.supportsService("com.sun.star.text.Paragraph"):
|
||||||
|
@ -33,9 +33,9 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
|
||||||
from openlp.plugins.songs.lib import VerseType
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -78,58 +78,55 @@ class SongBeamerImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Receive a single file or a list of files to import.
|
Receive a single file or a list of files to import.
|
||||||
"""
|
"""
|
||||||
if isinstance(self.import_source, list):
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
self.import_wizard.progressBar.setMaximum(
|
if not isinstance(self.import_source, list):
|
||||||
len(self.import_source))
|
return
|
||||||
for file in self.import_source:
|
for file in self.import_source:
|
||||||
# TODO: check that it is a valid SongBeamer file
|
# TODO: check that it is a valid SongBeamer file
|
||||||
self.set_defaults()
|
if self.stop_import_flag:
|
||||||
self.current_verse = u''
|
return
|
||||||
self.current_verse_type = VerseType.Tags[VerseType.Verse]
|
self.set_defaults()
|
||||||
read_verses = False
|
self.current_verse = u''
|
||||||
file_name = os.path.split(file)[1]
|
self.current_verse_type = VerseType.Tags[VerseType.Verse]
|
||||||
self.import_wizard.incrementProgressBar(
|
read_verses = False
|
||||||
WizardStrings.ImportingType % file_name, 0)
|
file_name = os.path.split(file)[1]
|
||||||
if os.path.isfile(file):
|
if os.path.isfile(file):
|
||||||
detect_file = open(file, u'r')
|
detect_file = open(file, u'r')
|
||||||
details = chardet.detect(detect_file.read(2048))
|
details = chardet.detect(detect_file.read(2048))
|
||||||
detect_file.close()
|
detect_file.close()
|
||||||
infile = codecs.open(file, u'r', details['encoding'])
|
infile = codecs.open(file, u'r', details['encoding'])
|
||||||
songData = infile.readlines()
|
songData = infile.readlines()
|
||||||
infile.close()
|
infile.close()
|
||||||
else:
|
else:
|
||||||
return False
|
continue
|
||||||
self.title = file_name.split('.sng')[0]
|
self.title = file_name.split('.sng')[0]
|
||||||
read_verses = False
|
read_verses = False
|
||||||
for line in songData:
|
for line in songData:
|
||||||
# Just make sure that the line is of the type 'Unicode'.
|
# Just make sure that the line is of the type 'Unicode'.
|
||||||
line = unicode(line).strip()
|
line = unicode(line).strip()
|
||||||
if line.startswith(u'#') and not read_verses:
|
if line.startswith(u'#') and not read_verses:
|
||||||
self.parse_tags(line)
|
self.parse_tags(line)
|
||||||
elif line.startswith(u'---'):
|
elif line.startswith(u'---'):
|
||||||
if self.current_verse:
|
if self.current_verse:
|
||||||
self.replace_html_tags()
|
self.replace_html_tags()
|
||||||
self.add_verse(self.current_verse,
|
self.add_verse(self.current_verse,
|
||||||
self.current_verse_type)
|
self.current_verse_type)
|
||||||
self.current_verse = u''
|
self.current_verse = u''
|
||||||
self.current_verse_type = VerseType.Tags[VerseType.Verse]
|
self.current_verse_type = VerseType.Tags[VerseType.Verse]
|
||||||
read_verses = True
|
read_verses = True
|
||||||
verse_start = True
|
verse_start = True
|
||||||
elif read_verses:
|
elif read_verses:
|
||||||
if verse_start:
|
if verse_start:
|
||||||
verse_start = False
|
verse_start = False
|
||||||
if not self.check_verse_marks(line):
|
if not self.check_verse_marks(line):
|
||||||
self.current_verse = line + u'\n'
|
self.current_verse = line + u'\n'
|
||||||
else:
|
else:
|
||||||
self.current_verse += line + u'\n'
|
self.current_verse += line + u'\n'
|
||||||
if self.current_verse:
|
if self.current_verse:
|
||||||
self.replace_html_tags()
|
self.replace_html_tags()
|
||||||
self.add_verse(self.current_verse, self.current_verse_type)
|
self.add_verse(self.current_verse, self.current_verse_type)
|
||||||
if self.check_complete():
|
if not self.finish():
|
||||||
self.finish()
|
self.log_error(file)
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % file_name)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def replace_html_tags(self):
|
def replace_html_tags(self):
|
||||||
"""
|
"""
|
||||||
@ -189,7 +186,7 @@ class SongBeamerImport(SongImport):
|
|||||||
elif tag_val[0] == u'#Bible':
|
elif tag_val[0] == u'#Bible':
|
||||||
pass
|
pass
|
||||||
elif tag_val[0] == u'#Categories':
|
elif tag_val[0] == u'#Categories':
|
||||||
self.topics = line.split(',')
|
self.topics = tag_val[1].split(',')
|
||||||
elif tag_val[0] == u'#CCLI':
|
elif tag_val[0] == u'#CCLI':
|
||||||
self.ccli_number = tag_val[1]
|
self.ccli_number = tag_val[1]
|
||||||
elif tag_val[0] == u'#Chords':
|
elif tag_val[0] == u'#Chords':
|
||||||
@ -236,11 +233,12 @@ class SongBeamerImport(SongImport):
|
|||||||
pass
|
pass
|
||||||
elif tag_val[0] == u'#Rights':
|
elif tag_val[0] == u'#Rights':
|
||||||
song_book_pub = tag_val[1]
|
song_book_pub = tag_val[1]
|
||||||
elif tag_val[0] == u'#Songbook':
|
elif tag_val[0] == u'#Songbook' or tag_val[0] == u'#SongBook':
|
||||||
book_num = tag_val[1].split(' / ')
|
book_data = tag_val[1].split(u'/')
|
||||||
self.song_book_name = book_num[0]
|
self.song_book_name = book_data[0].strip()
|
||||||
if len(book_num) == book_num[1]:
|
if len(book_data) == 2:
|
||||||
self.song_number = u''
|
number = book_data[1].strip()
|
||||||
|
self.song_number = number if number.isdigit() else u''
|
||||||
elif tag_val[0] == u'#Speed':
|
elif tag_val[0] == u'#Speed':
|
||||||
pass
|
pass
|
||||||
elif tag_val[0] == u'Tempo':
|
elif tag_val[0] == u'Tempo':
|
||||||
@ -287,5 +285,4 @@ class SongBeamerImport(SongImport):
|
|||||||
if marks[1].isdigit():
|
if marks[1].isdigit():
|
||||||
self.current_verse_type += marks[1]
|
self.current_verse_type += marks[1]
|
||||||
return True
|
return True
|
||||||
else:
|
return False
|
||||||
return False
|
|
||||||
|
@ -23,12 +23,14 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
from openlp.core.lib import Receiver, translate
|
from openlp.core.lib import Receiver, translate, check_directory_exists
|
||||||
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
|
from openlp.core.utils import AppLocation
|
||||||
from openlp.plugins.songs.lib import clean_song, VerseType
|
from openlp.plugins.songs.lib import clean_song, VerseType
|
||||||
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
|
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
|
||||||
from openlp.plugins.songs.lib.ui import SongStrings
|
from openlp.plugins.songs.lib.ui import SongStrings
|
||||||
@ -66,6 +68,7 @@ class SongImport(QtCore.QObject):
|
|||||||
self.song = None
|
self.song = None
|
||||||
self.stop_import_flag = False
|
self.stop_import_flag = False
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
|
self.error_log = []
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
|
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
|
||||||
|
|
||||||
@ -94,6 +97,32 @@ class SongImport(QtCore.QObject):
|
|||||||
self.copyright_string = unicode(translate(
|
self.copyright_string = unicode(translate(
|
||||||
'SongsPlugin.SongImport', 'copyright'))
|
'SongsPlugin.SongImport', 'copyright'))
|
||||||
|
|
||||||
|
def log_error(self, filepath, reason=SongStrings.SongIncomplete):
|
||||||
|
"""
|
||||||
|
This should be called, when a song could not be imported.
|
||||||
|
|
||||||
|
``filepath``
|
||||||
|
This should be the file path if ``self.import_source`` is a list
|
||||||
|
with different files. If it is not a list, but a single file (for
|
||||||
|
instance a database), then this should be the song's title.
|
||||||
|
|
||||||
|
``reason``
|
||||||
|
The reason, why the import failed. The string should be as
|
||||||
|
informative as possible.
|
||||||
|
"""
|
||||||
|
self.set_defaults()
|
||||||
|
if self.import_wizard is None:
|
||||||
|
return
|
||||||
|
if self.import_wizard.errorReportTextEdit.isHidden():
|
||||||
|
self.import_wizard.errorReportTextEdit.setText(
|
||||||
|
translate('SongsPlugin.SongImport',
|
||||||
|
'The following songs could not be imported:'))
|
||||||
|
self.import_wizard.errorReportTextEdit.setVisible(True)
|
||||||
|
self.import_wizard.errorCopyToButton.setVisible(True)
|
||||||
|
self.import_wizard.errorSaveToButton.setVisible(True)
|
||||||
|
self.import_wizard.errorReportTextEdit.append(
|
||||||
|
u'- %s (%s)' % (filepath, reason))
|
||||||
|
|
||||||
def stop_import(self):
|
def stop_import(self):
|
||||||
"""
|
"""
|
||||||
Sets the flag for importers to stop their import
|
Sets the flag for importers to stop their import
|
||||||
@ -240,7 +269,7 @@ class SongImport(QtCore.QObject):
|
|||||||
Author not checked here, if no author then "Author unknown" is
|
Author not checked here, if no author then "Author unknown" is
|
||||||
automatically added
|
automatically added
|
||||||
"""
|
"""
|
||||||
if self.title == u'' or len(self.verses) == 0:
|
if not self.title or not len(self.verses):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
@ -249,9 +278,15 @@ class SongImport(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
All fields have been set to this song. Write the song to disk.
|
All fields have been set to this song. Write the song to disk.
|
||||||
"""
|
"""
|
||||||
|
if not self.check_complete():
|
||||||
|
self.set_defaults()
|
||||||
|
return False
|
||||||
log.info(u'committing song %s to database', self.title)
|
log.info(u'committing song %s to database', self.title)
|
||||||
song = Song()
|
song = Song()
|
||||||
song.title = self.title
|
song.title = self.title
|
||||||
|
if self.import_wizard is not None:
|
||||||
|
self.import_wizard.incrementProgressBar(
|
||||||
|
WizardStrings.ImportingType % song.title)
|
||||||
song.alternate_title = self.alternate_title
|
song.alternate_title = self.alternate_title
|
||||||
# Values will be set when cleaning the song.
|
# Values will be set when cleaning the song.
|
||||||
song.search_title = u''
|
song.search_title = u''
|
||||||
@ -308,7 +343,7 @@ class SongImport(QtCore.QObject):
|
|||||||
publisher=self.song_book_pub)
|
publisher=self.song_book_pub)
|
||||||
song.book = song_book
|
song.book = song_book
|
||||||
for topictext in self.topics:
|
for topictext in self.topics:
|
||||||
if len(topictext) == 0:
|
if not topictext:
|
||||||
continue
|
continue
|
||||||
topic = self.manager.get_object_filtered(Topic,
|
topic = self.manager.get_object_filtered(Topic,
|
||||||
Topic.name == topictext)
|
Topic.name == topictext)
|
||||||
@ -318,6 +353,7 @@ class SongImport(QtCore.QObject):
|
|||||||
clean_song(self.manager, song)
|
clean_song(self.manager, song)
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
|
return True
|
||||||
|
|
||||||
def print_song(self):
|
def print_song(self):
|
||||||
"""
|
"""
|
||||||
|
@ -32,6 +32,7 @@ import logging
|
|||||||
import struct
|
import struct
|
||||||
|
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
|
from openlp.plugins.songs.lib import VerseType
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
TITLE = 1
|
TITLE = 1
|
||||||
@ -97,83 +98,81 @@ class SongShowPlusImport(SongImport):
|
|||||||
Receive a single file or a list of files to import.
|
Receive a single file or a list of files to import.
|
||||||
"""
|
"""
|
||||||
if isinstance(self.import_source, list):
|
if isinstance(self.import_source, list):
|
||||||
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
return
|
||||||
for file in self.import_source:
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
author = u''
|
for file in self.import_source:
|
||||||
self.sspVerseOrderList = []
|
self.sspVerseOrderList = []
|
||||||
otherCount = 0
|
otherCount = 0
|
||||||
otherList = {}
|
otherList = {}
|
||||||
file_name = os.path.split(file)[1]
|
file_name = os.path.split(file)[1]
|
||||||
self.import_wizard.incrementProgressBar(
|
self.import_wizard.incrementProgressBar(
|
||||||
WizardStrings.ImportingType % file_name, 0)
|
WizardStrings.ImportingType % file_name, 0)
|
||||||
songData = open(file, 'rb')
|
songData = open(file, 'rb')
|
||||||
while (1):
|
while True:
|
||||||
blockKey, = struct.unpack("I", songData.read(4))
|
blockKey, = struct.unpack("I", songData.read(4))
|
||||||
# The file ends with 4 NUL's
|
# The file ends with 4 NUL's
|
||||||
if blockKey == 0:
|
if blockKey == 0:
|
||||||
break
|
break
|
||||||
nextBlockStarts, = struct.unpack("I", songData.read(4))
|
nextBlockStarts, = struct.unpack("I", songData.read(4))
|
||||||
if blockKey == VERSE or blockKey == CHORUS:
|
if blockKey == VERSE or blockKey == CHORUS:
|
||||||
null, verseNo, = struct.unpack("BB", songData.read(2))
|
null, verseNo, = struct.unpack("BB", songData.read(2))
|
||||||
elif blockKey == CUSTOM_VERSE:
|
elif blockKey == CUSTOM_VERSE:
|
||||||
null, verseNameLength, = struct.unpack("BB",
|
null, verseNameLength, = struct.unpack("BB",
|
||||||
songData.read(2))
|
songData.read(2))
|
||||||
verseName = songData.read(verseNameLength)
|
verseName = songData.read(verseNameLength)
|
||||||
lengthDescriptorSize, = struct.unpack("B", songData.read(1))
|
lengthDescriptorSize, = struct.unpack("B", songData.read(1))
|
||||||
# Detect if/how long the length descriptor is
|
# Detect if/how long the length descriptor is
|
||||||
if lengthDescriptorSize == 12:
|
if lengthDescriptorSize == 12:
|
||||||
lengthDescriptor, = struct.unpack("I", songData.read(4))
|
lengthDescriptor, = struct.unpack("I", songData.read(4))
|
||||||
elif lengthDescriptorSize == 2:
|
elif lengthDescriptorSize == 2:
|
||||||
lengthDescriptor = 1
|
lengthDescriptor = 1
|
||||||
elif lengthDescriptorSize == 9:
|
elif lengthDescriptorSize == 9:
|
||||||
lengthDescriptor = 0
|
lengthDescriptor = 0
|
||||||
else:
|
else:
|
||||||
lengthDescriptor, = struct.unpack("B", songData.read(1))
|
lengthDescriptor, = struct.unpack("B", songData.read(1))
|
||||||
data = songData.read(lengthDescriptor)
|
data = songData.read(lengthDescriptor)
|
||||||
if blockKey == TITLE:
|
if blockKey == TITLE:
|
||||||
self.title = unicode(data, u'cp1252')
|
self.title = unicode(data, u'cp1252')
|
||||||
elif blockKey == AUTHOR:
|
elif blockKey == AUTHOR:
|
||||||
authors = data.split(" / ")
|
authors = data.split(" / ")
|
||||||
for author in authors:
|
for author in authors:
|
||||||
if author.find(",") !=-1:
|
if author.find(",") !=-1:
|
||||||
authorParts = author.split(", ")
|
authorParts = author.split(", ")
|
||||||
author = authorParts[1] + " " + authorParts[0]
|
author = authorParts[1] + " " + authorParts[0]
|
||||||
self.parse_author(unicode(author, u'cp1252'))
|
self.parse_author(unicode(author, u'cp1252'))
|
||||||
elif blockKey == COPYRIGHT:
|
elif blockKey == COPYRIGHT:
|
||||||
self.add_copyright(unicode(data, u'cp1252'))
|
self.add_copyright(unicode(data, u'cp1252'))
|
||||||
elif blockKey == CCLI_NO:
|
elif blockKey == CCLI_NO:
|
||||||
self.ccli_number = int(data)
|
self.ccli_number = int(data)
|
||||||
elif blockKey == VERSE:
|
elif blockKey == VERSE:
|
||||||
self.add_verse(unicode(data, u'cp1252'),
|
self.add_verse(unicode(data, u'cp1252'),
|
||||||
"V%s" % verseNo)
|
"V%s" % verseNo)
|
||||||
elif blockKey == CHORUS:
|
elif blockKey == CHORUS:
|
||||||
self.add_verse(unicode(data, u'cp1252'),
|
self.add_verse(unicode(data, u'cp1252'),
|
||||||
"C%s" % verseNo)
|
"C%s" % verseNo)
|
||||||
elif blockKey == TOPIC:
|
elif blockKey == TOPIC:
|
||||||
self.topics.append(unicode(data, u'cp1252'))
|
self.topics.append(unicode(data, u'cp1252'))
|
||||||
elif blockKey == COMMENTS:
|
elif blockKey == COMMENTS:
|
||||||
self.comments = unicode(data, u'cp1252')
|
self.comments = unicode(data, u'cp1252')
|
||||||
elif blockKey == VERSE_ORDER:
|
elif blockKey == VERSE_ORDER:
|
||||||
verseTag = self.toOpenLPVerseTag(data, True)
|
verseTag = self.toOpenLPVerseTag(data, True)
|
||||||
if verseTag:
|
if verseTag:
|
||||||
self.sspVerseOrderList.append(unicode(verseTag,
|
self.sspVerseOrderList.append(unicode(verseTag,
|
||||||
u'cp1252'))
|
u'cp1252'))
|
||||||
elif blockKey == SONG_BOOK:
|
elif blockKey == SONG_BOOK:
|
||||||
self.song_book_name = unicode(data, u'cp1252')
|
self.song_book_name = unicode(data, u'cp1252')
|
||||||
elif blockKey == SONG_NUMBER:
|
elif blockKey == SONG_NUMBER:
|
||||||
self.song_number = ord(data)
|
self.song_number = ord(data)
|
||||||
elif blockKey == CUSTOM_VERSE:
|
elif blockKey == CUSTOM_VERSE:
|
||||||
verseTag = self.toOpenLPVerseTag(verseName)
|
verseTag = self.toOpenLPVerseTag(verseName)
|
||||||
self.add_verse(unicode(data, u'cp1252'), verseTag)
|
self.add_verse(unicode(data, u'cp1252'), verseTag)
|
||||||
else:
|
else:
|
||||||
log.debug("Unrecognised blockKey: %s, data: %s"
|
log.debug("Unrecognised blockKey: %s, data: %s"
|
||||||
%(blockKey, data))
|
% (blockKey, data))
|
||||||
self.verse_order_list = self.sspVerseOrderList
|
self.verse_order_list = self.sspVerseOrderList
|
||||||
songData.close()
|
songData.close()
|
||||||
self.finish()
|
if not self.finish():
|
||||||
self.import_wizard.incrementProgressBar(
|
self.log_error(file)
|
||||||
WizardStrings.ImportingType % file_name)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def toOpenLPVerseTag(self, verseName, ignoreUnique=False):
|
def toOpenLPVerseTag(self, verseName, ignoreUnique=False):
|
||||||
if verseName.find(" ") != -1:
|
if verseName.find(" ") != -1:
|
||||||
@ -185,22 +184,19 @@ class SongShowPlusImport(SongImport):
|
|||||||
verseNumber = "1"
|
verseNumber = "1"
|
||||||
verseType = verseType.lower()
|
verseType = verseType.lower()
|
||||||
if verseType == "verse":
|
if verseType == "verse":
|
||||||
verseTag = "V"
|
verseTag = VerseType.Tags[VerseType.Verse]
|
||||||
elif verseType == "chorus":
|
elif verseType == "chorus":
|
||||||
verseTag = "C"
|
verseTag = VerseType.Tags[VerseType.Chorus]
|
||||||
elif verseType == "bridge":
|
elif verseType == "bridge":
|
||||||
verseTag = "B"
|
verseTag = VerseType.Tags[VerseType.Bridge]
|
||||||
elif verseType == "pre-chorus":
|
elif verseType == "pre-chorus":
|
||||||
verseTag = "P"
|
verseTag = VerseType.Tags[VerseType.PreChorus]
|
||||||
elif verseType == "bridge":
|
|
||||||
verseTag = "B"
|
|
||||||
else:
|
else:
|
||||||
if not self.otherList.has_key(verseName):
|
if not self.otherList.has_key(verseName):
|
||||||
if ignoreUnique:
|
if ignoreUnique:
|
||||||
return None
|
return None
|
||||||
self.otherCount = self.otherCount + 1
|
self.otherCount = self.otherCount + 1
|
||||||
self.otherList[verseName] = str(self.otherCount)
|
self.otherList[verseName] = str(self.otherCount)
|
||||||
verseTag = "O"
|
verseTag = VerseType.Tags[VerseType.Other]
|
||||||
verseNumber = self.otherList[verseName]
|
verseNumber = self.otherList[verseName]
|
||||||
verseTag = verseTag + verseNumber
|
return verseTag + verseNumber
|
||||||
return verseTag
|
|
||||||
|
@ -40,6 +40,8 @@ class SongStrings(object):
|
|||||||
CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.')
|
CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.')
|
||||||
SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular')
|
SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular')
|
||||||
SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural')
|
SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural')
|
||||||
|
SongIncomplete = translate('OpenLP.Ui','Title and/or verses not found')
|
||||||
SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance')
|
SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance')
|
||||||
Topic = translate('OpenLP.Ui', 'Topic', 'Singular')
|
Topic = translate('OpenLP.Ui', 'Topic', 'Singular')
|
||||||
Topics = translate('OpenLP.Ui', 'Topics', 'Plural')
|
Topics = translate('OpenLP.Ui', 'Topics', 'Plural')
|
||||||
|
XMLSyntaxError = translate('OpenLP.Ui', 'XML syntax error')
|
||||||
|
@ -105,11 +105,7 @@ class WowImport(SongImport):
|
|||||||
if isinstance(self.import_source, list):
|
if isinstance(self.import_source, list):
|
||||||
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
self.import_wizard.progressBar.setMaximum(len(self.import_source))
|
||||||
for file in self.import_source:
|
for file in self.import_source:
|
||||||
author = u''
|
|
||||||
copyright = u''
|
|
||||||
file_name = os.path.split(file)[1]
|
file_name = os.path.split(file)[1]
|
||||||
self.import_wizard.incrementProgressBar(
|
|
||||||
WizardStrings.ImportingType % file_name, 0)
|
|
||||||
# Get the song title
|
# Get the song title
|
||||||
self.title = file_name.rpartition(u'.')[0]
|
self.title = file_name.rpartition(u'.')[0]
|
||||||
songData = open(file, 'rb')
|
songData = open(file, 'rb')
|
||||||
@ -129,7 +125,7 @@ class WowImport(SongImport):
|
|||||||
self.line_text = unicode(
|
self.line_text = unicode(
|
||||||
songData.read(ord(songData.read(1))), u'cp1252')
|
songData.read(ord(songData.read(1))), u'cp1252')
|
||||||
songData.seek(1, os.SEEK_CUR)
|
songData.seek(1, os.SEEK_CUR)
|
||||||
if block_text != u'':
|
if block_text:
|
||||||
block_text += u'\n'
|
block_text += u'\n'
|
||||||
block_text += self.line_text
|
block_text += self.line_text
|
||||||
self.lines_to_read -= 1
|
self.lines_to_read -= 1
|
||||||
@ -138,22 +134,19 @@ class WowImport(SongImport):
|
|||||||
songData.seek(3, os.SEEK_CUR)
|
songData.seek(3, os.SEEK_CUR)
|
||||||
# Blocks are seperated by 2 bytes, skip them, but not if
|
# Blocks are seperated by 2 bytes, skip them, but not if
|
||||||
# this is the last block!
|
# this is the last block!
|
||||||
if (block + 1) < no_of_blocks:
|
if block + 1 < no_of_blocks:
|
||||||
songData.seek(2, os.SEEK_CUR)
|
songData.seek(2, os.SEEK_CUR)
|
||||||
self.add_verse(block_text, block_type)
|
self.add_verse(block_text, block_type)
|
||||||
# Now to extract the author
|
# Now to extract the author
|
||||||
author_length = ord(songData.read(1))
|
author_length = ord(songData.read(1))
|
||||||
if author_length != 0:
|
if author_length:
|
||||||
author = unicode(songData.read(author_length), u'cp1252')
|
self.parse_author(
|
||||||
|
unicode(songData.read(author_length), u'cp1252'))
|
||||||
# Finally the copyright
|
# Finally the copyright
|
||||||
copyright_length = ord(songData.read(1))
|
copyright_length = ord(songData.read(1))
|
||||||
if copyright_length != 0:
|
if copyright_length:
|
||||||
copyright = unicode(
|
self.add_copyright(unicode(
|
||||||
songData.read(copyright_length), u'cp1252')
|
songData.read(copyright_length), u'cp1252'))
|
||||||
self.parse_author(author)
|
|
||||||
self.add_copyright(copyright)
|
|
||||||
songData.close()
|
songData.close()
|
||||||
self.finish()
|
if not self.finish():
|
||||||
self.import_wizard.incrementProgressBar(
|
self.log_error(file)
|
||||||
WizardStrings.ImportingType % file_name)
|
|
||||||
return True
|
|
||||||
|