From 237cabfeff8744971b7dd877cd6073025ccd9df1 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Fri, 15 Apr 2011 16:10:31 +0200 Subject: [PATCH 01/12] only try to import a database when it is a v1 database, clean ups --- openlp/plugins/songs/forms/songimportform.py | 5 +- openlp/plugins/songs/lib/olp1import.py | 4 +- openlp/plugins/songs/lib/songbeamerimport.py | 106 ++++++++++--------- 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 468d2f341..7666d8f52 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -459,10 +459,7 @@ class SongImportForm(OpenLPWizard): """ Return a list of file from the listbox """ - files = [] - for row in range(0, listbox.count()): - files.append(unicode(listbox.item(row).text())) - return files + return [unicode(listbox.item(i).text()) for i in range(listbox.count())] def removeSelectedItems(self, listbox): """ diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index 232b17db0..61cdcbe06 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -61,10 +61,12 @@ class OpenLP1SongImport(SongImport): """ Run the import for an openlp.org 1.x song database. """ - # Connect to the database + if not self.import_source.endswith(u'.olp'): + return False encoding = self.get_encoding() if not encoding: return False + # Connect to the database connection = sqlite.connect(self.import_source, mode=0444, encoding=(encoding, 'replace')) cursor = connection.cursor() diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 5cd2c4329..f90c05965 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -78,58 +78,60 @@ class SongBeamerImport(SongImport): """ Receive a single file or a list of files to import. """ - if isinstance(self.import_source, list): - self.import_wizard.progressBar.setMaximum( - len(self.import_source)) - for file in self.import_source: - # TODO: check that it is a valid SongBeamer file - self.set_defaults() - self.current_verse = u'' - self.current_verse_type = VerseType.Tags[VerseType.Verse] - read_verses = False - file_name = os.path.split(file)[1] - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name, 0) - if os.path.isfile(file): - detect_file = open(file, u'r') - details = chardet.detect(detect_file.read(2048)) - detect_file.close() - infile = codecs.open(file, u'r', details['encoding']) - songData = infile.readlines() - infile.close() - else: - return False - self.title = file_name.split('.sng')[0] - read_verses = False - for line in songData: - # Just make sure that the line is of the type 'Unicode'. - line = unicode(line).strip() - if line.startswith(u'#') and not read_verses: - self.parse_tags(line) - elif line.startswith(u'---'): - if self.current_verse: - self.replace_html_tags() - self.add_verse(self.current_verse, - self.current_verse_type) - self.current_verse = u'' - self.current_verse_type = VerseType.Tags[VerseType.Verse] - read_verses = True - verse_start = True - elif read_verses: - if verse_start: - verse_start = False - if not self.check_verse_marks(line): - self.current_verse = line + u'\n' - else: - self.current_verse += line + u'\n' - if self.current_verse: - self.replace_html_tags() - self.add_verse(self.current_verse, self.current_verse_type) - if self.check_complete(): - self.finish() - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name) - return True + self.import_wizard.progressBar.setMaximum(len(self.import_source)) + if not isinstance(self.import_source, list): + return False + for file in self.import_source: + # TODO: check that it is a valid SongBeamer file + if self.stop_import_flag: + return False + self.set_defaults() + self.current_verse = u'' + self.current_verse_type = VerseType.Tags[VerseType.Verse] + read_verses = False + file_name = os.path.split(file)[1] + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name, 0) + if os.path.isfile(file): + detect_file = open(file, u'r') + details = chardet.detect(detect_file.read(2048)) + detect_file.close() + infile = codecs.open(file, u'r', details['encoding']) + songData = infile.readlines() + infile.close() + else: + return False + self.title = file_name.split('.sng')[0] + read_verses = False + for line in songData: + # Just make sure that the line is of the type 'Unicode'. + line = unicode(line).strip() + if line.startswith(u'#') and not read_verses: + self.parse_tags(line) + elif line.startswith(u'---'): + if self.current_verse: + self.replace_html_tags() + self.add_verse(self.current_verse, + self.current_verse_type) + self.current_verse = u'' + self.current_verse_type = VerseType.Tags[VerseType.Verse] + read_verses = True + verse_start = True + elif read_verses: + if verse_start: + verse_start = False + if not self.check_verse_marks(line): + self.current_verse = line + u'\n' + else: + self.current_verse += line + u'\n' + if self.current_verse: + self.replace_html_tags() + self.add_verse(self.current_verse, self.current_verse_type) + if self.check_complete(): + self.finish() + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name) + return True def replace_html_tags(self): """ From a13cf4994078f0d9dbaa1410ce774ed879de436a Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Fri, 15 Apr 2011 18:01:15 +0200 Subject: [PATCH 02/12] idea to improve song import feedback --- openlp/core/ui/wizard.py | 1 + openlp/plugins/songs/forms/songimportform.py | 13 ++++++++----- openlp/plugins/songs/lib/cclifileimport.py | 1 - openlp/plugins/songs/lib/easislidesimport.py | 1 - openlp/plugins/songs/lib/ewimport.py | 3 ++- openlp/plugins/songs/lib/foilpresenterimport.py | 2 -- openlp/plugins/songs/lib/olp1import.py | 5 ++++- openlp/plugins/songs/lib/olpimport.py | 4 +++- openlp/plugins/songs/lib/oooimport.py | 9 ++------- openlp/plugins/songs/lib/openlyricsimport.py | 1 - openlp/plugins/songs/lib/opensongimport.py | 3 ++- openlp/plugins/songs/lib/sofimport.py | 2 +- openlp/plugins/songs/lib/songbeamerimport.py | 1 - openlp/plugins/songs/lib/songshowplusimport.py | 3 +-- openlp/plugins/songs/lib/wowimport.py | 1 - 15 files changed, 24 insertions(+), 26 deletions(-) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index cb3a75294..a27086b33 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -132,6 +132,7 @@ class OpenLPWizard(QtGui.QWizard): self.progressLayout.addWidget(self.progressLabel) self.progressBar = QtGui.QProgressBar(self.progressPage) self.progressBar.setObjectName(u'progressBar') + self.progressLabel.setWordWrap(True) self.progressLayout.addWidget(self.progressBar) self.addPage(self.progressPage) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 7666d8f52..786bbb960 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -740,12 +740,15 @@ class SongImportForm(OpenLPWizard): importer = self.plugin.importSongs(SongFormat.FoilPresenter, filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) - if importer.do_import(): - self.progressLabel.setText(WizardStrings.FinishedImport) - else: - self.progressLabel.setText( + message = importer.do_import() + if isinstance(message, bool) and not message: + self.progressLabel.setText(self.progressLabel.setText( translate('SongsPlugin.SongImportForm', - 'Your song import failed.')) + 'Your song import failed.'))) + elif not isinstance(message, bool) and message: + self.progressLabel.setText(message) + else: + self.progressLabel.setText(WizardStrings.FinishedImport) def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False, single_select=False): diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 03a86c455..c63a9fa98 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -93,7 +93,6 @@ class CCLIFileImport(SongImport): song_count += 1 if self.stop_import_flag: return False - return True def do_import_usr_file(self, textList): """ diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index d326e83ca..8ef6dc1a7 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -75,7 +75,6 @@ class EasiSlidesImport(SongImport): return False elif self.commit: self.finish() - return True def _parse_song(self, song): self._success = True diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index e68b19494..43be5bd07 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -273,7 +273,8 @@ class EasyWorshipSongImport(SongImport): self.import_wizard.incrementProgressBar(u'') db_file.close() self.memo_file.close() - return success + if not success: + return False def find_field(self, field_name): return [i for i, x in enumerate(self.field_descs) \ diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index 44ea56147..fef2bd41b 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -131,7 +131,6 @@ class FoilPresenterImport(SongImport): log.debug(u'File could not be imported: %s' % file_path) except etree.XMLSyntaxError: log.exception(u'XML syntax error in file %s' % file_path) - return True class FoilPresenter(object): @@ -235,7 +234,6 @@ class FoilPresenter(object): self._process_topics(foilpresenterfolie, song) clean_song(self.manager, song) self.manager.save_object(song) - return song.id def _child(self, element): """ diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index 61cdcbe06..b4995caed 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -32,6 +32,7 @@ import logging from chardet.universaldetector import UniversalDetector import sqlite +from openlp.core.lib import translate from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import retrieve_windows_encoding from songimport import SongImport @@ -62,7 +63,9 @@ class OpenLP1SongImport(SongImport): Run the import for an openlp.org 1.x song database. """ if not self.import_source.endswith(u'.olp'): - return False + return translate('SongsPlugin.OpenLP1SongImport', 'The file you ' + 'were trying to import is not a valid openlp.org 1.x song ' + 'database.') encoding = self.get_encoding() if not encoding: return False diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index e8b9f0dd7..4e0116198 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -100,6 +100,9 @@ class OpenLPSongImport(SongImport): """ Run the import for an OpenLP version 2 song database. """ + if not self.import_source.endswith(u'.sqlite'): + return translate('SongsPlugin.OpenLPSongImport', 'The file you were' + ' trying to import is not a valid OpenLP 2.0 song database.') engine = create_engine(self.import_source) source_meta = MetaData() source_meta.reflect(engine) @@ -217,4 +220,3 @@ class OpenLPSongImport(SongImport): if self.stop_import_flag: return False engine.dispose() - return True diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 2ab66820c..47cdace26 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -56,13 +56,11 @@ class OooImport(SongImport): self.process_started = False def do_import(self): - self.stop_import_flag = False - self.import_wizard.progressBar.setMaximum(0) self.start_ooo() + self.import_wizard.progressBar.setMaximum(self.import_source) for filename in self.import_source: if self.stop_import_flag: - self.import_wizard.incrementProgressBar(u'Import cancelled', 0) - return + return False filename = unicode(filename) if os.path.isfile(filename): self.open_ooo_file(filename) @@ -70,9 +68,6 @@ class OooImport(SongImport): self.process_ooo_document() self.close_ooo_file() self.close_ooo() - self.import_wizard.progressBar.setMaximum(1) - self.import_wizard.incrementProgressBar(u'', 1) - return True def process_ooo_document(self): """ diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index c29abc0b5..c72f1af89 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -71,4 +71,3 @@ class OpenLyricsImport(SongImport): log.debug(u'File could not be imported: %s' % file_path) except etree.XMLSyntaxError: log.exception(u'XML syntax error in file %s' % file_path) - return True diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 37fc2b5ef..a5798dc33 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -163,7 +163,8 @@ class OpenSongImport(SongImport): else: success = False break - return success + if not success: + return False def do_import_file(self, file): """ diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index 0b7e0c139..84955f33a 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -89,7 +89,7 @@ class SofImport(OooImport): while paragraphs.hasMoreElements(): if self.stop_import_flag: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) - return + return False paragraph = paragraphs.nextElement() if paragraph.supportsService("com.sun.star.text.Paragraph"): self.process_paragraph(paragraph) diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index f90c05965..fcfa2f44b 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -131,7 +131,6 @@ class SongBeamerImport(SongImport): self.finish() self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % file_name) - return True def replace_html_tags(self): """ diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index d5ab85f89..c7a6b6a3c 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -107,7 +107,7 @@ class SongShowPlusImport(SongImport): self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % file_name, 0) songData = open(file, 'rb') - while (1): + while True: blockKey, = struct.unpack("I", songData.read(4)) # The file ends with 4 NUL's if blockKey == 0: @@ -173,7 +173,6 @@ class SongShowPlusImport(SongImport): self.finish() self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % file_name) - return True def toOpenLPVerseTag(self, verseName, ignoreUnique=False): if verseName.find(" ") != -1: diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index cbdd40758..e6495a2b9 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -156,4 +156,3 @@ class WowImport(SongImport): self.finish() self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % file_name) - return True From 2d02f3e9a052469f117e349b7483310357b2c2c7 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 17 Apr 2011 17:47:02 +0200 Subject: [PATCH 03/12] --- openlp/plugins/songs/forms/songimportform.py | 14 +- openlp/plugins/songs/lib/cclifileimport.py | 18 +- openlp/plugins/songs/lib/easislidesimport.py | 36 ++-- openlp/plugins/songs/lib/ewimport.py | 23 +-- .../plugins/songs/lib/foilpresenterimport.py | 48 +++--- openlp/plugins/songs/lib/olp1import.py | 23 ++- openlp/plugins/songs/lib/olpimport.py | 12 +- openlp/plugins/songs/lib/oooimport.py | 2 +- openlp/plugins/songs/lib/openlyricsimport.py | 2 +- openlp/plugins/songs/lib/opensongimport.py | 47 ++---- openlp/plugins/songs/lib/sofimport.py | 3 +- openlp/plugins/songs/lib/songbeamerimport.py | 17 +- openlp/plugins/songs/lib/songimport.py | 23 +++ .../plugins/songs/lib/songshowplusimport.py | 154 +++++++++--------- 14 files changed, 209 insertions(+), 213 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4ee7d9fd8..3fc802ed9 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -740,13 +740,17 @@ class SongImportForm(OpenLPWizard): importer = self.plugin.importSongs(SongFormat.FoilPresenter, filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) - message = importer.do_import() - if isinstance(message, bool) and not message: + test = importer.do_import() + print test + if test is not None: + raise A + print importer.import_error_log + if importer.stop_import_flag: + print u'cancelled' + elif importer.import_error_log: self.progressLabel.setText(self.progressLabel.setText( translate('SongsPlugin.SongImportForm', 'Your song import failed.'))) - elif not isinstance(message, bool) and message: - self.progressLabel.setText(message) else: self.progressLabel.setText(WizardStrings.FinishedImport) @@ -836,4 +840,4 @@ class SongImportForm(OpenLPWizard): setattr(self, prefix + u'DisabledLayout', disabledLayout) setattr(self, prefix + u'DisabledLabel', disabledLabel) setattr(self, prefix + u'ImportWidget', importWidget) - return importWidget \ No newline at end of file + return importWidget diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index c63a9fa98..35e138a19 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -59,16 +59,10 @@ class CCLIFileImport(SongImport): Import either a ``.usr`` or a ``.txt`` SongSelect file. """ log.debug(u'Starting CCLI File Import') - song_total = len(self.import_source) - self.import_wizard.progressBar.setMaximum(song_total) - song_count = 1 + self.import_wizard.progressBar.setMaximum(len(self.import_source)) for filename in self.import_source: - self.import_wizard.incrementProgressBar(unicode(translate( - 'SongsPlugin.CCLIFileImport', 'Importing song %d of %d')) % - (song_count, song_total)) filename = unicode(filename) log.debug(u'Importing CCLI File: %s', filename) - self.set_defaults() lines = [] if os.path.isfile(filename): detect_file = open(filename, u'r') @@ -81,6 +75,7 @@ class CCLIFileImport(SongImport): detect_file.close() infile = codecs.open(filename, u'r', details['encoding']) lines = infile.readlines() + infile.close() ext = os.path.splitext(filename)[1] if ext.lower() == u'.usr': log.info(u'SongSelect .usr format file found: %s', filename) @@ -89,10 +84,12 @@ class CCLIFileImport(SongImport): log.info(u'SongSelect .txt format file found: %s', filename) self.do_import_txt_file(lines) else: + self.log_error(filename, + translate('SongsPlugin.CCLIFileImport', + 'The file does not have a valid extension.')) log.info(u'Extension %s is not valid', filename) - song_count += 1 if self.stop_import_flag: - return False + return def do_import_usr_file(self, textList): """ @@ -333,6 +330,5 @@ class CCLIFileImport(SongImport): if len(author_list) < 2: author_list = song_author.split(u'|') # Clean spaces before and after author names. - for author_name in author_list: - self.add_author(author_name.strip()) + [self.add_author(author_name.strip()) for author_name in author_list] self.finish() diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 8ef6dc1a7..f2b38c26e 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -26,11 +26,13 @@ import logging import os -from lxml import etree, objectify import re +from lxml import etree, objectify + from openlp.core.lib import translate from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) @@ -56,27 +58,19 @@ 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). """ - self.import_wizard.progressBar.setMaximum(1) log.info(u'Importing EasiSlides XML file %s', self.import_source) parser = etree.XMLParser(remove_blank_text=True) file = etree.parse(self.import_source, parser) xml = unicode(etree.tostring(file)) song_xml = objectify.fromstring(xml) - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % os.path.split(self.import_source)[-1]) self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) for song in song_xml.Item: - self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - u'Importing %s, song %s...')) % - (os.path.split(self.import_source)[-1], song.Title1)) - success = self._parse_song(song) - if not success or self.stop_import_flag: - return False - elif self.commit: - self.finish() + if self.stop_import_flag: + return + self._parse_song(song) def _parse_song(self, song): + self.set_defaults() self._success = True self._add_unicode_attribute(u'title', song.Title1, True) self._add_unicode_attribute(u'alternate_title', song.Title2) @@ -89,7 +83,8 @@ class EasiSlidesImport(SongImport): self._add_copyright(song.LicenceAdmin2) self._add_unicode_attribute(u'song_book_name', song.BookReference) self._parse_and_add_lyrics(song) - return self._success + if self._success: + self.finish() def _add_unicode_attribute(self, self_attribute, import_attribute, mandatory=False): @@ -187,12 +182,13 @@ 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', - u'INTRO': u'I', - u'ENDING': u'E', - u'BRIDGE': u'B', - u'PRECHORUS': u'P'} + u'CHORUS': VerseType.Tags[VerseType.Chorus], + u'VERSE': VerseType.Tags[VerseType.Verse], + u'INTRO': VerseType.Tags[VerseType.Intro], + u'ENDING': VerseType.Tags[VerseType.Ending], + u'BRIDGE': VerseType.Tags[VerseType.Bridge], + u'PRECHORUS': VerseType.Tags[VerseType.PreChorus] + } verses = {} # list as [region, versetype, versenum, instance] our_verse_order = [] diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 43be5bd07..66f6eec42 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -33,6 +33,7 @@ import struct from openlp.core.lib import translate from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import retrieve_windows_encoding from songimport import SongImport @@ -203,8 +204,8 @@ class EasyWorshipSongImport(SongImport): field_size)) self.set_record_struct(field_descs) # Pick out the field description indexes we will need - success = True try: + success = True fi_title = self.find_field(u'Title') fi_author = self.find_field(u'Author') fi_copy = self.find_field(u'Copyright') @@ -223,24 +224,18 @@ class EasyWorshipSongImport(SongImport): # Loop through each record within the current block for i in range(rec_count): if self.stop_import_flag: - success = False break raw_record = db_file.read(record_size) self.fields = self.record_struct.unpack(raw_record) self.set_defaults() - # Get title and update progress bar message - title = self.get_field(fi_title) - if title: - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % title, 0) - self.title = title - # Get remaining fields + self.title = self.get_field(fi_title) + # Get remaining fields. copy = self.get_field(fi_copy) admin = self.get_field(fi_admin) ccli = self.get_field(fi_ccli) authors = self.get_field(fi_author) words = self.get_field(fi_words) - # Set the SongImport object members + # Set the SongImport object members. if copy: self.copyright = copy if admin: @@ -264,17 +259,13 @@ class EasyWorshipSongImport(SongImport): # Format the lyrics words = strip_rtf(words, self.encoding) for verse in words.split(u'\n\n'): - self.add_verse(verse.strip(), u'V') + self.add_verse( + verse.strip(), VerseType.Tags[VerseType.Verse]) if self.stop_import_flag: - success = False break self.finish() - if not self.stop_import_flag: - self.import_wizard.incrementProgressBar(u'') db_file.close() self.memo_file.close() - if not success: - return False def find_field(self, field_name): return [i for i, x in enumerate(self.field_descs) \ diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index fef2bd41b..dd98bc415 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -121,7 +121,7 @@ class FoilPresenterImport(SongImport): parser = etree.XMLParser(remove_blank_text=True) for file_path in self.import_source: if self.stop_import_flag: - return False + return self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % os.path.basename(file_path)) try: @@ -303,9 +303,8 @@ class FoilPresenter(object): for marker in markers: copyright = re.compile(marker).sub(u'', copyright, re.U) copyright = re.compile(u'(?<=) *:').sub(u'', copyright) - i = 0 x = 0 - while i != 1: + while True: if copyright.find(u'') != -1: temp = copyright.partition(u'') if temp[0].strip() and x > 0: @@ -314,9 +313,9 @@ class FoilPresenter(object): x += 1 elif x > 0: strings.append(copyright) - i = 1 + break else: - i = 1 + break author_temp = [] for author in strings: temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', @@ -347,8 +346,8 @@ class FoilPresenter(object): if author is None: # We need to create a new author, as the author does not exist. author = Author.populate(display_name=display_name, - last_name = display_name.split(u' ')[-1], - first_name = u' '.join(display_name.split(u' ')[:-1])) + last_name=display_name.split(u' ')[-1], + first_name=u' '.join(display_name.split(u' ')[:-1])) self.manager.save_object(author) song.authors.append(author) @@ -412,8 +411,15 @@ class FoilPresenter(object): temp_verse_order_backup = [] temp_sortnr_backup = 1 temp_sortnr_liste = [] - versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1, - u'P': 1} + versenumber = { + VerseType.Tags[VerseType.Verse]: 1, + VerseType.Tags[VerseType.Chorus]: 1, + VerseType.Tags[VerseType.Bridge]: 1, + VerseType.Tags[VerseType.Ending]: 1, + VerseType.Tags[VerseType.Other]: 1, + VerseType.Tags[VerseType.Intro]: 1, + VerseType.Tags[VerseType.PreChorus]: 1 + } for strophe in foilpresenterfolie.strophen.strophe: text = self._child(strophe.text_) verse_name = self._child(strophe.key) @@ -432,25 +438,25 @@ class FoilPresenter(object): temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name) temp_verse_name = temp_verse_name[:3].lower() if temp_verse_name == u'ref': - verse_type = u'C' + verse_type = VerseType.Tags[VerseType.Chorus] elif temp_verse_name == u'r': - verse_type = u'C' + verse_type = VerseType.Tags[VerseType.Chorus] elif temp_verse_name == u'': - verse_type = u'V' + verse_type = VerseType.Tags[VerseType.Verse] elif temp_verse_name == u'v': - verse_type = u'V' + verse_type = VerseType.Tags[VerseType.Verse] elif temp_verse_name == u'bri': - verse_type = u'B' + verse_type = VerseType.Tags[VerseType.Bridge] elif temp_verse_name == u'cod': - verse_type = u'E' + verse_type = VerseType.Tags[VerseType.Ending] elif temp_verse_name == u'sch': - verse_type = u'E' + verse_type = VerseType.Tags[VerseType.Ending] elif temp_verse_name == u'pre': - verse_type = u'P' + verse_type = VerseType.Tags[VerseType.PreChorus] elif temp_verse_name == u'int': - verse_type = u'I' + verse_type = VerseType.Tags[VerseType.Intro] else: - verse_type = u'O' + verse_type = VerseType.Tags[VerseType.Other] verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name) # Foilpresenter allows e. g. "C", but we need "C1". if not verse_number: @@ -464,8 +470,8 @@ class FoilPresenter(object): verse_number = unicode(int(verse_number) + 1) verse_type_index = VerseType.from_tag(verse_type[0]) verse_type = VerseType.Names[verse_type_index] - temp_verse_order[verse_sortnr] = (u''.join((verse_type[0], - verse_number))) + temp_verse_order[verse_sortnr] = u''.join((verse_type[0], + verse_number)) temp_verse_order_backup.append(u''.join((verse_type[0], verse_number))) sxml.add_verse_to_lyrics(verse_type, verse_number, text) diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index b4995caed..765794d05 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -63,12 +63,18 @@ class OpenLP1SongImport(SongImport): Run the import for an openlp.org 1.x song database. """ if not self.import_source.endswith(u'.olp'): - return translate('SongsPlugin.OpenLP1SongImport', 'The file you ' + self.log_error(self.import_source, + translate('SongsPlugin.OpenLP1SongImport', 'The file you ' 'were trying to import is not a valid openlp.org 1.x song ' - 'database.') + 'database.')) + return encoding = self.get_encoding() if not encoding: - return False + self.log_error(self.import_source, + translate('SongsPlugin.OpenLP1SongImport', 'The file you ' + 'were trying to import is not a valid openlp.org 1.x song ' + 'database.')) + return # Connect to the database connection = sqlite.connect(self.import_source, mode=0444, encoding=(encoding, 'replace')) @@ -81,7 +87,6 @@ class OpenLP1SongImport(SongImport): cursor.execute(u'-- types int') cursor.execute(u'SELECT COUNT(songid) FROM songs') count = cursor.fetchone()[0] - success = True self.import_wizard.progressBar.setMaximum(count) # "cache" our list of authors cursor.execute(u'-- types int, unicode') @@ -100,7 +105,6 @@ class OpenLP1SongImport(SongImport): for song in songs: self.set_defaults() if self.stop_import_flag: - success = False break song_id = song[0] title = song[1] @@ -110,9 +114,7 @@ class OpenLP1SongImport(SongImport): WizardStrings.ImportingType % title) self.title = title verses = lyrics.split(u'\n\n') - for verse in verses: - if verse.strip() != u'': - self.add_verse(verse.strip()) + [self.add_verse(verse.strip()) for verse in verses if verse.strip()] self.add_copyright(copyright) cursor.execute(u'-- types int') cursor.execute(u'SELECT authorid FROM songauthors ' @@ -120,14 +122,12 @@ class OpenLP1SongImport(SongImport): author_ids = cursor.fetchall() for author_id in author_ids: if self.stop_import_flag: - success = False break for author in authors: if author[0] == author_id[0]: self.parse_author(author[1]) break if self.stop_import_flag: - success = False break if new_db: cursor.execute(u'-- types int') @@ -136,17 +136,14 @@ class OpenLP1SongImport(SongImport): track_ids = cursor.fetchall() for track_id in track_ids: if self.stop_import_flag: - success = False break for track in tracks: if track[0] == track_id[0]: self.add_media_file(track[1]) break if self.stop_import_flag: - success = False break self.finish() - return success def get_encoding(self): """ diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index 4e0116198..d89ba5c46 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -101,8 +101,10 @@ class OpenLPSongImport(SongImport): Run the import for an OpenLP version 2 song database. """ if not self.import_source.endswith(u'.sqlite'): - return translate('SongsPlugin.OpenLPSongImport', 'The file you were' - ' trying to import is not a valid OpenLP 2.0 song database.') + self.log_error(self.import_source, + translate('SongsPlugin.OpenLPSongImport', 'The file you were ' + 'trying to import is not a valid OpenLP 2.0 song database.')) + return engine = create_engine(self.import_source) source_meta = MetaData() source_meta.reflect(engine) @@ -127,10 +129,10 @@ class OpenLPSongImport(SongImport): mapper(OldMediaFile, source_media_files_table) song_props = { 'authors': relation(OldAuthor, backref='songs', - secondary=source_authors_songs_table), + secondary=source_authors_songs_table), 'book': relation(OldBook, backref='songs'), 'topics': relation(OldTopic, backref='songs', - secondary=source_songs_topics_table) + secondary=source_songs_topics_table) } if has_media_files: song_props['media_files'] = relation(OldMediaFile, backref='songs', @@ -218,5 +220,5 @@ class OpenLPSongImport(SongImport): self.manager.save_object(new_song) song_count += 1 if self.stop_import_flag: - return False + break engine.dispose() diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 47cdace26..3abc17a7a 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -60,7 +60,7 @@ class OooImport(SongImport): self.import_wizard.progressBar.setMaximum(self.import_source) for filename in self.import_source: if self.stop_import_flag: - return False + break filename = unicode(filename) if os.path.isfile(filename): self.open_ooo_file(filename) diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index c72f1af89..cf46d7449 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -59,7 +59,7 @@ class OpenLyricsImport(SongImport): parser = etree.XMLParser(remove_blank_text=True) for file_path in self.import_source: if self.stop_import_flag: - return False + return self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % os.path.basename(file_path)) try: diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index a5798dc33..aebb865b8 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -26,12 +26,14 @@ import logging import os +import re from zipfile import ZipFile + from lxml import objectify from lxml.etree import Error, LxmlError -import re from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) @@ -105,29 +107,26 @@ class OpenSongImport(SongImport): Initialise the class. """ SongImport.__init__(self, manager, **kwargs) - self.commit = True def do_import(self): """ Import either each of the files in self.import_source - each element of which can be either a single opensong file, or a zipfile containing - multiple opensong files. If `self.commit` is set False, the - import will not be committed to the database (useful for test scripts). + multiple opensong files. """ - success = True numfiles = 0 for filename in self.import_source: ext = os.path.splitext(filename)[1] if ext.lower() == u'.zip': z = ZipFile(filename, u'r') numfiles += len(z.infolist()) + z.close() else: numfiles += 1 log.debug(u'Total number of files: %d', numfiles) self.import_wizard.progressBar.setMaximum(numfiles) for filename in self.import_source: if self.stop_import_flag: - success = False break ext = os.path.splitext(filename)[1] if ext.lower() == u'.zip': @@ -135,48 +134,36 @@ class OpenSongImport(SongImport): z = ZipFile(filename, u'r') for song in z.infolist(): if self.stop_import_flag: - success = False break parts = os.path.split(song.filename) if parts[-1] == u'': - #No final part => directory + # No final part => directory continue log.info(u'Zip importing %s', parts[-1]) self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % parts[-1]) - songfile = z.open(song) - if self.do_import_file(songfile) and self.commit and \ - not self.stop_import_flag: - self.finish() - else: - success = False - break + song_file = z.open(song) + self.do_import_file(song_file) + song_file.close() + z.close() else: # not a zipfile log.info(u'Direct import %s', filename) self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % os.path.split(filename)[-1]) song_file = open(filename) - if self.do_import_file(song_file) and self.commit and \ - not self.stop_import_flag: - self.finish() - else: - success = False - break - if not success: - return False + self.do_import_file(song_file) + song_file.close() def do_import_file(self, file): """ - Process the OpenSong file - pass in a file-like object, - not a filename + Process the OpenSong file - pass in a file-like object, not a file path. """ self.set_defaults() try: tree = objectify.parse(file) except (Error, LxmlError): log.exception(u'Error parsing XML') - return False root = tree.getroot() fields = dir(root) decode = { @@ -196,7 +183,7 @@ class OpenSongImport(SongImport): fn_or_string(ustring) if not len(self.title): # to prevent creation of empty songs from wrong files - return False + return if u'theme' in fields and unicode(root.theme) not in self.topics: self.topics.append(unicode(root.theme)) if u'alttheme' in fields and unicode(root.alttheme) not in self.topics: @@ -206,7 +193,7 @@ class OpenSongImport(SongImport): # keep track of verses appearance order our_verse_order = [] # default verse - verse_tag = u'v' + verse_tag = VerseType.Tags[VerseType.Verse] verse_num = u'1' # for the case where song has several sections with same marker inst = 1 @@ -244,7 +231,7 @@ class OpenSongImport(SongImport): if [verse_tag, verse_num, inst] in our_verse_order \ and verses.has_key(verse_tag) \ and verses[verse_tag].has_key(verse_num): - inst = len(verses[verse_tag][verse_num])+1 + inst = len(verses[verse_tag][verse_num]) + 1 our_verse_order.append([verse_tag, verse_num, inst]) continue # number at start of line.. it's verse number @@ -293,4 +280,4 @@ class OpenSongImport(SongImport): else: log.info(u'Got order %s but not in verse tags, dropping' u'this item from presentation order', verse_def) - return True + self.finish() diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index 84955f33a..7f9fa16bc 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -88,8 +88,7 @@ class SofImport(OooImport): paragraphs = self.document.getText().createEnumeration() while paragraphs.hasMoreElements(): if self.stop_import_flag: - self.import_wizard.incrementProgressBar(u'Import cancelled', 0) - return False + return paragraph = paragraphs.nextElement() if paragraph.supportsService("com.sun.star.text.Paragraph"): self.process_paragraph(paragraph) diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index fcfa2f44b..be0fae589 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -33,7 +33,6 @@ import logging import os import re -from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport @@ -80,18 +79,16 @@ class SongBeamerImport(SongImport): """ self.import_wizard.progressBar.setMaximum(len(self.import_source)) if not isinstance(self.import_source, list): - return False + return for file in self.import_source: # TODO: check that it is a valid SongBeamer file if self.stop_import_flag: - return False + return self.set_defaults() self.current_verse = u'' self.current_verse_type = VerseType.Tags[VerseType.Verse] read_verses = False file_name = os.path.split(file)[1] - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name, 0) if os.path.isfile(file): detect_file = open(file, u'r') details = chardet.detect(detect_file.read(2048)) @@ -100,7 +97,7 @@ class SongBeamerImport(SongImport): songData = infile.readlines() infile.close() else: - return False + continue self.title = file_name.split('.sng')[0] read_verses = False for line in songData: @@ -127,10 +124,7 @@ class SongBeamerImport(SongImport): if self.current_verse: self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) - if self.check_complete(): - self.finish() - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name) + self.finish() def replace_html_tags(self): """ @@ -288,5 +282,4 @@ class SongBeamerImport(SongImport): if marks[1].isdigit(): self.current_verse_type += marks[1] return True - else: - return False + return False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 5bc1f15d0..87aa09bcb 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -29,6 +29,7 @@ import re from PyQt4 import QtCore from openlp.core.lib import Receiver, translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile from openlp.plugins.songs.lib.ui import SongStrings @@ -66,6 +67,7 @@ class SongImport(QtCore.QObject): self.song = None self.stop_import_flag = False self.set_defaults() + self.import_error_log = [] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) @@ -94,6 +96,21 @@ class SongImport(QtCore.QObject): self.copyright_string = unicode(translate( 'SongsPlugin.SongImport', 'copyright')) + def log_error(self, filepath, reason=None): + """ + This should be called, when a song could not be imported. + + ``filepath`` + This should be the file path if ``self.import_source`` is a list + with different files. If it is not a list, but a single file (for + instance a database), then this should be the song's title. + + ``reason`` + The reason, why the import failed. The string should be as + informative as possible. + """ + self.import_error_log.append((filepath, unicode(reason))) + def stop_import(self): """ Sets the flag for importers to stop their import @@ -249,9 +266,15 @@ class SongImport(QtCore.QObject): """ All fields have been set to this song. Write the song to disk. """ + if not self.check_complete(): + self.set_defaults() + return log.info(u'committing song %s to database', self.title) song = Song() song.title = self.title + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % song.title) + print WizardStrings.ImportingType song.alternate_title = self.alternate_title # Values will be set when cleaning the song. song.search_title = u'' diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index c7a6b6a3c..28f07ea31 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -32,6 +32,7 @@ import logging import struct from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport TITLE = 1 @@ -97,82 +98,83 @@ class SongShowPlusImport(SongImport): Receive a single file or a list of files to import. """ if isinstance(self.import_source, list): - self.import_wizard.progressBar.setMaximum(len(self.import_source)) - for file in self.import_source: - author = u'' - self.sspVerseOrderList = [] - otherCount = 0 - otherList = {} - file_name = os.path.split(file)[1] - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name, 0) - songData = open(file, 'rb') - while True: - blockKey, = struct.unpack("I", songData.read(4)) - # The file ends with 4 NUL's - if blockKey == 0: - break - nextBlockStarts, = struct.unpack("I", songData.read(4)) - if blockKey == VERSE or blockKey == CHORUS: - null, verseNo, = struct.unpack("BB", songData.read(2)) - elif blockKey == CUSTOM_VERSE: - null, verseNameLength, = struct.unpack("BB", - songData.read(2)) - verseName = songData.read(verseNameLength) - lengthDescriptorSize, = struct.unpack("B", songData.read(1)) - # Detect if/how long the length descriptor is - if lengthDescriptorSize == 12: - lengthDescriptor, = struct.unpack("I", songData.read(4)) - elif lengthDescriptorSize == 2: - lengthDescriptor = 1 - elif lengthDescriptorSize == 9: - lengthDescriptor = 0 - else: - lengthDescriptor, = struct.unpack("B", songData.read(1)) - data = songData.read(lengthDescriptor) - if blockKey == TITLE: - self.title = unicode(data, u'cp1252') - elif blockKey == AUTHOR: - authors = data.split(" / ") - for author in authors: - if author.find(",") !=-1: - authorParts = author.split(", ") - author = authorParts[1] + " " + authorParts[0] - self.parse_author(unicode(author, u'cp1252')) - elif blockKey == COPYRIGHT: - self.add_copyright(unicode(data, u'cp1252')) - elif blockKey == CCLI_NO: - self.ccli_number = int(data) - elif blockKey == VERSE: - self.add_verse(unicode(data, u'cp1252'), - "V%s" % verseNo) - elif blockKey == CHORUS: - self.add_verse(unicode(data, u'cp1252'), - "C%s" % verseNo) - elif blockKey == TOPIC: - self.topics.append(unicode(data, u'cp1252')) - elif blockKey == COMMENTS: - self.comments = unicode(data, u'cp1252') - elif blockKey == VERSE_ORDER: - verseTag = self.toOpenLPVerseTag(data, True) - if verseTag: - self.sspVerseOrderList.append(unicode(verseTag, - u'cp1252')) - elif blockKey == SONG_BOOK: - self.song_book_name = unicode(data, u'cp1252') - elif blockKey == SONG_NUMBER: - self.song_number = ord(data) - elif blockKey == CUSTOM_VERSE: - verseTag = self.toOpenLPVerseTag(verseName) - self.add_verse(unicode(data, u'cp1252'), verseTag) - else: - log.debug("Unrecognised blockKey: %s, data: %s" - %(blockKey, data)) - self.verse_order_list = self.sspVerseOrderList - songData.close() - self.finish() - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name) + return + self.import_wizard.progressBar.setMaximum(len(self.import_source)) + for file in self.import_source: + author = u'' + self.sspVerseOrderList = [] + otherCount = 0 + otherList = {} + file_name = os.path.split(file)[1] + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name, 0) + songData = open(file, 'rb') + while True: + blockKey, = struct.unpack("I", songData.read(4)) + # The file ends with 4 NUL's + if blockKey == 0: + break + nextBlockStarts, = struct.unpack("I", songData.read(4)) + if blockKey == VERSE or blockKey == CHORUS: + null, verseNo, = struct.unpack("BB", songData.read(2)) + elif blockKey == CUSTOM_VERSE: + null, verseNameLength, = struct.unpack("BB", + songData.read(2)) + verseName = songData.read(verseNameLength) + lengthDescriptorSize, = struct.unpack("B", songData.read(1)) + # Detect if/how long the length descriptor is + if lengthDescriptorSize == 12: + lengthDescriptor, = struct.unpack("I", songData.read(4)) + elif lengthDescriptorSize == 2: + lengthDescriptor = 1 + elif lengthDescriptorSize == 9: + lengthDescriptor = 0 + else: + lengthDescriptor, = struct.unpack("B", songData.read(1)) + data = songData.read(lengthDescriptor) + if blockKey == TITLE: + self.title = unicode(data, u'cp1252') + elif blockKey == AUTHOR: + authors = data.split(" / ") + for author in authors: + if author.find(",") !=-1: + authorParts = author.split(", ") + author = authorParts[1] + " " + authorParts[0] + self.parse_author(unicode(author, u'cp1252')) + elif blockKey == COPYRIGHT: + self.add_copyright(unicode(data, u'cp1252')) + elif blockKey == CCLI_NO: + self.ccli_number = int(data) + elif blockKey == VERSE: + self.add_verse(unicode(data, u'cp1252'), + "V%s" % verseNo) + elif blockKey == CHORUS: + self.add_verse(unicode(data, u'cp1252'), + "C%s" % verseNo) + elif blockKey == TOPIC: + self.topics.append(unicode(data, u'cp1252')) + elif blockKey == COMMENTS: + self.comments = unicode(data, u'cp1252') + elif blockKey == VERSE_ORDER: + verseTag = self.toOpenLPVerseTag(data, True) + if verseTag: + self.sspVerseOrderList.append(unicode(verseTag, + u'cp1252')) + elif blockKey == SONG_BOOK: + self.song_book_name = unicode(data, u'cp1252') + elif blockKey == SONG_NUMBER: + self.song_number = ord(data) + elif blockKey == CUSTOM_VERSE: + verseTag = self.toOpenLPVerseTag(verseName) + self.add_verse(unicode(data, u'cp1252'), verseTag) + else: + log.debug("Unrecognised blockKey: %s, data: %s" + %(blockKey, data)) + self.verse_order_list = self.sspVerseOrderList + songData.close() + self.finish() + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name) def toOpenLPVerseTag(self, verseName, ignoreUnique=False): if verseName.find(" ") != -1: From a530851124840e0f4d4547b5d85d3874b9afd882 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 18 Apr 2011 18:46:22 +0200 Subject: [PATCH 04/12] added error logger methods --- openlp/plugins/songs/forms/songimportform.py | 14 +++++--- openlp/plugins/songs/lib/cclifileimport.py | 10 +++--- openlp/plugins/songs/lib/easislidesimport.py | 12 +++---- openlp/plugins/songs/lib/ewimport.py | 3 +- .../plugins/songs/lib/foilpresenterimport.py | 3 ++ openlp/plugins/songs/lib/olp1import.py | 3 +- openlp/plugins/songs/lib/olpimport.py | 12 +++---- openlp/plugins/songs/lib/openlyricsimport.py | 3 ++ openlp/plugins/songs/lib/opensongimport.py | 11 +++--- openlp/plugins/songs/lib/songbeamerimport.py | 11 ++++-- openlp/plugins/songs/lib/songimport.py | 35 ++++++++++++++----- .../plugins/songs/lib/songshowplusimport.py | 22 +++++------- openlp/plugins/songs/lib/ui.py | 3 ++ openlp/plugins/songs/lib/wowimport.py | 24 +++++-------- 14 files changed, 97 insertions(+), 69 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 4986c26a4..e3b44237f 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -741,15 +741,19 @@ class SongImportForm(OpenLPWizard): filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) test = importer.do_import() + importer.write_error_report() if isinstance(test, bool): raise received_boolean if importer.stop_import_flag: - print importer.import_error_log - print u'cancelled' + self.progressLabel.setText(translate('SongsPlugin.SongImportForm', + 'Song import has been cancelled.')) elif importer.import_error_log: - self.progressLabel.setText(self.progressLabel.setText( - translate('SongsPlugin.SongImportForm', - 'Your song import failed.'))) + error_path = importer.write_error_report() + self.progressLabel.setTextInteractionFlags( + QtCore.Qt.TextSelectableByMouse) + self.progressLabel.setText(unicode(translate( + 'SongsPlugin.SongImportForm', 'Your song import failed. See ' + 'the error report for more details:\n%s')) % error_path) else: self.progressLabel.setText(WizardStrings.FinishedImport) diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 35e138a19..d304b0241 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -79,10 +79,12 @@ class CCLIFileImport(SongImport): ext = os.path.splitext(filename)[1] if ext.lower() == u'.usr': log.info(u'SongSelect .usr format file found: %s', filename) - self.do_import_usr_file(lines) + if not self.do_import_usr_file(lines): + self.log_error(filename) elif ext.lower() == u'.txt': log.info(u'SongSelect .txt format file found: %s', filename) - self.do_import_txt_file(lines) + if not self.do_import_txt_file(lines): + self.log_error(filename) else: self.log_error(filename, translate('SongsPlugin.CCLIFileImport', @@ -214,7 +216,7 @@ class CCLIFileImport(SongImport): else: self.add_author(author) self.topics = [topic.strip() for topic in song_topics.split(u'/t')] - self.finish() + return self.finish() def do_import_txt_file(self, textList): """ @@ -331,4 +333,4 @@ class CCLIFileImport(SongImport): author_list = song_author.split(u'|') # Clean spaces before and after author names. [self.add_author(author_name.strip()) for author_name in author_list] - self.finish() + return self.finish() diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index f2b38c26e..0c710377a 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -70,7 +70,6 @@ class EasiSlidesImport(SongImport): self._parse_song(song) def _parse_song(self, song): - self.set_defaults() self._success = True self._add_unicode_attribute(u'title', song.Title1, True) self._add_unicode_attribute(u'alternate_title', song.Title2) @@ -84,7 +83,10 @@ class EasiSlidesImport(SongImport): self._add_unicode_attribute(u'song_book_name', song.BookReference) self._parse_and_add_lyrics(song) if self._success: - self.finish() + if not self.finish(): + self.log_error(song.Title1 if song.Title1 else u'') + else: + self.set_defaults() def _add_unicode_attribute(self, self_attribute, import_attribute, mandatory=False): @@ -116,10 +118,8 @@ class EasiSlidesImport(SongImport): def _add_authors(self, song): try: authors = unicode(song.Writer).split(u',') - for author in authors: - author = author.strip() - if len(author): - self.authors.append(author) + self.authors = \ + [author.strip() for author in authors if author.strip()] except UnicodeDecodeError: log.exception(u'Unicode decode error while decoding Writer') self._success = False diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 66f6eec42..85a0b88c2 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -263,7 +263,8 @@ class EasyWorshipSongImport(SongImport): verse.strip(), VerseType.Tags[VerseType.Verse]) if self.stop_import_flag: break - self.finish() + if not self.finish(): + self.log_error(self.import_source) db_file.close() self.memo_file.close() diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index dd98bc415..dcbc4367d 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -97,6 +97,7 @@ from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.db import Author, Book, Song, Topic +from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.xml import SongXML log = logging.getLogger(__name__) @@ -128,8 +129,10 @@ class FoilPresenterImport(SongImport): parsed_file = etree.parse(file_path, parser) xml = unicode(etree.tostring(parsed_file)) if self.FoilPresenter.xml_to_song(xml) is None: + self.log_error(file_path, SongStrings.NoXML) log.debug(u'File could not be imported: %s' % file_path) except etree.XMLSyntaxError: + self.log_error(file_path, SongStrings.XMLSyntaxError) log.exception(u'XML syntax error in file %s' % file_path) diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index 765794d05..26fdf19a9 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -143,7 +143,8 @@ class OpenLP1SongImport(SongImport): break if self.stop_import_flag: break - self.finish() + if not self.finish(): + self.log_error(self.import_source) def get_encoding(self): """ diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index d89ba5c46..c69e5ded0 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -155,15 +155,9 @@ class OpenLPSongImport(SongImport): mapper(OldTopic, source_topics_table) source_songs = self.source_session.query(OldSong).all() - song_total = len(source_songs) if self.import_wizard: - self.import_wizard.progressBar.setMaximum(song_total) - song_count = 1 + self.import_wizard.progressBar.setMaximum(len(source_songs)) for song in source_songs: - if self.import_wizard: - self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.OpenLPSongImport', - 'Importing song %d of %d.')) % (song_count, song_total)) new_song = Song() new_song.title = song.title if has_media_files and hasattr(song, 'alternate_title'): @@ -218,7 +212,9 @@ class OpenLPSongImport(SongImport): # file_name=media_file.file_name)) clean_song(self.manager, new_song) self.manager.save_object(new_song) - song_count += 1 + if self.import_wizard: + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % new_song.title) if self.stop_import_flag: break engine.dispose() diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index cf46d7449..687a949af 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -35,6 +35,7 @@ from lxml import etree from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib import OpenLyrics log = logging.getLogger(__name__) @@ -69,5 +70,7 @@ class OpenLyricsImport(SongImport): xml = unicode(etree.tostring(parsed_file)) if self.openLyrics.xml_to_song(xml) is None: log.debug(u'File could not be imported: %s' % file_path) + self.log_error(file_path, SongStrings.NoXML) except etree.XMLSyntaxError: log.exception(u'XML syntax error in file %s' % file_path) + self.log_error(file_path, SongStrings.XMLSyntaxError) diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index aebb865b8..7cff1522f 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -35,6 +35,7 @@ from lxml.etree import Error, LxmlError from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) @@ -181,9 +182,6 @@ class OpenSongImport(SongImport): setattr(self, fn_or_string, ustring) else: fn_or_string(ustring) - if not len(self.title): - # to prevent creation of empty songs from wrong files - return if u'theme' in fields and unicode(root.theme) not in self.topics: self.topics.append(unicode(root.theme)) if u'alttheme' in fields and unicode(root.alttheme) not in self.topics: @@ -274,10 +272,11 @@ class OpenSongImport(SongImport): verse_tag = verse_def verse_num = u'1' verse_def = u'%s%s' % (verse_tag, verse_num) - if verses.has_key(verse_tag) \ - and verses[verse_tag].has_key(verse_num): + if verses.has_key(verse_tag) and \ + verses[verse_tag].has_key(verse_num): self.verse_order_list.append(verse_def) else: log.info(u'Got order %s but not in verse tags, dropping' u'this item from presentation order', verse_def) - self.finish() + if not self.finish(): + self.log_error(file.name) diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index be0fae589..2813240a4 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -35,6 +35,7 @@ import re from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) @@ -72,6 +73,11 @@ class SongBeamerImport(SongImport): Initialise the Song Beamer importer. """ SongImport.__init__(self, manager, **kwargs) + self.log_error(u'/home/andreas/1.sng', u'aaaa') + self.log_error(u'/home/andreas/4.sng', u'asdfsdfsadfds') + self.log_error(u'/home/andreas/3.sng', u'asdf3q4') + self.log_error(u'/home/andreas/2.sng', u'sadfasdf') + self.log_error(u'/home/andreas/ä.sng', u'kqwjw32w3') def do_import(self): """ @@ -124,7 +130,8 @@ class SongBeamerImport(SongImport): if self.current_verse: self.replace_html_tags() self.add_verse(self.current_verse, self.current_verse_type) - self.finish() + if not self.finish(): + self.log_error(file) def replace_html_tags(self): """ @@ -184,7 +191,7 @@ class SongBeamerImport(SongImport): elif tag_val[0] == u'#Bible': pass elif tag_val[0] == u'#Categories': - self.topics = line.split(',') + self.topics = tag_val[1].split(',') elif tag_val[0] == u'#CCLI': self.ccli_number = tag_val[1] elif tag_val[0] == u'#Chords': diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 87aa09bcb..80eebde43 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -23,13 +23,17 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +import codecs +import datetime import logging +import os import re + from PyQt4 import QtCore from openlp.core.lib import Receiver, translate from openlp.core.ui.wizard import WizardStrings +from openlp.core.utils import AppLocation from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile from openlp.plugins.songs.lib.ui import SongStrings @@ -67,7 +71,7 @@ class SongImport(QtCore.QObject): self.song = None self.stop_import_flag = False self.set_defaults() - self.import_error_log = [] + self.error_log = [] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) @@ -96,7 +100,7 @@ class SongImport(QtCore.QObject): self.copyright_string = unicode(translate( 'SongsPlugin.SongImport', 'copyright')) - def log_error(self, filepath, reason=None): + def log_error(self, filepath, reason=SongStrings.SongIncomplete): """ This should be called, when a song could not be imported. @@ -109,7 +113,22 @@ class SongImport(QtCore.QObject): The reason, why the import failed. The string should be as informative as possible. """ - self.import_error_log.append((filepath, unicode(reason))) + self.error_log.append((filepath, unicode(reason))) + + def write_error_report(self): + """ + Creates a error import containing all error messages. + """ + report_path = os.path.join(AppLocation.get_data_path(), unicode(translate( + 'SongsPlugin.SongImport','song_import_report (%s).txt')) % + datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S')) + report_file = codecs.open(report_path, u'w', u'utf-8') + report_file.write(translate('SongsPlugin.SongImport', + 'The following songs could not be imported:\n')) + for filepath, reason in self.error_log: + report_file.write(u'- %s (%s)\n' % (filepath, reason)) + report_file.close() + return report_path def stop_import(self): """ @@ -257,7 +276,7 @@ class SongImport(QtCore.QObject): Author not checked here, if no author then "Author unknown" is automatically added """ - if self.title == u'' or len(self.verses) == 0: + if not self.title or not len(self.verses): return False else: return True @@ -268,13 +287,12 @@ class SongImport(QtCore.QObject): """ if not self.check_complete(): self.set_defaults() - return + return False log.info(u'committing song %s to database', self.title) song = Song() song.title = self.title self.import_wizard.incrementProgressBar( WizardStrings.ImportingType % song.title) - print WizardStrings.ImportingType song.alternate_title = self.alternate_title # Values will be set when cleaning the song. song.search_title = u'' @@ -331,7 +349,7 @@ class SongImport(QtCore.QObject): publisher=self.song_book_pub) song.book = song_book for topictext in self.topics: - if len(topictext) == 0: + if not topictext: continue topic = self.manager.get_object_filtered(Topic, Topic.name == topictext) @@ -341,6 +359,7 @@ class SongImport(QtCore.QObject): clean_song(self.manager, song) self.manager.save_object(song) self.set_defaults() + return True def print_song(self): """ diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index 28f07ea31..27620d11a 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -169,12 +169,11 @@ class SongShowPlusImport(SongImport): self.add_verse(unicode(data, u'cp1252'), verseTag) else: log.debug("Unrecognised blockKey: %s, data: %s" - %(blockKey, data)) + % (blockKey, data)) self.verse_order_list = self.sspVerseOrderList songData.close() - self.finish() - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name) + if not self.finish(): + self.log_error(file) def toOpenLPVerseTag(self, verseName, ignoreUnique=False): if verseName.find(" ") != -1: @@ -186,22 +185,19 @@ class SongShowPlusImport(SongImport): verseNumber = "1" verseType = verseType.lower() if verseType == "verse": - verseTag = "V" + verseTag = VerseType.Tags[VerseType.Verse] elif verseType == "chorus": - verseTag = "C" + verseTag = VerseType.Tags[VerseType.Chorus] elif verseType == "bridge": - verseTag = "B" + verseTag = VerseType.Tags[VerseType.Bridge] elif verseType == "pre-chorus": - verseTag = "P" - elif verseType == "bridge": - verseTag = "B" + verseTag = VerseType.Tags[VerseType.PreChorus] else: if not self.otherList.has_key(verseName): if ignoreUnique: return None self.otherCount = self.otherCount + 1 self.otherList[verseName] = str(self.otherCount) - verseTag = "O" + verseTag = VerseType.Tags[VerseType.Other] verseNumber = self.otherList[verseName] - verseTag = verseTag + verseNumber - return verseTag + return verseTag + verseNumber diff --git a/openlp/plugins/songs/lib/ui.py b/openlp/plugins/songs/lib/ui.py index 0a389087e..e9dfd0f13 100644 --- a/openlp/plugins/songs/lib/ui.py +++ b/openlp/plugins/songs/lib/ui.py @@ -38,8 +38,11 @@ class SongStrings(object): Authors = translate('OpenLP.Ui', 'Authors', 'Plural') AuthorUnknown = u'Author Unknown' # Used to populate the database. CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.') + NoXML = translate('OpenLP.Ui', 'Song does not contain any XML') SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular') SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural') + SongIncomplete = translate('OpenLP.Ui','Title and/or verses not found') SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance') Topic = translate('OpenLP.Ui', 'Topic', 'Singular') Topics = translate('OpenLP.Ui', 'Topics', 'Plural') + XMLSyntaxError = translate('OpenLP.Ui', 'XML syntax error') diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index e6495a2b9..661e6787d 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -105,11 +105,7 @@ class WowImport(SongImport): if isinstance(self.import_source, list): self.import_wizard.progressBar.setMaximum(len(self.import_source)) for file in self.import_source: - author = u'' - copyright = u'' file_name = os.path.split(file)[1] - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name, 0) # Get the song title self.title = file_name.rpartition(u'.')[0] songData = open(file, 'rb') @@ -129,7 +125,7 @@ class WowImport(SongImport): self.line_text = unicode( songData.read(ord(songData.read(1))), u'cp1252') songData.seek(1, os.SEEK_CUR) - if block_text != u'': + if block_text: block_text += u'\n' block_text += self.line_text self.lines_to_read -= 1 @@ -143,16 +139,14 @@ class WowImport(SongImport): self.add_verse(block_text, block_type) # Now to extract the author author_length = ord(songData.read(1)) - if author_length != 0: - author = unicode(songData.read(author_length), u'cp1252') + if author_length: + self.parse_author( + unicode(songData.read(author_length), u'cp1252')) # Finally the copyright copyright_length = ord(songData.read(1)) - if copyright_length != 0: - copyright = unicode( - songData.read(copyright_length), u'cp1252') - self.parse_author(author) - self.add_copyright(copyright) + if copyright_length: + self.add_copyright(unicode( + songData.read(copyright_length), u'cp1252')) songData.close() - self.finish() - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % file_name) + if not self.finish(): + self.log_error(file) From 16fa78bbe32c12a3272240bf13ff36b9c4a21e31 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 18 Apr 2011 19:15:41 +0200 Subject: [PATCH 05/12] fixes --- openlp/plugins/songs/forms/songimportform.py | 3 +-- openlp/plugins/songs/lib/foilpresenterimport.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index e3b44237f..36fdf0181 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -741,13 +741,12 @@ class SongImportForm(OpenLPWizard): filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) test = importer.do_import() - importer.write_error_report() if isinstance(test, bool): raise received_boolean if importer.stop_import_flag: self.progressLabel.setText(translate('SongsPlugin.SongImportForm', 'Song import has been cancelled.')) - elif importer.import_error_log: + elif importer.error_log: error_path = importer.write_error_report() self.progressLabel.setTextInteractionFlags( QtCore.Qt.TextSelectableByMouse) diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index dcbc4367d..6f4164d17 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -237,6 +237,7 @@ class FoilPresenter(object): self._process_topics(foilpresenterfolie, song) clean_song(self.manager, song) self.manager.save_object(song) + return song.id def _child(self, element): """ From 757933c448480daa964e6944c42f996ee768adfc Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 18 Apr 2011 20:03:41 +0200 Subject: [PATCH 06/12] clean ups --- openlp/plugins/songs/forms/songimportform.py | 4 +--- openlp/plugins/songs/lib/ewimport.py | 14 +++++++------- openlp/plugins/songs/lib/olp1import.py | 10 ++++------ openlp/plugins/songs/lib/olpimport.py | 4 ++-- openlp/plugins/songs/lib/opensongimport.py | 4 ++-- openlp/plugins/songs/lib/songbeamerimport.py | 16 ++++++---------- openlp/plugins/songs/lib/songshowplusimport.py | 1 - openlp/plugins/songs/lib/wowimport.py | 2 +- 8 files changed, 23 insertions(+), 32 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 36fdf0181..73fa7c79d 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -740,9 +740,7 @@ class SongImportForm(OpenLPWizard): importer = self.plugin.importSongs(SongFormat.FoilPresenter, filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) - test = importer.do_import() - if isinstance(test, bool): - raise received_boolean + importer.do_import() if importer.stop_import_flag: self.progressLabel.setText(translate('SongsPlugin.SongImportForm', 'Song import has been cancelled.')) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 85a0b88c2..784558c5b 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -143,12 +143,12 @@ class EasyWorshipSongImport(SongImport): # Open the DB and MB files if they exist import_source_mb = self.import_source.replace('.DB', '.MB') if not os.path.isfile(self.import_source): - return False + return if not os.path.isfile(import_source_mb): - return False + return db_size = os.path.getsize(self.import_source) if db_size < 0x800: - return False + return db_file = open(self.import_source, 'rb') self.memo_file = open(import_source_mb, 'rb') # Don't accept files that are clearly not paradox files @@ -157,7 +157,7 @@ class EasyWorshipSongImport(SongImport): if header_size != 0x800 or block_size < 1 or block_size > 4: db_file.close() self.memo_file.close() - return False + return # Take a stab at how text is encoded self.encoding = u'cp1252' db_file.seek(106) @@ -184,7 +184,7 @@ class EasyWorshipSongImport(SongImport): self.encoding = u'cp874' self.encoding = retrieve_windows_encoding(self.encoding) if not self.encoding: - return False + return # There does not appear to be a _reliable_ way of getting the number # of songs/records, so let's use file blocks for measuring progress. total_blocks = (db_size - header_size) / (block_size * 1024) @@ -242,7 +242,7 @@ class EasyWorshipSongImport(SongImport): if copy: self.copyright += u', ' self.copyright += \ - unicode(translate('SongsPlugin.ImportWizardForm', + unicode(translate('SongsPlugin.EasyWorshipSongImport', 'Administered by %s')) % admin if ccli: self.ccli_number = ccli @@ -269,7 +269,7 @@ class EasyWorshipSongImport(SongImport): self.memo_file.close() def find_field(self, field_name): - return [i for i, x in enumerate(self.field_descs) \ + return [i for i, x in enumerate(self.field_descs) if x.name == field_name][0] def set_record_struct(self, field_descs): diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index 26fdf19a9..b282a8dd7 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -64,16 +64,14 @@ class OpenLP1SongImport(SongImport): """ if not self.import_source.endswith(u'.olp'): self.log_error(self.import_source, - translate('SongsPlugin.OpenLP1SongImport', 'The file you ' - 'were trying to import is not a valid openlp.org 1.x song ' - 'database.')) + translate('SongsPlugin.OpenLP1SongImport', + 'Not a valid openlp.org 1.x song database.')) return encoding = self.get_encoding() if not encoding: self.log_error(self.import_source, - translate('SongsPlugin.OpenLP1SongImport', 'The file you ' - 'were trying to import is not a valid openlp.org 1.x song ' - 'database.')) + translate('SongsPlugin.OpenLP1SongImport', + 'Not a valid openlp.org 1.x song database.')) return # Connect to the database connection = sqlite.connect(self.import_source, mode=0444, diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index c69e5ded0..bbfabce3e 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -102,8 +102,8 @@ class OpenLPSongImport(SongImport): """ if not self.import_source.endswith(u'.sqlite'): self.log_error(self.import_source, - translate('SongsPlugin.OpenLPSongImport', 'The file you were ' - 'trying to import is not a valid OpenLP 2.0 song database.')) + translate('SongsPlugin.OpenLPSongImport', + 'Not a valid OpenLP 2.0 song database.')) return engine = create_engine(self.import_source) source_meta = MetaData() diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 7cff1522f..acf672ca0 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -255,7 +255,7 @@ class OpenSongImport(SongImport): lines = u'\n'.join(verses[verse_tag][verse_num][inst]) self.add_verse(lines, verse_def) # figure out the presentation order, if present - if u'presentation' in fields and root.presentation != u'': + if u'presentation' in fields and root.presentation: order = unicode(root.presentation) # We make all the tags in the lyrics lower case, so match that here # and then split into a list on the whitespace @@ -266,7 +266,7 @@ class OpenSongImport(SongImport): verse_tag = match.group(1) verse_num = match.group(2) if not len(verse_tag): - verse_tag = u'v' + verse_tag = VerseType.Tags[VerseType.Verse] else: # Assume it's no.1 if there are no digits verse_tag = verse_def diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 2813240a4..5a8ee9ca8 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -73,11 +73,6 @@ class SongBeamerImport(SongImport): Initialise the Song Beamer importer. """ SongImport.__init__(self, manager, **kwargs) - self.log_error(u'/home/andreas/1.sng', u'aaaa') - self.log_error(u'/home/andreas/4.sng', u'asdfsdfsadfds') - self.log_error(u'/home/andreas/3.sng', u'asdf3q4') - self.log_error(u'/home/andreas/2.sng', u'sadfasdf') - self.log_error(u'/home/andreas/ä.sng', u'kqwjw32w3') def do_import(self): """ @@ -238,11 +233,12 @@ class SongBeamerImport(SongImport): pass elif tag_val[0] == u'#Rights': song_book_pub = tag_val[1] - elif tag_val[0] == u'#Songbook': - book_num = tag_val[1].split(' / ') - self.song_book_name = book_num[0] - if len(book_num) == book_num[1]: - self.song_number = u'' + elif tag_val[0] == u'#Songbook' or tag_val[0] == u'#SongBook': + book_data = tag_val[1].split(u'/') + self.song_book_name = book_data[0].strip() + if len(book_data) == 2: + number = book_data[1].strip() + self.song_number = number if number.isdigit() else u'' elif tag_val[0] == u'#Speed': pass elif tag_val[0] == u'Tempo': diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index 27620d11a..9fdc5804a 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -101,7 +101,6 @@ class SongShowPlusImport(SongImport): return self.import_wizard.progressBar.setMaximum(len(self.import_source)) for file in self.import_source: - author = u'' self.sspVerseOrderList = [] otherCount = 0 otherList = {} diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index 661e6787d..f5293a53c 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -134,7 +134,7 @@ class WowImport(SongImport): songData.seek(3, os.SEEK_CUR) # Blocks are seperated by 2 bytes, skip them, but not if # this is the last block! - if (block + 1) < no_of_blocks: + if block + 1 < no_of_blocks: songData.seek(2, os.SEEK_CUR) self.add_verse(block_text, block_type) # Now to extract the author From 6baefdadced3cc201e38cfeb6f6007e69080b5b2 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 18 Apr 2011 20:57:58 +0200 Subject: [PATCH 07/12] more fixes --- openlp/plugins/songs/forms/songimportform.py | 5 +---- openlp/plugins/songs/lib/olp1import.py | 18 +++--------------- openlp/plugins/songs/lib/olpimport.py | 1 + openlp/plugins/songs/lib/oooimport.py | 2 +- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 73fa7c79d..3d3421d8b 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -741,10 +741,7 @@ class SongImportForm(OpenLPWizard): filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) importer.do_import() - if importer.stop_import_flag: - self.progressLabel.setText(translate('SongsPlugin.SongImportForm', - 'Song import has been cancelled.')) - elif importer.error_log: + if importer.error_log: error_path = importer.write_error_report() self.progressLabel.setTextInteractionFlags( QtCore.Qt.TextSelectableByMouse) diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index b282a8dd7..7ba933a8f 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -33,7 +33,6 @@ from chardet.universaldetector import UniversalDetector import sqlite from openlp.core.lib import translate -from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import retrieve_windows_encoding from songimport import SongImport @@ -69,9 +68,6 @@ class OpenLP1SongImport(SongImport): return encoding = self.get_encoding() if not encoding: - self.log_error(self.import_source, - translate('SongsPlugin.OpenLP1SongImport', - 'Not a valid openlp.org 1.x song database.')) return # Connect to the database connection = sqlite.connect(self.import_source, mode=0444, @@ -81,11 +77,6 @@ class OpenLP1SongImport(SongImport): cursor.execute(u'SELECT name FROM sqlite_master ' u'WHERE type = \'table\' AND name = \'tracks\'') new_db = len(cursor.fetchall()) > 0 - # Count the number of records we need to import, for the progress bar - cursor.execute(u'-- types int') - cursor.execute(u'SELECT COUNT(songid) FROM songs') - count = cursor.fetchone()[0] - self.import_wizard.progressBar.setMaximum(count) # "cache" our list of authors cursor.execute(u'-- types int, unicode') cursor.execute(u'SELECT authorid, authorname FROM authors') @@ -100,20 +91,17 @@ class OpenLP1SongImport(SongImport): cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, ' u'copyrightinfo FROM songs') songs = cursor.fetchall() + self.import_wizard.progressBar.setMaximum(len(songs)) for song in songs: self.set_defaults() if self.stop_import_flag: break song_id = song[0] - title = song[1] + self.title = song[1] lyrics = song[2].replace(u'\r\n', u'\n') - copyright = song[3] - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % title) - self.title = title + self.add_copyright(song[3]) verses = lyrics.split(u'\n\n') [self.add_verse(verse.strip()) for verse in verses if verse.strip()] - self.add_copyright(copyright) cursor.execute(u'-- types int') cursor.execute(u'SELECT authorid FROM songauthors ' u'WHERE songid = %s' % song_id) diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index bbfabce3e..f17ac188b 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError from openlp.core.lib import translate from openlp.core.lib.db import BaseModel +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import clean_song from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile from songimport import SongImport diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 3abc17a7a..d43541bc7 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -57,7 +57,7 @@ class OooImport(SongImport): def do_import(self): self.start_ooo() - self.import_wizard.progressBar.setMaximum(self.import_source) + self.import_wizard.progressBar.setMaximum(len(self.import_source)) for filename in self.import_source: if self.stop_import_flag: break From 974a90a173f97454795f8b9176a0d4b8d4624f1c Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Mon, 18 Apr 2011 21:24:06 +0200 Subject: [PATCH 08/12] no xml raises XMLSyntaxError, that is why this is not needed --- openlp/plugins/songs/lib/foilpresenterimport.py | 7 ++----- openlp/plugins/songs/lib/openlyricsimport.py | 4 +--- openlp/plugins/songs/lib/ui.py | 1 - 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index 6f4164d17..0c7152bfd 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -128,9 +128,7 @@ class FoilPresenterImport(SongImport): try: parsed_file = etree.parse(file_path, parser) xml = unicode(etree.tostring(parsed_file)) - if self.FoilPresenter.xml_to_song(xml) is None: - self.log_error(file_path, SongStrings.NoXML) - log.debug(u'File could not be imported: %s' % file_path) + self.FoilPresenter.xml_to_song(xml) except etree.XMLSyntaxError: self.log_error(file_path, SongStrings.XMLSyntaxError) log.exception(u'XML syntax error in file %s' % file_path) @@ -213,7 +211,7 @@ class FoilPresenter(object): """ # No xml get out of here. if not xml: - return None + return if xml[:5] == u' Date: Tue, 19 Apr 2011 13:34:04 +0200 Subject: [PATCH 09/12] fixed OpenSong import --- openlp/plugins/songs/lib/opensongimport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index acf672ca0..fa20dfcac 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -164,7 +164,9 @@ class OpenSongImport(SongImport): try: tree = objectify.parse(file) except (Error, LxmlError): + self.log_error(file.name, SongStrings.XMLSyntaxError) log.exception(u'Error parsing XML') + return root = tree.getroot() fields = dir(root) decode = { From d45f93b5941f4bb4970d99d2ee1ef17a5263e9c4 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 19 Apr 2011 13:46:25 +0200 Subject: [PATCH 10/12] return where possible instead of breaking --- openlp/plugins/songs/lib/opensongimport.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index fa20dfcac..54b96043d 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -128,14 +128,15 @@ class OpenSongImport(SongImport): self.import_wizard.progressBar.setMaximum(numfiles) for filename in self.import_source: if self.stop_import_flag: - break + return ext = os.path.splitext(filename)[1] if ext.lower() == u'.zip': log.debug(u'Zipfile found %s', filename) z = ZipFile(filename, u'r') for song in z.infolist(): if self.stop_import_flag: - break + z.close() + return parts = os.path.split(song.filename) if parts[-1] == u'': # No final part => directory From 48d0d39a17d80911460ba579f53ed21073b400bf Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Tue, 19 Apr 2011 17:55:36 +0200 Subject: [PATCH 11/12] ask before creating an error report copy not imported files to a folder --- openlp/plugins/songs/forms/songimportform.py | 13 ++++++++++--- openlp/plugins/songs/lib/olpimport.py | 2 +- openlp/plugins/songs/lib/songimport.py | 12 ++++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 3d3421d8b..05de6c8a1 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -742,12 +742,19 @@ class SongImportForm(OpenLPWizard): ) importer.do_import() if importer.error_log: - error_path = importer.write_error_report() self.progressLabel.setTextInteractionFlags( QtCore.Qt.TextSelectableByMouse) + self.progressLabel.setText(translate( + 'SongsPlugin.SongImportForm', 'Your song import failed.')) + if critical_error_message_box(translate('SongsPlugin.SongImportForm', + 'Song import failed.'), translate('SongsPlugin.SongImportForm', + 'Your song import failed. Do you want to create an error ' + 'report?'), self, True) == QtGui.QMessageBox.No: + return + error_path = importer.write_error_report() self.progressLabel.setText(unicode(translate( - 'SongsPlugin.SongImportForm', 'Your song import failed. See ' - 'the error report for more details:\n%s')) % error_path) + 'SongsPlugin.SongImportForm', 'Your song import failed. ' + 'For more details see the error report:\n%s')) % error_path) else: self.progressLabel.setText(WizardStrings.FinishedImport) diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index f17ac188b..a201c1783 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -94,7 +94,6 @@ class OpenLPSongImport(SongImport): The database providing the data to import. """ SongImport.__init__(self, manager, **kwargs) - self.import_source = u'sqlite:///%s' % self.import_source self.source_session = None def do_import(self): @@ -106,6 +105,7 @@ class OpenLPSongImport(SongImport): translate('SongsPlugin.OpenLPSongImport', 'Not a valid OpenLP 2.0 song database.')) return + self.import_source = u'sqlite:///%s' % self.import_source engine = create_engine(self.import_source) source_meta = MetaData() source_meta.reflect(engine) diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 80eebde43..b8163fab6 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,10 +28,11 @@ import datetime import logging import os import re +import shutil from PyQt4 import QtCore -from openlp.core.lib import Receiver, translate +from openlp.core.lib import Receiver, translate, check_directory_exists from openlp.core.ui.wizard import WizardStrings from openlp.core.utils import AppLocation from openlp.plugins.songs.lib import clean_song, VerseType @@ -121,12 +122,19 @@ class SongImport(QtCore.QObject): """ report_path = os.path.join(AppLocation.get_data_path(), unicode(translate( 'SongsPlugin.SongImport','song_import_report (%s).txt')) % - datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S')) + datetime.datetime.now().strftime(u'%Y-%m-%d %H:%M:%S')) report_file = codecs.open(report_path, u'w', u'utf-8') report_file.write(translate('SongsPlugin.SongImport', 'The following songs could not be imported:\n')) for filepath, reason in self.error_log: report_file.write(u'- %s (%s)\n' % (filepath, reason)) + if not os.path.isfile(filepath): + continue + check_directory_exists(report_path[:-4]) + new_song_path = \ + os.path.join(report_path[:-4], os.path.basename(filepath)) + if not os.path.exists(new_song_path): + shutil.copyfile(filepath, new_song_path) report_file.close() return report_path From 8cd3742c874f1acdc829a7a9991bfdae53cd250f Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 20 Apr 2011 19:36:16 +0200 Subject: [PATCH 12/12] added textEdit and buttons for better feedback --- openlp/core/ui/wizard.py | 46 +++++++++++++++++++- openlp/plugins/songs/forms/songimportform.py | 39 ++++++++++++----- openlp/plugins/songs/lib/opensongimport.py | 5 --- openlp/plugins/songs/lib/songimport.py | 43 ++++++------------ 4 files changed, 86 insertions(+), 47 deletions(-) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index bc21c1295..9d1147638 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -95,6 +95,10 @@ class OpenLPWizard(QtGui.QWizard): self.customSignals() QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged) + QtCore.QObject.connect(self.errorCopyToButton, + QtCore.SIGNAL(u'clicked()'), self.onErrorCopyToButtonClicked) + QtCore.QObject.connect(self.errorSaveToButton, + QtCore.SIGNAL(u'clicked()'), self.onErrorSaveToButtonClicked) def setupUi(self, image): """ @@ -129,11 +133,36 @@ class OpenLPWizard(QtGui.QWizard): self.progressLayout.setObjectName(u'progressLayout') self.progressLabel = QtGui.QLabel(self.progressPage) self.progressLabel.setObjectName(u'progressLabel') + self.progressLabel.setWordWrap(True) self.progressLayout.addWidget(self.progressLabel) self.progressBar = QtGui.QProgressBar(self.progressPage) self.progressBar.setObjectName(u'progressBar') - self.progressLabel.setWordWrap(True) self.progressLayout.addWidget(self.progressBar) + # Add a QTextEdit and a copy to file and copy to clipboard button to be + # able to provide feedback to the user. Hidden by default. + self.errorReportTextEdit = QtGui.QTextEdit(self.progressPage) + self.errorReportTextEdit.setObjectName(u'progresserrorReportTextEdit') + self.errorReportTextEdit.setHidden(True) + self.errorReportTextEdit.setReadOnly(True) + self.progressLayout.addWidget(self.errorReportTextEdit) + self.errorButtonLayout = QtGui.QHBoxLayout() + self.errorButtonLayout.setObjectName(u'errorButtonLayout') + spacer = QtGui.QSpacerItem(40, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.errorButtonLayout.addItem(spacer) + self.errorCopyToButton = QtGui.QPushButton(self.progressPage) + self.errorCopyToButton.setObjectName(u'errorCopyToButton') + self.errorCopyToButton.setHidden(True) + self.errorCopyToButton.setIcon( + build_icon(u':/system/system_edit_copy.png')) + self.errorButtonLayout.addWidget(self.errorCopyToButton) + self.errorSaveToButton = QtGui.QPushButton(self.progressPage) + self.errorSaveToButton.setObjectName(u'errorSaveToButton') + self.errorSaveToButton.setHidden(True) + self.errorSaveToButton.setIcon( + build_icon(u':/general/general_save.png')) + self.errorButtonLayout.addWidget(self.errorSaveToButton) + self.progressLayout.addLayout(self.errorButtonLayout) self.addPage(self.progressPage) def exec_(self): @@ -161,6 +190,18 @@ class OpenLPWizard(QtGui.QWizard): self.performWizard() self.postWizard() + def onErrorCopyToButtonClicked(self): + """ + Called when the ``onErrorCopyToButtonClicked`` has been clicked. + """ + pass + + def onErrorSaveToButtonClicked(self): + """ + Called when the ``onErrorSaveToButtonClicked`` has been clicked. + """ + pass + def incrementProgressBar(self, status_text, increment=1): """ Update the wizard progress page. @@ -220,4 +261,5 @@ class OpenLPWizard(QtGui.QWizard): if filename: editbox.setText(filename) SettingsManager.set_last_dir(self.plugin.settingsSection, - filename, 1) \ No newline at end of file + filename, 1) + diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 05de6c8a1..8c5dbeb8a 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -26,6 +26,7 @@ """ The song import functions for OpenLP. """ +import codecs import logging import os @@ -55,6 +56,7 @@ class SongImportForm(OpenLPWizard): ``plugin`` The songs plugin. """ + self.clipboard = plugin.formparent.clipboard OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', u':/wizards/wizard_importsong.bmp') @@ -330,6 +332,10 @@ class SongImportForm(OpenLPWizard): 'Please wait while your songs are imported.')) self.progressLabel.setText(WizardStrings.Ready) self.progressBar.setFormat(WizardStrings.PercentSymbolFormat) + self.errorCopyToButton.setText(translate('SongsPlugin.ImportWizardForm', + 'Copy')) + self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm', + 'Save to File')) # Align all QFormLayouts towards each other. width = max(self.formatLabel.minimumSizeHint().width(), self.openLP2FilenameLabel.minimumSizeHint().width()) @@ -656,6 +662,10 @@ class SongImportForm(OpenLPWizard): self.songShowPlusFileListWidget.clear() self.foilPresenterFileListWidget.clear() #self.csvFilenameEdit.setText(u'') + self.errorReportTextEdit.clear() + self.errorReportTextEdit.setHidden(True) + self.errorCopyToButton.setHidden(True) + self.errorSaveToButton.setHidden(True) def preWizard(self): """ @@ -742,22 +752,29 @@ class SongImportForm(OpenLPWizard): ) importer.do_import() if importer.error_log: - self.progressLabel.setTextInteractionFlags( - QtCore.Qt.TextSelectableByMouse) self.progressLabel.setText(translate( 'SongsPlugin.SongImportForm', 'Your song import failed.')) - if critical_error_message_box(translate('SongsPlugin.SongImportForm', - 'Song import failed.'), translate('SongsPlugin.SongImportForm', - 'Your song import failed. Do you want to create an error ' - 'report?'), self, True) == QtGui.QMessageBox.No: - return - error_path = importer.write_error_report() - self.progressLabel.setText(unicode(translate( - 'SongsPlugin.SongImportForm', 'Your song import failed. ' - 'For more details see the error report:\n%s')) % error_path) else: self.progressLabel.setText(WizardStrings.FinishedImport) + def onErrorCopyToButtonClicked(self): + """ + Copy the error report to the clipboard. + """ + self.clipboard.setText(self.errorReportTextEdit.toPlainText()) + + def onErrorSaveToButtonClicked(self): + """ + Save the error report to a file. + """ + filename = QtGui.QFileDialog.getSaveFileName(self, + SettingsManager.get_last_dir(self.plugin.settingsSection, 1)) + if not filename: + return + file = codecs.open(filename, u'w', u'utf-8') + file.write(self.errorReportTextEdit.toPlainText()) + file.close() + def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False, single_select=False): if not obj_prefix: diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index 54b96043d..ab8f8c9fa 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -32,7 +32,6 @@ from zipfile import ZipFile from lxml import objectify from lxml.etree import Error, LxmlError -from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.ui import SongStrings @@ -142,8 +141,6 @@ class OpenSongImport(SongImport): # No final part => directory continue log.info(u'Zip importing %s', parts[-1]) - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % parts[-1]) song_file = z.open(song) self.do_import_file(song_file) song_file.close() @@ -151,8 +148,6 @@ class OpenSongImport(SongImport): else: # not a zipfile log.info(u'Direct import %s', filename) - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % os.path.split(filename)[-1]) song_file = open(filename) self.do_import_file(song_file) song_file.close() diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index b8163fab6..3c7ab8885 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -23,12 +23,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import codecs -import datetime import logging -import os import re -import shutil from PyQt4 import QtCore @@ -114,29 +110,17 @@ class SongImport(QtCore.QObject): The reason, why the import failed. The string should be as informative as possible. """ - self.error_log.append((filepath, unicode(reason))) - - def write_error_report(self): - """ - Creates a error import containing all error messages. - """ - report_path = os.path.join(AppLocation.get_data_path(), unicode(translate( - 'SongsPlugin.SongImport','song_import_report (%s).txt')) % - datetime.datetime.now().strftime(u'%Y-%m-%d %H:%M:%S')) - report_file = codecs.open(report_path, u'w', u'utf-8') - report_file.write(translate('SongsPlugin.SongImport', - 'The following songs could not be imported:\n')) - for filepath, reason in self.error_log: - report_file.write(u'- %s (%s)\n' % (filepath, reason)) - if not os.path.isfile(filepath): - continue - check_directory_exists(report_path[:-4]) - new_song_path = \ - os.path.join(report_path[:-4], os.path.basename(filepath)) - if not os.path.exists(new_song_path): - shutil.copyfile(filepath, new_song_path) - report_file.close() - return report_path + if self.import_wizard is None: + return + if self.import_wizard.errorReportTextEdit.isHidden(): + self.import_wizard.errorReportTextEdit.setText( + translate('SongsPlugin.SongImport', + 'The following songs could not be imported:')) + self.import_wizard.errorReportTextEdit.setVisible(True) + self.import_wizard.errorCopyToButton.setVisible(True) + self.import_wizard.errorSaveToButton.setVisible(True) + self.import_wizard.errorReportTextEdit.append( + u'- %s (%s)' % (filepath, reason)) def stop_import(self): """ @@ -299,8 +283,9 @@ class SongImport(QtCore.QObject): log.info(u'committing song %s to database', self.title) song = Song() song.title = self.title - self.import_wizard.incrementProgressBar( - WizardStrings.ImportingType % song.title) + if self.import_wizard is not None: + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % song.title) song.alternate_title = self.alternate_title # Values will be set when cleaning the song. song.search_title = u''