fix opensong order shuffling + refactoring

This commit is contained in:
Mattias Põldaru 2011-02-16 11:36:59 +02:00
parent 893a1a6859
commit 7e18b8e3e6
2 changed files with 83 additions and 86 deletions

View File

@ -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) songfile = open(filename)
self.do_import_file(file) if self.do_import_file(songfile) 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,19 +198,22 @@ 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 versetype
# in the absence of any other indication, verses are the default, vt = u'V'
# erm, versetype! vn = 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 thisline in lyrics.split(u'\n'):
# remove comments # remove comments
@ -216,14 +221,14 @@ class OpenSongImport(SongImport):
if semicolon >= 0: if semicolon >= 0:
thisline = thisline[:semicolon] thisline = thisline[:semicolon]
thisline = thisline.strip() thisline = thisline.strip()
if len(thisline) == 0: if not len(thisline):
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 thisline.startswith(u'.') or thisline.startswith(u'---') \
or thisline.startswith(u'-!!'): or thisline.startswith(u'-!!'):
continue continue
# verse/chorus/etc. marker # verse/chorus/etc. marker
if thisline[0] == u'[': if thisline.startswith(u'['):
# drop the square brackets # drop the square brackets
right_bracket = thisline.find(u']') right_bracket = thisline.find(u']')
content = thisline[1:right_bracket].upper() content = thisline[1:right_bracket].upper()
@ -232,78 +237,63 @@ class OpenSongImport(SongImport):
# 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) vt = match.group(1)
versenum = match.group(2) vn = 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 versetype
versetype = content vt = content
versenum = u'1' vn = u'1'
inst = 1
if [vt, vn, inst] in our_verse_order and verses.has_key(vt) \
and verses[vt].has_key(vn):
inst = len(verses[vt][vn])+1
our_verse_order.append([vt, vn, 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 thisline[0].isdigit():
versenum = thisline[0] vn = thisline[0]
words = thisline[1:].strip() thisline = thisline[1:].strip()
if words is None: our_verse_order.append([vt, vn, inst])
words = thisline if not verses.has_key(vt):
if not versenum: verses[vt] = {}
versenum = u'1' if not verses[vt].has_key(vn):
if versenum is not None: verses[vt][vn] = {}
versetag = u'%s%s' % (versetype, versenum) if not verses[vt][vn].has_key(inst):
if not verses.has_key(versetype): verses[vt][vn][inst] = []
verses[versetype] = {}
if not verses[versetype].has_key(versenum):
# storage for lines in this verse
verses[versetype][versenum] = []
if not verses_seen.has_key(versetag):
verses_seen[versetag] = 1
our_verse_order.append(versetag)
if words: if words:
# Tidy text and remove the ____s from extended words # Tidy text and remove the ____s from extended words
words = self.tidy_text(words) thisline = self.tidy_text(thisline)
words = words.replace('_', '') thisline = thisline.replace(u'_', u'')
verses[versetype][versenum].append(words) thisline = thisline.replace(u'|', u'\n')
verses[vt][vn][inst].append(thisline)
# done parsing # done parsing
versetypes = verses.keys() # add verses in original order
versetypes.sort() for (vt, vn, inst) in our_verse_order:
versetags = {} vtag = u'%s%s' % (vt, vn)
for versetype in versetypes: lines = u'\n'.join(verses[vt][vn][inst])
our_verse_type = versetype self.add_verse(lines, vtag)
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 upper 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.upper().split()
else: for tag in order:
if len(our_verse_order) > 0: match = re.match(u'(.*)(\d+.*)', tag)
order = our_verse_order if match is not None:
else: vt = match.group(1)
log.warn(u'No verse order available for %s, skipping.', vn = match.group(2)
self.title) if not len(vt):
# TODO: make sure that the default order list will be overwritten, if vt = 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(): vt = tag
# Assume it's a verse if it has no prefix vn = u'1'
tag = u'V' + tag vtagString = u'%s%s' % (vt, vn)
elif not re.search('\d+', tag): if verses.has_key(vt) and verses[vt].has_key(vn):
# Assume it's no.1 if there's no digits self.verse_order_list.append(vtagString)
tag = tag + u'1' else:
if not versetags.has_key(tag): log.info(u'Got order %s but not in versetags, dropping'
log.info(u'Got order %s but not in versetags, dropping this' u'this item from presentation order', vtagString)
u'item from presentation order', tag) return True
else:
self.verse_order_list.append(tag)

View File

@ -75,6 +75,8 @@ 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.versecounts = {}
@ -217,7 +219,8 @@ class SongImport(QtCore.QObject):
""" """
for (oldversetag, oldverse, oldlang) in self.verses: for (oldversetag, oldverse, oldlang) in self.verses:
if oldverse.strip() == versetext.strip(): if oldverse.strip() == versetext.strip():
self.verse_order_list.append(oldversetag) self.verse_order_list_generated.append(oldversetag)
self.verse_order_list_generated_useful = True
return return
if versetag[0] in self.versecounts: if versetag[0] in self.versecounts:
self.versecounts[versetag[0]] += 1 self.versecounts[versetag[0]] += 1
@ -228,15 +231,15 @@ class SongImport(QtCore.QObject):
elif int(versetag[1:]) > self.versecounts[versetag[0]]: elif int(versetag[1:]) > self.versecounts[versetag[0]]:
self.versecounts[versetag[0]] = int(versetag[1:]) self.versecounts[versetag[0]] = int(versetag[1:])
self.verses.append([versetag, versetext.rstrip(), lang]) self.verses.append([versetag, versetext.rstrip(), lang])
self.verse_order_list.append(versetag) self.verse_order_list_generated.append(versetag)
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):
""" """
@ -297,6 +300,9 @@ class SongImport(QtCore.QObject):
song.search_lyrics += u' ' + self.remove_punctuation(versetext) song.search_lyrics += u' ' + self.remove_punctuation(versetext)
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')
if not len(self.verse_order_list) and \
self.verse_order_list_generated_useful:
self.verse_order_list = self.verse_order_list_generated
for i, current_verse_tag in enumerate(self.verse_order_list): for i, current_verse_tag in enumerate(self.verse_order_list):
if verses_changed_to_other.has_key(current_verse_tag): if verses_changed_to_other.has_key(current_verse_tag):
self.verse_order_list[i] = \ self.verse_order_list[i] = \
@ -348,6 +354,7 @@ class SongImport(QtCore.QObject):
for (versetag, versetext, lang) in self.verses: for (versetag, versetext, lang) in self.verses:
print u'VERSE ' + versetag + u': ' + versetext print u'VERSE ' + versetag + u': ' + versetext
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: