From 39bd27d0dfeb65e48aee39a0b65b5f5cbc793348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Wed, 12 Jan 2011 10:59:14 +0200 Subject: [PATCH 01/11] first working example --- openlp/plugins/songs/forms/songimportform.py | 28 +- .../plugins/songs/forms/songimportwizard.py | 12 +- openlp/plugins/songs/lib/easislidesimport.py | 319 ++++++++++++++++++ openlp/plugins/songs/lib/importer.py | 11 +- 4 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 openlp/plugins/songs/lib/easislidesimport.py diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 5776dd21a..63d3da322 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -109,6 +109,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): QtCore.QObject.connect(self.genericRemoveButton, QtCore.SIGNAL(u'clicked()'), self.onGenericRemoveButtonClicked) + QtCore.QObject.connect(self.easiSlidesBrowseButton, + QtCore.SIGNAL(u'clicked()'), + self.onEasiSlidesBrowseButtonClicked) QtCore.QObject.connect(self.ewBrowseButton, QtCore.SIGNAL(u'clicked()'), self.onEWBrowseButtonClicked) @@ -226,6 +229,16 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): 'presentation file to import from.')) self.genericAddButton.setFocus() return False + elif source_format == SongFormat.EasiSlides: + if self.easiSlidesFilenameEdit.text().isEmpty(): + QtGui.QMessageBox.critical(self, + translate('SongsPlugin.ImportWizardForm', + 'No Easislides Song selected'), + translate('SongsPlugin.ImportWizardForm', + 'You need to select an xml song file exported from ' + 'EasiSlides, to import from.')) + self.easiSlidesBrowseButton.setFocus() + return False elif source_format == SongFormat.EasyWorship: if self.ewFilenameEdit.text().isEmpty(): QtGui.QMessageBox.critical(self, @@ -400,6 +413,13 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): def onGenericRemoveButtonClicked(self): self.removeSelectedItems(self.genericFileListWidget) + def onEasiSlidesBrowseButtonClicked(self): + self.getFileName( + translate('SongsPlugin.ImportWizardForm', + 'Select EasiSlides songfile'), + self.easiSlidesFilenameEdit + ) + def onEWBrowseButtonClicked(self): self.getFileName( translate('SongsPlugin.ImportWizardForm', @@ -440,6 +460,7 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): self.ccliFileListWidget.clear() self.songsOfFellowshipFileListWidget.clear() self.genericFileListWidget.clear() + self.easiSlidesFilenameEdit.setText(u'') self.ewFilenameEdit.setText(u'') self.songBeamerFileListWidget.clear() #self.csvFilenameEdit.setText(u'') @@ -512,8 +533,13 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard): importer = self.plugin.importSongs(SongFormat.Generic, filenames=self.getListOfFiles(self.genericFileListWidget) ) + elif source_format == SongFormat.EasiSlides: + # Import an EasiSlides export file + importer = self.plugin.importSongs(SongFormat.EasiSlides, + filename=unicode(self.easiSlidesFilenameEdit.text()) + ) elif source_format == SongFormat.EasyWorship: - # Import an OpenLP 2.0 database + # Import an EasyWorship database importer = self.plugin.importSongs(SongFormat.EasyWorship, filename=unicode(self.ewFilenameEdit.text()) ) diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py index 903300d0c..b6ff4584a 100644 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ b/openlp/plugins/songs/forms/songimportwizard.py @@ -92,6 +92,8 @@ class Ui_SongImportWizard(object): # Generic Document/Presentation import self.addMultiFileSelectItem(u'generic', None, True) # EasyWorship + self.addSingleFileSelectItem(u'easiSlides') + # EasyWorship self.addSingleFileSelectItem(u'ew') # Words of Worship self.addMultiFileSelectItem(u'songBeamer') @@ -156,8 +158,10 @@ class Ui_SongImportWizard(object): translate('SongsPlugin.ImportWizardForm', 'Generic Document/Presentation')) self.formatComboBox.setItemText(8, - translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) + translate('SongsPlugin.ImportWizardForm', 'EasiSlides')) self.formatComboBox.setItemText(9, + translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) + self.formatComboBox.setItemText(10, translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) # self.formatComboBox.setItemText(9, # translate('SongsPlugin.ImportWizardForm', 'CSV')) @@ -211,6 +215,10 @@ class Ui_SongImportWizard(object): translate('SongsPlugin.ImportWizardForm', 'The generic document/' 'presentation importer has been disabled because OpenLP cannot ' 'find OpenOffice.org on your computer.')) + self.easiSlidesFilenameLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Filename:')) + self.easiSlidesBrowseButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Browse...')) self.ewFilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) self.ewBrowseButton.setText( @@ -241,6 +249,8 @@ class Ui_SongImportWizard(object): QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.openLP1FormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.easiSlidesFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, + QtGui.QSizePolicy.Fixed) self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) # self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py new file mode 100644 index 000000000..1dcd2336f --- /dev/null +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -0,0 +1,319 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import logging +import os +from lxml import etree +from lxml.etree import Error, LxmlError +import re + +from openlp.core.lib import translate +from openlp.plugins.songs.lib.songimport import SongImport + +log = logging.getLogger(__name__) + +class EasiSlidesImportError(Exception): + pass + +class EasiSlidesImport(SongImport): + """ + Import songs exported from EasiSlides + + The format example is here: + http://wiki.openlp.org/Development:EasiSlides_-_Song_Data_Format + """ + def __init__(self, manager, **kwargs): + """ + Initialise the class. + """ + SongImport.__init__(self, manager) + self.filename = kwargs[u'filename'] + self.song = None + self.commit = True + + def do_import(self): + """ + Import either each of the files in self.filenames - each element of + which can be either a single opensong file, or a zipfile containing + multiple opensong files. If `self.commit` is set False, the + import will not be committed to the database (useful for test scripts). + """ + success = True + + self.import_wizard.importProgressBar.setMaximum(1) + + log.info(u'Direct import %s', self.filename) + self.import_wizard.incrementProgressBar( + unicode(translate('SongsPlugin.ImportWizardForm', + 'Importing %s...')) % os.path.split(self.filename)[-1]) + file = open(self.filename) + count = file.read().count('') + file.seek(0) + self.import_wizard.importProgressBar.setMaximum(count) + self.do_import_file(file) + + return success + + def do_import_file(self, file): + """ + Process the EasiSlides file - pass in a file-like object, + not a filename + """ + self.set_defaults() + try: + context = etree.iterparse(file) + except (Error, LxmlError): + log.exception(u'Error parsing XML') + return + + song_dict = {} + for action, elem in context: + if not elem.text: + text = None + else: + text = elem.text + + song_dict[elem.tag] = text + + if elem.tag.lower() == u"item": + self.parse_song(song_dict) + self.import_wizard.incrementProgressBar( + unicode(translate('SongsPlugin.ImportWizardForm', + 'Importing %s, song %s...')) % + (os.path.split(self.filename)[-1], self.title)) + if self.commit: + self.finish() + song_dict = {} + + def notCapsLock(self, string): + if string.upper() == string: + return string.lower() + else: + return string + + def notCapsLockTitle(self, string): + if string.upper() == string: + ret = string.lower() + return u"%s%s" % (ret[0].upper(), ret[1:]) + else: + return string + + def parse_song(self, song_dict): + #for i in song_dict: + #if i != 'Contents' and song_dict[i] != None: + #print u"%s = '%s'" % (i, song_dict[i]) + toLower = True + + title = unicode(song_dict['Title1']) + if toLower: + self.title = self.notCapsLockTitle(title) + + if song_dict['Title2'] != None: + alttitle = unicode(song_dict['Title2']) + if toLower: + self.alternate_title = self.notCapsLockTitle(alttitle) + + if song_dict['SongNumber'] != None: + self.song_number = int(song_dict['SongNumber']) + else: + self.song_number = 0 + + #song_dict['Notations'] + if song_dict['Sequence'] != None: + seq = song_dict['Sequence'].split(",") + print seq + + if song_dict['Writer'] != None: + self.authors.append(song_dict['Writer']) + + lyrics = unicode(song_dict['Contents']) + + titleIsFirstLine = True + if titleIsFirstLine: + lyrics = u"%s\n%s" % (self.title, lyrics) + + + # data storage while importing + verses = {} + # keep track of a "default" verse order, in case none is specified + our_verse_order = [] + verses_seen = {} + # in the absence of any other indication, verses are the default, + # erm, versetype! + versetype = u'V' + versenum = None + seenorder = [] + + lines = lyrics.split(u'\n') + length = len(lines) + + regions = 0 + separators = 0 + if lyrics.find(u'[') != -1: + match = -1 + while True: + match = lyrics.find(u'[', match+1) + if match == -1: + break + if lyrics[match:match+7].lower() == u'[region': + regions = regions+1 + else: + separators = separators+1 + + for i in range(length): + thisline = lines[i].strip() + if i < length-1: + nextline = lines[i+1].strip() + # we don't care about nextline at the last line + else: + nextline = False + + + if len(thisline) is 0: + if separators == 0: + # empty line starts a new verse or chorus + if nextline and nextline is nextline.upper(): + # the next line is all uppercase, it is chorus + versetype = u'C' + else: + # if the next line is not uppercase, it must be verse + versetype = u'V' + + if verses.has_key(versetype): + keys = verses[versetype].keys() + #print keys + versenum = len(keys)+1 + else: + versenum = u'1' + + seenorder.append([versetype, versenum]) + continue + + # verse/chorus/etc. marker + if thisline[0] == u'[': + if regions > 1: + # region markers are inside verse markers + if thisline[0:6] == u'[region': + # this is a region marker inside verse + # by now we do nothing + print 'region inside verse markers' + continue + elif regions == 0: + # there is only one region marker + if thisline[0:6] == u'[region': + # we should restart verse count + # by now we do nothing + continue + # this is to be handled as normal marker + # drop the square brackets + right_bracket = thisline.find(u']') + content = thisline[1:right_bracket].upper() + # have we got any digits? + # If so, versenumber is everything from the digits + # to the end (even if there are some alpha chars on the end) + match = re.match(u'(.*)(\d+.*)', content) + if match is not None: + versetype = match.group(1) + versenum = match.group(2) + else: + # otherwise we assume number 1 and take the whole prefix as + # the versetype + versetype = content + versenum = u'1' + seenorder.append([versetype, versenum]) + continue + + if i == 0: + # this is the first line, but no separator is found, + # let's say it's V1 + versetype = u'V' + versenum = u'1' + seenorder.append([versetype, versenum]) + + words = None + # number at start of line.. it's verse number + if thisline[0].isdigit(): + versenum = thisline[0] + words = thisline[1:].strip() + if words is None: + words = thisline + if not versenum: + versenum = u'1' + if versenum is not None: + versetag = u'%s%s' % (versetype, versenum) + if not verses.has_key(versetype): + 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: + # Tidy text and remove the ____s from extended words + words = self.tidy_text(words) + words = words.replace('_', '') + if toLower: + words = self.notCapsLock(words) + + verses[versetype][versenum].append(words) + # done parsing + + versetypes = verses.keys() + versetags = {} + + for tag in seenorder: + vtype = tag[0] + vnum = tag[1] + + if not vtype in verses: + # something may have gone wrong + continue + if not vnum in verses[vtype]: + # this most likely is caused by an extra empty line at the end, + # to be debugged later + continue + versetag = u'%s%s' % (vtype, vnum) + lines = u'\n'.join(verses[vtype][vnum]) + self.verses.append([versetag, lines]) + + if song_dict['Sequence'] != None: + order = song_dict['Sequence'].split(u',') + for tag in order: + if tag[0].isdigit(): + # Assume it's a verse if it has no prefix + tag = u'V' + tag + elif not re.search('\d+', tag): + # Assume it's no.1 if there's no digits + tag = tag + u'1' + if not versetags.has_key(tag): + log.info(u'Got order %s but not in versetags, dropping this' + u'item from presentation order', tag) + else: + self.verse_order_list.append(tag) + else: + for tag in seenorder: + self.verse_order_list.append(u'%s%s' % (tag[0], tag[1])) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 128d80138..038eaa2a2 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -25,6 +25,7 @@ ############################################################################### from opensongimport import OpenSongImport +from easislidesimport import EasiSlidesImport from olpimport import OpenLPSongImport from openlyricsimport import OpenLyricsImport from wowimport import WowImport @@ -65,8 +66,9 @@ class SongFormat(object): SongsOfFellowship = 6 Generic = 7 #CSV = 8 - EasyWorship = 8 - SongBeamer = 9 + EasiSlides = 8 + EasyWorship = 9 + SongBeamer = 10 @staticmethod def get_class(format): @@ -92,6 +94,8 @@ class SongFormat(object): return OooImport elif format == SongFormat.CCLI: return CCLIFileImport + elif format == SongFormat.EasiSlides: + return EasiSlidesImport elif format == SongFormat.EasyWorship: return EasyWorshipSongImport elif format == SongFormat.SongBeamer: @@ -112,6 +116,7 @@ class SongFormat(object): SongFormat.CCLI, SongFormat.SongsOfFellowship, SongFormat.Generic, + SongFormat.EasiSlides, SongFormat.EasyWorship, SongFormat.SongBeamer ] @@ -128,4 +133,4 @@ SongFormat.set_availability(SongFormat.OpenLP1, has_openlp1) SongFormat.set_availability(SongFormat.SongsOfFellowship, has_sof) SongFormat.set_availability(SongFormat.Generic, has_ooo) -__all__ = [u'SongFormat'] \ No newline at end of file +__all__ = [u'SongFormat'] From f1a437891ae3d176371409be64351802caac10f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Wed, 12 Jan 2011 17:10:20 +0200 Subject: [PATCH 02/11] a lot of changes for better code --- openlp/plugins/songs/lib/easislidesimport.py | 267 ++++++++++++------- 1 file changed, 164 insertions(+), 103 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 1dcd2336f..435e2177f 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -83,93 +83,145 @@ class EasiSlidesImport(SongImport): not a filename """ self.set_defaults() + + # determines, if ENTIRELY UPPERCASE lines should be converted to lower + self.toLower = True + # determines, if title should be prepended to lyrics + self.titleIsLyrics = True + try: context = etree.iterparse(file) except (Error, LxmlError): log.exception(u'Error parsing XML') return - song_dict = {} + data = {} for action, elem in context: if not elem.text: text = None else: - text = elem.text + text = unicode(elem.text) - song_dict[elem.tag] = text + data[elem.tag.lower()] = text if elem.tag.lower() == u"item": - self.parse_song(song_dict) + self.parse_song(data) self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', 'Importing %s, song %s...')) % (os.path.split(self.filename)[-1], self.title)) if self.commit: self.finish() - song_dict = {} + data = {} def notCapsLock(self, string): - if string.upper() == string: + if self.toLower and string.upper() == string: return string.lower() else: return string def notCapsLockTitle(self, string): - if string.upper() == string: + if self.toLower and string.upper() == string: ret = string.lower() return u"%s%s" % (ret[0].upper(), ret[1:]) else: return string - def parse_song(self, song_dict): - #for i in song_dict: - #if i != 'Contents' and song_dict[i] != None: - #print u"%s = '%s'" % (i, song_dict[i]) - toLower = True + def parse_song(self, data): + # We should also check if the title is already used, if yes, + # maybe user sould decide if we should import - title = unicode(song_dict['Title1']) - if toLower: - self.title = self.notCapsLockTitle(title) + # set title + self.title = self.notCapsLockTitle(data['title1']) - if song_dict['Title2'] != None: - alttitle = unicode(song_dict['Title2']) - if toLower: - self.alternate_title = self.notCapsLockTitle(alttitle) + # set alternate title, if present + if data['title2'] != None: + self.alternate_title = self.notCapsLockTitle(data['title2']) - if song_dict['SongNumber'] != None: - self.song_number = int(song_dict['SongNumber']) + # folder name, we have no use for it, usually only one folder is + # used in easislides and this contains no actual data, easislides + # default database is named English, but usersmay not follow their + # example + # data['folder'] + + # set song number, if present, 0 otherwise + if data['songnumber'] != None: + self.song_number = int(data['songnumber']) else: self.song_number = 0 - - #song_dict['Notations'] - if song_dict['Sequence'] != None: - seq = song_dict['Sequence'].split(",") - print seq - if song_dict['Writer'] != None: - self.authors.append(song_dict['Writer']) - - lyrics = unicode(song_dict['Contents']) + # Don't know how to use Notations + # data['notations'] - titleIsFirstLine = True - if titleIsFirstLine: + # set song authors + if data['writer'] != None: + authors = data['writer'].split(u',') + for author in authors: + self.authors.append(author.strip()) + + # set copyright data + # licenceadmins may contain Public Domain or CCLI, as shown in examples + # let's just concatenate these fields, it should be determined, if song + # No is actually CCLI nr, if it is set + copyright = [] + if data['copyright']: + copyright.append(data['copyright'].strip()) + if data['licenceadmin1']: + copyright.append(data['licenceadmin1'].strip()) + if data['licenceadmin2']: + copyright.append(data['licenceadmin2'].strip()) + self.add_copyright(" ".join(copyright)) + + # set topic data, I have seen no example, and should not use it, + # I even was not able to find place to set categories in easislides + # but then again, it would not hurt either + if data['category']: + for topic in data['category'].split(u','): + self.topics.append(topic.strip()) + + # don't know what to do with timing data + # may be either 3/4 or 4/4 + # data['timing'] + + # don't know what to do with music key + # data['musickey'], may be Db, C, G, F#, F#m + # data['capo'], is a number from 0 to 11, determing where to + # place a capo on guitar neck + + # set book data + if data['bookreference']: + for book in data['bookreference'].split(u','): + self.books.append(book.strip()) + + # don't know what to do with user + # data['userreference'], this is simple text entry, no + # notable restrictions + + # there is nothing to do with formatdata, this for sure is a messy + # thing, see an example: + # 21=1>23=0>22=2>25=2>26=-16777216> + # 27=-16777216>28=11>29=-1>30=-256>31=2>32=2> + # 41=16>42=16>43=Microsoft Sans Serif> + # 44=Microsoft Sans Serif>45=0>46=45>47=20>48=40> + # 50=0>51=>52=50>53=-1>54=0>55=1>61=>62=2> + # 63=1>64=2>65=2>66=0>71=0>72=Fade>73=Fade> + # + # data['formatdata'] + + # don't know what to do with settings data either, this is similar + # nonsense: 10=2;5;0;0;1;0;»126;232;> + # data['settings'] + + # LYRICS LYRICS LYRICS + # the big and messy part to handle lyrics + lyrics = data['contents'] + + # we add title to first line, if supposed to do so + if self.titleIsLyrics: lyrics = u"%s\n%s" % (self.title, lyrics) - - - # data storage while importing - verses = {} - # keep track of a "default" verse order, in case none is specified - our_verse_order = [] - verses_seen = {} - # in the absence of any other indication, verses are the default, - # erm, versetype! - versetype = u'V' - versenum = None - seenorder = [] - - lines = lyrics.split(u'\n') - length = len(lines) + # we count the [region 2] and [whatever] separartors, to be able + # to tell how region data is used regions = 0 separators = 0 if lyrics.find(u'[') != -1: @@ -182,37 +234,44 @@ class EasiSlidesImport(SongImport): regions = regions+1 else: separators = separators+1 - + + # data storage while importing + verses = {} + # keep track of a "default" verse order, in case none is specified + our_verse_order = [] + + lines = lyrics.split(u'\n') + length = len(lines) for i in range(length): thisline = lines[i].strip() if i < length-1: nextline = lines[i+1].strip() - # we don't care about nextline at the last line else: + # there is no nextline at the last line nextline = False - if len(thisline) is 0: if separators == 0: # empty line starts a new verse or chorus if nextline and nextline is nextline.upper(): - # the next line is all uppercase, it is chorus + # the next line is all uppercase, it must be chorus versetype = u'C' else: # if the next line is not uppercase, it must be verse versetype = u'V' if verses.has_key(versetype): - keys = verses[versetype].keys() - #print keys - versenum = len(keys)+1 + versenum = len(verses[versetype].keys())+1 else: versenum = u'1' - seenorder.append([versetype, versenum]) + our_verse_order.append([versetype, versenum]) + else: + # separators are not used, something must be done + continue continue - - # verse/chorus/etc. marker + + # verse/chorus/etc. marker, this line contains no other data if thisline[0] == u'[': if regions > 1: # region markers are inside verse markers @@ -236,6 +295,11 @@ class EasiSlidesImport(SongImport): # to the end (even if there are some alpha chars on the end) match = re.match(u'(.*)(\d+.*)', content) if match is not None: + # versetype normally is one of the following: + # not set for verse (only number) + # prechorus (p), chorus (c), bridge (w), + # ending, none of these is numbered in sequence + # empty line means split screen versetype = match.group(1) versenum = match.group(2) else: @@ -243,65 +307,51 @@ class EasiSlidesImport(SongImport): # the versetype versetype = content versenum = u'1' - seenorder.append([versetype, versenum]) + our_verse_order.append([versetype, versenum]) continue - + if i == 0: - # this is the first line, but no separator is found, - # let's say it's V1 + # this is the first line, but still no separator is found, + # we say it's V1 versetype = u'V' versenum = u'1' - seenorder.append([versetype, versenum]) + our_verse_order.append([versetype, versenum]) - words = None - # number at start of line.. it's verse number - if thisline[0].isdigit(): - versenum = thisline[0] - words = thisline[1:].strip() - if words is None: - words = thisline - if not versenum: - versenum = u'1' - if versenum is not None: - versetag = u'%s%s' % (versetype, versenum) - if not verses.has_key(versetype): - 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: - # Tidy text and remove the ____s from extended words - words = self.tidy_text(words) - words = words.replace('_', '') - if toLower: - words = self.notCapsLock(words) - - verses[versetype][versenum].append(words) + # We have versetype/number data, if it was there, now + # we parse text + if not verses.has_key(versetype): + verses[versetype] = {} + if not verses[versetype].has_key(versenum): + verses[versetype][versenum] = [] + + # Tidy text and remove the ____s from extended words + words = self.tidy_text(thisline) + words = words.replace('_', '') + words = self.notCapsLock(words) + + verses[versetype][versenum].append(words) # done parsing - - versetypes = verses.keys() - versetags = {} - - for tag in seenorder: - vtype = tag[0] - vnum = tag[1] + + # we use our_verse_order to ensure, we insert lyrics in the same order + # as these appeared originally in the file + for tag in our_verse_order: + versetype = tag[0] + versenum = tag[1] - if not vtype in verses: + if not versetype in verses: # something may have gone wrong continue - if not vnum in verses[vtype]: + if not versenum in verses[versetype]: # this most likely is caused by an extra empty line at the end, # to be debugged later continue - versetag = u'%s%s' % (vtype, vnum) - lines = u'\n'.join(verses[vtype][vnum]) + versetag = u'%s%s' % (versetype, versenum) + lines = u'\n'.join(verses[versetype][versenum]) self.verses.append([versetag, lines]) - if song_dict['Sequence'] != None: - order = song_dict['Sequence'].split(u',') + # Make use of Sequence data, determining the order of verses, choruses + if data['sequence'] != None: + order = data['sequence'].split(u',') for tag in order: if tag[0].isdigit(): # Assume it's a verse if it has no prefix @@ -315,5 +365,16 @@ class EasiSlidesImport(SongImport): else: self.verse_order_list.append(tag) else: - for tag in seenorder: + 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])) From ccb2e8693c6d7b379a284b059fa0c58241f52b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Thu, 13 Jan 2011 12:54:36 +0200 Subject: [PATCH 03/11] more changes --- openlp/plugins/songs/lib/easislidesimport.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 435e2177f..736d85304 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -367,14 +367,14 @@ class EasiSlidesImport(SongImport): 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]) + #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]) + #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])) From a93a37c494923e9d849f8a36cef8926a7b063ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 17 Jan 2011 18:21:46 +0200 Subject: [PATCH 04/11] just another massive rewrite, now with regions --- openlp/plugins/songs/lib/easislidesimport.py | 390 +++++++++++++------ openlp/plugins/songs/lib/songimport.py | 3 +- 2 files changed, 263 insertions(+), 130 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 736d85304..608777fe2 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -62,19 +62,19 @@ class EasiSlidesImport(SongImport): import will not be committed to the database (useful for test scripts). """ success = True - + self.import_wizard.importProgressBar.setMaximum(1) - + log.info(u'Direct import %s', self.filename) self.import_wizard.incrementProgressBar( 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) count = file.read().count('') file.seek(0) self.import_wizard.importProgressBar.setMaximum(count) self.do_import_file(file) - + return success def do_import_file(self, file): @@ -85,16 +85,19 @@ class EasiSlidesImport(SongImport): self.set_defaults() # 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 - self.titleIsLyrics = True - + self.titleIsLyrics = False + try: context = etree.iterparse(file) except (Error, LxmlError): log.exception(u'Error parsing XML') return - + data = {} for action, elem in context: if not elem.text: @@ -108,25 +111,51 @@ class EasiSlidesImport(SongImport): self.parse_song(data) self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', - 'Importing %s, song %s...')) % + u'Importing %s, song %s...')) % (os.path.split(self.filename)[-1], self.title)) if self.commit: self.finish() data = {} - + def notCapsLock(self, 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: return string - + def notCapsLockTitle(self, string): if self.toLower and string.upper() == string: 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:]) else: 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): # We should also check if the title is already used, if yes, # maybe user sould decide if we should import @@ -137,6 +166,9 @@ class EasiSlidesImport(SongImport): # set alternate title, if present if data['title2'] != None: 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 # used in easislides and this contains no actual data, easislides @@ -154,6 +186,7 @@ class EasiSlidesImport(SongImport): # data['notations'] # set song authors + # we don't have to handle the no author case, it is done afterwards if data['writer'] != None: authors = data['writer'].split(u',') for author in authors: @@ -170,9 +203,9 @@ class EasiSlidesImport(SongImport): copyright.append(data['licenceadmin1'].strip()) if data['licenceadmin2']: 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 # but then again, it would not hurt either if data['category']: @@ -189,13 +222,16 @@ class EasiSlidesImport(SongImport): # place a capo on guitar neck # set book data - if data['bookreference']: - for book in data['bookreference'].split(u','): - self.books.append(book.strip()) - + #if data['bookreference']: + # for book in data['bookreference'].split(u','): + # self.books.append(book.strip()) + # THIS NEEDS ATTENTION, DON'T KNOW HOW TO MAKE THIS WORK ↑ + # don't know what to do with user # 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 # thing, see an example: @@ -209,172 +245,268 @@ class EasiSlidesImport(SongImport): # data['formatdata'] # don't know what to do with settings data either, this is similar - # nonsense: 10=2;5;0;0;1;0;»126;232;> + # nonsense as formatdata: 10=2;5;0;0;1;0;»126;232;> # data['settings'] - + # LYRICS LYRICS LYRICS # the big and messy part to handle lyrics lyrics = data['contents'] # 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: - lyrics = u"%s\n%s" % (self.title, lyrics) - - # we count the [region 2] and [whatever] separartors, to be able - # to tell how region data is used - regions = 0 - separators = 0 - if lyrics.find(u'[') != -1: - match = -1 - while True: - match = lyrics.find(u'[', match+1) - if match == -1: - break - if lyrics[match:match+7].lower() == u'[region': - regions = regions+1 - else: - separators = separators+1 + lyrics = u"%s\n%s" % (data['title1'], lyrics) + #if lyrics.find(u'[') != -1: + # # this must have at least one separator + # match = -1 + # while True: + # match = lyrics.find(u'[', match+1) + # if match == -1: + # break + # elif lyrics[match:match+7].lower() == u'[region': + # regions = regions+1 + # else: + # separators = separators+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: + 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 verses = {} # keep track of a "default" verse order, in case none is specified + # this list contains list as [region, versetype, versenum, instance] 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): - thisline = lines[i].strip() + # we iterate once more over lines + thisline = lines[i] if i < length-1: nextline = lines[i+1].strip() else: # there is no nextline at the last line nextline = False - - if len(thisline) is 0: - if separators == 0: - # empty line starts a new verse or chorus - if nextline and nextline is nextline.upper(): - # the next line is all uppercase, it must be chorus - versetype = u'C' - else: - # if the next line is not uppercase, it must be verse - versetype = u'V' - - if verses.has_key(versetype): - versenum = len(verses[versetype].keys())+1 - else: - versenum = u'1' - - our_verse_order.append([versetype, versenum]) + + + if len(thisline) == 0: + if separators: + # 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, something must be done + # 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 + vt = u'C' + else: + # if the next line is not uppercase, + # or whole song is uppercase, this must be verse + vt = u'V' + + # changing the region is not possible in this case + + if verses[reg].has_key(vt): + vn = len(verses[reg][vt].keys())+1 + else: + 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 - # verse/chorus/etc. marker, this line contains no other data - if thisline[0] == u'[': - if regions > 1: - # region markers are inside verse markers - if thisline[0:6] == u'[region': - # this is a region marker inside verse - # by now we do nothing - print 'region inside verse markers' - continue - elif regions == 0: - # there is only one region marker - if thisline[0:6] == u'[region': - # we should restart verse count - # by now we do nothing - continue - # this is to be handled as normal marker + elif thisline[0:7] == u'[region': + reg = self.extractRegion(thisline) + if not verses.has_key(reg): + verses[reg] = {} + if i == 0: + # the file started with [region 2] + vt = u'V' + vn = u'1' + our_verse_order.append([reg, vt, vn, inst]) + continue + + elif thisline[0] == u'[': + # this is a normal section marker # drop the square brackets right_bracket = thisline.find(u']') - content = thisline[1:right_bracket].upper() + marker = thisline[1:right_bracket].upper() # have we got any digits? # If so, versenumber is everything from the digits # 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: - # versetype normally is one of the following: - # not set for verse (only number) - # prechorus (p), chorus (c), bridge (w), - # ending, none of these is numbered in sequence - # empty line means split screen - versetype = match.group(1) - versenum = match.group(2) + vt = match.group(1).strip() + vn = match.group(2) + if vt == u'': + vt = u'V' + elif MarkTypes.has_key(vt.lower()): + vt = MarkTypes[vt.lower()] + else: + vt = u'O' else: - # otherwise we assume number 1 and take the whole prefix as - # the versetype - versetype = content - versenum = u'1' - our_verse_order.append([versetype, versenum]) + if marker == u'': + vt = u'V' + 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 - + 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 - versetype = u'V' - versenum = u'1' - our_verse_order.append([versetype, versenum]) + vt = u'V' + vn = u'1' + our_verse_order.append([reg, vt, vn, inst]) # We have versetype/number data, if it was there, now # we parse text - if not verses.has_key(versetype): - verses[versetype] = {} - if not verses[versetype].has_key(versenum): - verses[versetype][versenum] = [] + if not verses[reg].has_key(vt): + verses[reg][vt] = {} + if not verses[reg][vt].has_key(vn): + 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 words = self.tidy_text(thisline) - words = words.replace('_', '') words = self.notCapsLock(words) - verses[versetype][versenum].append(words) + verses[reg][vt][vn][inst].append(words) # done parsing + + versetags = [] # we use our_verse_order to ensure, we insert lyrics in the same order # as these appeared originally in the file + for tag in our_verse_order: - versetype = tag[0] - versenum = tag[1] + reg = tag[0] + vt = tag[1] + vn = tag[2] + inst = tag[3] - if not versetype in verses: - # something may have gone wrong + if not self.listHas(verses, [reg, vt, vn, inst]): continue - if not versenum in verses[versetype]: - # this most likely is caused by an extra empty line at the end, - # to be debugged later - continue - versetag = u'%s%s' % (versetype, versenum) - lines = u'\n'.join(verses[versetype][versenum]) + versetag = u'%s%s' % (vt, vn) + versetags.append(versetag) + lines = u'\n'.join(verses[reg][vt][vn][inst]) 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 + # if this is not present, we don't need it either, since the + # verses already are in the right order if data['sequence'] != None: order = data['sequence'].split(u',') for tag in order: 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 - elif not re.search('\d+', tag): - # Assume it's no.1 if there's no digits - tag = tag + u'1' - if not versetags.has_key(tag): + elif SeqTypes.has_key(tag.lower()): + tag = SeqTypes[tag.lower()] + else: + # 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' u'item from presentation order', tag) else: 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])) diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 05ed320a9..4bae9f2e5 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -265,6 +265,7 @@ class SongImport(QtCore.QObject): log.info(u'commiting song %s to database', self.title) song = Song() song.title = self.title + song.alternate_title = self.title song.search_title = self.remove_punctuation(self.title).lower() \ + '@' + self.remove_punctuation(self.alternate_title).lower() song.song_number = self.song_number @@ -364,4 +365,4 @@ class SongImport(QtCore.QObject): if self.theme_name: print u'THEME: ' + self.theme_name if self.ccli_number: - print u'CCLI: ' + self.ccli_number \ No newline at end of file + print u'CCLI: ' + self.ccli_number From 83ca6f4230d8dbd3a4a194491353de5ef500c93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 17 Jan 2011 19:35:19 +0200 Subject: [PATCH 05/11] more modifications, now this works again --- openlp/plugins/songs/forms/songimportform.py | 16 ++++++++++--- .../plugins/songs/forms/songimportwizard.py | 2 +- openlp/plugins/songs/lib/easislidesimport.py | 23 ++++++++----------- openlp/plugins/songs/lib/opensongimport.py | 2 +- openlp/plugins/songs/lib/songimport.py | 2 +- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 445170ce5..ae4b289b1 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -180,6 +180,8 @@ class SongImportForm(OpenLPWizard): self.addMultiFileSelectItem(u'songsOfFellowship', None, True) # Generic Document/Presentation import self.addMultiFileSelectItem(u'generic', None, True) + # EasySlides + self.addSingleFileSelectItem(u'easiSlides') # EasyWorship self.addSingleFileSelectItem(u'ew') # Words of Worship @@ -229,10 +231,12 @@ class SongImportForm(OpenLPWizard): translate('SongsPlugin.ImportWizardForm', 'Generic Document/Presentation')) self.formatComboBox.setItemText(8, - translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) + translate('SongsPlugin.ImportWizardForm', 'EasiSlides')) self.formatComboBox.setItemText(9, + translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) + self.formatComboBox.setItemText(10, translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) -# self.formatComboBox.setItemText(9, +# self.formatComboBox.setItemText(11, # translate('SongsPlugin.ImportWizardForm', 'CSV')) self.openLP2FilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) @@ -284,6 +288,10 @@ class SongImportForm(OpenLPWizard): translate('SongsPlugin.ImportWizardForm', 'The generic document/' 'presentation importer has been disabled because OpenLP cannot ' 'find OpenOffice.org on your computer.')) + self.easiSlidesFilenameLabel.setText( + translate('SongsPlugin.ImportWizardForm', 'Filename:')) + self.easiSlidesBrowseButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Browse...')) self.ewFilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) self.ewBrowseButton.setText( @@ -314,6 +322,8 @@ class SongImportForm(OpenLPWizard): QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.openLP1FormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + self.easiSlidesFormLabelSpacer.changeSize(width, 0, + QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) # self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, @@ -411,7 +421,7 @@ class SongImportForm(OpenLPWizard): if self.easiSlidesFilenameEdit.text().isEmpty(): QtGui.QMessageBox.critical(self, translate('SongsPlugin.ImportWizardForm', - 'No Easislides Song selected'), + 'No Easislides Songs file selected'), translate('SongsPlugin.ImportWizardForm', 'You need to select an xml song file exported from ' 'EasiSlides, to import from.')) diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py index b6ff4584a..56346ead9 100644 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ b/openlp/plugins/songs/forms/songimportwizard.py @@ -91,7 +91,7 @@ class Ui_SongImportWizard(object): self.addMultiFileSelectItem(u'songsOfFellowship', None, True) # Generic Document/Presentation import self.addMultiFileSelectItem(u'generic', None, True) - # EasyWorship + # EasySlides self.addSingleFileSelectItem(u'easiSlides') # EasyWorship self.addSingleFileSelectItem(u'ew') diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 608777fe2..6e610518f 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -63,7 +63,7 @@ class EasiSlidesImport(SongImport): """ success = True - self.import_wizard.importProgressBar.setMaximum(1) + self.import_wizard.progressBar.setMaximum(1) log.info(u'Direct import %s', self.filename) self.import_wizard.incrementProgressBar( @@ -72,7 +72,7 @@ class EasiSlidesImport(SongImport): file = open(self.filename) count = file.read().count('') file.seek(0) - self.import_wizard.importProgressBar.setMaximum(count) + self.import_wizard.progressBar.setMaximum(count) self.do_import_file(file) return success @@ -158,7 +158,7 @@ class EasiSlidesImport(SongImport): def parse_song(self, data): # We should also check if the title is already used, if yes, - # maybe user sould decide if we should import + # maybe user sould be asked if we should import or not # set title self.title = self.notCapsLockTitle(data['title1']) @@ -166,9 +166,6 @@ class EasiSlidesImport(SongImport): # set alternate title, if present if data['title2'] != None: 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 # used in easislides and this contains no actual data, easislides @@ -176,11 +173,11 @@ class EasiSlidesImport(SongImport): # example # data['folder'] - # set song number, if present, 0 otherwise - if data['songnumber'] != None: + # set song number, if present, empty otherwise + # EasiSlides tends to set all not changed song numbers to 0, + # so this hardly ever carries any information + if data['songnumber'] != None and data['songnumber'] != u'0': self.song_number = int(data['songnumber']) - else: - self.song_number = 0 # Don't know how to use Notations # data['notations'] @@ -222,10 +219,8 @@ class EasiSlidesImport(SongImport): # place a capo on guitar neck # set book data - #if data['bookreference']: - # for book in data['bookreference'].split(u','): - # self.books.append(book.strip()) - # THIS NEEDS ATTENTION, DON'T KNOW HOW TO MAKE THIS WORK ↑ + if data['bookreference']: + self.song_book_name = data['bookreference'].strip() # don't know what to do with user # data['userreference'], this is simple text entry, no diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index eb16f4ba4..6a60fcc6c 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -129,7 +129,7 @@ class OpenSongImport(SongImport): else: numfiles += 1 log.debug(u'Total number of files: %d', numfiles) - self.import_wizard.progressBar.setMaximum(numfiles) + self.import_wizard.importProgressBar.setMaximum(numfiles) for filename in self.filenames: if self.stop_import_flag: success = False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 5af871c00..4720ec1c5 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -265,7 +265,7 @@ class SongImport(QtCore.QObject): log.info(u'commiting song %s to database', self.title) song = Song() song.title = self.title - song.alternate_title = self.title + song.alternate_title = self.alternate_title song.search_title = self.remove_punctuation(self.title).lower() \ + '@' + self.remove_punctuation(self.alternate_title).lower() song.song_number = self.song_number From 9e02f15995f8d37c755b454540626de0572e6741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 17 Jan 2011 21:09:35 +0200 Subject: [PATCH 06/11] more fixes, thanks to o123hallo and Meths --- openlp/plugins/songs/forms/songimportform.py | 2 +- .../plugins/songs/forms/songimportwizard.py | 372 ------------------ openlp/plugins/songs/lib/easislidesimport.py | 148 ++----- 3 files changed, 31 insertions(+), 491 deletions(-) delete mode 100644 openlp/plugins/songs/forms/songimportwizard.py diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index ae4b289b1..433c9abfc 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -419,7 +419,7 @@ class SongImportForm(OpenLPWizard): return False elif source_format == SongFormat.EasiSlides: if self.easiSlidesFilenameEdit.text().isEmpty(): - QtGui.QMessageBox.critical(self, + criticalErrorMessageBox( translate('SongsPlugin.ImportWizardForm', 'No Easislides Songs file selected'), translate('SongsPlugin.ImportWizardForm', diff --git a/openlp/plugins/songs/forms/songimportwizard.py b/openlp/plugins/songs/forms/songimportwizard.py deleted file mode 100644 index 56346ead9..000000000 --- a/openlp/plugins/songs/forms/songimportwizard.py +++ /dev/null @@ -1,372 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2011 Raoul Snyman # -# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import build_icon, translate - -class Ui_SongImportWizard(object): - def setupUi(self, songImportWizard): - self.openIcon = build_icon(u':/general/general_open.png') - self.deleteIcon = build_icon(u':/general/general_delete.png') - songImportWizard.setObjectName(u'songImportWizard') - songImportWizard.setModal(True) - songImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle) - songImportWizard.setOptions( - QtGui.QWizard.IndependentPages | - QtGui.QWizard.NoBackButtonOnStartPage | - QtGui.QWizard.NoBackButtonOnLastPage) - # Welcome Page - self.welcomePage = QtGui.QWizardPage() - self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap, - QtGui.QPixmap(u':/wizards/wizard_importsong.bmp')) - self.welcomePage.setObjectName(u'WelcomePage') - self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage) - self.welcomeLayout.setObjectName(u'WelcomeLayout') - self.titleLabel = QtGui.QLabel(self.welcomePage) - self.titleLabel.setObjectName(u'TitleLabel') - self.welcomeLayout.addWidget(self.titleLabel) - self.welcomeLayout.addSpacing(40) - self.informationLabel = QtGui.QLabel(self.welcomePage) - self.informationLabel.setWordWrap(True) - self.informationLabel.setObjectName(u'InformationLabel') - self.welcomeLayout.addWidget(self.informationLabel) - self.welcomeLayout.addStretch() - songImportWizard.addPage(self.welcomePage) - # Source Page - self.sourcePage = QtGui.QWizardPage() - self.sourcePage.setObjectName(u'SourcePage') - self.sourceLayout = QtGui.QVBoxLayout(self.sourcePage) - self.sourceLayout.setObjectName(u'SourceLayout') - self.formatLayout = QtGui.QFormLayout() - self.formatLayout.setObjectName(u'FormatLayout') - self.formatLabel = QtGui.QLabel(self.sourcePage) - self.formatLabel.setObjectName(u'FormatLabel') - self.formatComboBox = QtGui.QComboBox(self.sourcePage) - self.formatComboBox.setObjectName(u'FormatComboBox') - self.formatLayout.addRow(self.formatLabel, self.formatComboBox) - self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, - self.formatSpacer) - self.sourceLayout.addLayout(self.formatLayout) - self.formatStack = QtGui.QStackedLayout() - self.formatStack.setObjectName(u'FormatStack') - # OpenLP 2.0 - self.addSingleFileSelectItem(u'openLP2') - # openlp.org 1.x - self.addSingleFileSelectItem(u'openLP1', None, True) - # OpenLyrics - self.addMultiFileSelectItem(u'openLyrics', u'OpenLyrics', True) - # Open Song - self.addMultiFileSelectItem(u'openSong', u'OpenSong') - # Words of Worship - self.addMultiFileSelectItem(u'wordsOfWorship') - # CCLI File import - self.addMultiFileSelectItem(u'ccli') - # Songs of Fellowship - self.addMultiFileSelectItem(u'songsOfFellowship', None, True) - # Generic Document/Presentation import - self.addMultiFileSelectItem(u'generic', None, True) - # EasySlides - self.addSingleFileSelectItem(u'easiSlides') - # EasyWorship - self.addSingleFileSelectItem(u'ew') - # Words of Worship - self.addMultiFileSelectItem(u'songBeamer') -# Commented out for future use. -# self.addSingleFileSelectItem(u'csv', u'CSV') - self.sourceLayout.addLayout(self.formatStack) - songImportWizard.addPage(self.sourcePage) - # Import Page - self.importPage = QtGui.QWizardPage() - self.importPage.setObjectName(u'ImportPage') - self.importLayout = QtGui.QVBoxLayout(self.importPage) - self.importLayout.setMargin(48) - self.importLayout.setObjectName(u'ImportLayout') - self.importProgressLabel = QtGui.QLabel(self.importPage) - self.importProgressLabel.setObjectName(u'ImportProgressLabel') - self.importLayout.addWidget(self.importProgressLabel) - self.importProgressBar = QtGui.QProgressBar(self.importPage) - self.importProgressBar.setObjectName(u'ImportProgressBar') - self.importLayout.addWidget(self.importProgressBar) - songImportWizard.addPage(self.importPage) - self.retranslateUi(songImportWizard) - self.formatStack.setCurrentIndex(0) - QtCore.QObject.connect(self.formatComboBox, - QtCore.SIGNAL(u'currentIndexChanged(int)'), - self.formatStack.setCurrentIndex) - QtCore.QMetaObject.connectSlotsByName(songImportWizard) - - def retranslateUi(self, songImportWizard): - songImportWizard.setWindowTitle( - translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard')) - self.titleLabel.setText( - u'%s' % \ - translate('SongsPlugin.ImportWizardForm', - 'Welcome to the Song Import Wizard')) - self.informationLabel.setText( - translate('SongsPlugin.ImportWizardForm', - 'This wizard will help you to import songs from a variety of ' - 'formats. Click the next button below to start the process by ' - 'selecting a format to import from.')) - self.sourcePage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Select Import Source')) - self.sourcePage.setSubTitle( - translate('SongsPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.formatLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Format:')) - self.formatComboBox.setItemText(0, - translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0')) - self.formatComboBox.setItemText(1, - translate('SongsPlugin.ImportWizardForm', 'openlp.org 1.x')) - self.formatComboBox.setItemText(2, - translate('SongsPlugin.ImportWizardForm', 'OpenLyrics')) - self.formatComboBox.setItemText(3, - translate('SongsPlugin.ImportWizardForm', 'OpenSong')) - self.formatComboBox.setItemText(4, - translate('SongsPlugin.ImportWizardForm', 'Words of Worship')) - self.formatComboBox.setItemText(5, - translate('SongsPlugin.ImportWizardForm', 'CCLI/SongSelect')) - self.formatComboBox.setItemText(6, - translate('SongsPlugin.ImportWizardForm', 'Songs of Fellowship')) - self.formatComboBox.setItemText(7, - translate('SongsPlugin.ImportWizardForm', - 'Generic Document/Presentation')) - self.formatComboBox.setItemText(8, - translate('SongsPlugin.ImportWizardForm', 'EasiSlides')) - self.formatComboBox.setItemText(9, - translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) - self.formatComboBox.setItemText(10, - translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) -# self.formatComboBox.setItemText(9, -# translate('SongsPlugin.ImportWizardForm', 'CSV')) - self.openLP2FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP2BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.openLP1FilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP1BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.openLP1DisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The openlp.org 1.x ' - 'importer has been disabled due to a missing Python module. If ' - 'you want to use this importer, you will need to install the ' - '"python-sqlite" module.')) - self.openLyricsAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.openLyricsRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.openLyricsDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics ' - 'importer has not yet been developed, but as you can see, we are ' - 'still intending to do so. Hopefully it will be in the next ' - 'release.')) - self.openSongAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.openSongRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.wordsOfWorshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.wordsOfWorshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.ccliAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.ccliRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songsOfFellowshipRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.songsOfFellowshipDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The Songs of ' - 'Fellowship importer has been disabled because OpenLP cannot ' - 'find OpenOffice.org on your computer.')) - self.genericAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.genericRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) - self.genericDisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The generic document/' - 'presentation importer has been disabled because OpenLP cannot ' - 'find OpenOffice.org on your computer.')) - self.easiSlidesFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.easiSlidesBrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.ewFilenameLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.ewBrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.songBeamerAddButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Add Files...')) - self.songBeamerRemoveButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) -# self.csvFilenameLabel.setText( -# translate('SongsPlugin.ImportWizardForm', 'Filename:')) -# self.csvBrowseButton.setText( -# translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.importPage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Importing')) - self.importPage.setSubTitle( - translate('SongsPlugin.ImportWizardForm', - 'Please wait while your songs are imported.')) - self.importProgressLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Ready.')) - self.importProgressBar.setFormat( - translate('SongsPlugin.ImportWizardForm', '%p%')) - # Align all QFormLayouts towards each other. - width = max(self.formatLabel.minimumSizeHint().width(), - self.openLP2FilenameLabel.minimumSizeHint().width()) - self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.openLP2FormLabelSpacer.changeSize(width, 0, - QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - self.openLP1FormLabelSpacer.changeSize(width, 0, - QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - self.easiSlidesFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) -# self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed, -# QtGui.QSizePolicy.Fixed) - - def addSingleFileSelectItem(self, prefix, obj_prefix=None, - can_disable=False): - if not obj_prefix: - obj_prefix = prefix - page = QtGui.QWidget() - page.setObjectName(obj_prefix + u'Page') - if can_disable: - importWidget = self.disablableWidget(page, prefix, obj_prefix) - else: - importWidget = page - importLayout = QtGui.QFormLayout(importWidget) - importLayout.setMargin(0) - if can_disable: - importLayout.setObjectName(obj_prefix + u'ImportLayout') - else: - importLayout.setObjectName(obj_prefix + u'Layout') - filenameLabel = QtGui.QLabel(importWidget) - filenameLabel.setObjectName(obj_prefix + u'FilenameLabel') - fileLayout = QtGui.QHBoxLayout() - fileLayout.setObjectName(obj_prefix + u'FileLayout') - filenameEdit = QtGui.QLineEdit(importWidget) - filenameEdit.setObjectName(obj_prefix + u'FilenameEdit') - fileLayout.addWidget(filenameEdit) - browseButton = QtGui.QToolButton(importWidget) - browseButton.setIcon(self.openIcon) - browseButton.setObjectName(obj_prefix + u'BrowseButton') - fileLayout.addWidget(browseButton) - importLayout.addRow(filenameLabel, fileLayout) - formSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Minimum) - importLayout.setItem(1, QtGui.QFormLayout.LabelRole, formSpacer) - self.formatStack.addWidget(page) - setattr(self, prefix + u'Page', page) - setattr(self, prefix + u'FilenameLabel', filenameLabel) - setattr(self, prefix + u'FormLabelSpacer', formSpacer) - setattr(self, prefix + u'FileLayout', fileLayout) - setattr(self, prefix + u'FilenameEdit', filenameEdit) - setattr(self, prefix + u'BrowseButton', browseButton) - if can_disable: - setattr(self, prefix + u'ImportLayout', importLayout) - else: - setattr(self, prefix + u'Layout', importLayout) - self.formatComboBox.addItem(u'') - - def addMultiFileSelectItem(self, prefix, obj_prefix=None, - can_disable=False): - if not obj_prefix: - obj_prefix = prefix - page = QtGui.QWidget() - page.setObjectName(obj_prefix + u'Page') - if can_disable: - importWidget = self.disablableWidget(page, prefix, obj_prefix) - else: - importWidget = page - importLayout = QtGui.QVBoxLayout(importWidget) - importLayout.setMargin(0) - if can_disable: - importLayout.setObjectName(obj_prefix + u'ImportLayout') - else: - importLayout.setObjectName(obj_prefix + u'Layout') - fileListWidget = QtGui.QListWidget(importWidget) - fileListWidget.setSelectionMode( - QtGui.QAbstractItemView.ExtendedSelection) - fileListWidget.setObjectName(obj_prefix + u'FileListWidget') - importLayout.addWidget(fileListWidget) - buttonLayout = QtGui.QHBoxLayout() - buttonLayout.setObjectName(obj_prefix + u'ButtonLayout') - addButton = QtGui.QPushButton(importWidget) - addButton.setIcon(self.openIcon) - addButton.setObjectName(obj_prefix + u'AddButton') - buttonLayout.addWidget(addButton) - buttonLayout.addStretch() - removeButton = QtGui.QPushButton(importWidget) - removeButton.setIcon(self.deleteIcon) - removeButton.setObjectName(obj_prefix + u'RemoveButton') - buttonLayout.addWidget(removeButton) - importLayout.addLayout(buttonLayout) - self.formatStack.addWidget(page) - setattr(self, prefix + u'Page', page) - setattr(self, prefix + u'FileListWidget', fileListWidget) - setattr(self, prefix + u'ButtonLayout', buttonLayout) - setattr(self, prefix + u'AddButton', addButton) - setattr(self, prefix + u'RemoveButton', removeButton) - if can_disable: - setattr(self, prefix + u'ImportLayout', importLayout) - else: - setattr(self, prefix + u'Layout', importLayout) - self.formatComboBox.addItem(u'') - - def disablableWidget(self, page, prefix, obj_prefix): - layout = QtGui.QVBoxLayout(page) - layout.setMargin(0) - layout.setSpacing(0) - layout.setObjectName(obj_prefix + u'Layout') - disabledWidget = QtGui.QWidget(page) - disabledWidget.setVisible(False) - disabledWidget.setObjectName(obj_prefix + u'DisabledWidget') - disabledLayout = QtGui.QVBoxLayout(disabledWidget) - disabledLayout.setMargin(0) - disabledLayout.setObjectName(obj_prefix + u'DisabledLayout') - disabledLabel = QtGui.QLabel(disabledWidget) - disabledLabel.setWordWrap(True) - disabledLabel.setObjectName(obj_prefix + u'DisabledLabel') - disabledLayout.addWidget(disabledLabel) - layout.addWidget(disabledWidget) - importWidget = QtGui.QWidget(page) - importWidget.setObjectName(obj_prefix + u'ImportWidget') - layout.addWidget(importWidget) - setattr(self, prefix + u'Layout', layout) - setattr(self, prefix + u'DisabledWidget', disabledWidget) - setattr(self, prefix + u'DisabledLayout', disabledLayout) - setattr(self, prefix + u'DisabledLabel', disabledLabel) - setattr(self, prefix + u'ImportWidget', importWidget) - return importWidget diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 6e610518f..11f4df1e2 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -35,9 +35,6 @@ from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) -class EasiSlidesImportError(Exception): - pass - class EasiSlidesImport(SongImport): """ Import songs exported from EasiSlides @@ -61,8 +58,6 @@ class EasiSlidesImport(SongImport): multiple opensong files. If `self.commit` is set False, the import will not be committed to the database (useful for test scripts). """ - success = True - self.import_wizard.progressBar.setMaximum(1) log.info(u'Direct import %s', self.filename) @@ -73,9 +68,7 @@ class EasiSlidesImport(SongImport): count = file.read().count('') file.seek(0) self.import_wizard.progressBar.setMaximum(count) - self.do_import_file(file) - - return success + return self.do_import_file(file) def do_import_file(self, file): """ @@ -83,6 +76,7 @@ class EasiSlidesImport(SongImport): not a filename """ self.set_defaults() + success = True # determines, if ENTIRELY UPPERCASE lines should be converted to lower self.toLower = False @@ -108,6 +102,8 @@ class EasiSlidesImport(SongImport): data[elem.tag.lower()] = text if elem.tag.lower() == u"item": + # just in case, it worked without set_defaults as well + self.set_defaults() self.parse_song(data) self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', @@ -116,6 +112,11 @@ class EasiSlidesImport(SongImport): if self.commit: self.finish() data = {} + # breakpoint here + if self.stop_import_flag: + success = False + break + return success def notCapsLock(self, string): if self.toLower and string.upper() == string: @@ -157,42 +158,23 @@ class EasiSlidesImport(SongImport): return line[7:right_bracket].strip() def parse_song(self, data): - # We should also check if the title is already used, if yes, - # maybe user sould be asked if we should import or not - - # set title self.title = self.notCapsLockTitle(data['title1']) - # set alternate title, if present if data['title2'] != None: self.alternate_title = self.notCapsLockTitle(data['title2']) - # folder name, we have no use for it, usually only one folder is - # used in easislides and this contains no actual data, easislides - # default database is named English, but usersmay not follow their - # example - # data['folder'] - - # set song number, if present, empty otherwise # EasiSlides tends to set all not changed song numbers to 0, # so this hardly ever carries any information if data['songnumber'] != None and data['songnumber'] != u'0': self.song_number = int(data['songnumber']) - # Don't know how to use Notations - # data['notations'] - - # set song authors - # we don't have to handle the no author case, it is done afterwards if data['writer'] != None: authors = data['writer'].split(u',') for author in authors: self.authors.append(author.strip()) - # set copyright data # licenceadmins may contain Public Domain or CCLI, as shown in examples - # let's just concatenate these fields, it should be determined, if song - # No is actually CCLI nr, if it is set + # let's just concatenate these fields copyright = [] if data['copyright']: copyright.append(data['copyright'].strip()) @@ -202,72 +184,26 @@ class EasiSlidesImport(SongImport): copyright.append(data['licenceadmin2'].strip()) self.add_copyright(u' '.join(copyright)) - # 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 - # but then again, it would not hurt either + # I was not able to find place to set categories in easislides + # but then again, it does not hurt either if data['category']: for topic in data['category'].split(u','): self.topics.append(topic.strip()) - - # don't know what to do with timing data - # may be either 3/4 or 4/4 - # data['timing'] - # don't know what to do with music key - # data['musickey'], may be Db, C, G, F#, F#m - # data['capo'], is a number from 0 to 11, determing where to - # place a capo on guitar neck - - # set book data if data['bookreference']: self.song_book_name = data['bookreference'].strip() - # don't know what to do with user - # data['userreference'], this is simple text entry, no - # 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 - # thing, see an example: - # 21=1>23=0>22=2>25=2>26=-16777216> - # 27=-16777216>28=11>29=-1>30=-256>31=2>32=2> - # 41=16>42=16>43=Microsoft Sans Serif> - # 44=Microsoft Sans Serif>45=0>46=45>47=20>48=40> - # 50=0>51=>52=50>53=-1>54=0>55=1>61=>62=2> - # 63=1>64=2>65=2>66=0>71=0>72=Fade>73=Fade> - # - # data['formatdata'] - - # don't know what to do with settings data either, this is similar - # nonsense as formatdata: 10=2;5;0;0;1;0;»126;232;> - # data['settings'] - # LYRICS LYRICS LYRICS - # the big and messy part to handle lyrics lyrics = data['contents'] # 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: lyrics = u"%s\n%s" % (data['title1'], lyrics) - #if lyrics.find(u'[') != -1: - # # this must have at least one separator - # match = -1 - # while True: - # match = lyrics.find(u'[', match+1) - # if match == -1: - # break - # elif lyrics[match:match+7].lower() == u'[region': - # regions = regions+1 - # else: - # separators = separators+1 - lines = lyrics.split(u'\n') length = len(lines) - # we go over lines first, to determine some information, + # we go over all lines first, to determine some information, # which tells us how to parse verses later emptylines = 0 regionlines = {} @@ -298,34 +234,30 @@ class EasiSlidesImport(SongImport): 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: + # the number of different regions in song - 1 + if len(regionlines) > 1: 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', + u'tested, encountered 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 \ + regions = (len(regionlines) > 0) + # if the regions are inside verses + regionsInVerses = (regions and \ regionlines[regionlines.keys()[0]] > 1) - # data storage while importing verses = {} - # keep track of a "default" verse order, in case none is specified - # this list contains list as [region, versetype, versenum, instance] + # list as [region, versetype, versenum, instance] our_verse_order = [] - # default region defaultregion = u'1' reg = defaultregion verses[reg] = {} - # instance + # instance differentiates occurrences of same verse tag inst = 1 MarkTypes = { @@ -334,11 +266,9 @@ class EasiSlidesImport(SongImport): u'intro': u'I', u'ending': u'E', u'bridge': u'B', - u'prechorus': u'P', - } + u'prechorus': u'P'} for i in range(length): - # we iterate once more over lines thisline = lines[i] if i < length-1: nextline = lines[i+1].strip() @@ -346,7 +276,6 @@ class EasiSlidesImport(SongImport): # there is no nextline at the last line nextline = False - if len(thisline) == 0: if separators: # separators are used, so empty line means slide break @@ -364,8 +293,6 @@ class EasiSlidesImport(SongImport): # or whole song is uppercase, this must be verse vt = u'V' - # changing the region is not possible in this case - if verses[reg].has_key(vt): vn = len(verses[reg][vt].keys())+1 else: @@ -394,8 +321,7 @@ class EasiSlidesImport(SongImport): right_bracket = thisline.find(u']') marker = thisline[1:right_bracket].upper() # have we got any digits? - # If so, versenumber is everything from the digits - # to the end (even if there are some alpha chars on the end) + # If so, versenumber is everything from the digits to the end match = re.match(u'(.*)(\d+.*)', marker) if match is not None: vt = match.group(1).strip() @@ -442,13 +368,12 @@ class EasiSlidesImport(SongImport): if not verses[reg][vt][vn].has_key(inst): verses[reg][vt][vn][inst] = [] - # Tidy text and remove the ____s from extended words words = self.tidy_text(thisline) words = self.notCapsLock(words) verses[reg][vt][vn][inst].append(words) # done parsing - + versetags = [] # we use our_verse_order to ensure, we insert lyrics in the same order @@ -467,15 +392,6 @@ class EasiSlidesImport(SongImport): lines = u'\n'.join(verses[reg][vt][vn][inst]) 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', @@ -483,11 +399,8 @@ class EasiSlidesImport(SongImport): 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 - # if this is not present, we don't need it either, since the - # verses already are in the right order + u'e': u'E1'} + # Make use of Sequence data, determining the order of verses if data['sequence'] != None: order = data['sequence'].split(u',') for tag in order: @@ -497,11 +410,10 @@ class EasiSlidesImport(SongImport): elif SeqTypes.has_key(tag.lower()): tag = SeqTypes[tag.lower()] else: - # maybe we should continue here instead - tag = u'O1' + continue if not tag in versetags: - log.info(u'Got order %s but not in versetags, dropping this' - u'item from presentation order', tag) + log.info(u'Got order item %s, which is not in versetags,' + u'dropping item from presentation order', tag) else: self.verse_order_list.append(tag) From f090c5409f10fb534a491486e13e1c687b29c112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 17 Jan 2011 22:47:46 +0200 Subject: [PATCH 07/11] smart features removed, using objectify now --- openlp/plugins/songs/lib/easislidesimport.py | 257 ++++++++----------- 1 file changed, 105 insertions(+), 152 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 11f4df1e2..c66d35847 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -26,7 +26,7 @@ import logging import os -from lxml import etree +from lxml import etree, objectify from lxml.etree import Error, LxmlError import re @@ -60,156 +60,107 @@ class EasiSlidesImport(SongImport): """ self.import_wizard.progressBar.setMaximum(1) - log.info(u'Direct import %s', self.filename) + log.info(u'Importing XML file %s', self.filename) + parser = etree.XMLParser(remove_blank_text=True) + file = etree.parse(self.filename, parser) + xml = unicode(etree.tostring(file)) + song_xml = objectify.fromstring(xml) + self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', u'Importing %s...')) % os.path.split(self.filename)[-1]) - file = open(self.filename) - count = file.read().count('') - file.seek(0) - self.import_wizard.progressBar.setMaximum(count) - return self.do_import_file(file) - - def do_import_file(self, file): - """ - Process the EasiSlides file - pass in a file-like object, - not a filename - """ - self.set_defaults() - success = True + self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) - # determines, if ENTIRELY UPPERCASE lines should be converted to lower - 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 - self.titleIsLyrics = False - - try: - context = etree.iterparse(file) - except (Error, LxmlError): - log.exception(u'Error parsing XML') - return - - data = {} - for action, elem in context: - if not elem.text: - text = None - else: - text = unicode(elem.text) - - data[elem.tag.lower()] = text - - if elem.tag.lower() == u"item": - # just in case, it worked without set_defaults as well - self.set_defaults() - self.parse_song(data) - self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - u'Importing %s, song %s...')) % - (os.path.split(self.filename)[-1], self.title)) - if self.commit: - self.finish() - data = {} - # breakpoint here - if self.stop_import_flag: - success = False - break - return success - - def notCapsLock(self, string): - if self.toLower and string.upper() == string: - 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: - return string - - def notCapsLockTitle(self, string): - if self.toLower and string.upper() == string: - 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:]) - else: - 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: + for song in song_xml.Item: + self.import_wizard.incrementProgressBar( + unicode(translate('SongsPlugin.ImportWizardForm', + u'Importing %s, song %s...')) % + (os.path.split(self.filename)[-1], song.Title1)) + success = self._parse_song(song) + if not success or self.stop_import_flag: return False + if self.commit: + self.finish() 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, song): + self._success = True + self._add_title(song) + self._add_alttitle(song) + self._add_number(song) + self._add_authors(song) + self._add_copyright(song) + self._add_book(song) + self._parse_and_add_lyrics(song) + return self._success - def parse_song(self, data): - self.title = self.notCapsLockTitle(data['title1']) + def _add_title(self, song): + try: + self.title = unicode(song.Title1).strip() + except: + log.info(u'no Title1') + self._success = False - if data['title2'] != None: - self.alternate_title = self.notCapsLockTitle(data['title2']) - - # EasiSlides tends to set all not changed song numbers to 0, - # so this hardly ever carries any information - if data['songnumber'] != None and data['songnumber'] != u'0': - self.song_number = int(data['songnumber']) - - if data['writer'] != None: - authors = data['writer'].split(u',') + def _add_alttitle(self, song): + try: + self.alternate_title = unicode(self.song.Title2).strip() + except: + pass + + def _add_number(self, song): + try: + number = int(song.SongNumber) + if number != 0: + self.song_number = number + print number + except: + pass + + def _add_authors(self, song): + try: + authors = unicode(song.Writer).strip().split(u',') for author in authors: self.authors.append(author.strip()) - - # licenceadmins may contain Public Domain or CCLI, as shown in examples - # let's just concatenate these fields + except: + pass + + def _add_copyright(self, song): copyright = [] - if data['copyright']: - copyright.append(data['copyright'].strip()) - if data['licenceadmin1']: - copyright.append(data['licenceadmin1'].strip()) - if data['licenceadmin2']: - copyright.append(data['licenceadmin2'].strip()) + try: + copyright.append(unicode(song.Copyright).strip()) + except: + pass + try: + copyright.append(unicode(song.LicenceAdmin1).strip()) + except: + pass + try: + copyright.append(unicode(song.LicenceAdmin2).strip()) + except: + pass self.add_copyright(u' '.join(copyright)) - - # I was not able to find place to set categories in easislides - # but then again, it does not hurt either - if data['category']: - for topic in data['category'].split(u','): - self.topics.append(topic.strip()) - if data['bookreference']: - self.song_book_name = data['bookreference'].strip() + def _add_book(self, song): + try: + self.song_book_name = unicode(song.BookReference).strip() + except: + pass - # LYRICS LYRICS LYRICS - lyrics = data['contents'] - - # we add title to first line, if supposed to do so - if self.titleIsLyrics: - lyrics = u"%s\n%s" % (data['title1'], lyrics) - + def _parse_and_add_lyrics(self, song): + try: + lyrics = unicode(song.Contents).strip() + except: + log.info(u'no Contents') + self._success = False + lines = lyrics.split(u'\n') length = len(lines) - # we go over all lines first, to determine some information, + # we go over all lines first, to determine 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] @@ -223,20 +174,14 @@ class EasiSlidesImport(SongImport): # 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) + region = self._extractRegion(thisline) if regionlines.has_key(region): regionlines[region] = regionlines[region] + 1 else: 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 different regions in song - 1 @@ -280,18 +225,11 @@ class EasiSlidesImport(SongImport): if separators: # separators are used, so empty line means slide break # inside verse - if self.listHas(verses, [reg, vt, vn, inst]): + 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 - vt = u'C' - else: - # if the next line is not uppercase, - # or whole song is uppercase, this must be verse - vt = u'V' + vt = u'V' if verses[reg].has_key(vt): vn = len(verses[reg][vt].keys())+1 @@ -305,7 +243,7 @@ class EasiSlidesImport(SongImport): continue elif thisline[0:7] == u'[region': - reg = self.extractRegion(thisline) + reg = self._extractRegion(thisline) if not verses.has_key(reg): verses[reg] = {} if i == 0: @@ -345,7 +283,7 @@ class EasiSlidesImport(SongImport): region = defaultregion inst = 1 - if self.listHas(verses, [reg, vt, vn, inst]): + 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: @@ -369,8 +307,6 @@ class EasiSlidesImport(SongImport): verses[reg][vt][vn][inst] = [] words = self.tidy_text(thisline) - words = self.notCapsLock(words) - verses[reg][vt][vn][inst].append(words) # done parsing @@ -385,7 +321,7 @@ class EasiSlidesImport(SongImport): vn = tag[2] inst = tag[3] - if not self.listHas(verses, [reg, vt, vn, inst]): + if not self._listHas(verses, [reg, vt, vn, inst]): continue versetag = u'%s%s' % (vt, vn) versetags.append(versetag) @@ -401,8 +337,8 @@ class EasiSlidesImport(SongImport): u'w': u'B2', u'e': u'E1'} # Make use of Sequence data, determining the order of verses - if data['sequence'] != None: - order = data['sequence'].split(u',') + try: + order = unicode(song.Sequence).strip().split(u',') for tag in order: if tag[0].isdigit(): # it's a verse if it has no prefix, but has a number @@ -417,3 +353,20 @@ class EasiSlidesImport(SongImport): u'dropping item from presentation order', tag) else: self.verse_order_list.append(tag) + except: + pass + + 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() From 0c38bccd45a40143e10343bc13daa5db7bd6c5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 18 Jan 2011 00:27:25 +0200 Subject: [PATCH 08/11] more exceptions and a few other changes --- openlp/plugins/songs/lib/easislidesimport.py | 159 +++++++++---------- openlp/plugins/songs/lib/opensongimport.py | 2 +- 2 files changed, 77 insertions(+), 84 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index c66d35847..7974a8842 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -79,7 +79,7 @@ class EasiSlidesImport(SongImport): success = self._parse_song(song) if not success or self.stop_import_flag: return False - if self.commit: + elif self.commit: self.finish() return True @@ -97,14 +97,18 @@ class EasiSlidesImport(SongImport): def _add_title(self, song): try: self.title = unicode(song.Title1).strip() - except: - log.info(u'no Title1') + except UnicodeDecodeError: + log.exception(u'Title1 unicode decode error') + except AttributeError: + log.exception(u'no Title1') self._success = False def _add_alttitle(self, song): try: - self.alternate_title = unicode(self.song.Title2).strip() - except: + self.alternate_title = unicode(song.Title2).strip() + except UnicodeDecodeError: + log.exception(u'Title2 unicode decode error') + except AttributeError: pass def _add_number(self, song): @@ -112,75 +116,81 @@ class EasiSlidesImport(SongImport): number = int(song.SongNumber) if number != 0: self.song_number = number - print number - except: + except UnicodeDecodeError: + log.exception(u'SongNumber unicode decode error') + except AttributeError: pass def _add_authors(self, song): try: - authors = unicode(song.Writer).strip().split(u',') + authors = unicode(song.Writer).split(u',') for author in authors: - self.authors.append(author.strip()) - except: + author = author.strip() + if len(author) > 0: + self.authors.append(author) + except UnicodeDecodeError: + log.exception(u'Writer unicode decode error') + except AttributeError: pass def _add_copyright(self, song): copyright = [] try: copyright.append(unicode(song.Copyright).strip()) - except: + except UnicodeDecodeError: + log.exception(u'Copyright unicode decode error') + except AttributeError: pass try: copyright.append(unicode(song.LicenceAdmin1).strip()) - except: + except UnicodeDecodeError: + log.exception(u'LicenceAdmin1 unicode decode error') + except AttributeError: pass try: copyright.append(unicode(song.LicenceAdmin2).strip()) - except: + except UnicodeDecodeError: + log.exception(u'LicenceAdmin2 unicode decode error') + except AttributeError: pass self.add_copyright(u' '.join(copyright)) def _add_book(self, song): try: self.song_book_name = unicode(song.BookReference).strip() - except: + except UnicodeDecodeError: + log.exception(u'BookReference unicode decode error') + except AttributeError: pass def _parse_and_add_lyrics(self, song): try: lyrics = unicode(song.Contents).strip() - except: - log.info(u'no Contents') + except UnicodeDecodeError: + log.exception(u'Contents unicode decode error') + except AttributeError: + log.exception(u'no Contents') self._success = False lines = lyrics.split(u'\n') - length = len(lines) # we go over all lines first, to determine information, # which tells us how to parse verses later - emptylines = 0 regionlines = {} separatorlines = 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: - regionlines[region] = 1 + for line in lines: + line = line.strip() + if len(line) == 0: + continue + elif line[1:7] == u'region': + # this is region separator, probably [region 2] + region = self._extractRegion(line) + if regionlines.has_key(region): + regionlines[region] = regionlines[region] + 1 else: - separatorlines = separatorlines + 1 + regionlines[region] = 1 + elif line[0] == u'[': + separatorlines = separatorlines + 1 # if the song has separators separators = (separatorlines > 0) @@ -196,6 +206,14 @@ class EasiSlidesImport(SongImport): regionsInVerses = (regions and \ regionlines[regionlines.keys()[0]] > 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'} + verses = {} # list as [region, versetype, versenum, instance] our_verse_order = [] @@ -204,24 +222,13 @@ class EasiSlidesImport(SongImport): verses[reg] = {} # instance differentiates occurrences of same verse tag 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'} + vt = u'V' + vn = u'1' - for i in range(length): - thisline = lines[i] - if i < length-1: - nextline = lines[i+1].strip() - else: - # there is no nextline at the last line - nextline = False + for line in lines: + line = line.strip() - if len(thisline) == 0: + if len(line) == 0: if separators: # separators are used, so empty line means slide break # inside verse @@ -237,43 +244,32 @@ class EasiSlidesImport(SongImport): 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 - elif thisline[0:7] == u'[region': - reg = self._extractRegion(thisline) + elif line[0:7] == u'[region': + reg = self._extractRegion(line) if not verses.has_key(reg): verses[reg] = {} - if i == 0: - # the file started with [region 2] - vt = u'V' - vn = u'1' - our_verse_order.append([reg, vt, vn, inst]) continue - elif thisline[0] == u'[': + elif line[0] == u'[': # this is a normal section marker # drop the square brackets - right_bracket = thisline.find(u']') - marker = thisline[1:right_bracket].upper() + right_bracket = line.find(u']') + marker = line[1:right_bracket].upper() # have we got any digits? # If so, versenumber is everything from the digits to the end match = re.match(u'(.*)(\d+.*)', marker) if match is not None: vt = match.group(1).strip() vn = match.group(2) - if vt == u'': - vt = u'V' - elif MarkTypes.has_key(vt.lower()): + if MarkTypes.has_key(vt.lower()): vt = MarkTypes[vt.lower()] else: vt = u'O' else: - if marker == u'': - vt = u'V' - elif MarkTypes.has_key(marker.lower()): + if MarkTypes.has_key(marker.lower()): vt = MarkTypes[marker.lower()] else: vt = u'O' @@ -285,16 +281,9 @@ class EasiSlidesImport(SongImport): 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 - if i == 0: - # this is the first line, but no separator is found, - # we say it's V1 - vt = u'V' - vn = u'1' + if not [reg, vt, vn, inst] in our_verse_order: our_verse_order.append([reg, vt, vn, inst]) # We have versetype/number data, if it was there, now @@ -306,7 +295,7 @@ class EasiSlidesImport(SongImport): if not verses[reg][vt][vn].has_key(inst): verses[reg][vt][vn][inst] = [] - words = self.tidy_text(thisline) + words = self.tidy_text(line) verses[reg][vt][vn][inst].append(words) # done parsing @@ -340,7 +329,9 @@ class EasiSlidesImport(SongImport): try: order = unicode(song.Sequence).strip().split(u',') for tag in order: - if tag[0].isdigit(): + if len(tag) == 0: + continue + elif tag[0].isdigit(): # it's a verse if it has no prefix, but has a number tag = u'V' + tag elif SeqTypes.has_key(tag.lower()): @@ -353,7 +344,9 @@ class EasiSlidesImport(SongImport): u'dropping item from presentation order', tag) else: self.verse_order_list.append(tag) - except: + except UnicodeDecodeError: + log.exception(u'Sequence unicode decode error') + except AttributeError: pass def _listHas(self, lst, subitems): @@ -367,6 +360,6 @@ class EasiSlidesImport(SongImport): return True def _extractRegion(self, line): - # this was true already: thisline[0:7] == u'[region': + # this was true already: line[0:7] == u'[region': right_bracket = line.find(u']') return line[7:right_bracket].strip() diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 6a60fcc6c..eb16f4ba4 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -129,7 +129,7 @@ class OpenSongImport(SongImport): else: numfiles += 1 log.debug(u'Total number of files: %d', numfiles) - self.import_wizard.importProgressBar.setMaximum(numfiles) + self.import_wizard.progressBar.setMaximum(numfiles) for filename in self.filenames: if self.stop_import_flag: success = False From 1c1e66bba87ed80f772bfbd73a37e033735c5909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 18 Jan 2011 01:16:30 +0200 Subject: [PATCH 09/11] refurbished, added self._success = False to exceptions --- openlp/plugins/songs/lib/easislidesimport.py | 106 +++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 7974a8842..26bb105af 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -98,7 +98,8 @@ class EasiSlidesImport(SongImport): try: self.title = unicode(song.Title1).strip() except UnicodeDecodeError: - log.exception(u'Title1 unicode decode error') + log.exception(u'Unicode decode error while decoding Title1') + self._success = False except AttributeError: log.exception(u'no Title1') self._success = False @@ -107,7 +108,8 @@ class EasiSlidesImport(SongImport): try: self.alternate_title = unicode(song.Title2).strip() except UnicodeDecodeError: - log.exception(u'Title2 unicode decode error') + log.exception(u'Unicode decode error while decoding Title2') + self._success = False except AttributeError: pass @@ -117,7 +119,8 @@ class EasiSlidesImport(SongImport): if number != 0: self.song_number = number except UnicodeDecodeError: - log.exception(u'SongNumber unicode decode error') + log.exception(u'Unicode decode error while decoding SongNumber') + self._success = False except AttributeError: pass @@ -129,7 +132,8 @@ class EasiSlidesImport(SongImport): if len(author) > 0: self.authors.append(author) except UnicodeDecodeError: - log.exception(u'Writer unicode decode error') + log.exception(u'Unicode decode error while decoding Writer') + self._success = False except AttributeError: pass @@ -138,19 +142,22 @@ class EasiSlidesImport(SongImport): try: copyright.append(unicode(song.Copyright).strip()) except UnicodeDecodeError: - log.exception(u'Copyright unicode decode error') + log.exception(u'Unicode decode error while decoding Copyright') + self._success = False except AttributeError: pass try: copyright.append(unicode(song.LicenceAdmin1).strip()) except UnicodeDecodeError: - log.exception(u'LicenceAdmin1 unicode decode error') + log.exception(u'Unicode decode error while decoding LicenceAdmin1') + self._success = False except AttributeError: pass try: copyright.append(unicode(song.LicenceAdmin2).strip()) except UnicodeDecodeError: - log.exception(u'LicenceAdmin2 unicode decode error') + log.exception(u'Unicode decode error while decoding LicenceAdmin2') + self._success = False except AttributeError: pass self.add_copyright(u' '.join(copyright)) @@ -159,7 +166,8 @@ class EasiSlidesImport(SongImport): try: self.song_book_name = unicode(song.BookReference).strip() except UnicodeDecodeError: - log.exception(u'BookReference unicode decode error') + log.exception(u'Unicode decode error while decoding BookReference') + self._success = False except AttributeError: pass @@ -167,7 +175,8 @@ class EasiSlidesImport(SongImport): try: lyrics = unicode(song.Contents).strip() except UnicodeDecodeError: - log.exception(u'Contents unicode decode error') + log.exception(u'Unicode decode error while decoding Contents') + self._success = False except AttributeError: log.exception(u'no Contents') self._success = False @@ -207,12 +216,12 @@ class EasiSlidesImport(SongImport): regionlines[regionlines.keys()[0]] > 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'} + u'CHORUS': u'C', + u'VERSE': u'V', + u'INTRO': u'I', + u'ENDING': u'E', + u'BRIDGE': u'B', + u'PRECHORUS': u'P'} verses = {} # list as [region, versetype, versenum, instance] @@ -221,9 +230,9 @@ class EasiSlidesImport(SongImport): reg = defaultregion verses[reg] = {} # instance differentiates occurrences of same verse tag - inst = 1 vt = u'V' vn = u'1' + inst = 1 for line in lines: line = line.strip() @@ -237,47 +246,39 @@ class EasiSlidesImport(SongImport): else: # separators are not used, so empty line starts a new verse vt = u'V' - if verses[reg].has_key(vt): vn = len(verses[reg][vt].keys())+1 else: vn = u'1' - inst = 1 - continue continue - elif line[0:7] == u'[region': reg = self._extractRegion(line) if not verses.has_key(reg): verses[reg] = {} + if not regionsInVerses: + vt = u'V' + vn = u'1' + inst = 1 continue - elif line[0] == u'[': # this is a normal section marker - # drop the square brackets - right_bracket = line.find(u']') - marker = line[1:right_bracket].upper() + marker = line[1:line.find(u']')].upper() + vn = u'1' # have we got any digits? # If so, versenumber is everything from the digits to the end match = re.match(u'(.*)(\d+.*)', marker) - if match is not None: - vt = match.group(1).strip() + if match: + marker = match.group(1).strip() vn = match.group(2) - if MarkTypes.has_key(vt.lower()): - vt = MarkTypes[vt.lower()] - else: - vt = u'O' + if len(marker) == 0: + vt = u'V' + elif MarkTypes.has_key(marker): + vt = MarkTypes[marker] else: - if MarkTypes.has_key(marker.lower()): - vt = MarkTypes[marker.lower()] - else: - vt = u'O' - vn = u'1' - + vt = u'O' if regionsInVerses: region = defaultregion - inst = 1 if self._listHas(verses, [reg, vt, vn, inst]): inst = len(verses[reg][vt][vn])+1 @@ -286,8 +287,6 @@ class EasiSlidesImport(SongImport): if not [reg, vt, vn, inst] in our_verse_order: our_verse_order.append([reg, vt, vn, inst]) - # We have versetype/number data, if it was there, now - # we parse text if not verses[reg].has_key(vt): verses[reg][vt] = {} if not verses[reg][vt].has_key(vn): @@ -303,19 +302,12 @@ class EasiSlidesImport(SongImport): # we use our_verse_order to ensure, we insert lyrics in the same order # as these appeared originally in the file - - for tag in our_verse_order: - reg = tag[0] - vt = tag[1] - vn = tag[2] - inst = tag[3] - - if not self._listHas(verses, [reg, vt, vn, inst]): - continue - versetag = u'%s%s' % (vt, vn) - versetags.append(versetag) - lines = u'\n'.join(verses[reg][vt][vn][inst]) - self.verses.append([versetag, lines]) + for [reg, vt, vn, inst] in our_verse_order: + if self._listHas(verses, [reg, vt, vn, inst]): + versetag = u'%s%s' % (vt, vn) + versetags.append(versetag) + lines = u'\n'.join(verses[reg][vt][vn][inst]) + self.verses.append([versetag, lines]) SeqTypes = { u'p': u'P1', @@ -332,20 +324,20 @@ class EasiSlidesImport(SongImport): if len(tag) == 0: continue elif tag[0].isdigit(): - # it's a verse if it has no prefix, but has a number tag = u'V' + tag elif SeqTypes.has_key(tag.lower()): tag = SeqTypes[tag.lower()] else: continue - if not tag in versetags: + if tag in versetags: + self.verse_order_list.append(tag) + else: log.info(u'Got order item %s, which is not in versetags,' u'dropping item from presentation order', tag) - else: - self.verse_order_list.append(tag) except UnicodeDecodeError: - log.exception(u'Sequence unicode decode error') + log.exception(u'Unicode decode error while decoding Sequence') + self._success = False except AttributeError: pass From ff80150fc171ca629c61c5925af625ab149071c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 18 Jan 2011 11:09:00 +0200 Subject: [PATCH 10/11] removed extra empty lines, removed leading spaces --- openlp/plugins/songs/lib/easislidesimport.py | 61 ++++++++------------ openlp/plugins/songs/lib/importer.py | 1 + 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 26bb105af..571f9d047 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -59,18 +59,15 @@ class EasiSlidesImport(SongImport): import will not be committed to the database (useful for test scripts). """ self.import_wizard.progressBar.setMaximum(1) - - log.info(u'Importing XML file %s', self.filename) + log.info(u'Importing EasiSlides XML file %s', self.filename) parser = etree.XMLParser(remove_blank_text=True) file = etree.parse(self.filename, parser) xml = unicode(etree.tostring(file)) song_xml = objectify.fromstring(xml) - self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', u'Importing %s...')) % os.path.split(self.filename)[-1]) self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) - for song in song_xml.Item: self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', @@ -82,7 +79,7 @@ class EasiSlidesImport(SongImport): elif self.commit: self.finish() return True - + def _parse_song(self, song): self._success = True self._add_title(song) @@ -93,7 +90,7 @@ class EasiSlidesImport(SongImport): self._add_book(song) self._parse_and_add_lyrics(song) return self._success - + def _add_title(self, song): try: self.title = unicode(song.Title1).strip() @@ -103,7 +100,7 @@ class EasiSlidesImport(SongImport): except AttributeError: log.exception(u'no Title1') self._success = False - + def _add_alttitle(self, song): try: self.alternate_title = unicode(song.Title2).strip() @@ -112,7 +109,7 @@ class EasiSlidesImport(SongImport): self._success = False except AttributeError: pass - + def _add_number(self, song): try: number = int(song.SongNumber) @@ -136,7 +133,7 @@ class EasiSlidesImport(SongImport): self._success = False except AttributeError: pass - + def _add_copyright(self, song): copyright = [] try: @@ -161,7 +158,7 @@ class EasiSlidesImport(SongImport): except AttributeError: pass self.add_copyright(u' '.join(copyright)) - + def _add_book(self, song): try: self.song_book_name = unicode(song.BookReference).strip() @@ -170,7 +167,7 @@ class EasiSlidesImport(SongImport): self._success = False except AttributeError: pass - + def _parse_and_add_lyrics(self, song): try: lyrics = unicode(song.Contents).strip() @@ -180,9 +177,7 @@ class EasiSlidesImport(SongImport): except AttributeError: log.exception(u'no Contents') self._success = False - lines = lyrics.split(u'\n') - # we go over all lines first, to determine information, # which tells us how to parse verses later regionlines = {} @@ -200,7 +195,6 @@ class EasiSlidesImport(SongImport): regionlines[region] = 1 elif line[0] == u'[': separatorlines = separatorlines + 1 - # if the song has separators separators = (separatorlines > 0) # the number of different regions in song - 1 @@ -214,7 +208,6 @@ class EasiSlidesImport(SongImport): # if the regions are inside verses regionsInVerses = (regions and \ regionlines[regionlines.keys()[0]] > 1) - MarkTypes = { u'CHORUS': u'C', u'VERSE': u'V', @@ -222,7 +215,6 @@ class EasiSlidesImport(SongImport): u'ENDING': u'E', u'BRIDGE': u'B', u'PRECHORUS': u'P'} - verses = {} # list as [region, versetype, versenum, instance] our_verse_order = [] @@ -236,7 +228,6 @@ class EasiSlidesImport(SongImport): for line in lines: line = line.strip() - if len(line) == 0: if separators: # separators are used, so empty line means slide break @@ -251,7 +242,6 @@ class EasiSlidesImport(SongImport): else: vn = u'1' inst = 1 - continue elif line[0:7] == u'[region': reg = self._extractRegion(line) if not verses.has_key(reg): @@ -260,7 +250,6 @@ class EasiSlidesImport(SongImport): vt = u'V' vn = u'1' inst = 1 - continue elif line[0] == u'[': # this is a normal section marker marker = line[1:line.find(u']')].upper() @@ -282,24 +271,20 @@ class EasiSlidesImport(SongImport): inst = 1 if self._listHas(verses, [reg, vt, vn, inst]): inst = len(verses[reg][vt][vn])+1 - continue - - if not [reg, vt, vn, inst] in our_verse_order: - our_verse_order.append([reg, vt, vn, inst]) - - if not verses[reg].has_key(vt): - verses[reg][vt] = {} - if not verses[reg][vt].has_key(vn): - verses[reg][vt][vn] = {} - if not verses[reg][vt][vn].has_key(inst): - verses[reg][vt][vn][inst] = [] - - words = self.tidy_text(line) - verses[reg][vt][vn][inst].append(words) + else: + if not [reg, vt, vn, inst] in our_verse_order: + our_verse_order.append([reg, vt, vn, inst]) + if not verses[reg].has_key(vt): + verses[reg][vt] = {} + if not verses[reg][vt].has_key(vn): + verses[reg][vt][vn] = {} + if not verses[reg][vt][vn].has_key(inst): + verses[reg][vt][vn][inst] = [] + words = self.tidy_text(line) + verses[reg][vt][vn][inst].append(words) # done parsing - + versetags = [] - # we use our_verse_order to ensure, we insert lyrics in the same order # as these appeared originally in the file for [reg, vt, vn, inst] in our_verse_order: @@ -308,7 +293,7 @@ class EasiSlidesImport(SongImport): versetags.append(versetag) lines = u'\n'.join(verses[reg][vt][vn][inst]) self.verses.append([versetag, lines]) - + SeqTypes = { u'p': u'P1', u'q': u'P2', @@ -340,7 +325,7 @@ class EasiSlidesImport(SongImport): self._success = False except AttributeError: pass - + def _listHas(self, lst, subitems): for i in subitems: if type(lst) == type({}) and lst.has_key(i): @@ -350,7 +335,7 @@ class EasiSlidesImport(SongImport): else: return False return True - + def _extractRegion(self, line): # this was true already: line[0:7] == u'[region': right_bracket = line.find(u']') diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 038eaa2a2..9e35c6204 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -134,3 +134,4 @@ SongFormat.set_availability(SongFormat.SongsOfFellowship, has_sof) SongFormat.set_availability(SongFormat.Generic, has_ooo) __all__ = [u'SongFormat'] + From ddcda85090c0f49de13767048fbc277f51759b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Tue, 18 Jan 2011 17:18:04 +0200 Subject: [PATCH 11/11] indentation fix, songbook number back to unicode, these sometimes contain letters like 104a --- openlp/plugins/songs/lib/easislidesimport.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 571f9d047..fac376134 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -112,8 +112,8 @@ class EasiSlidesImport(SongImport): def _add_number(self, song): try: - number = int(song.SongNumber) - if number != 0: + number = unicode(song.SongNumber) + if number != u'0': self.song_number = number except UnicodeDecodeError: log.exception(u'Unicode decode error while decoding SongNumber') @@ -206,8 +206,7 @@ class EasiSlidesImport(SongImport): # if the song has regions regions = (len(regionlines) > 0) # if the regions are inside verses - regionsInVerses = (regions and \ - regionlines[regionlines.keys()[0]] > 1) + regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1) MarkTypes = { u'CHORUS': u'C', u'VERSE': u'V',