forked from openlp/openlp
More changes, now internally tags are held not as Salm:1 (previously), nor v:1 (in the meantime), but just as in openlyrics format, v1.
The v1a is not yet supported, it requires spinboxes to be changed first. The old and new should be handled silently side-by-side. bzr-revno: 1310
This commit is contained in:
commit
4a8b29aae9
@ -603,14 +603,15 @@ class SlideController(QtGui.QWidget):
|
|||||||
slideHeight = 0
|
slideHeight = 0
|
||||||
if self.serviceItem.is_text():
|
if self.serviceItem.is_text():
|
||||||
if frame[u'verseTag']:
|
if frame[u'verseTag']:
|
||||||
bits = frame[u'verseTag'].split(u':')
|
# These tags are already translated.
|
||||||
tag = u'%s\n%s' % (bits[0][0], bits[1][0:] )
|
verse_def = frame[u'verseTag']
|
||||||
tag1 = u'%s%s' % (bits[0][0], bits[1][0:] )
|
verse_def = u'%s%s' % (verse_def[0].upper(), verse_def[1:])
|
||||||
row = tag
|
two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:] )
|
||||||
|
row = two_line_def
|
||||||
if self.isLive:
|
if self.isLive:
|
||||||
if tag1 not in self.slideList:
|
if verse_def not in self.slideList:
|
||||||
self.slideList[tag1] = framenumber
|
self.slideList[verse_def] = framenumber
|
||||||
self.songMenu.menu().addAction(tag1,
|
self.songMenu.menu().addAction(verse_def,
|
||||||
self.onSongBarHandler)
|
self.onSongBarHandler)
|
||||||
else:
|
else:
|
||||||
row += 1
|
row += 1
|
||||||
|
@ -227,10 +227,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.copyrightEdit.setText(u'')
|
self.copyrightEdit.setText(u'')
|
||||||
self.verseListWidget.clear()
|
self.verseListWidget.clear()
|
||||||
self.verseListWidget.setRowCount(0)
|
self.verseListWidget.setRowCount(0)
|
||||||
if self.song.verse_order:
|
|
||||||
self.verseOrderEdit.setText(self.song.verse_order)
|
|
||||||
else:
|
|
||||||
self.verseOrderEdit.setText(u'')
|
|
||||||
if self.song.comments:
|
if self.song.comments:
|
||||||
self.commentsEdit.setPlainText(self.song.comments)
|
self.commentsEdit.setPlainText(self.song.comments)
|
||||||
else:
|
else:
|
||||||
@ -250,15 +246,31 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
# This is just because occasionally the lyrics come back as a "buffer"
|
# This is just because occasionally the lyrics come back as a "buffer"
|
||||||
if isinstance(self.song.lyrics, buffer):
|
if isinstance(self.song.lyrics, buffer):
|
||||||
self.song.lyrics = unicode(self.song.lyrics)
|
self.song.lyrics = unicode(self.song.lyrics)
|
||||||
|
verse_tags_translated = False
|
||||||
if self.song.lyrics.startswith(u'<?xml version='):
|
if self.song.lyrics.startswith(u'<?xml version='):
|
||||||
songXML = SongXML()
|
songXML = SongXML()
|
||||||
verseList = songXML.get_verses(self.song.lyrics)
|
verseList = songXML.get_verses(self.song.lyrics)
|
||||||
for count, verse in enumerate(verseList):
|
for count, verse in enumerate(verseList):
|
||||||
self.verseListWidget.setRowCount(
|
self.verseListWidget.setRowCount(
|
||||||
self.verseListWidget.rowCount() + 1)
|
self.verseListWidget.rowCount() + 1)
|
||||||
variant = u'%s:%s' % (verse[0][u'type'], verse[0][u'label'])
|
# This silently migrates from localized verse type markup.
|
||||||
|
# If we trusted the database, this would be unnecessary.
|
||||||
|
verse_tag = verse[0][u'type']
|
||||||
|
index = None
|
||||||
|
if len(verse_tag) > 1:
|
||||||
|
index = VerseType.from_translated_string(verse_tag)
|
||||||
|
if index is None:
|
||||||
|
index = VerseType.from_string(verse_tag)
|
||||||
|
else:
|
||||||
|
verse_tags_translated = True
|
||||||
|
if index is None:
|
||||||
|
index = VerseType.from_tag(verse_tag)
|
||||||
|
if index is None:
|
||||||
|
index = VerseType.Other
|
||||||
|
verse[0][u'type'] = VerseType.Tags[index]
|
||||||
|
verse_def = u'%s%s' % (verse[0][u'type'], verse[0][u'label'])
|
||||||
item = QtGui.QTableWidgetItem(verse[1])
|
item = QtGui.QTableWidgetItem(verse[1])
|
||||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(variant))
|
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
|
||||||
self.verseListWidget.setItem(count, 0, item)
|
self.verseListWidget.setItem(count, 0, item)
|
||||||
else:
|
else:
|
||||||
verses = self.song.lyrics.split(u'\n\n')
|
verses = self.song.lyrics.split(u'\n\n')
|
||||||
@ -266,10 +278,24 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.verseListWidget.setRowCount(
|
self.verseListWidget.setRowCount(
|
||||||
self.verseListWidget.rowCount() + 1)
|
self.verseListWidget.rowCount() + 1)
|
||||||
item = QtGui.QTableWidgetItem(verse)
|
item = QtGui.QTableWidgetItem(verse)
|
||||||
variant = u'%s:%s' % \
|
verse_def = u'%s%s' % \
|
||||||
(VerseType.to_string(VerseType.Verse), unicode(count + 1))
|
(VerseType.Tags[VerseType.Verse], unicode(count + 1))
|
||||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(variant))
|
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
|
||||||
self.verseListWidget.setItem(count, 0, item)
|
self.verseListWidget.setItem(count, 0, item)
|
||||||
|
if self.song.verse_order:
|
||||||
|
# we translate verse order
|
||||||
|
translated = []
|
||||||
|
for verse_def in self.song.verse_order.split():
|
||||||
|
verse_index = None
|
||||||
|
if verse_tags_translated:
|
||||||
|
verse_index = VerseType.from_translated_tag(verse_def[0])
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_tag(verse_def[0])
|
||||||
|
verse_tag = VerseType.TranslatedTags[verse_index].upper()
|
||||||
|
translated.append(u'%s%s' % (verse_tag, verse_def[1:]))
|
||||||
|
self.verseOrderEdit.setText(u' '.join(translated))
|
||||||
|
else:
|
||||||
|
self.verseOrderEdit.setText(u'')
|
||||||
self.verseListWidget.resizeRowsToContents()
|
self.verseListWidget.resizeRowsToContents()
|
||||||
self.tagRows()
|
self.tagRows()
|
||||||
# clear the results
|
# clear the results
|
||||||
@ -294,14 +320,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
"""
|
"""
|
||||||
Tag the Song List rows based on the verse list
|
Tag the Song List rows based on the verse list
|
||||||
"""
|
"""
|
||||||
rowLabel = []
|
row_label = []
|
||||||
for row in range(0, self.verseListWidget.rowCount()):
|
for row in range(0, self.verseListWidget.rowCount()):
|
||||||
item = self.verseListWidget.item(row, 0)
|
item = self.verseListWidget.item(row, 0)
|
||||||
data = unicode(item.data(QtCore.Qt.UserRole).toString())
|
verse_def = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
bit = data.split(u':')
|
verse_tag = VerseType.translated_tag(verse_def[0])
|
||||||
rowTag = u'%s%s' % (bit[0][0:1], bit[1])
|
row_def = u'%s%s' % (verse_tag, verse_def[1:])
|
||||||
rowLabel.append(rowTag)
|
row_label.append(row_def)
|
||||||
self.verseListWidget.setVerticalHeaderLabels(rowLabel)
|
self.verseListWidget.setVerticalHeaderLabels(row_label)
|
||||||
|
|
||||||
def onAuthorAddButtonClicked(self):
|
def onAuthorAddButtonClicked(self):
|
||||||
item = int(self.authorsComboBox.currentIndex())
|
item = int(self.authorsComboBox.currentIndex())
|
||||||
@ -420,11 +446,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
def onVerseAddButtonClicked(self):
|
def onVerseAddButtonClicked(self):
|
||||||
self.verse_form.setVerse(u'', True)
|
self.verse_form.setVerse(u'', True)
|
||||||
if self.verse_form.exec_():
|
if self.verse_form.exec_():
|
||||||
afterText, verse, subVerse = self.verse_form.getVerse()
|
after_text, verse_tag, verse_num = self.verse_form.getVerse()
|
||||||
data = u'%s:%s' % (verse, subVerse)
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
item = QtGui.QTableWidgetItem(afterText)
|
item = QtGui.QTableWidgetItem(after_text)
|
||||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(data))
|
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
|
||||||
item.setText(afterText)
|
item.setText(after_text)
|
||||||
self.verseListWidget.setRowCount(
|
self.verseListWidget.setRowCount(
|
||||||
self.verseListWidget.rowCount() + 1)
|
self.verseListWidget.rowCount() + 1)
|
||||||
self.verseListWidget.setItem(
|
self.verseListWidget.setItem(
|
||||||
@ -440,12 +466,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
self.verse_form.setVerse(tempText, True, verseId)
|
self.verse_form.setVerse(tempText, True, verseId)
|
||||||
if self.verse_form.exec_():
|
if self.verse_form.exec_():
|
||||||
afterText, verse, subVerse = self.verse_form.getVerse()
|
after_text, verse_tag, verse_num = self.verse_form.getVerse()
|
||||||
data = u'%s:%s' % (verse, subVerse)
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(data))
|
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def))
|
||||||
item.setText(afterText)
|
item.setText(after_text)
|
||||||
# number of lines has change so repaint the list moving the data
|
# number of lines has change so repaint the list moving the data
|
||||||
if len(tempText.split(u'\n')) != len(afterText.split(u'\n')):
|
if len(tempText.split(u'\n')) != len(after_text.split(u'\n')):
|
||||||
tempList = {}
|
tempList = {}
|
||||||
tempId = {}
|
tempId = {}
|
||||||
for row in range(0, self.verseListWidget.rowCount()):
|
for row in range(0, self.verseListWidget.rowCount()):
|
||||||
@ -467,7 +493,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
for row in range(0, self.verseListWidget.rowCount()):
|
for row in range(0, self.verseListWidget.rowCount()):
|
||||||
item = self.verseListWidget.item(row, 0)
|
item = self.verseListWidget.item(row, 0)
|
||||||
field = unicode(item.data(QtCore.Qt.UserRole).toString())
|
field = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
verse_list += u'---[%s]---\n' % field
|
verse_tag = VerseType.translated_name(field[0])
|
||||||
|
verse_num = field[1:]
|
||||||
|
verse_list += u'---[%s:%s]---\n' % (verse_tag, verse_num)
|
||||||
verse_list += item.text()
|
verse_list += item.text()
|
||||||
verse_list += u'\n'
|
verse_list += u'\n'
|
||||||
self.verse_form.setVerse(verse_list)
|
self.verse_form.setVerse(verse_list)
|
||||||
@ -483,15 +511,32 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
for count, parts in enumerate(match.split(u']---\n')):
|
for count, parts in enumerate(match.split(u']---\n')):
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
if count == 0:
|
if count == 0:
|
||||||
# make sure the tag is correctly cased
|
# handling carefully user inputted versetags
|
||||||
variant = u'%s%s' % \
|
separator = parts.find(u':')
|
||||||
(parts[0:1].upper(), parts[1:].lower())
|
if separator >= 0:
|
||||||
|
verse_name = parts[0:separator].strip()
|
||||||
|
verse_num = parts[separator+1:].strip()
|
||||||
|
else:
|
||||||
|
verse_name = parts
|
||||||
|
verse_num = u'1'
|
||||||
|
verse_index = \
|
||||||
|
VerseType.from_loose_input(verse_name)
|
||||||
|
verse_tag = VerseType.Tags[verse_index]
|
||||||
|
# Later we need to handle v1a as well.
|
||||||
|
#regex = re.compile(r'(\d+\w.)')
|
||||||
|
regex = re.compile(r'\D*(\d+)\D*')
|
||||||
|
match = regex.match(verse_num)
|
||||||
|
if match:
|
||||||
|
verse_num = match.group(1)
|
||||||
|
else:
|
||||||
|
verse_num = u'1'
|
||||||
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
else:
|
else:
|
||||||
if parts.endswith(u'\n'):
|
if parts.endswith(u'\n'):
|
||||||
parts = parts.rstrip(u'\n')
|
parts = parts.rstrip(u'\n')
|
||||||
item = QtGui.QTableWidgetItem(parts)
|
item = QtGui.QTableWidgetItem(parts)
|
||||||
item.setData(QtCore.Qt.UserRole,
|
item.setData(QtCore.Qt.UserRole,
|
||||||
QtCore.QVariant(variant))
|
QtCore.QVariant(verse_def))
|
||||||
self.verseListWidget.setRowCount(
|
self.verseListWidget.setRowCount(
|
||||||
self.verseListWidget.rowCount() + 1)
|
self.verseListWidget.rowCount() + 1)
|
||||||
self.verseListWidget.setItem(
|
self.verseListWidget.setItem(
|
||||||
@ -543,25 +588,31 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
order_names = unicode(self.verseOrderEdit.text()).split()
|
order_names = unicode(self.verseOrderEdit.text()).split()
|
||||||
for item in order_names:
|
for item in order_names:
|
||||||
if len(item) == 1:
|
if len(item) == 1:
|
||||||
order.append(item.lower() + u'1')
|
verse_index = VerseType.from_translated_tag(item)
|
||||||
|
if verse_index is not None:
|
||||||
|
order.append(VerseType.Tags[verse_index] + u'1')
|
||||||
|
else:
|
||||||
|
order.append(u'') # it matches no verses anyway
|
||||||
else:
|
else:
|
||||||
order.append(item.lower())
|
verse_index = VerseType.from_translated_tag(item[0])
|
||||||
|
if verse_index is None:
|
||||||
|
order.append(u'') # same as above
|
||||||
|
else:
|
||||||
|
verse_tag = VerseType.Tags[verse_index]
|
||||||
|
verse_num = item[1:].lower()
|
||||||
|
order.append(verse_tag + verse_num)
|
||||||
verses = []
|
verses = []
|
||||||
verse_names = []
|
verse_names = []
|
||||||
for index in range (0, self.verseListWidget.rowCount()):
|
for index in range(0, self.verseListWidget.rowCount()):
|
||||||
verse = self.verseListWidget.item(index, 0)
|
verse = self.verseListWidget.item(index, 0)
|
||||||
verse = unicode(verse.data(QtCore.Qt.UserRole).toString())
|
verse = unicode(verse.data(QtCore.Qt.UserRole).toString())
|
||||||
if verse not in verse_names:
|
if verse not in verse_names:
|
||||||
verses.append(
|
verses.append(verse)
|
||||||
re.sub(r'(.)[^:]*:(.*)', r'\1\2', verse.lower()))
|
verse_names.append(u'%s%s' % (
|
||||||
verse_names.append(verse)
|
VerseType.translated_tag(verse[0]), verse[1:]))
|
||||||
for count, item in enumerate(order):
|
for count, item in enumerate(order):
|
||||||
if item not in verses:
|
if item not in verses:
|
||||||
self.songTabWidget.setCurrentIndex(0)
|
valid = u', '.join(verse_names)
|
||||||
self.verseOrderEdit.setFocus()
|
|
||||||
valid = verses.pop(0)
|
|
||||||
for verse in verses:
|
|
||||||
valid = valid + u', ' + verse
|
|
||||||
critical_error_message_box(
|
critical_error_message_box(
|
||||||
message=unicode(translate('SongsPlugin.EditSongForm',
|
message=unicode(translate('SongsPlugin.EditSongForm',
|
||||||
'The verse order is invalid. There is no verse '
|
'The verse order is invalid. There is no verse '
|
||||||
@ -577,7 +628,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
unicode(translate('SongsPlugin.EditSongForm',
|
unicode(translate('SongsPlugin.EditSongForm',
|
||||||
'You have not used %s anywhere in the verse '
|
'You have not used %s anywhere in the verse '
|
||||||
'order. Are you sure you want to save the song '
|
'order. Are you sure you want to save the song '
|
||||||
'like this?')) % verse_names[count].replace(u':', u' '),
|
'like this?')) % verse_names[count],
|
||||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
|
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
|
||||||
if answer == QtGui.QMessageBox.No:
|
if answer == QtGui.QMessageBox.No:
|
||||||
return False
|
return False
|
||||||
@ -684,7 +735,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
else:
|
else:
|
||||||
self.song.search_title = self.song.title
|
self.song.search_title = self.song.title
|
||||||
self.song.comments = unicode(self.commentsEdit.toPlainText())
|
self.song.comments = unicode(self.commentsEdit.toPlainText())
|
||||||
self.song.verse_order = unicode(self.verseOrderEdit.text())
|
ordertext = unicode(self.verseOrderEdit.text())
|
||||||
|
order = []
|
||||||
|
for item in ordertext.split():
|
||||||
|
verse_tag = VerseType.Tags[
|
||||||
|
VerseType.from_translated_tag(item[0])]
|
||||||
|
verse_num = item[1:].lower()
|
||||||
|
order.append(u'%s%s' % (verse_tag, verse_num))
|
||||||
|
self.song.verse_order = u' '.join(order)
|
||||||
self.song.ccli_number = unicode(self.CCLNumberEdit.text())
|
self.song.ccli_number = unicode(self.CCLNumberEdit.text())
|
||||||
self.song.song_number = unicode(self.songBookNumberEdit.text())
|
self.song.song_number = unicode(self.songBookNumberEdit.text())
|
||||||
book_name = unicode(self.songBookComboBox.currentText())
|
book_name = unicode(self.songBookComboBox.currentText())
|
||||||
@ -727,12 +785,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
for i in range(0, self.verseListWidget.rowCount()):
|
for i in range(0, self.verseListWidget.rowCount()):
|
||||||
item = self.verseListWidget.item(i, 0)
|
item = self.verseListWidget.item(i, 0)
|
||||||
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
bits = verseId.split(u':')
|
verse_tag = verseId[0]
|
||||||
sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text()))
|
verse_num = verseId[1:]
|
||||||
|
sxml.add_verse_to_lyrics(verse_tag, verse_num,
|
||||||
|
unicode(item.text()))
|
||||||
text = text + self.whitespace.sub(u' ',
|
text = text + self.whitespace.sub(u' ',
|
||||||
unicode(self.verseListWidget.item(i, 0).text())) + u' '
|
unicode(self.verseListWidget.item(i, 0).text())) + u' '
|
||||||
if (bits[1] > u'1') and (bits[0][0] not in multiple):
|
if (verse_num > u'1') and (verse_tag not in multiple):
|
||||||
multiple.append(bits[0][0])
|
multiple.append(verse_tag)
|
||||||
self.song.search_lyrics = text.lower()
|
self.song.search_lyrics = text.lower()
|
||||||
self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
for verse in multiple:
|
for verse in multiple:
|
||||||
|
@ -70,19 +70,19 @@ class Ui_EditVerseDialog(object):
|
|||||||
translate('SongsPlugin.EditVerseForm', 'Edit Verse'))
|
translate('SongsPlugin.EditVerseForm', 'Edit Verse'))
|
||||||
self.verseTypeLabel.setText(
|
self.verseTypeLabel.setText(
|
||||||
translate('SongsPlugin.EditVerseForm', '&Verse type:'))
|
translate('SongsPlugin.EditVerseForm', '&Verse type:'))
|
||||||
self.verseTypeComboBox.setItemText(0,
|
self.verseTypeComboBox.setItemText(VerseType.Verse,
|
||||||
VerseType.to_string(VerseType.Verse))
|
VerseType.TranslatedNames[VerseType.Verse])
|
||||||
self.verseTypeComboBox.setItemText(1,
|
self.verseTypeComboBox.setItemText(VerseType.Chorus,
|
||||||
VerseType.to_string(VerseType.Chorus))
|
VerseType.TranslatedNames[VerseType.Chorus])
|
||||||
self.verseTypeComboBox.setItemText(2,
|
self.verseTypeComboBox.setItemText(VerseType.Bridge,
|
||||||
VerseType.to_string(VerseType.Bridge))
|
VerseType.TranslatedNames[VerseType.Bridge])
|
||||||
self.verseTypeComboBox.setItemText(3,
|
self.verseTypeComboBox.setItemText(VerseType.PreChorus,
|
||||||
VerseType.to_string(VerseType.PreChorus))
|
VerseType.TranslatedNames[VerseType.PreChorus])
|
||||||
self.verseTypeComboBox.setItemText(4,
|
self.verseTypeComboBox.setItemText(VerseType.Intro,
|
||||||
VerseType.to_string(VerseType.Intro))
|
VerseType.TranslatedNames[VerseType.Intro])
|
||||||
self.verseTypeComboBox.setItemText(5,
|
self.verseTypeComboBox.setItemText(VerseType.Ending,
|
||||||
VerseType.to_string(VerseType.Ending))
|
VerseType.TranslatedNames[VerseType.Ending])
|
||||||
self.verseTypeComboBox.setItemText(6,
|
self.verseTypeComboBox.setItemText(VerseType.Other,
|
||||||
VerseType.to_string(VerseType.Other))
|
VerseType.TranslatedNames[VerseType.Other])
|
||||||
self.insertButton.setText(
|
self.insertButton.setText(
|
||||||
translate('SongsPlugin.EditVerseForm', '&Insert'))
|
translate('SongsPlugin.EditVerseForm', '&Insert'))
|
||||||
|
@ -57,22 +57,23 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
QtCore.QObject.connect(self.verseTypeComboBox,
|
QtCore.QObject.connect(self.verseTypeComboBox,
|
||||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||||
self.onVerseTypeComboBoxChanged)
|
self.onVerseTypeComboBoxChanged)
|
||||||
self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---')
|
self.verse_regex = re.compile(r'---\[(.+):\D*(\d*)\D*.*\]---')
|
||||||
|
|
||||||
def contextMenu(self, point):
|
def contextMenu(self, point):
|
||||||
item = self.serviceManagerList.itemAt(point)
|
item = self.serviceManagerList.itemAt(point)
|
||||||
|
|
||||||
def insertVerse(self, title, num=1):
|
def insertVerse(self, verse_tag, verse_num=1):
|
||||||
if self.verseTextEdit.textCursor().columnNumber() != 0:
|
if self.verseTextEdit.textCursor().columnNumber() != 0:
|
||||||
self.verseTextEdit.insertPlainText(u'\n')
|
self.verseTextEdit.insertPlainText(u'\n')
|
||||||
self.verseTextEdit.insertPlainText(u'---[%s:%s]---\n' % (title, num))
|
verse_tag = VerseType.translated_name(verse_tag)
|
||||||
|
self.verseTextEdit.insertPlainText(u'---[%s:%s]---\n' %
|
||||||
|
(verse_tag, verse_num))
|
||||||
self.verseTextEdit.setFocus()
|
self.verseTextEdit.setFocus()
|
||||||
|
|
||||||
def onInsertButtonClicked(self):
|
def onInsertButtonClicked(self):
|
||||||
verse_type = self.verseTypeComboBox.currentIndex()
|
verse_type_index = self.verseTypeComboBox.currentIndex()
|
||||||
if VerseType.to_string(verse_type) is not None:
|
self.insertVerse(VerseType.Tags[verse_type_index],
|
||||||
self.insertVerse(VerseType.to_string(verse_type),
|
self.verseNumberBox.value())
|
||||||
self.verseNumberBox.value())
|
|
||||||
|
|
||||||
def onVerseTypeComboBoxChanged(self):
|
def onVerseTypeComboBoxChanged(self):
|
||||||
"""
|
"""
|
||||||
@ -81,10 +82,11 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
"""
|
"""
|
||||||
position = self.verseTextEdit.textCursor().position()
|
position = self.verseTextEdit.textCursor().position()
|
||||||
text = unicode(self.verseTextEdit.toPlainText())
|
text = unicode(self.verseTextEdit.toPlainText())
|
||||||
verse_type = VerseType.to_string(self.verseTypeComboBox.currentIndex())
|
verse_name = VerseType.TranslatedNames[
|
||||||
|
self.verseTypeComboBox.currentIndex()]
|
||||||
if not text:
|
if not text:
|
||||||
return
|
return
|
||||||
position = text.rfind(u'---[%s' % verse_type, 0, position)
|
position = text.rfind(u'---[%s' % verse_name, 0, position)
|
||||||
if position == -1:
|
if position == -1:
|
||||||
self.verseNumberBox.setValue(1)
|
self.verseNumberBox.setValue(1)
|
||||||
return
|
return
|
||||||
@ -95,11 +97,11 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
text = text[:position + 4]
|
text = text[:position + 4]
|
||||||
match = self.verse_regex.match(text)
|
match = self.verse_regex.match(text)
|
||||||
if match:
|
if match:
|
||||||
verse_type = match.group(1)
|
verse_tag = match.group(1)
|
||||||
verse_number = int(match.group(2))
|
verse_num = int(match.group(2))
|
||||||
verse_type_index = VerseType.from_string(verse_type)
|
verse_type_index = VerseType.from_loose_input(verse_tag)
|
||||||
if verse_type_index is not None:
|
if verse_type_index is not None:
|
||||||
self.verseNumberBox.setValue(verse_number)
|
self.verseNumberBox.setValue(verse_num)
|
||||||
|
|
||||||
def onCursorPositionChanged(self):
|
def onCursorPositionChanged(self):
|
||||||
"""
|
"""
|
||||||
@ -124,25 +126,26 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
match = self.verse_regex.match(text)
|
match = self.verse_regex.match(text)
|
||||||
if match:
|
if match:
|
||||||
verse_type = match.group(1)
|
verse_type = match.group(1)
|
||||||
|
verse_type_index = VerseType.from_loose_input(verse_type)
|
||||||
verse_number = int(match.group(2))
|
verse_number = int(match.group(2))
|
||||||
verse_type_index = VerseType.from_string(verse_type)
|
|
||||||
if verse_type_index is not None:
|
if verse_type_index is not None:
|
||||||
self.verseTypeComboBox.setCurrentIndex(verse_type_index)
|
self.verseTypeComboBox.setCurrentIndex(verse_type_index)
|
||||||
self.verseNumberBox.setValue(verse_number)
|
self.verseNumberBox.setValue(verse_number)
|
||||||
|
|
||||||
def setVerse(self, text, single=False,
|
def setVerse(self, text, single=False,
|
||||||
tag=u'%s:1' % VerseType.to_string(VerseType.Verse)):
|
tag=u'%s1' % VerseType.Tags[VerseType.Verse]):
|
||||||
self.hasSingleVerse = single
|
self.hasSingleVerse = single
|
||||||
if single:
|
if single:
|
||||||
verse_type, verse_number = tag.split(u':')
|
verse_type_index = VerseType.from_tag(tag[0])
|
||||||
verse_type_index = VerseType.from_string(verse_type)
|
verse_number = tag[1:]
|
||||||
if verse_type_index is not None:
|
if verse_type_index is not None:
|
||||||
self.verseTypeComboBox.setCurrentIndex(verse_type_index)
|
self.verseTypeComboBox.setCurrentIndex(verse_type_index)
|
||||||
self.verseNumberBox.setValue(int(verse_number))
|
self.verseNumberBox.setValue(int(verse_number))
|
||||||
self.insertButton.setVisible(False)
|
self.insertButton.setVisible(False)
|
||||||
else:
|
else:
|
||||||
if not text:
|
if not text:
|
||||||
text = u'---[%s:1]---\n' % VerseType.to_string(VerseType.Verse)
|
text = u'---[%s:1]---\n' % \
|
||||||
|
VerseType.TranslatedNames[VerseType.Verse]
|
||||||
self.verseTypeComboBox.setCurrentIndex(0)
|
self.verseTypeComboBox.setCurrentIndex(0)
|
||||||
self.verseNumberBox.setValue(1)
|
self.verseNumberBox.setValue(1)
|
||||||
self.insertButton.setVisible(True)
|
self.insertButton.setVisible(True)
|
||||||
@ -152,14 +155,14 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
|||||||
|
|
||||||
def getVerse(self):
|
def getVerse(self):
|
||||||
return self.verseTextEdit.toPlainText(), \
|
return self.verseTextEdit.toPlainText(), \
|
||||||
VerseType.to_string(self.verseTypeComboBox.currentIndex()), \
|
VerseType.Tags[self.verseTypeComboBox.currentIndex()], \
|
||||||
unicode(self.verseNumberBox.value())
|
unicode(self.verseNumberBox.value())
|
||||||
|
|
||||||
def getVerseAll(self):
|
def getVerseAll(self):
|
||||||
text = self.verseTextEdit.toPlainText()
|
text = self.verseTextEdit.toPlainText()
|
||||||
if not text.startsWith(u'---['):
|
if not text.startsWith(u'---['):
|
||||||
text = u'---[%s:1]---\n%s' % (VerseType.to_string(VerseType.Verse),
|
text = u'---[%s:1]---\n%s' % \
|
||||||
text)
|
(VerseType.TranslatedNames[VerseType.Verse], text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
|
@ -40,68 +40,147 @@ class VerseType(object):
|
|||||||
Ending = 5
|
Ending = 5
|
||||||
Other = 6
|
Other = 6
|
||||||
|
|
||||||
@staticmethod
|
Names = [
|
||||||
def to_string(verse_type):
|
u'Verse',
|
||||||
"""
|
u'Chorus',
|
||||||
Return a string for a given VerseType
|
u'Bridge',
|
||||||
|
u'Pre-Chorus',
|
||||||
|
u'Intro',
|
||||||
|
u'Ending',
|
||||||
|
u'Other']
|
||||||
|
Tags = [name[0].lower() for name in Names]
|
||||||
|
|
||||||
``verse_type``
|
TranslatedNames = [
|
||||||
The type to return a string for
|
unicode(translate('SongsPlugin.VerseType', 'Verse')),
|
||||||
"""
|
unicode(translate('SongsPlugin.VerseType', 'Chorus')),
|
||||||
if not isinstance(verse_type, int):
|
unicode(translate('SongsPlugin.VerseType', 'Bridge')),
|
||||||
verse_type = verse_type.lower()
|
unicode(translate('SongsPlugin.VerseType', 'Pre-Chorus')),
|
||||||
if verse_type == VerseType.Verse or verse_type == \
|
unicode(translate('SongsPlugin.VerseType', 'Intro')),
|
||||||
unicode(VerseType.to_string(VerseType.Verse)).lower()[0]:
|
unicode(translate('SongsPlugin.VerseType', 'Ending')),
|
||||||
return translate('SongsPlugin.VerseType', 'Verse')
|
unicode(translate('SongsPlugin.VerseType', 'Other'))]
|
||||||
elif verse_type == VerseType.Chorus or verse_type == \
|
TranslatedTags = [name[0].lower() for name in TranslatedNames]
|
||||||
unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Chorus')
|
|
||||||
elif verse_type == VerseType.Bridge or verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Bridge)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Bridge')
|
|
||||||
elif verse_type == VerseType.PreChorus or verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.PreChorus)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Pre-Chorus')
|
|
||||||
elif verse_type == VerseType.Intro or verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Intro)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Intro')
|
|
||||||
elif verse_type == VerseType.Ending or verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Ending)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Ending')
|
|
||||||
elif verse_type == VerseType.Other or verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Other)).lower()[0]:
|
|
||||||
return translate('SongsPlugin.VerseType', 'Other')
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_string(verse_type):
|
def translated_tag(verse_tag, strict=False):
|
||||||
|
"""
|
||||||
|
Return the translated UPPERCASE tag for a given tag,
|
||||||
|
used to show translated verse tags in UI
|
||||||
|
|
||||||
|
``verse_tag``
|
||||||
|
The string to return a VerseType for
|
||||||
|
|
||||||
|
``strict``
|
||||||
|
Determines if the default Other or None should be returned
|
||||||
|
"""
|
||||||
|
if strict:
|
||||||
|
not_found_value = None
|
||||||
|
else:
|
||||||
|
not_found_value = VerseType.TranslatedTags[VerseType.Other].upper()
|
||||||
|
verse_tag = verse_tag[0].lower()
|
||||||
|
for num, tag in enumerate(VerseType.Tags):
|
||||||
|
if verse_tag == tag:
|
||||||
|
return VerseType.TranslatedTags[num].upper()
|
||||||
|
return not_found_value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def translated_name(verse_tag, strict=False):
|
||||||
|
"""
|
||||||
|
Return the translated name for a given tag
|
||||||
|
|
||||||
|
``verse_tag``
|
||||||
|
The string to return a VerseType for
|
||||||
|
|
||||||
|
``strict``
|
||||||
|
Determines if the default Other or None should be returned
|
||||||
|
"""
|
||||||
|
if strict:
|
||||||
|
not_found_value = None
|
||||||
|
else:
|
||||||
|
not_found_value = VerseType.TranslatedNames[VerseType.Other]
|
||||||
|
verse_tag = verse_tag[0].lower()
|
||||||
|
for num, tag in enumerate(VerseType.Tags):
|
||||||
|
if verse_tag == tag:
|
||||||
|
return VerseType.TranslatedNames[num]
|
||||||
|
return not_found_value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_tag(verse_tag, strict=False):
|
||||||
|
"""
|
||||||
|
Return the VerseType for a given tag
|
||||||
|
|
||||||
|
``verse_tag``
|
||||||
|
The string to return a VerseType for
|
||||||
|
|
||||||
|
``strict``
|
||||||
|
Determines if the default Other or None should be returned
|
||||||
|
"""
|
||||||
|
if strict:
|
||||||
|
no_return_value = None
|
||||||
|
else:
|
||||||
|
no_return_value = VerseType.Other
|
||||||
|
verse_tag = verse_tag[0].lower()
|
||||||
|
for num, tag in enumerate(VerseType.Tags):
|
||||||
|
if verse_tag == tag:
|
||||||
|
return num
|
||||||
|
return no_return_value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_translated_tag(verse_tag):
|
||||||
|
"""
|
||||||
|
Return the VerseType for a given tag
|
||||||
|
|
||||||
|
``verse_tag``
|
||||||
|
The string to return a VerseType for
|
||||||
|
"""
|
||||||
|
verse_tag = verse_tag[0].lower()
|
||||||
|
for num, tag in enumerate(VerseType.TranslatedTags):
|
||||||
|
if verse_tag == tag:
|
||||||
|
return num
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_string(verse_name):
|
||||||
"""
|
"""
|
||||||
Return the VerseType for a given string
|
Return the VerseType for a given string
|
||||||
|
|
||||||
``verse_type``
|
``verse_name``
|
||||||
The string to return a VerseType for
|
The string to return a VerseType for
|
||||||
"""
|
"""
|
||||||
verse_type = verse_type.lower()
|
verse_name = verse_name.lower()
|
||||||
if verse_type == unicode(VerseType.to_string(VerseType.Verse)).lower():
|
for num, name in enumerate(VerseType.Names):
|
||||||
return VerseType.Verse
|
if verse_name == name.lower():
|
||||||
elif verse_type == \
|
return num
|
||||||
unicode(VerseType.to_string(VerseType.Chorus)).lower():
|
|
||||||
return VerseType.Chorus
|
|
||||||
elif verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Bridge)).lower():
|
|
||||||
return VerseType.Bridge
|
|
||||||
elif verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.PreChorus)).lower():
|
|
||||||
return VerseType.PreChorus
|
|
||||||
elif verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Intro)).lower():
|
|
||||||
return VerseType.Intro
|
|
||||||
elif verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Ending)).lower():
|
|
||||||
return VerseType.Ending
|
|
||||||
elif verse_type == \
|
|
||||||
unicode(VerseType.to_string(VerseType.Other)).lower():
|
|
||||||
return VerseType.Other
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_translated_string(verse_name):
|
||||||
|
"""
|
||||||
|
Return the VerseType for a given string
|
||||||
|
|
||||||
|
``verse_name``
|
||||||
|
The string to return a VerseType for
|
||||||
|
"""
|
||||||
|
verse_name = verse_name.lower()
|
||||||
|
for num, translation in enumerate(VerseType.TranslatedNames):
|
||||||
|
if verse_name == translation.lower():
|
||||||
|
return num
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_loose_input(verse_name):
|
||||||
|
"""
|
||||||
|
Return the VerseType for a given string, Other if not found
|
||||||
|
|
||||||
|
``verse_name``
|
||||||
|
The string to return a VerseType for
|
||||||
|
"""
|
||||||
|
verse_index = None
|
||||||
|
if len(verse_name) > 1:
|
||||||
|
verse_index = VerseType.from_translated_string(verse_name)
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_string(verse_name)
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_translated_tag(verse_name)
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_tag(verse_name)
|
||||||
|
return verse_index
|
||||||
|
|
||||||
def retrieve_windows_encoding(recommendation=None):
|
def retrieve_windows_encoding(recommendation=None):
|
||||||
"""
|
"""
|
||||||
|
@ -36,7 +36,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
|||||||
from openlp.core.lib.ui import UiStrings
|
from openlp.core.lib.ui import UiStrings
|
||||||
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
|
||||||
SongImportForm, SongExportForm
|
SongImportForm, SongExportForm
|
||||||
from openlp.plugins.songs.lib import OpenLyrics, SongXML
|
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType
|
||||||
from openlp.plugins.songs.lib.db import Author, Song
|
from openlp.plugins.songs.lib.db import Author, Song
|
||||||
from openlp.core.lib.searchedit import SearchEdit
|
from openlp.core.lib.searchedit import SearchEdit
|
||||||
|
|
||||||
@ -344,24 +344,49 @@ class SongMediaItem(MediaManagerItem):
|
|||||||
if song.lyrics.startswith(u'<?xml version='):
|
if song.lyrics.startswith(u'<?xml version='):
|
||||||
verseList = SongXML().get_verses(song.lyrics)
|
verseList = SongXML().get_verses(song.lyrics)
|
||||||
# no verse list or only 1 space (in error)
|
# no verse list or only 1 space (in error)
|
||||||
if not song.verse_order or not song.verse_order.strip():
|
verse_tags_translated = False
|
||||||
|
if VerseType.from_translated_string(unicode(
|
||||||
|
verseList[0][0][u'type'])) is not None:
|
||||||
|
verse_tags_translated = True
|
||||||
|
if not song.verse_order.strip():
|
||||||
for verse in verseList:
|
for verse in verseList:
|
||||||
verseTag = u'%s:%s' % (
|
# We cannot use from_loose_input() here, because database
|
||||||
verse[0][u'type'], verse[0][u'label'])
|
# is supposed to contain English lowercase singlechar tags.
|
||||||
|
verse_tag = verse[0][u'type']
|
||||||
|
verse_index = None
|
||||||
|
if len(verse_tag) > 1:
|
||||||
|
verse_index = \
|
||||||
|
VerseType.from_translated_string(verse_tag)
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_string(verse_tag)
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.from_tag(verse_tag)
|
||||||
|
verse_tag = VerseType.TranslatedTags[verse_index].upper()
|
||||||
|
verse_def = u'%s%s' % (verse_tag, verse[0][u'label'])
|
||||||
service_item.add_from_text(
|
service_item.add_from_text(
|
||||||
verse[1][:30], unicode(verse[1]), verseTag)
|
verse[1][:30], unicode(verse[1]), verse_def)
|
||||||
else:
|
else:
|
||||||
# Loop through the verse list and expand the song accordingly.
|
# Loop through the verse list and expand the song accordingly.
|
||||||
for order in song.verse_order.upper().split():
|
for order in song.verse_order.lower().split():
|
||||||
if len(order) == 0:
|
if len(order) == 0:
|
||||||
break
|
break
|
||||||
for verse in verseList:
|
for verse in verseList:
|
||||||
if verse[0][u'type'][0] == order[0] and \
|
if verse[0][u'type'][0].lower() == order[0] and \
|
||||||
(verse[0][u'label'] == order[1:] or not order[1:]):
|
(verse[0][u'label'].lower() == order[1:] or \
|
||||||
verseTag = u'%s:%s' % \
|
not order[1:]):
|
||||||
(verse[0][u'type'], verse[0][u'label'])
|
if verse_tags_translated:
|
||||||
|
verse_index = VerseType.from_translated_tag(
|
||||||
|
verse[0][u'type'])
|
||||||
|
else:
|
||||||
|
verse_index = VerseType.from_tag(
|
||||||
|
verse[0][u'type'])
|
||||||
|
if verse_index is None:
|
||||||
|
verse_index = VerseType.Other
|
||||||
|
verse_tag = VerseType.TranslatedTags[verse_index]
|
||||||
|
verse_def = u'%s%s' % (verse_tag,
|
||||||
|
verse[0][u'label'])
|
||||||
service_item.add_from_text(
|
service_item.add_from_text(
|
||||||
verse[1][:30], verse[1], verseTag)
|
verse[1][:30], verse[1], verse_def)
|
||||||
else:
|
else:
|
||||||
verses = song.lyrics.split(u'\n\n')
|
verses = song.lyrics.split(u'\n\n')
|
||||||
for slide in verses:
|
for slide in verses:
|
||||||
|
@ -149,23 +149,25 @@ class OpenSongImport(SongImport):
|
|||||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
unicode(translate('SongsPlugin.ImportWizardForm',
|
||||||
'Importing %s...')) % parts[-1])
|
'Importing %s...')) % parts[-1])
|
||||||
songfile = z.open(song)
|
songfile = z.open(song)
|
||||||
self.do_import_file(songfile)
|
if self.do_import_file(songfile) and self.commit and \
|
||||||
if self.commit:
|
not self.stop_import_flag:
|
||||||
self.finish()
|
self.finish()
|
||||||
if self.stop_import_flag:
|
else:
|
||||||
success = False
|
success = False
|
||||||
break
|
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(
|
self.import_wizard.incrementProgressBar(
|
||||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
unicode(translate('SongsPlugin.ImportWizardForm',
|
||||||
'Importing %s...')) % os.path.split(filename)[-1])
|
'Importing %s...')) % os.path.split(filename)[-1])
|
||||||
file = open(filename)
|
song_file = open(filename)
|
||||||
self.do_import_file(file)
|
if self.do_import_file(song_file) and self.commit and \
|
||||||
if self.commit:
|
not self.stop_import_flag:
|
||||||
self.finish()
|
self.finish()
|
||||||
|
else:
|
||||||
|
success = False
|
||||||
|
break
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def do_import_file(self, file):
|
def do_import_file(self, file):
|
||||||
@ -178,7 +180,7 @@ class OpenSongImport(SongImport):
|
|||||||
tree = objectify.parse(file)
|
tree = objectify.parse(file)
|
||||||
except (Error, LxmlError):
|
except (Error, LxmlError):
|
||||||
log.exception(u'Error parsing XML')
|
log.exception(u'Error parsing XML')
|
||||||
return
|
return False
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
fields = dir(root)
|
fields = dir(root)
|
||||||
decode = {
|
decode = {
|
||||||
@ -196,114 +198,103 @@ 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:
|
||||||
self.topics.append(unicode(root.alttheme))
|
self.topics.append(unicode(root.alttheme))
|
||||||
# data storage while importing
|
# data storage while importing
|
||||||
verses = {}
|
verses = {}
|
||||||
# keep track of a "default" verse order, in case none is specified
|
# keep track of verses appearance order
|
||||||
our_verse_order = []
|
our_verse_order = []
|
||||||
verses_seen = {}
|
# default verse
|
||||||
# in the absence of any other indication, verses are the default,
|
verse_tag = u'v'
|
||||||
# erm, versetype!
|
verse_num = u'1'
|
||||||
versetype = u'V'
|
# for the case where song has several sections with same marker
|
||||||
versenum = None
|
inst = 1
|
||||||
lyrics = unicode(root.lyrics)
|
lyrics = unicode(root.lyrics)
|
||||||
for thisline in lyrics.split(u'\n'):
|
for this_line in lyrics.split(u'\n'):
|
||||||
# remove comments
|
# remove comments
|
||||||
semicolon = thisline.find(u';')
|
semicolon = this_line.find(u';')
|
||||||
if semicolon >= 0:
|
if semicolon >= 0:
|
||||||
thisline = thisline[:semicolon]
|
this_line = this_line[:semicolon]
|
||||||
thisline = thisline.strip()
|
this_line = this_line.strip()
|
||||||
if len(thisline) == 0:
|
if not len(this_line):
|
||||||
continue
|
continue
|
||||||
# skip inthisline guitar chords and page and column breaks
|
# skip guitar chords and page and column breaks
|
||||||
if thisline[0] == u'.' or thisline.startswith(u'---') \
|
if this_line.startswith(u'.') or this_line.startswith(u'---') \
|
||||||
or thisline.startswith(u'-!!'):
|
or this_line.startswith(u'-!!'):
|
||||||
continue
|
continue
|
||||||
# verse/chorus/etc. marker
|
# verse/chorus/etc. marker
|
||||||
if thisline[0] == u'[':
|
if this_line.startswith(u'['):
|
||||||
# drop the square brackets
|
# drop the square brackets
|
||||||
right_bracket = thisline.find(u']')
|
right_bracket = this_line.find(u']')
|
||||||
content = thisline[1:right_bracket].upper()
|
content = this_line[1:right_bracket].lower()
|
||||||
# have we got any digits?
|
# have we got any digits?
|
||||||
# If so, versenumber 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+.*)', content)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
versetype = match.group(1)
|
verse_tag = match.group(1)
|
||||||
versenum = match.group(2)
|
verse_num = match.group(2)
|
||||||
else:
|
else:
|
||||||
# otherwise we assume number 1 and take the whole prefix as
|
# otherwise we assume number 1 and take the whole prefix as
|
||||||
# the versetype
|
# the verse tag
|
||||||
versetype = content
|
verse_tag = content
|
||||||
versenum = u'1'
|
verse_num = u'1'
|
||||||
|
inst = 1
|
||||||
|
if [verse_tag, verse_num, inst] in our_verse_order \
|
||||||
|
and verses.has_key(verse_tag) \
|
||||||
|
and verses[verse_tag].has_key(verse_num):
|
||||||
|
inst = len(verses[verse_tag][verse_num])+1
|
||||||
|
our_verse_order.append([verse_tag, verse_num, inst])
|
||||||
continue
|
continue
|
||||||
words = None
|
|
||||||
# number at start of line.. it's verse number
|
# number at start of line.. it's verse number
|
||||||
if thisline[0].isdigit():
|
if this_line[0].isdigit():
|
||||||
versenum = thisline[0]
|
verse_num = this_line[0]
|
||||||
words = thisline[1:].strip()
|
this_line = this_line[1:].strip()
|
||||||
if words is None:
|
our_verse_order.append([verse_tag, verse_num, inst])
|
||||||
words = thisline
|
if not verses.has_key(verse_tag):
|
||||||
if not versenum:
|
verses[verse_tag] = {}
|
||||||
versenum = u'1'
|
if not verses[verse_tag].has_key(verse_num):
|
||||||
if versenum is not None:
|
verses[verse_tag][verse_num] = {}
|
||||||
versetag = u'%s%s' % (versetype, versenum)
|
if not verses[verse_tag][verse_num].has_key(inst):
|
||||||
if not verses.has_key(versetype):
|
verses[verse_tag][verse_num][inst] = []
|
||||||
verses[versetype] = {}
|
# Tidy text and remove the ____s from extended words
|
||||||
if not verses[versetype].has_key(versenum):
|
this_line = self.tidy_text(this_line)
|
||||||
# storage for lines in this verse
|
this_line = this_line.replace(u'_', u'')
|
||||||
verses[versetype][versenum] = []
|
this_line = this_line.replace(u'|', u'\n')
|
||||||
if not verses_seen.has_key(versetag):
|
verses[verse_tag][verse_num][inst].append(this_line)
|
||||||
verses_seen[versetag] = 1
|
|
||||||
our_verse_order.append(versetag)
|
|
||||||
if words:
|
|
||||||
# Tidy text and remove the ____s from extended words
|
|
||||||
words = self.tidy_text(words)
|
|
||||||
words = words.replace('_', '')
|
|
||||||
verses[versetype][versenum].append(words)
|
|
||||||
# done parsing
|
# done parsing
|
||||||
versetypes = verses.keys()
|
# add verses in original order
|
||||||
versetypes.sort()
|
for (verse_tag, verse_num, inst) in our_verse_order:
|
||||||
versetags = {}
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
for versetype in versetypes:
|
lines = u'\n'.join(verses[verse_tag][verse_num][inst])
|
||||||
our_verse_type = versetype
|
self.add_verse(lines, verse_def)
|
||||||
if our_verse_type == u'':
|
# figure out the presentation order, if present
|
||||||
our_verse_type = u'V'
|
|
||||||
versenums = verses[versetype].keys()
|
|
||||||
versenums.sort()
|
|
||||||
for num in versenums:
|
|
||||||
versetag = u'%s%s' % (our_verse_type, num)
|
|
||||||
lines = u'\n'.join(verses[versetype][num])
|
|
||||||
self.add_verse(lines, versetag)
|
|
||||||
# Keep track of what we have for error checking later
|
|
||||||
versetags[versetag] = 1
|
|
||||||
# now figure out the presentation order
|
|
||||||
order = []
|
|
||||||
if u'presentation' in fields and root.presentation != u'':
|
if u'presentation' in fields and root.presentation != u'':
|
||||||
order = unicode(root.presentation)
|
order = unicode(root.presentation)
|
||||||
# We make all the tags in the lyrics upper 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.upper().split()
|
order = order.lower().split()
|
||||||
else:
|
for verse_def in order:
|
||||||
if len(our_verse_order) > 0:
|
match = re.match(u'(.*)(\d+.*)', verse_def)
|
||||||
order = our_verse_order
|
if match is not None:
|
||||||
else:
|
verse_tag = match.group(1)
|
||||||
log.warn(u'No verse order available for %s, skipping.',
|
verse_num = match.group(2)
|
||||||
self.title)
|
if not len(verse_tag):
|
||||||
# TODO: make sure that the default order list will be overwritten, if
|
verse_tag = u'v'
|
||||||
# the songs provides its own order list.
|
else:
|
||||||
for tag in order:
|
# Assume it's no.1 if there are no digits
|
||||||
if tag[0].isdigit():
|
verse_tag = verse_def
|
||||||
# Assume it's a verse if it has no prefix
|
verse_num = u'1'
|
||||||
tag = u'V' + tag
|
verse_def = u'%s%s' % (verse_tag, verse_num)
|
||||||
elif not re.search('\d+', tag):
|
if verses.has_key(verse_tag) \
|
||||||
# Assume it's no.1 if there's no digits
|
and verses[verse_tag].has_key(verse_num):
|
||||||
tag = tag + u'1'
|
self.verse_order_list.append(verse_def)
|
||||||
if not versetags.has_key(tag):
|
else:
|
||||||
log.info(u'Got order %s but not in versetags, dropping this'
|
log.info(u'Got order %s but not in verse tags, dropping'
|
||||||
u'item from presentation order', tag)
|
u'this item from presentation order', verse_def)
|
||||||
else:
|
return True
|
||||||
self.verse_order_list.append(tag)
|
|
||||||
|
@ -75,9 +75,11 @@ class SongImport(QtCore.QObject):
|
|||||||
self.media_files = []
|
self.media_files = []
|
||||||
self.song_book_name = u''
|
self.song_book_name = u''
|
||||||
self.song_book_pub = u''
|
self.song_book_pub = u''
|
||||||
|
self.verse_order_list_generated_useful = False
|
||||||
|
self.verse_order_list_generated = []
|
||||||
self.verse_order_list = []
|
self.verse_order_list = []
|
||||||
self.verses = []
|
self.verses = []
|
||||||
self.versecounts = {}
|
self.verse_counts = {}
|
||||||
self.copyright_string = unicode(translate(
|
self.copyright_string = unicode(translate(
|
||||||
'SongsPlugin.SongImport', 'copyright'))
|
'SongsPlugin.SongImport', 'copyright'))
|
||||||
self.copyright_symbol = unicode(translate(
|
self.copyright_symbol = unicode(translate(
|
||||||
@ -128,20 +130,20 @@ class SongImport(QtCore.QObject):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
def process_song_text(self, text):
|
def process_song_text(self, text):
|
||||||
versetexts = text.split(u'\n\n')
|
verse_texts = text.split(u'\n\n')
|
||||||
for versetext in versetexts:
|
for verse_text in verse_texts:
|
||||||
if versetext.strip() != u'':
|
if verse_text.strip() != u'':
|
||||||
self.process_verse_text(versetext.strip())
|
self.process_verse_text(verse_text.strip())
|
||||||
|
|
||||||
def process_verse_text(self, text):
|
def process_verse_text(self, text):
|
||||||
lines = text.split(u'\n')
|
lines = text.split(u'\n')
|
||||||
if text.lower().find(self.copyright_string) >= 0 \
|
if text.lower().find(self.copyright_string) >= 0 \
|
||||||
or text.lower().find(self.copyright_symbol) >= 0:
|
or text.find(self.copyright_symbol) >= 0:
|
||||||
copyright_found = False
|
copyright_found = False
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if (copyright_found or
|
if (copyright_found or
|
||||||
line.lower().find(self.copyright_string) >= 0 or
|
line.lower().find(self.copyright_string) >= 0 or
|
||||||
line.lower().find(self.copyright_symbol) >= 0):
|
line.find(self.copyright_symbol) >= 0):
|
||||||
copyright_found = True
|
copyright_found = True
|
||||||
self.add_copyright(line)
|
self.add_copyright(line)
|
||||||
else:
|
else:
|
||||||
@ -198,45 +200,46 @@ class SongImport(QtCore.QObject):
|
|||||||
return
|
return
|
||||||
self.media_files.append(filename)
|
self.media_files.append(filename)
|
||||||
|
|
||||||
def add_verse(self, versetext, versetag=u'V', lang=None):
|
def add_verse(self, verse_text, verse_def=u'v', lang=None):
|
||||||
"""
|
"""
|
||||||
Add a verse. This is the whole verse, lines split by \\n. It will also
|
Add a verse. This is the whole verse, lines split by \\n. It will also
|
||||||
attempt to detect duplicates. In this case it will just add to the verse
|
attempt to detect duplicates. In this case it will just add to the verse
|
||||||
order.
|
order.
|
||||||
|
|
||||||
``versetext``
|
``verse_text``
|
||||||
The text of the verse.
|
The text of the verse.
|
||||||
|
|
||||||
``versetag``
|
``verse_def``
|
||||||
The verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the
|
The verse tag can be v1/c1/b etc, or 'v' and 'c' (will count the
|
||||||
verses/choruses itself) or None, where it will assume verse.
|
verses/choruses itself) or None, where it will assume verse.
|
||||||
|
|
||||||
``lang``
|
``lang``
|
||||||
The language code (ISO-639) of the verse, for example *en* or *de*.
|
The language code (ISO-639) of the verse, for example *en* or *de*.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for (oldversetag, oldverse, oldlang) in self.verses:
|
for (old_verse_def, old_verse, old_lang) in self.verses:
|
||||||
if oldverse.strip() == versetext.strip():
|
if old_verse.strip() == verse_text.strip():
|
||||||
self.verse_order_list.append(oldversetag)
|
self.verse_order_list_generated.append(old_verse_def)
|
||||||
|
self.verse_order_list_generated_useful = True
|
||||||
return
|
return
|
||||||
if versetag[0] in self.versecounts:
|
if verse_def[0] in self.verse_counts:
|
||||||
self.versecounts[versetag[0]] += 1
|
self.verse_counts[verse_def[0]] += 1
|
||||||
else:
|
else:
|
||||||
self.versecounts[versetag[0]] = 1
|
self.verse_counts[verse_def[0]] = 1
|
||||||
if len(versetag) == 1:
|
if len(verse_def) == 1:
|
||||||
versetag += unicode(self.versecounts[versetag[0]])
|
verse_def += unicode(self.verse_counts[verse_def[0]])
|
||||||
elif int(versetag[1:]) > self.versecounts[versetag[0]]:
|
elif int(verse_def[1:]) > self.verse_counts[verse_def[0]]:
|
||||||
self.versecounts[versetag[0]] = int(versetag[1:])
|
self.verse_counts[verse_def[0]] = int(verse_def[1:])
|
||||||
self.verses.append([versetag, versetext.rstrip(), lang])
|
self.verses.append([verse_def, verse_text.rstrip(), lang])
|
||||||
self.verse_order_list.append(versetag)
|
self.verse_order_list_generated.append(verse_def)
|
||||||
if versetag.startswith(u'V') and u'C1' in self.verse_order_list:
|
|
||||||
self.verse_order_list.append(u'C1')
|
|
||||||
|
|
||||||
def repeat_verse(self):
|
def repeat_verse(self):
|
||||||
"""
|
"""
|
||||||
Repeat the previous verse in the verse order
|
Repeat the previous verse in the verse order
|
||||||
"""
|
"""
|
||||||
self.verse_order_list.append(self.verse_order_list[-1])
|
self.verse_order_list_generated.append(
|
||||||
|
self.verse_order_list_generated[-1])
|
||||||
|
self.verse_order_list_generated_useful = True
|
||||||
|
|
||||||
def check_complete(self):
|
def check_complete(self):
|
||||||
"""
|
"""
|
||||||
@ -273,34 +276,29 @@ class SongImport(QtCore.QObject):
|
|||||||
verses_changed_to_other = {}
|
verses_changed_to_other = {}
|
||||||
sxml = SongXML()
|
sxml = SongXML()
|
||||||
other_count = 1
|
other_count = 1
|
||||||
for (versetag, versetext, lang) in self.verses:
|
for (verse_def, verse_text, lang) in self.verses:
|
||||||
if versetag[0] == u'C':
|
if verse_def[0].lower() in VerseType.Tags:
|
||||||
versetype = VerseType.to_string(VerseType.Chorus)
|
verse_tag = verse_def[0].lower()
|
||||||
elif versetag[0] == u'V':
|
|
||||||
versetype = VerseType.to_string(VerseType.Verse)
|
|
||||||
elif versetag[0] == u'B':
|
|
||||||
versetype = VerseType.to_string(VerseType.Bridge)
|
|
||||||
elif versetag[0] == u'I':
|
|
||||||
versetype = VerseType.to_string(VerseType.Intro)
|
|
||||||
elif versetag[0] == u'P':
|
|
||||||
versetype = VerseType.to_string(VerseType.PreChorus)
|
|
||||||
elif versetag[0] == u'E':
|
|
||||||
versetype = VerseType.to_string(VerseType.Ending)
|
|
||||||
else:
|
else:
|
||||||
newversetag = u'O%d' % other_count
|
new_verse_def = u'%s%d' % (VerseType.Tags[VerseType.Other],
|
||||||
verses_changed_to_other[versetag] = newversetag
|
other_count)
|
||||||
|
verses_changed_to_other[verse_def] = new_verse_def
|
||||||
other_count += 1
|
other_count += 1
|
||||||
versetype = VerseType.to_string(VerseType.Other)
|
verse_tag = VerseType.Tags[VerseType.Other]
|
||||||
log.info(u'Versetype %s changing to %s' , versetag, newversetag)
|
log.info(u'Versetype %s changing to %s' , verse_def,
|
||||||
versetag = newversetag
|
new_verse_def)
|
||||||
sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext, lang)
|
verse_def = new_verse_def
|
||||||
song.search_lyrics += u' ' + self.remove_punctuation(versetext)
|
sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang)
|
||||||
|
song.search_lyrics += u' ' + self.remove_punctuation(verse_text)
|
||||||
song.search_lyrics = song.search_lyrics.lower()
|
song.search_lyrics = song.search_lyrics.lower()
|
||||||
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
|
||||||
for i, current_verse_tag in enumerate(self.verse_order_list):
|
if not len(self.verse_order_list) and \
|
||||||
if verses_changed_to_other.has_key(current_verse_tag):
|
self.verse_order_list_generated_useful:
|
||||||
|
self.verse_order_list = self.verse_order_list_generated
|
||||||
|
for i, current_verse_def in enumerate(self.verse_order_list):
|
||||||
|
if verses_changed_to_other.has_key(current_verse_def):
|
||||||
self.verse_order_list[i] = \
|
self.verse_order_list[i] = \
|
||||||
verses_changed_to_other[current_verse_tag]
|
verses_changed_to_other[current_verse_def]
|
||||||
song.verse_order = u' '.join(self.verse_order_list)
|
song.verse_order = u' '.join(self.verse_order_list)
|
||||||
song.copyright = self.copyright
|
song.copyright = self.copyright
|
||||||
song.comments = self.comments
|
song.comments = self.comments
|
||||||
@ -345,9 +343,10 @@ class SongImport(QtCore.QObject):
|
|||||||
+ u'========================================'
|
+ u'========================================'
|
||||||
print u'TITLE: ' + self.title
|
print u'TITLE: ' + self.title
|
||||||
print u'ALT TITLE: ' + self.alternate_title
|
print u'ALT TITLE: ' + self.alternate_title
|
||||||
for (versetag, versetext, lang) in self.verses:
|
for (verse_def, verse_text, lang) in self.verses:
|
||||||
print u'VERSE ' + versetag + u': ' + versetext
|
print u'VERSE ' + verse_def + u': ' + verse_text
|
||||||
print u'ORDER: ' + u' '.join(self.verse_order_list)
|
print u'ORDER: ' + u' '.join(self.verse_order_list)
|
||||||
|
print u'GENERATED ORDER: ' + u' '.join(self.verse_order_list_generated)
|
||||||
for author in self.authors:
|
for author in self.authors:
|
||||||
print u'AUTHOR: ' + author
|
print u'AUTHOR: ' + author
|
||||||
if self.copyright:
|
if self.copyright:
|
||||||
|
@ -464,7 +464,8 @@ class OpenLyrics(object):
|
|||||||
text += u'\n'
|
text += u'\n'
|
||||||
text += u'\n'.join([unicode(line) for line in lines.line])
|
text += u'\n'.join([unicode(line) for line in lines.line])
|
||||||
verse_name = self._get(verse, u'name')
|
verse_name = self._get(verse, u'name')
|
||||||
verse_type = unicode(VerseType.to_string(verse_name[0]))
|
verse_type_index = VerseType.from_tag(verse_name[0])
|
||||||
|
verse_type = VerseType.Names[verse_type_index]
|
||||||
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name)
|
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name)
|
||||||
verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
|
verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
|
||||||
# OpenLyrics allows e. g. "c", but we need "c1".
|
# OpenLyrics allows e. g. "c", but we need "c1".
|
||||||
|
Loading…
Reference in New Issue
Block a user