just another massive rewrite, now with regions

This commit is contained in:
Mattias Põldaru 2011-01-17 18:21:46 +02:00
parent f523181533
commit a93a37c494
2 changed files with 263 additions and 130 deletions

View File

@ -68,7 +68,7 @@ class EasiSlidesImport(SongImport):
log.info(u'Direct import %s', self.filename) log.info(u'Direct import %s', self.filename)
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm', unicode(translate('SongsPlugin.ImportWizardForm',
'Importing %s...')) % os.path.split(self.filename)[-1]) u'Importing %s...')) % os.path.split(self.filename)[-1])
file = open(self.filename) file = open(self.filename)
count = file.read().count('<Item>') count = file.read().count('<Item>')
file.seek(0) file.seek(0)
@ -85,9 +85,12 @@ class EasiSlidesImport(SongImport):
self.set_defaults() self.set_defaults()
# determines, if ENTIRELY UPPERCASE lines should be converted to lower # determines, if ENTIRELY UPPERCASE lines should be converted to lower
self.toLower = True self.toLower = False
# list of names, which have always to be Uppercase, like Jesus
# only used, when self.toLower is True
self.backToUpper = [u'Jesus', u'God']
# determines, if title should be prepended to lyrics # determines, if title should be prepended to lyrics
self.titleIsLyrics = True self.titleIsLyrics = False
try: try:
context = etree.iterparse(file) context = etree.iterparse(file)
@ -108,7 +111,7 @@ class EasiSlidesImport(SongImport):
self.parse_song(data) self.parse_song(data)
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm', unicode(translate('SongsPlugin.ImportWizardForm',
'Importing %s, song %s...')) % u'Importing %s, song %s...')) %
(os.path.split(self.filename)[-1], self.title)) (os.path.split(self.filename)[-1], self.title))
if self.commit: if self.commit:
self.finish() self.finish()
@ -116,17 +119,43 @@ class EasiSlidesImport(SongImport):
def notCapsLock(self, string): def notCapsLock(self, string):
if self.toLower and string.upper() == string: if self.toLower and string.upper() == string:
return string.lower() ret = string.lower()
if len(self.backToUpper) > 0:
for repl in self.backToUpper:
if repl == u'':
continue
ret = ret.replace(repl.lower(), repl)
return ret
else: else:
return string return string
def notCapsLockTitle(self, string): def notCapsLockTitle(self, string):
if self.toLower and string.upper() == string: if self.toLower and string.upper() == string:
ret = string.lower() ret = string.lower()
if len(self.backToUpper) > 0:
for repl in self.backToUpper:
if repl == u'':
continue
ret = ret.replace(repl.lower(), repl)
return u"%s%s" % (ret[0].upper(), ret[1:]) return u"%s%s" % (ret[0].upper(), ret[1:])
else: else:
return string return string
def listHas(self, lst, subitems):
for i in subitems:
if type(lst) == type({}) and lst.has_key(i):
lst = lst[i]
elif type(lst) == type([]) and i in lst:
lst = lst[i]
else:
return False
return True
def extractRegion(self, line):
# this was true already: thisline[0:7] == u'[region':
right_bracket = line.find(u']')
return line[7:right_bracket].strip()
def parse_song(self, data): def parse_song(self, data):
# We should also check if the title is already used, if yes, # We should also check if the title is already used, if yes,
# maybe user sould decide if we should import # maybe user sould decide if we should import
@ -137,6 +166,9 @@ class EasiSlidesImport(SongImport):
# set alternate title, if present # set alternate title, if present
if data['title2'] != None: if data['title2'] != None:
self.alternate_title = self.notCapsLockTitle(data['title2']) self.alternate_title = self.notCapsLockTitle(data['title2'])
print self.alternate_title
print data['title2']
print "HERE HERE HERE"
# folder name, we have no use for it, usually only one folder is # folder name, we have no use for it, usually only one folder is
# used in easislides and this contains no actual data, easislides # used in easislides and this contains no actual data, easislides
@ -154,6 +186,7 @@ class EasiSlidesImport(SongImport):
# data['notations'] # data['notations']
# set song authors # set song authors
# we don't have to handle the no author case, it is done afterwards
if data['writer'] != None: if data['writer'] != None:
authors = data['writer'].split(u',') authors = data['writer'].split(u',')
for author in authors: for author in authors:
@ -170,9 +203,9 @@ class EasiSlidesImport(SongImport):
copyright.append(data['licenceadmin1'].strip()) copyright.append(data['licenceadmin1'].strip())
if data['licenceadmin2']: if data['licenceadmin2']:
copyright.append(data['licenceadmin2'].strip()) copyright.append(data['licenceadmin2'].strip())
self.add_copyright(" ".join(copyright)) self.add_copyright(u' '.join(copyright))
# set topic data, I have seen no example, and should not use it, # set topic data, I have seen no example, and probably should not do it,
# I even was not able to find place to set categories in easislides # I even was not able to find place to set categories in easislides
# but then again, it would not hurt either # but then again, it would not hurt either
if data['category']: if data['category']:
@ -189,13 +222,16 @@ class EasiSlidesImport(SongImport):
# place a capo on guitar neck # place a capo on guitar neck
# set book data # set book data
if data['bookreference']: #if data['bookreference']:
for book in data['bookreference'].split(u','): # for book in data['bookreference'].split(u','):
self.books.append(book.strip()) # self.books.append(book.strip())
# THIS NEEDS ATTENTION, DON'T KNOW HOW TO MAKE THIS WORK ↑
# don't know what to do with user # don't know what to do with user
# data['userreference'], this is simple text entry, no # data['userreference'], this is simple text entry, no
# notable restrictions # notable restrictions, no idea what this is used for
# U: I have seen one use of this as "searchable field" or similar,
# still no use for us
# there is nothing to do with formatdata, this for sure is a messy # there is nothing to do with formatdata, this for sure is a messy
# thing, see an example: # thing, see an example:
@ -209,7 +245,7 @@ class EasiSlidesImport(SongImport):
# data['formatdata'] # data['formatdata']
# don't know what to do with settings data either, this is similar # don't know what to do with settings data either, this is similar
# nonsense: 10=2;5;0;0;1;0;»126;232;&gt; # nonsense as formatdata: 10=2;5;0;0;1;0;»126;232;&gt;
# data['settings'] # data['settings']
# LYRICS LYRICS LYRICS # LYRICS LYRICS LYRICS
@ -217,164 +253,260 @@ class EasiSlidesImport(SongImport):
lyrics = data['contents'] lyrics = data['contents']
# we add title to first line, if supposed to do so # we add title to first line, if supposed to do so
# we don't use self.title, because this may have changed case
if self.titleIsLyrics: if self.titleIsLyrics:
lyrics = u"%s\n%s" % (self.title, lyrics) lyrics = u"%s\n%s" % (data['title1'], lyrics)
# we count the [region 2] and [whatever] separartors, to be able #if lyrics.find(u'[') != -1:
# to tell how region data is used # # this must have at least one separator
regions = 0 # match = -1
separators = 0 # while True:
if lyrics.find(u'[') != -1: # match = lyrics.find(u'[', match+1)
match = -1 # if match == -1:
while True: # break
match = lyrics.find(u'[', match+1) # elif lyrics[match:match+7].lower() == u'[region':
if match == -1: # regions = regions+1
break # else:
if lyrics[match:match+7].lower() == u'[region': # separators = separators+1
regions = regions+1
lines = lyrics.split(u'\n')
length = len(lines)
# we go over lines first, to determine some information,
# which tells us how to parse verses later
emptylines = 0
regionlines = {}
separatorlines = 0
uppercaselines = 0
notuppercaselines = 0
for i in range(length):
lines[i] = lines[i].strip()
thisline = lines[i]
if len(thisline) == 0:
emptylines = emptylines + 1
elif thisline[0] == u'[':
if thisline[1:7] == u'region':
# this is region separator [region 2]
# Easislides song can have only one extra region zone,
# at least by now, but just in case the file happens
# to have [region 3] or more, we add a possiblity to
# count these separately, yeah, rather stupid, but
# count this as a programming exercise
region = self.extractRegion(thisline)
if regionlines.has_key(region):
regionlines[region] = regionlines[region] + 1
else: else:
separators = separators+1 regionlines[region] = 1
else:
separatorlines = separatorlines + 1
elif thisline == thisline.upper():
uppercaselines = uppercaselines + 1
else:
notuppercaselines = notuppercaselines + 1
# if the whole song is entirely UPPERCASE
allUpperCase = (notuppercaselines == 0)
# if the song has separators
separators = (separatorlines > 0)
# the number of regions in song, conting the default as one
regions = len(regionlines)+1
if regions > 2:
log.info(u'EasiSlidesImport: the file contained a song named "%s"'
u'with more than two regions, but only two regions are',
u'tested, all regions were: %s',
self.title, u','.join(regionlines.keys()))
# if the song has regions
regions = (len(regionlines) > 1)
# if the regions are inside verses (more than one )
regionsInVerses = (len(regionlines) and \
regionlines[regionlines.keys()[0]] > 1)
# 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 a "default" verse order, in case none is specified
# this list contains list as [region, versetype, versenum, instance]
our_verse_order = [] our_verse_order = []
# default region
defaultregion = u'1'
reg = defaultregion
verses[reg] = {}
# instance
inst = 1
MarkTypes = {
u'chorus': u'C',
u'verse': u'V',
u'intro': u'I',
u'ending': u'E',
u'bridge': u'B',
u'prechorus': u'P',
}
lines = lyrics.split(u'\n')
length = len(lines)
for i in range(length): for i in range(length):
thisline = lines[i].strip() # we iterate once more over lines
thisline = lines[i]
if i < length-1: if i < length-1:
nextline = lines[i+1].strip() nextline = lines[i+1].strip()
else: else:
# there is no nextline at the last line # there is no nextline at the last line
nextline = False nextline = False
if len(thisline) is 0:
if separators == 0: if len(thisline) == 0:
# empty line starts a new verse or chorus if separators:
if nextline and nextline is nextline.upper(): # separators are used, so empty line means slide break
# inside verse
if self.listHas(verses, [reg, vt, vn, inst]):
inst = inst + 1
else:
# separators are not used, so empty line starts a new verse
if not allUpperCase and nextline and \
nextline is nextline.upper():
# the next line is all uppercase, it must be chorus # the next line is all uppercase, it must be chorus
versetype = u'C' vt = u'C'
else: else:
# if the next line is not uppercase, it must be verse # if the next line is not uppercase,
versetype = u'V' # or whole song is uppercase, this must be verse
vt = u'V'
if verses.has_key(versetype): # changing the region is not possible in this case
versenum = len(verses[versetype].keys())+1
else:
versenum = u'1'
our_verse_order.append([versetype, versenum]) if verses[reg].has_key(vt):
vn = len(verses[reg][vt].keys())+1
else: else:
# separators are not used, something must be done vn = u'1'
inst = 1
if not [reg, vt, vn, inst] in our_verse_order:
our_verse_order.append([reg, vt, vn, inst])
continue continue
continue continue
# verse/chorus/etc. marker, this line contains no other data elif thisline[0:7] == u'[region':
if thisline[0] == u'[': reg = self.extractRegion(thisline)
if regions > 1: if not verses.has_key(reg):
# region markers are inside verse markers verses[reg] = {}
if thisline[0:6] == u'[region': if i == 0:
# this is a region marker inside verse # the file started with [region 2]
# by now we do nothing vt = u'V'
print 'region inside verse markers' vn = u'1'
our_verse_order.append([reg, vt, vn, inst])
continue continue
elif regions == 0:
# there is only one region marker elif thisline[0] == u'[':
if thisline[0:6] == u'[region': # this is a normal section marker
# we should restart verse count
# by now we do nothing
continue
# this is to be handled as normal marker
# drop the square brackets # drop the square brackets
right_bracket = thisline.find(u']') right_bracket = thisline.find(u']')
content = thisline[1:right_bracket].upper() marker = thisline[1:right_bracket].upper()
# have we got any digits? # have we got any digits?
# If so, versenumber is everything from the digits # If so, versenumber 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+.*)', marker)
if match is not None: if match is not None:
# versetype normally is one of the following: vt = match.group(1).strip()
# not set for verse (only number) vn = match.group(2)
# prechorus (p), chorus (c), bridge (w), if vt == u'':
# ending, none of these is numbered in sequence vt = u'V'
# empty line means split screen elif MarkTypes.has_key(vt.lower()):
versetype = match.group(1) vt = MarkTypes[vt.lower()]
versenum = match.group(2)
else: else:
# otherwise we assume number 1 and take the whole prefix as vt = u'O'
# the versetype else:
versetype = content if marker == u'':
versenum = u'1' vt = u'V'
our_verse_order.append([versetype, versenum]) elif MarkTypes.has_key(marker.lower()):
vt = MarkTypes[marker.lower()]
else:
vt = u'O'
vn = u'1'
if regionsInVerses:
region = defaultregion
inst = 1
if self.listHas(verses, [reg, vt, vn, inst]):
inst = len(verses[reg][vt][vn])+1
if not [reg, vt, vn, inst] in our_verse_order:
our_verse_order.append([reg, vt, vn, inst])
continue continue
if i == 0: if i == 0:
# this is the first line, but still no separator is found, # this is the first line, but no separator is found,
# we say it's V1 # we say it's V1
versetype = u'V' vt = u'V'
versenum = u'1' vn = u'1'
our_verse_order.append([versetype, versenum]) our_verse_order.append([reg, vt, vn, inst])
# We have versetype/number data, if it was there, now # We have versetype/number data, if it was there, now
# we parse text # we parse text
if not verses.has_key(versetype): if not verses[reg].has_key(vt):
verses[versetype] = {} verses[reg][vt] = {}
if not verses[versetype].has_key(versenum): if not verses[reg][vt].has_key(vn):
verses[versetype][versenum] = [] verses[reg][vt][vn] = {}
if not verses[reg][vt][vn].has_key(inst):
verses[reg][vt][vn][inst] = []
# Tidy text and remove the ____s from extended words # Tidy text and remove the ____s from extended words
words = self.tidy_text(thisline) words = self.tidy_text(thisline)
words = words.replace('_', '')
words = self.notCapsLock(words) words = self.notCapsLock(words)
verses[versetype][versenum].append(words) verses[reg][vt][vn][inst].append(words)
# done parsing # done parsing
versetags = []
# we use our_verse_order to ensure, we insert lyrics in the same order # we use our_verse_order to ensure, we insert lyrics in the same order
# as these appeared originally in the file # as these appeared originally in the file
for tag in our_verse_order:
versetype = tag[0]
versenum = tag[1]
if not versetype in verses: for tag in our_verse_order:
# something may have gone wrong reg = tag[0]
vt = tag[1]
vn = tag[2]
inst = tag[3]
if not self.listHas(verses, [reg, vt, vn, inst]):
continue continue
if not versenum in verses[versetype]: versetag = u'%s%s' % (vt, vn)
# this most likely is caused by an extra empty line at the end, versetags.append(versetag)
# to be debugged later lines = u'\n'.join(verses[reg][vt][vn][inst])
continue
versetag = u'%s%s' % (versetype, versenum)
lines = u'\n'.join(verses[versetype][versenum])
self.verses.append([versetag, lines]) self.verses.append([versetag, lines])
# Sequence keys:
# numbers refer to verses
# p = prechorus
# q = prechorus 2
# c = chorus
# t = chorus 2
# b = bridge
# w = bridge 2
# e = ending
SeqTypes = {
u'p': u'P1',
u'q': u'P2',
u'c': u'C1',
u't': u'C2',
u'b': u'B1',
u'w': u'B2',
u'e': u'E1'
}
# Make use of Sequence data, determining the order of verses, choruses # Make use of Sequence data, determining the order of verses, choruses
# if this is not present, we don't need it either, since the
# verses already are in the right order
if data['sequence'] != None: if data['sequence'] != None:
order = data['sequence'].split(u',') order = data['sequence'].split(u',')
for tag in order: for tag in order:
if tag[0].isdigit(): if tag[0].isdigit():
# Assume it's a verse if it has no prefix # it's a verse if it has no prefix, but has a number
tag = u'V' + tag tag = u'V' + tag
elif not re.search('\d+', tag): elif SeqTypes.has_key(tag.lower()):
# Assume it's no.1 if there's no digits tag = SeqTypes[tag.lower()]
tag = tag + u'1' else:
if not versetags.has_key(tag): # maybe we should continue here instead
tag = u'O1'
if not tag in versetags:
log.info(u'Got order %s but not in versetags, dropping this' log.info(u'Got order %s but not in versetags, dropping this'
u'item from presentation order', tag) u'item from presentation order', tag)
else: else:
self.verse_order_list.append(tag) self.verse_order_list.append(tag)
else:
for tag in our_verse_order:
if not tag[0] in verses:
#log.info(u'Got order from our_verse_order %s but not in'
# u'versetags, dropping this item from presentation order'
# u'missing was versetag %s', tag, tag[0])
continue
if not tag[1] in verses[tag[0]]:
#log.info(u'Got order from our_verse_order %s but not in'
# u'versetags, dropping this item from presentation order'
# u'missing was versenum %s for versetag %s',
# tag, tag[1], tag[0])
continue
self.verse_order_list.append(u'%s%s' % (tag[0], tag[1]))

View File

@ -265,6 +265,7 @@ class SongImport(QtCore.QObject):
log.info(u'commiting song %s to database', self.title) log.info(u'commiting song %s to database', self.title)
song = Song() song = Song()
song.title = self.title song.title = self.title
song.alternate_title = self.title
song.search_title = self.remove_punctuation(self.title).lower() \ song.search_title = self.remove_punctuation(self.title).lower() \
+ '@' + self.remove_punctuation(self.alternate_title).lower() + '@' + self.remove_punctuation(self.alternate_title).lower()
song.song_number = self.song_number song.song_number = self.song_number