This commit is contained in:
Andreas Preikschat 2011-04-17 17:47:02 +02:00
parent 6fb421825c
commit 2d02f3e9a0
14 changed files with 209 additions and 213 deletions

View File

@ -740,13 +740,17 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.FoilPresenter, importer = self.plugin.importSongs(SongFormat.FoilPresenter,
filenames=self.getListOfFiles(self.foilPresenterFileListWidget) filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
) )
message = importer.do_import() test = importer.do_import()
if isinstance(message, bool) and not message: 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( self.progressLabel.setText(self.progressLabel.setText(
translate('SongsPlugin.SongImportForm', translate('SongsPlugin.SongImportForm',
'Your song import failed.'))) 'Your song import failed.')))
elif not isinstance(message, bool) and message:
self.progressLabel.setText(message)
else: else:
self.progressLabel.setText(WizardStrings.FinishedImport) self.progressLabel.setText(WizardStrings.FinishedImport)
@ -836,4 +840,4 @@ class SongImportForm(OpenLPWizard):
setattr(self, prefix + u'DisabledLayout', disabledLayout) setattr(self, prefix + u'DisabledLayout', disabledLayout)
setattr(self, prefix + u'DisabledLabel', disabledLabel) setattr(self, prefix + u'DisabledLabel', disabledLabel)
setattr(self, prefix + u'ImportWidget', importWidget) setattr(self, prefix + u'ImportWidget', importWidget)
return importWidget return importWidget

View File

@ -59,16 +59,10 @@ class CCLIFileImport(SongImport):
Import either a ``.usr`` or a ``.txt`` SongSelect file. Import either a ``.usr`` or a ``.txt`` SongSelect file.
""" """
log.debug(u'Starting CCLI File Import') log.debug(u'Starting CCLI File Import')
song_total = len(self.import_source) self.import_wizard.progressBar.setMaximum(len(self.import_source))
self.import_wizard.progressBar.setMaximum(song_total)
song_count = 1
for filename in 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) filename = unicode(filename)
log.debug(u'Importing CCLI File: %s', filename) log.debug(u'Importing CCLI File: %s', filename)
self.set_defaults()
lines = [] lines = []
if os.path.isfile(filename): if os.path.isfile(filename):
detect_file = open(filename, u'r') detect_file = open(filename, u'r')
@ -81,6 +75,7 @@ class CCLIFileImport(SongImport):
detect_file.close() detect_file.close()
infile = codecs.open(filename, u'r', details['encoding']) infile = codecs.open(filename, u'r', details['encoding'])
lines = infile.readlines() lines = infile.readlines()
infile.close()
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.usr': if ext.lower() == u'.usr':
log.info(u'SongSelect .usr format file found: %s', filename) 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) log.info(u'SongSelect .txt format file found: %s', filename)
self.do_import_txt_file(lines) self.do_import_txt_file(lines)
else: 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) log.info(u'Extension %s is not valid', filename)
song_count += 1
if self.stop_import_flag: if self.stop_import_flag:
return False return
def do_import_usr_file(self, textList): def do_import_usr_file(self, textList):
""" """
@ -333,6 +330,5 @@ class CCLIFileImport(SongImport):
if len(author_list) < 2: if len(author_list) < 2:
author_list = song_author.split(u'|') author_list = song_author.split(u'|')
# Clean spaces before and after author names. # Clean spaces before and after author names.
for author_name in author_list: [self.add_author(author_name.strip()) for author_name in author_list]
self.add_author(author_name.strip())
self.finish() self.finish()

View File

@ -26,11 +26,13 @@
import logging import logging
import os import os
from lxml import etree, objectify
import re import re
from lxml import etree, objectify
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings 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.songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -56,27 +58,19 @@ class EasiSlidesImport(SongImport):
multiple opensong files. If `self.commit` is set False, the multiple opensong files. If `self.commit` is set False, the
import will not be committed to the database (useful for test scripts). 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) log.info(u'Importing EasiSlides XML file %s', self.import_source)
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
file = etree.parse(self.import_source, parser) file = etree.parse(self.import_source, parser)
xml = unicode(etree.tostring(file)) xml = unicode(etree.tostring(file))
song_xml = objectify.fromstring(xml) 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)) self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
for song in song_xml.Item: for song in song_xml.Item:
self.import_wizard.incrementProgressBar( if self.stop_import_flag:
unicode(translate('SongsPlugin.ImportWizardForm', return
u'Importing %s, song %s...')) % self._parse_song(song)
(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()
def _parse_song(self, song): def _parse_song(self, song):
self.set_defaults()
self._success = True self._success = True
self._add_unicode_attribute(u'title', song.Title1, True) self._add_unicode_attribute(u'title', song.Title1, True)
self._add_unicode_attribute(u'alternate_title', song.Title2) self._add_unicode_attribute(u'alternate_title', song.Title2)
@ -89,7 +83,8 @@ class EasiSlidesImport(SongImport):
self._add_copyright(song.LicenceAdmin2) self._add_copyright(song.LicenceAdmin2)
self._add_unicode_attribute(u'song_book_name', song.BookReference) self._add_unicode_attribute(u'song_book_name', song.BookReference)
self._parse_and_add_lyrics(song) self._parse_and_add_lyrics(song)
return self._success if self._success:
self.finish()
def _add_unicode_attribute(self, self_attribute, import_attribute, def _add_unicode_attribute(self, self_attribute, import_attribute,
mandatory=False): mandatory=False):
@ -187,12 +182,13 @@ class EasiSlidesImport(SongImport):
# if the regions are inside verses # if the regions are inside verses
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1) regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
MarkTypes = { MarkTypes = {
u'CHORUS': u'C', u'CHORUS': VerseType.Tags[VerseType.Chorus],
u'VERSE': u'V', u'VERSE': VerseType.Tags[VerseType.Verse],
u'INTRO': u'I', u'INTRO': VerseType.Tags[VerseType.Intro],
u'ENDING': u'E', u'ENDING': VerseType.Tags[VerseType.Ending],
u'BRIDGE': u'B', u'BRIDGE': VerseType.Tags[VerseType.Bridge],
u'PRECHORUS': u'P'} u'PRECHORUS': VerseType.Tags[VerseType.PreChorus]
}
verses = {} verses = {}
# list as [region, versetype, versenum, instance] # list as [region, versetype, versenum, instance]
our_verse_order = [] our_verse_order = []

View File

@ -33,6 +33,7 @@ import struct
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib import retrieve_windows_encoding from openlp.plugins.songs.lib import retrieve_windows_encoding
from songimport import SongImport from songimport import SongImport
@ -203,8 +204,8 @@ class EasyWorshipSongImport(SongImport):
field_size)) field_size))
self.set_record_struct(field_descs) self.set_record_struct(field_descs)
# Pick out the field description indexes we will need # Pick out the field description indexes we will need
success = True
try: try:
success = True
fi_title = self.find_field(u'Title') fi_title = self.find_field(u'Title')
fi_author = self.find_field(u'Author') fi_author = self.find_field(u'Author')
fi_copy = self.find_field(u'Copyright') fi_copy = self.find_field(u'Copyright')
@ -223,24 +224,18 @@ class EasyWorshipSongImport(SongImport):
# Loop through each record within the current block # Loop through each record within the current block
for i in range(rec_count): for i in range(rec_count):
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
raw_record = db_file.read(record_size) raw_record = db_file.read(record_size)
self.fields = self.record_struct.unpack(raw_record) self.fields = self.record_struct.unpack(raw_record)
self.set_defaults() self.set_defaults()
# Get title and update progress bar message self.title = self.get_field(fi_title)
title = self.get_field(fi_title) # Get remaining fields.
if title:
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % title, 0)
self.title = title
# Get remaining fields
copy = self.get_field(fi_copy) copy = self.get_field(fi_copy)
admin = self.get_field(fi_admin) admin = self.get_field(fi_admin)
ccli = self.get_field(fi_ccli) ccli = self.get_field(fi_ccli)
authors = self.get_field(fi_author) authors = self.get_field(fi_author)
words = self.get_field(fi_words) words = self.get_field(fi_words)
# Set the SongImport object members # Set the SongImport object members.
if copy: if copy:
self.copyright = copy self.copyright = copy
if admin: if admin:
@ -264,17 +259,13 @@ class EasyWorshipSongImport(SongImport):
# Format the lyrics # Format the lyrics
words = strip_rtf(words, self.encoding) words = strip_rtf(words, self.encoding)
for verse in words.split(u'\n\n'): 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: if self.stop_import_flag:
success = False
break break
self.finish() self.finish()
if not self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'')
db_file.close() db_file.close()
self.memo_file.close() self.memo_file.close()
if not success:
return False
def find_field(self, field_name): 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) \

View File

@ -121,7 +121,7 @@ class FoilPresenterImport(SongImport):
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
for file_path in self.import_source: for file_path in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return False return
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.basename(file_path)) WizardStrings.ImportingType % os.path.basename(file_path))
try: try:
@ -303,9 +303,8 @@ class FoilPresenter(object):
for marker in markers: for marker in markers:
copyright = re.compile(marker).sub(u'<marker>', copyright, re.U) copyright = re.compile(marker).sub(u'<marker>', copyright, re.U)
copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright) copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright)
i = 0
x = 0 x = 0
while i != 1: while True:
if copyright.find(u'<marker>') != -1: if copyright.find(u'<marker>') != -1:
temp = copyright.partition(u'<marker>') temp = copyright.partition(u'<marker>')
if temp[0].strip() and x > 0: if temp[0].strip() and x > 0:
@ -314,9 +313,9 @@ class FoilPresenter(object):
x += 1 x += 1
elif x > 0: elif x > 0:
strings.append(copyright) strings.append(copyright)
i = 1 break
else: else:
i = 1 break
author_temp = [] author_temp = []
for author in strings: for author in strings:
temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);',
@ -347,8 +346,8 @@ class FoilPresenter(object):
if author is None: if author is None:
# We need to create a new author, as the author does not exist. # We need to create a new author, as the author does not exist.
author = Author.populate(display_name=display_name, author = Author.populate(display_name=display_name,
last_name = display_name.split(u' ')[-1], last_name=display_name.split(u' ')[-1],
first_name = u' '.join(display_name.split(u' ')[:-1])) first_name=u' '.join(display_name.split(u' ')[:-1]))
self.manager.save_object(author) self.manager.save_object(author)
song.authors.append(author) song.authors.append(author)
@ -412,8 +411,15 @@ class FoilPresenter(object):
temp_verse_order_backup = [] temp_verse_order_backup = []
temp_sortnr_backup = 1 temp_sortnr_backup = 1
temp_sortnr_liste = [] temp_sortnr_liste = []
versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1, versenumber = {
u'P': 1} 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: for strophe in foilpresenterfolie.strophen.strophe:
text = self._child(strophe.text_) text = self._child(strophe.text_)
verse_name = self._child(strophe.key) 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 = re.compile(u'[0-9].*').sub(u'', verse_name)
temp_verse_name = temp_verse_name[:3].lower() temp_verse_name = temp_verse_name[:3].lower()
if temp_verse_name == u'ref': if temp_verse_name == u'ref':
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif temp_verse_name == u'r': elif temp_verse_name == u'r':
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif temp_verse_name == u'': elif temp_verse_name == u'':
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif temp_verse_name == u'v': elif temp_verse_name == u'v':
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif temp_verse_name == u'bri': elif temp_verse_name == u'bri':
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
elif temp_verse_name == u'cod': elif temp_verse_name == u'cod':
verse_type = u'E' verse_type = VerseType.Tags[VerseType.Ending]
elif temp_verse_name == u'sch': elif temp_verse_name == u'sch':
verse_type = u'E' verse_type = VerseType.Tags[VerseType.Ending]
elif temp_verse_name == u'pre': elif temp_verse_name == u'pre':
verse_type = u'P' verse_type = VerseType.Tags[VerseType.PreChorus]
elif temp_verse_name == u'int': elif temp_verse_name == u'int':
verse_type = u'I' verse_type = VerseType.Tags[VerseType.Intro]
else: else:
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name) verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name)
# Foilpresenter allows e. g. "C", but we need "C1". # Foilpresenter allows e. g. "C", but we need "C1".
if not verse_number: if not verse_number:
@ -464,8 +470,8 @@ class FoilPresenter(object):
verse_number = unicode(int(verse_number) + 1) verse_number = unicode(int(verse_number) + 1)
verse_type_index = VerseType.from_tag(verse_type[0]) verse_type_index = VerseType.from_tag(verse_type[0])
verse_type = VerseType.Names[verse_type_index] verse_type = VerseType.Names[verse_type_index]
temp_verse_order[verse_sortnr] = (u''.join((verse_type[0], temp_verse_order[verse_sortnr] = u''.join((verse_type[0],
verse_number))) verse_number))
temp_verse_order_backup.append(u''.join((verse_type[0], temp_verse_order_backup.append(u''.join((verse_type[0],
verse_number))) verse_number)))
sxml.add_verse_to_lyrics(verse_type, verse_number, text) sxml.add_verse_to_lyrics(verse_type, verse_number, text)

View File

@ -63,12 +63,18 @@ class OpenLP1SongImport(SongImport):
Run the import for an openlp.org 1.x song database. Run the import for an openlp.org 1.x song database.
""" """
if not self.import_source.endswith(u'.olp'): 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 ' 'were trying to import is not a valid openlp.org 1.x song '
'database.') 'database.'))
return
encoding = self.get_encoding() encoding = self.get_encoding()
if not 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 # Connect to the database
connection = sqlite.connect(self.import_source, mode=0444, connection = sqlite.connect(self.import_source, mode=0444,
encoding=(encoding, 'replace')) encoding=(encoding, 'replace'))
@ -81,7 +87,6 @@ class OpenLP1SongImport(SongImport):
cursor.execute(u'-- types int') cursor.execute(u'-- types int')
cursor.execute(u'SELECT COUNT(songid) FROM songs') cursor.execute(u'SELECT COUNT(songid) FROM songs')
count = cursor.fetchone()[0] count = cursor.fetchone()[0]
success = True
self.import_wizard.progressBar.setMaximum(count) self.import_wizard.progressBar.setMaximum(count)
# "cache" our list of authors # "cache" our list of authors
cursor.execute(u'-- types int, unicode') cursor.execute(u'-- types int, unicode')
@ -100,7 +105,6 @@ class OpenLP1SongImport(SongImport):
for song in songs: for song in songs:
self.set_defaults() self.set_defaults()
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
song_id = song[0] song_id = song[0]
title = song[1] title = song[1]
@ -110,9 +114,7 @@ class OpenLP1SongImport(SongImport):
WizardStrings.ImportingType % title) WizardStrings.ImportingType % title)
self.title = title self.title = title
verses = lyrics.split(u'\n\n') verses = lyrics.split(u'\n\n')
for verse in verses: [self.add_verse(verse.strip()) for verse in verses if verse.strip()]
if verse.strip() != u'':
self.add_verse(verse.strip())
self.add_copyright(copyright) self.add_copyright(copyright)
cursor.execute(u'-- types int') cursor.execute(u'-- types int')
cursor.execute(u'SELECT authorid FROM songauthors ' cursor.execute(u'SELECT authorid FROM songauthors '
@ -120,14 +122,12 @@ class OpenLP1SongImport(SongImport):
author_ids = cursor.fetchall() author_ids = cursor.fetchall()
for author_id in author_ids: for author_id in author_ids:
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
for author in authors: for author in authors:
if author[0] == author_id[0]: if author[0] == author_id[0]:
self.parse_author(author[1]) self.parse_author(author[1])
break break
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
if new_db: if new_db:
cursor.execute(u'-- types int') cursor.execute(u'-- types int')
@ -136,17 +136,14 @@ class OpenLP1SongImport(SongImport):
track_ids = cursor.fetchall() track_ids = cursor.fetchall()
for track_id in track_ids: for track_id in track_ids:
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
for track in tracks: for track in tracks:
if track[0] == track_id[0]: if track[0] == track_id[0]:
self.add_media_file(track[1]) self.add_media_file(track[1])
break break
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
self.finish() self.finish()
return success
def get_encoding(self): def get_encoding(self):
""" """

View File

@ -101,8 +101,10 @@ class OpenLPSongImport(SongImport):
Run the import for an OpenLP version 2 song database. Run the import for an OpenLP version 2 song database.
""" """
if not self.import_source.endswith(u'.sqlite'): if not self.import_source.endswith(u'.sqlite'):
return translate('SongsPlugin.OpenLPSongImport', 'The file you were' self.log_error(self.import_source,
' trying to import is not a valid OpenLP 2.0 song database.') 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) engine = create_engine(self.import_source)
source_meta = MetaData() source_meta = MetaData()
source_meta.reflect(engine) source_meta.reflect(engine)
@ -127,10 +129,10 @@ class OpenLPSongImport(SongImport):
mapper(OldMediaFile, source_media_files_table) mapper(OldMediaFile, source_media_files_table)
song_props = { song_props = {
'authors': relation(OldAuthor, backref='songs', 'authors': relation(OldAuthor, backref='songs',
secondary=source_authors_songs_table), secondary=source_authors_songs_table),
'book': relation(OldBook, backref='songs'), 'book': relation(OldBook, backref='songs'),
'topics': relation(OldTopic, backref='songs', 'topics': relation(OldTopic, backref='songs',
secondary=source_songs_topics_table) secondary=source_songs_topics_table)
} }
if has_media_files: if has_media_files:
song_props['media_files'] = relation(OldMediaFile, backref='songs', song_props['media_files'] = relation(OldMediaFile, backref='songs',
@ -218,5 +220,5 @@ class OpenLPSongImport(SongImport):
self.manager.save_object(new_song) self.manager.save_object(new_song)
song_count += 1 song_count += 1
if self.stop_import_flag: if self.stop_import_flag:
return False break
engine.dispose() engine.dispose()

View File

@ -60,7 +60,7 @@ class OooImport(SongImport):
self.import_wizard.progressBar.setMaximum(self.import_source) self.import_wizard.progressBar.setMaximum(self.import_source)
for filename in self.import_source: for filename in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return False break
filename = unicode(filename) filename = unicode(filename)
if os.path.isfile(filename): if os.path.isfile(filename):
self.open_ooo_file(filename) self.open_ooo_file(filename)

View File

@ -59,7 +59,7 @@ class OpenLyricsImport(SongImport):
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
for file_path in self.import_source: for file_path in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return False return
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.basename(file_path)) WizardStrings.ImportingType % os.path.basename(file_path))
try: try:

View File

@ -26,12 +26,14 @@
import logging import logging
import os import os
import re
from zipfile import ZipFile from zipfile import ZipFile
from lxml import objectify from lxml import objectify
from lxml.etree import Error, LxmlError from lxml.etree import Error, LxmlError
import re
from openlp.core.ui.wizard import WizardStrings 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.songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -105,29 +107,26 @@ class OpenSongImport(SongImport):
Initialise the class. Initialise the class.
""" """
SongImport.__init__(self, manager, **kwargs) SongImport.__init__(self, manager, **kwargs)
self.commit = True
def do_import(self): def do_import(self):
""" """
Import either each of the files in self.import_source - each element of 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 which can be either a single opensong file, or a zipfile containing
multiple opensong files. If `self.commit` is set False, the multiple opensong files.
import will not be committed to the database (useful for test scripts).
""" """
success = True
numfiles = 0 numfiles = 0
for filename in self.import_source: for filename in self.import_source:
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.zip': if ext.lower() == u'.zip':
z = ZipFile(filename, u'r') z = ZipFile(filename, u'r')
numfiles += len(z.infolist()) numfiles += len(z.infolist())
z.close()
else: else:
numfiles += 1 numfiles += 1
log.debug(u'Total number of files: %d', numfiles) log.debug(u'Total number of files: %d', numfiles)
self.import_wizard.progressBar.setMaximum(numfiles) self.import_wizard.progressBar.setMaximum(numfiles)
for filename in self.import_source: for filename in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.zip': if ext.lower() == u'.zip':
@ -135,48 +134,36 @@ class OpenSongImport(SongImport):
z = ZipFile(filename, u'r') z = ZipFile(filename, u'r')
for song in z.infolist(): for song in z.infolist():
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
parts = os.path.split(song.filename) parts = os.path.split(song.filename)
if parts[-1] == u'': if parts[-1] == u'':
#No final part => directory # No final part => directory
continue continue
log.info(u'Zip importing %s', parts[-1]) log.info(u'Zip importing %s', parts[-1])
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % parts[-1]) WizardStrings.ImportingType % parts[-1])
songfile = z.open(song) song_file = z.open(song)
if self.do_import_file(songfile) and self.commit and \ self.do_import_file(song_file)
not self.stop_import_flag: song_file.close()
self.finish() z.close()
else:
success = False
break
else: else:
# not a zipfile # not a zipfile
log.info(u'Direct import %s', filename) log.info(u'Direct import %s', filename)
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.split(filename)[-1]) WizardStrings.ImportingType % os.path.split(filename)[-1])
song_file = open(filename) song_file = open(filename)
if self.do_import_file(song_file) and self.commit and \ self.do_import_file(song_file)
not self.stop_import_flag: song_file.close()
self.finish()
else:
success = False
break
if not success:
return False
def do_import_file(self, file): def do_import_file(self, file):
""" """
Process the OpenSong file - pass in a file-like object, Process the OpenSong file - pass in a file-like object, not a file path.
not a filename
""" """
self.set_defaults() self.set_defaults()
try: try:
tree = objectify.parse(file) tree = objectify.parse(file)
except (Error, LxmlError): except (Error, LxmlError):
log.exception(u'Error parsing XML') log.exception(u'Error parsing XML')
return False
root = tree.getroot() root = tree.getroot()
fields = dir(root) fields = dir(root)
decode = { decode = {
@ -196,7 +183,7 @@ class OpenSongImport(SongImport):
fn_or_string(ustring) fn_or_string(ustring)
if not len(self.title): if not len(self.title):
# to prevent creation of empty songs from wrong files # 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: if u'theme' in fields and unicode(root.theme) not in self.topics:
self.topics.append(unicode(root.theme)) self.topics.append(unicode(root.theme))
if u'alttheme' in fields and unicode(root.alttheme) not in self.topics: if u'alttheme' in fields and unicode(root.alttheme) not in self.topics:
@ -206,7 +193,7 @@ class OpenSongImport(SongImport):
# keep track of verses appearance order # keep track of verses appearance order
our_verse_order = [] our_verse_order = []
# default verse # default verse
verse_tag = u'v' verse_tag = VerseType.Tags[VerseType.Verse]
verse_num = u'1' verse_num = u'1'
# for the case where song has several sections with same marker # for the case where song has several sections with same marker
inst = 1 inst = 1
@ -244,7 +231,7 @@ class OpenSongImport(SongImport):
if [verse_tag, verse_num, inst] in our_verse_order \ if [verse_tag, verse_num, inst] in our_verse_order \
and verses.has_key(verse_tag) \ and verses.has_key(verse_tag) \
and verses[verse_tag].has_key(verse_num): 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]) our_verse_order.append([verse_tag, verse_num, inst])
continue continue
# number at start of line.. it's verse number # number at start of line.. it's verse number
@ -293,4 +280,4 @@ class OpenSongImport(SongImport):
else: else:
log.info(u'Got order %s but not in verse tags, dropping' log.info(u'Got order %s but not in verse tags, dropping'
u'this item from presentation order', verse_def) u'this item from presentation order', verse_def)
return True self.finish()

View File

@ -88,8 +88,7 @@ class SofImport(OooImport):
paragraphs = self.document.getText().createEnumeration() paragraphs = self.document.getText().createEnumeration()
while paragraphs.hasMoreElements(): while paragraphs.hasMoreElements():
if self.stop_import_flag: if self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return
return False
paragraph = paragraphs.nextElement() paragraph = paragraphs.nextElement()
if paragraph.supportsService("com.sun.star.text.Paragraph"): if paragraph.supportsService("com.sun.star.text.Paragraph"):
self.process_paragraph(paragraph) self.process_paragraph(paragraph)

View File

@ -33,7 +33,6 @@ import logging
import os import os
import re import re
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
@ -80,18 +79,16 @@ class SongBeamerImport(SongImport):
""" """
self.import_wizard.progressBar.setMaximum(len(self.import_source)) self.import_wizard.progressBar.setMaximum(len(self.import_source))
if not isinstance(self.import_source, list): if not isinstance(self.import_source, list):
return False return
for file in self.import_source: for file in self.import_source:
# TODO: check that it is a valid SongBeamer file # TODO: check that it is a valid SongBeamer file
if self.stop_import_flag: if self.stop_import_flag:
return False return
self.set_defaults() self.set_defaults()
self.current_verse = u'' self.current_verse = u''
self.current_verse_type = VerseType.Tags[VerseType.Verse] self.current_verse_type = VerseType.Tags[VerseType.Verse]
read_verses = False read_verses = False
file_name = os.path.split(file)[1] file_name = os.path.split(file)[1]
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name, 0)
if os.path.isfile(file): if os.path.isfile(file):
detect_file = open(file, u'r') detect_file = open(file, u'r')
details = chardet.detect(detect_file.read(2048)) details = chardet.detect(detect_file.read(2048))
@ -100,7 +97,7 @@ class SongBeamerImport(SongImport):
songData = infile.readlines() songData = infile.readlines()
infile.close() infile.close()
else: else:
return False continue
self.title = file_name.split('.sng')[0] self.title = file_name.split('.sng')[0]
read_verses = False read_verses = False
for line in songData: for line in songData:
@ -127,10 +124,7 @@ class SongBeamerImport(SongImport):
if self.current_verse: if self.current_verse:
self.replace_html_tags() self.replace_html_tags()
self.add_verse(self.current_verse, self.current_verse_type) self.add_verse(self.current_verse, self.current_verse_type)
if self.check_complete(): self.finish()
self.finish()
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name)
def replace_html_tags(self): def replace_html_tags(self):
""" """
@ -288,5 +282,4 @@ class SongBeamerImport(SongImport):
if marks[1].isdigit(): if marks[1].isdigit():
self.current_verse_type += marks[1] self.current_verse_type += marks[1]
return True return True
else: return False
return False

View File

@ -29,6 +29,7 @@ import re
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate 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 import clean_song, VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
@ -66,6 +67,7 @@ class SongImport(QtCore.QObject):
self.song = None self.song = None
self.stop_import_flag = False self.stop_import_flag = False
self.set_defaults() self.set_defaults()
self.import_error_log = []
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
@ -94,6 +96,21 @@ class SongImport(QtCore.QObject):
self.copyright_string = unicode(translate( self.copyright_string = unicode(translate(
'SongsPlugin.SongImport', 'copyright')) '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): def stop_import(self):
""" """
Sets the flag for importers to stop their import 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. 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) log.info(u'committing song %s to database', self.title)
song = Song() song = Song()
song.title = self.title song.title = self.title
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % song.title)
print WizardStrings.ImportingType
song.alternate_title = self.alternate_title song.alternate_title = self.alternate_title
# Values will be set when cleaning the song. # Values will be set when cleaning the song.
song.search_title = u'' song.search_title = u''

View File

@ -32,6 +32,7 @@ import logging
import struct import struct
from openlp.core.ui.wizard import WizardStrings 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.songimport import SongImport
TITLE = 1 TITLE = 1
@ -97,82 +98,83 @@ class SongShowPlusImport(SongImport):
Receive a single file or a list of files to import. Receive a single file or a list of files to import.
""" """
if isinstance(self.import_source, list): if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(len(self.import_source)) return
for file in self.import_source: self.import_wizard.progressBar.setMaximum(len(self.import_source))
author = u'' for file in self.import_source:
self.sspVerseOrderList = [] author = u''
otherCount = 0 self.sspVerseOrderList = []
otherList = {} otherCount = 0
file_name = os.path.split(file)[1] otherList = {}
self.import_wizard.incrementProgressBar( file_name = os.path.split(file)[1]
WizardStrings.ImportingType % file_name, 0) self.import_wizard.incrementProgressBar(
songData = open(file, 'rb') WizardStrings.ImportingType % file_name, 0)
while True: songData = open(file, 'rb')
blockKey, = struct.unpack("I", songData.read(4)) while True:
# The file ends with 4 NUL's blockKey, = struct.unpack("I", songData.read(4))
if blockKey == 0: # The file ends with 4 NUL's
break if blockKey == 0:
nextBlockStarts, = struct.unpack("I", songData.read(4)) break
if blockKey == VERSE or blockKey == CHORUS: nextBlockStarts, = struct.unpack("I", songData.read(4))
null, verseNo, = struct.unpack("BB", songData.read(2)) if blockKey == VERSE or blockKey == CHORUS:
elif blockKey == CUSTOM_VERSE: null, verseNo, = struct.unpack("BB", songData.read(2))
null, verseNameLength, = struct.unpack("BB", elif blockKey == CUSTOM_VERSE:
songData.read(2)) null, verseNameLength, = struct.unpack("BB",
verseName = songData.read(verseNameLength) songData.read(2))
lengthDescriptorSize, = struct.unpack("B", songData.read(1)) verseName = songData.read(verseNameLength)
# Detect if/how long the length descriptor is lengthDescriptorSize, = struct.unpack("B", songData.read(1))
if lengthDescriptorSize == 12: # Detect if/how long the length descriptor is
lengthDescriptor, = struct.unpack("I", songData.read(4)) if lengthDescriptorSize == 12:
elif lengthDescriptorSize == 2: lengthDescriptor, = struct.unpack("I", songData.read(4))
lengthDescriptor = 1 elif lengthDescriptorSize == 2:
elif lengthDescriptorSize == 9: lengthDescriptor = 1
lengthDescriptor = 0 elif lengthDescriptorSize == 9:
else: lengthDescriptor = 0
lengthDescriptor, = struct.unpack("B", songData.read(1)) else:
data = songData.read(lengthDescriptor) lengthDescriptor, = struct.unpack("B", songData.read(1))
if blockKey == TITLE: data = songData.read(lengthDescriptor)
self.title = unicode(data, u'cp1252') if blockKey == TITLE:
elif blockKey == AUTHOR: self.title = unicode(data, u'cp1252')
authors = data.split(" / ") elif blockKey == AUTHOR:
for author in authors: authors = data.split(" / ")
if author.find(",") !=-1: for author in authors:
authorParts = author.split(", ") if author.find(",") !=-1:
author = authorParts[1] + " " + authorParts[0] authorParts = author.split(", ")
self.parse_author(unicode(author, u'cp1252')) author = authorParts[1] + " " + authorParts[0]
elif blockKey == COPYRIGHT: self.parse_author(unicode(author, u'cp1252'))
self.add_copyright(unicode(data, u'cp1252')) elif blockKey == COPYRIGHT:
elif blockKey == CCLI_NO: self.add_copyright(unicode(data, u'cp1252'))
self.ccli_number = int(data) elif blockKey == CCLI_NO:
elif blockKey == VERSE: self.ccli_number = int(data)
self.add_verse(unicode(data, u'cp1252'), elif blockKey == VERSE:
"V%s" % verseNo) self.add_verse(unicode(data, u'cp1252'),
elif blockKey == CHORUS: "V%s" % verseNo)
self.add_verse(unicode(data, u'cp1252'), elif blockKey == CHORUS:
"C%s" % verseNo) self.add_verse(unicode(data, u'cp1252'),
elif blockKey == TOPIC: "C%s" % verseNo)
self.topics.append(unicode(data, u'cp1252')) elif blockKey == TOPIC:
elif blockKey == COMMENTS: self.topics.append(unicode(data, u'cp1252'))
self.comments = unicode(data, u'cp1252') elif blockKey == COMMENTS:
elif blockKey == VERSE_ORDER: self.comments = unicode(data, u'cp1252')
verseTag = self.toOpenLPVerseTag(data, True) elif blockKey == VERSE_ORDER:
if verseTag: verseTag = self.toOpenLPVerseTag(data, True)
self.sspVerseOrderList.append(unicode(verseTag, if verseTag:
u'cp1252')) self.sspVerseOrderList.append(unicode(verseTag,
elif blockKey == SONG_BOOK: u'cp1252'))
self.song_book_name = unicode(data, u'cp1252') elif blockKey == SONG_BOOK:
elif blockKey == SONG_NUMBER: self.song_book_name = unicode(data, u'cp1252')
self.song_number = ord(data) elif blockKey == SONG_NUMBER:
elif blockKey == CUSTOM_VERSE: self.song_number = ord(data)
verseTag = self.toOpenLPVerseTag(verseName) elif blockKey == CUSTOM_VERSE:
self.add_verse(unicode(data, u'cp1252'), verseTag) verseTag = self.toOpenLPVerseTag(verseName)
else: self.add_verse(unicode(data, u'cp1252'), verseTag)
log.debug("Unrecognised blockKey: %s, data: %s" else:
%(blockKey, data)) log.debug("Unrecognised blockKey: %s, data: %s"
self.verse_order_list = self.sspVerseOrderList %(blockKey, data))
songData.close() self.verse_order_list = self.sspVerseOrderList
self.finish() songData.close()
self.import_wizard.incrementProgressBar( self.finish()
WizardStrings.ImportingType % file_name) self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name)
def toOpenLPVerseTag(self, verseName, ignoreUnique=False): def toOpenLPVerseTag(self, verseName, ignoreUnique=False):
if verseName.find(" ") != -1: if verseName.find(" ") != -1: