From 8d6d2b8272481470315761c0369f69b282f51f8b Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Thu, 1 Apr 2010 00:06:57 +0100 Subject: [PATCH 1/4] standalone sof test script --- openlp/plugins/songs/lib/sofimport.py | 504 ++++++++++++++++++++++++++ 1 file changed, 504 insertions(+) create mode 100644 openlp/plugins/songs/lib/sofimport.py diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py new file mode 100644 index 000000000..7439978fd --- /dev/null +++ b/openlp/plugins/songs/lib/sofimport.py @@ -0,0 +1,504 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # +# Thompson, Jon Tibble, Carsten Tinggaard # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +# OOo API documentation: +# http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Structure_of_Text_Documents +# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Text/Iterating_over_Text +# http://www.oooforum.org/forum/viewtopic.phtml?t=14409 +# http://wiki.services.openoffice.org/wiki/Python + +import re +import os +import time +from PyQt4 import QtCore + +if os.name == u'nt': + from win32com.client import Dispatch + BOLD = 150.0 + ITALIC = 2 + PAGE_BEFORE = 4 + PAGE_AFTER = 5 + PAGE_BOTH = 6 +else: + import uno + from com.sun.star.beans import PropertyValue + from com.sun.star.awt.FontWeight import BOLD + from com.sun.star.awt.FontSlant import ITALIC + from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH + +class sofimport: + def __init__(self): + self.song = None + self.new_song() + + def start_ooo(self): + if os.name == u'nt': + manager = Dispatch(u'com.sun.star.ServiceManager') + manager._FlagAsMethod(u'Bridge_GetStruct') + manager._FlagAsMethod(u'Bridge_GetValueObject') + self.desktop = manager.createInstance(u'com.sun.star.frame.Desktop') + else: + cmd = u'openoffice.org -nologo -norestore -minimized -invisible -nofirststartwizard -accept="socket,host=localhost,port=2002;urp;"' + process = QtCore.QProcess() + process.startDetached(cmd) + process.waitForStarted() + context = uno.getComponentContext() + resolver = context.ServiceManager.createInstanceWithContext( + u'com.sun.star.bridge.UnoUrlResolver', context) + ctx = None + loop = 0 + while ctx is None and loop < 3: + try: + ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') + except: + time.sleep(1) + loop += 1 + manager = ctx.ServiceManager + self.desktop = manager.createInstanceWithContext( + "com.sun.star.frame.Desktop", ctx ) + + def open_sof_file(self, filepath): + if os.name == u'nt': + url = u'file:///' + filepath.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20') + else: + url = uno.systemPathToFileUrl(filepath) + properties = [] + properties = tuple(properties) + self.document = self.desktop.loadComponentFromURL(url, u'_blank', + 0, properties) + + def close_ooo(self): + self.desktop.terminate() + + def process_doc(self): + self.blanklines = 0 + paragraphs = self.document.getText().createEnumeration() + while paragraphs.hasMoreElements(): + paragraph = paragraphs.nextElement() + if paragraph.supportsService("com.sun.star.text.Paragraph"): + self.process_paragraph(paragraph) + if self.song: + self.song.finish() + self.song = None + + def process_paragraph(self, paragraph): + text = '' + textportions = paragraph.createEnumeration() + while textportions.hasMoreElements(): + textportion = textportions.nextElement() + if textportion.BreakType in (PAGE_BEFORE, PAGE_BOTH): + self.process_paragraph_text(text) + self.new_song() + text = '' + text += self.process_textportion(textportion) + if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH): + self.process_paragraph_text(text) + self.new_song() + text = '' + self.process_paragraph_text(text) + + def process_paragraph_text(self, text): + for line in text.split('\n'): + self.process_paragraph_line(line) + if self.blanklines > 2: + self.new_song() + + def process_paragraph_line(self, text): + text = text.strip() + if text == '': + self.blanklines += 1 + if self.blanklines > 1: + return + if self.song.title != '': + self.song.finish_verse() + return + #print ">" + text + "<" + self.blanklines = 0 + if self.skip_to_close_bracket: + if text.endswith(')'): + self.skip_to_close_bracket = False + return + if text.startswith('CCL Licence'): + self.in_chorus = False + return + if text == 'A Songs of Fellowship Worship Resource': + return + if text.startswith('(NB.') or text.startswith('(Regrettably') or text.startswith('(From'): + self.skip_to_close_bracket = True + return + if text.startswith('Copyright'): + self.song.copyright = text + return + if text == '(Repeat)': + self.song.repeat_verse() + return + if self.song.title == '': + if self.song.copyright == '': + self.song.add_author(text) + else: + self.song.copyright += ' ' + text + return + self.song.add_verse_line(text, self.in_chorus) + + def process_textportion(self, textportion): + text = textportion.getString() + text = self.tidy_text(text) + if text.strip() == '': + return text + if textportion.CharWeight == BOLD: + boldtext = text.strip() + if boldtext.isdigit() and self.song.songnumber == 0: + self.song.songnumber = int(boldtext) + return '' + if self.song.title == '': + text = self.uncap_text(text) + title = text.strip() + if title.startswith('\''): + title = title[1:] + if title.endswith(','): + title = title[:-1] + self.song.title = title + return text + if text.strip().startswith('('): + return text + self.in_chorus = (textportion.CharPosture == ITALIC) + return text + + def new_song(self): + if self.song: + if not self.song.finish(): + return + self.song = sofsong() + self.skip_to_close_bracket = False + self.in_chorus = False + + def tidy_text(self, text): + text = text.replace('\t', ' ') + text = text.replace('\r', '\n') + text = text.replace(u'\u2018', '\'') + text = text.replace(u'\u2019', '\'') + text = text.replace(u'\u201c', '"') + text = text.replace(u'\u201d', '"') + text = text.replace(u'\u2026', '...') + text = text.replace(u'\u2013', '-') + text = text.replace(u'\u2014', '-') + return text + + def uncap_text(self, text): + textarr = re.split('(\W+)', text) + textarr[0] = textarr[0].capitalize() + for i in range(1, len(textarr)): + if textarr[i] in ('JESUS', 'CHRIST', 'KING', 'ALMIGHTY', 'REDEEMER', 'SHEPHERD', + 'SON', 'GOD', 'LORD', 'FATHER', 'HOLY', 'SPIRIT', 'LAMB', 'YOU', + 'YOUR', 'I', 'I\'VE', 'I\'M', 'I\'LL', 'SAVIOUR', 'O', 'YOU\'RE', 'HE', 'HIS', 'HIM', 'ZION', + 'EMMANUEL', 'MAJESTY', 'JESUS\'', 'JIREH', 'JUDAH', 'LION', 'LORD\'S', 'ABRAHAM', 'GOD\'S', + 'FATHER\'S', 'ELIJAH'): + textarr[i] = textarr[i].capitalize() + else: + textarr[i] = textarr[i].lower() + text = ''.join(textarr) + return text + +class sofsong: + def __init__(self): + self.songnumber = 0 + self.title = "" + self.ischorus = False + self.versecount = 0 + self.choruscount = 0 + self.verses = [] + self.order = [] + self.authors = [] + self.copyright = "" + self.book = '' + self.currentverse = '' + + def finish_verse(self): + if self.currentverse.strip() == '': + return + if self.ischorus: + splitat = None + else: + splitat = self.verse_splits() + if splitat: + ln = 0 + verse = '' + for line in self.currentverse.split('\n'): + ln += 1 + if line == '' or ln > splitat: + self.append_verse(verse) + ln = 0 + if line: + verse = line + '\n' + else: + verse = '' + else: + verse += line + '\n' + if verse: + self.append_verse(verse) + else: + self.append_verse(self.currentverse) + self.currentverse = '' + self.ischorus = False + + def append_verse(self, verse): + if self.ischorus: + self.choruscount += 1 + versetag = 'C' + str(self.choruscount) + else: + self.versecount += 1 + versetag = 'V' + str(self.versecount) + self.verses.append([versetag, verse]) + self.order.append(versetag) + if self.choruscount > 0 and not self.ischorus: + self.order.append('C' + str(self.choruscount)) + + def repeat_verse(self): + self.finish_verse() + self.order.append(self.order[-1]) + + def add_verse_line(self, text, inchorus): + if inchorus != self.ischorus and ((len(self.verses) > 0) or + (self.currentverse.count('\n') > 1)): + self.finish_verse() + if inchorus: + self.ischorus = True + self.currentverse += text + '\n' + + def add_author(self, text): + text = text.replace(' and ', ' & ') + for author in text.split(','): + authors = author.split('&') + for i in range(len(authors)): + author2 = authors[i].strip() + if author2.find(' ') == -1 and i < len(authors) - 1: + author2 = author2 + ' ' + authors[i+1].split(' ')[-1] + self.authors.append(author2) + + def finish(self): + self.finish_verse() + if self.songnumber == 0 \ + or self.title == '' \ + or len(self.verses) == 0: + return False + if len(self.authors) == 0: + self.authors.append('Author Unknown') + self.title = self.title + ' - ' + str(self.songnumber) + if self.songnumber <= 640: + self.book = 'Songs of Fellowship 1' + elif self.songnumber <= 1150: + self.book = 'Songs of Fellowship 2' + elif self.songnumber <= 1690: + self.book = 'Songs of Fellowship 3' + else: + self.book = 'Songs of Fellowship 4' + self.print_song() + return True + + def print_song(self): + print '===== TITLE: ' + self.title + ' =====' + for (verselabel, verse) in self.verses: + print "VERSE " + verselabel + ": " + verse + print u'ORDER: ' + unicode(self.order) + for author in self.authors: + print u'AUTHORS: ' + author + print u'COPYRIGHT: ' + self.copyright + print u'BOOK: ' + self.book + + def verse_splits(self): + """ + Because someone at Kingsway forgot to check the 1+2 RTF file, + some verses were not formatted correctly. + """ + if self.songnumber == 11: return 8 + if self.songnumber == 18: return 5 + if self.songnumber == 21: return 6 + if self.songnumber == 23: return 4 + if self.songnumber == 24: return 7 + if self.songnumber == 27: return 4 + if self.songnumber == 31: return 6 + if self.songnumber == 49: return 4 + if self.songnumber == 50: return 8 + if self.songnumber == 70: return 4 + if self.songnumber == 75: return 8 + if self.songnumber == 79: return 6 + if self.songnumber == 97: return 7 + if self.songnumber == 107: return 4 + if self.songnumber == 109: return 4 + if self.songnumber == 133: return 4 + if self.songnumber == 155: return 10 + if self.songnumber == 156: return 8 + if self.songnumber == 171: return 4 + if self.songnumber == 188: return 7 + if self.songnumber == 192: return 4 + if self.songnumber == 208: return 8 + if self.songnumber == 215: return 8 + if self.songnumber == 220: return 4 + if self.songnumber == 247: return 6 + if self.songnumber == 248: return 6 + if self.songnumber == 251: return 8 + if self.songnumber == 295: return 8 + if self.songnumber == 307: return 5 + if self.songnumber == 314: return 6 + if self.songnumber == 325: return 8 + if self.songnumber == 386: return 6 + if self.songnumber == 415: return 4 + if self.songnumber == 426: return 4 + if self.songnumber == 434: return 5 + if self.songnumber == 437: return 4 + if self.songnumber == 438: return 6 + if self.songnumber == 456: return 8 + if self.songnumber == 461: return 4 + if self.songnumber == 469: return 4 + if self.songnumber == 470: return 5 + if self.songnumber == 476: return 6 + if self.songnumber == 477: return 7 + if self.songnumber == 480: return 8 + if self.songnumber == 482: return 4 + if self.songnumber == 512: return 4 + if self.songnumber == 513: return 8 + if self.songnumber == 518: return 5 + if self.songnumber == 520: return 4 + if self.songnumber == 523: return 6 + if self.songnumber == 526: return 8 + if self.songnumber == 527: return 4 + if self.songnumber == 529: return 4 + if self.songnumber == 537: return 4 + if self.songnumber == 555: return 6 + if self.songnumber == 581: return 4 + if self.songnumber == 589: return 6 + if self.songnumber == 590: return 4 + if self.songnumber == 593: return 8 + if self.songnumber == 596: return 4 + if self.songnumber == 610: return 6 + if self.songnumber == 611: return 6 + if self.songnumber == 619: return 8 + if self.songnumber == 645: return 5 + if self.songnumber == 653: return 6 + if self.songnumber == 683: return 7 + if self.songnumber == 686: return 4 + if self.songnumber == 697: return 8 + if self.songnumber == 698: return 4 + if self.songnumber == 704: return 6 + if self.songnumber == 716: return 4 + if self.songnumber == 717: return 6 + if self.songnumber == 730: return 4 + if self.songnumber == 731: return 8 + if self.songnumber == 732: return 8 + if self.songnumber == 738: return 4 + if self.songnumber == 756: return 9 + if self.songnumber == 815: return 6 + if self.songnumber == 830: return 8 + if self.songnumber == 831: return 4 + if self.songnumber == 876: return 6 + if self.songnumber == 877: return 6 + if self.songnumber == 892: return 4 + if self.songnumber == 894: return 6 + if self.songnumber == 902: return 8 + if self.songnumber == 905: return 8 + if self.songnumber == 921: return 6 + if self.songnumber == 940: return 7 + if self.songnumber == 955: return 9 + if self.songnumber == 968: return 8 + if self.songnumber == 972: return 7 + if self.songnumber == 974: return 4 + if self.songnumber == 988: return 6 + if self.songnumber == 991: return 5 + if self.songnumber == 1002: return 8 + if self.songnumber == 1024: return 8 + if self.songnumber == 1044: return 9 + if self.songnumber == 1088: return 6 + if self.songnumber == 1117: return 6 + if self.songnumber == 1119: return 7 + return None + +sof = sofimport() +sof.start_ooo() +sof.open_sof_file("/home/jonathan/sof.rtf") +#sof.open_sof_file("c:\users\jonathan\Desktop\sof3words.rtf") +#sof.open_sof_file("c:\users\jonathan\Desktop\sof4words.rtf") +sof.process_doc() +sof.close_ooo() + +""" + + +Sub FinishSong() + + sql = "SELECT songid FROM songs where songtitle = '" & Title & "'" + set rs = db.Execute(sql) + If Not rs.EOF Then + rs.MoveFirst + sid = rs("songid") + sql = "UPDATE songs SET songtitle='" & title & "', lyrics='" & lyrics & "', copyrightinfo='" & _ + Copyright & "', settingsid=0 WHERE songid=" & sid + db.Execute(sql) + Else + sql = "INSERT INTO songs ('songtitle', 'lyrics', 'copyrightinfo', 'settingsid') VALUES ('" & _ + Title & "', '" & Lyrics & "', '" & Copyright & "',0)" + db.Execute(sql) + sql = "SELECT songid FROM songs where songtitle = '" & Title & "'" + set rs = db.Execute(sql) + db.Execute(sql) + rs.MoveFirst + sid = rs("songid") + End If + For aut = LBound(Authors) To UBound(Authors) + Authors(Aut) = Trim(Authors(aut)) + If InStr(1, Authors(aut), " ") = 0 And aut < UBound(Authors) Then + temp = Split(Authors(aut+1), " ") + Authors(aut) = Authors(aut) + " " + temp(UBound(temp)) + End If + If Right(Authors(aut), 1) = "." Then Authors(aut) = Left(Authors(aut), Len(Authors(aut)) - 1) + Authors(aut) = Replace(Authors(aut), "'", "''") + sql = "SELECT authorid FROM authors where authorname = '" & Authors(aut) & "'" + set rs = db.Execute(sql) + If Not rs.EOF Then + rs.MoveFirst + aid = rs("authorid") + Else + sql = "INSERT INTO authors ('authorname') VALUES ('" & Authors(aut) & "')" + db.Execute(sql) + sql = "SELECT authorid FROM authors where authorname = '" & Authors(aut) & "'" + set rs = db.Execute(sql) + rs.MoveFirst + aid = rs("authorid") + End If + ' REPLACE seemed to insert a second duplicate row, so need to do select/insert instead. + sql = "SELECT count(*) FROM songauthors where songid = " & sid & " and authorid = " & aid + set rs = db.Execute(sql) + rs.MoveFirst + If rs(0)=0 Then + sql = "INSERT INTO songauthors VALUES (" & aid & "," & sid &")" + db.Execute(sql) + End If + Next + Exit Sub +End Sub + + + +""" + From 33f4bc05f228566ecadf8d5f376d7ec85380213a Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Thu, 1 Apr 2010 08:42:42 +0100 Subject: [PATCH 2/4] tidy --- openlp/plugins/songs/lib/sofimport.py | 209 ++++++++++---------------- 1 file changed, 77 insertions(+), 132 deletions(-) diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index 7439978fd..5c9cf1778 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -81,7 +81,8 @@ class sofimport: def open_sof_file(self, filepath): if os.name == u'nt': - url = u'file:///' + filepath.replace(u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20') + url = u'file:///' + filepath.replace(u'\\', u'/') + url = url.replace(u':', u'|').replace(u' ', u'%20') else: url = uno.systemPathToFileUrl(filepath) properties = [] @@ -104,84 +105,85 @@ class sofimport: self.song = None def process_paragraph(self, paragraph): - text = '' + text = u'' textportions = paragraph.createEnumeration() while textportions.hasMoreElements(): textportion = textportions.nextElement() if textportion.BreakType in (PAGE_BEFORE, PAGE_BOTH): self.process_paragraph_text(text) self.new_song() - text = '' + text = u'' text += self.process_textportion(textportion) if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH): self.process_paragraph_text(text) self.new_song() - text = '' + text = u'' self.process_paragraph_text(text) def process_paragraph_text(self, text): - for line in text.split('\n'): + for line in text.split(u'\n'): self.process_paragraph_line(line) if self.blanklines > 2: self.new_song() def process_paragraph_line(self, text): text = text.strip() - if text == '': + if text == u'': self.blanklines += 1 if self.blanklines > 1: return - if self.song.title != '': + if self.song.title != u'': self.song.finish_verse() return #print ">" + text + "<" self.blanklines = 0 if self.skip_to_close_bracket: - if text.endswith(')'): + if text.endswith(u')'): self.skip_to_close_bracket = False return - if text.startswith('CCL Licence'): + if text.startswith(u'CCL Licence'): self.in_chorus = False return - if text == 'A Songs of Fellowship Worship Resource': + if text == u'A Songs of Fellowship Worship Resource': return - if text.startswith('(NB.') or text.startswith('(Regrettably') or text.startswith('(From'): + if text.startswith(u'(NB.') or text.startswith(u'(Regrettably') \ + or text.startswith(u'(From'): self.skip_to_close_bracket = True return - if text.startswith('Copyright'): + if text.startswith(u'Copyright'): self.song.copyright = text return - if text == '(Repeat)': + if text == u'(Repeat)': self.song.repeat_verse() return - if self.song.title == '': - if self.song.copyright == '': + if self.song.title == u'': + if self.song.copyright == u'': self.song.add_author(text) else: - self.song.copyright += ' ' + text + self.song.copyright += u' ' + text return self.song.add_verse_line(text, self.in_chorus) def process_textportion(self, textportion): text = textportion.getString() text = self.tidy_text(text) - if text.strip() == '': + if text.strip() == u'': return text if textportion.CharWeight == BOLD: boldtext = text.strip() if boldtext.isdigit() and self.song.songnumber == 0: self.song.songnumber = int(boldtext) - return '' - if self.song.title == '': + return u'' + if self.song.title == u'': text = self.uncap_text(text) title = text.strip() - if title.startswith('\''): + if title.startswith(u'\''): title = title[1:] - if title.endswith(','): + if title.endswith(u','): title = title[:-1] self.song.title = title return text - if text.strip().startswith('('): + if text.strip().startswith(u'('): return text self.in_chorus = (textportion.CharPosture == ITALIC) return text @@ -195,48 +197,51 @@ class sofimport: self.in_chorus = False def tidy_text(self, text): - text = text.replace('\t', ' ') - text = text.replace('\r', '\n') - text = text.replace(u'\u2018', '\'') - text = text.replace(u'\u2019', '\'') - text = text.replace(u'\u201c', '"') - text = text.replace(u'\u201d', '"') - text = text.replace(u'\u2026', '...') - text = text.replace(u'\u2013', '-') - text = text.replace(u'\u2014', '-') + text = text.replace(u'\t', u' ') + text = text.replace(u'\r', u'\n') + text = text.replace(u'\u2018', u'\'') + text = text.replace(u'\u2019', u'\'') + text = text.replace(u'\u201c', u'"') + text = text.replace(u'\u201d', u'"') + text = text.replace(u'\u2026', u'...') + text = text.replace(u'\u2013', u'-') + text = text.replace(u'\u2014', u'-') return text def uncap_text(self, text): - textarr = re.split('(\W+)', text) + textarr = re.split(u'(\W+)', text) textarr[0] = textarr[0].capitalize() for i in range(1, len(textarr)): - if textarr[i] in ('JESUS', 'CHRIST', 'KING', 'ALMIGHTY', 'REDEEMER', 'SHEPHERD', - 'SON', 'GOD', 'LORD', 'FATHER', 'HOLY', 'SPIRIT', 'LAMB', 'YOU', - 'YOUR', 'I', 'I\'VE', 'I\'M', 'I\'LL', 'SAVIOUR', 'O', 'YOU\'RE', 'HE', 'HIS', 'HIM', 'ZION', - 'EMMANUEL', 'MAJESTY', 'JESUS\'', 'JIREH', 'JUDAH', 'LION', 'LORD\'S', 'ABRAHAM', 'GOD\'S', - 'FATHER\'S', 'ELIJAH'): + # Do not translate these. Fixed strings in SOF song file + if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', + u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', + u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', + u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', + u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', + u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', + u'FATHER\'S', u'ELIJAH'): textarr[i] = textarr[i].capitalize() else: textarr[i] = textarr[i].lower() - text = ''.join(textarr) + text = u''.join(textarr) return text class sofsong: def __init__(self): self.songnumber = 0 - self.title = "" + self.title = u'' self.ischorus = False self.versecount = 0 self.choruscount = 0 self.verses = [] self.order = [] self.authors = [] - self.copyright = "" - self.book = '' - self.currentverse = '' + self.copyright = u'' + self.book = u'' + self.currentverse = u'' def finish_verse(self): - if self.currentverse.strip() == '': + if self.currentverse.strip() == u'': return if self.ischorus: splitat = None @@ -244,36 +249,36 @@ class sofsong: splitat = self.verse_splits() if splitat: ln = 0 - verse = '' - for line in self.currentverse.split('\n'): + verse = u'' + for line in self.currentverse.split(u'\n'): ln += 1 - if line == '' or ln > splitat: + if line == u'' or ln > splitat: self.append_verse(verse) ln = 0 if line: - verse = line + '\n' + verse = line + u'\n' else: - verse = '' + verse = u'' else: - verse += line + '\n' + verse += line + u'\n' if verse: self.append_verse(verse) else: self.append_verse(self.currentverse) - self.currentverse = '' + self.currentverse = u'' self.ischorus = False def append_verse(self, verse): if self.ischorus: self.choruscount += 1 - versetag = 'C' + str(self.choruscount) + versetag = u'C' + unicode(self.choruscount) else: self.versecount += 1 - versetag = 'V' + str(self.versecount) + versetag = u'V' + unicode(self.versecount) self.verses.append([versetag, verse]) self.order.append(versetag) if self.choruscount > 0 and not self.ischorus: - self.order.append('C' + str(self.choruscount)) + self.order.append(u'C' + unicode(self.choruscount)) def repeat_verse(self): self.finish_verse() @@ -281,46 +286,46 @@ class sofsong: def add_verse_line(self, text, inchorus): if inchorus != self.ischorus and ((len(self.verses) > 0) or - (self.currentverse.count('\n') > 1)): + (self.currentverse.count(u'\n') > 1)): self.finish_verse() if inchorus: self.ischorus = True - self.currentverse += text + '\n' + self.currentverse += text + u'\n' def add_author(self, text): - text = text.replace(' and ', ' & ') - for author in text.split(','): - authors = author.split('&') + text = text.replace(u' and ', u' & ') + for author in text.split(u','): + authors = author.split(u'&') for i in range(len(authors)): author2 = authors[i].strip() - if author2.find(' ') == -1 and i < len(authors) - 1: - author2 = author2 + ' ' + authors[i+1].split(' ')[-1] + if author2.find(u' ') == -1 and i < len(authors) - 1: + author2 = author2 + u' ' + authors[i + 1].split(u' ')[-1] self.authors.append(author2) def finish(self): self.finish_verse() if self.songnumber == 0 \ - or self.title == '' \ + or self.title == u'' \ or len(self.verses) == 0: return False if len(self.authors) == 0: - self.authors.append('Author Unknown') - self.title = self.title + ' - ' + str(self.songnumber) + self.authors.append(u'Author Unknown') if self.songnumber <= 640: - self.book = 'Songs of Fellowship 1' + self.book = u'Songs of Fellowship 1' elif self.songnumber <= 1150: - self.book = 'Songs of Fellowship 2' + self.book = u'Songs of Fellowship 2' elif self.songnumber <= 1690: - self.book = 'Songs of Fellowship 3' + self.book = u'Songs of Fellowship 3' else: - self.book = 'Songs of Fellowship 4' + self.book = u'Songs of Fellowship 4' self.print_song() return True def print_song(self): - print '===== TITLE: ' + self.title + ' =====' + print u'===== TITLE: ' + self.title + u' =====' + print u'ALTTITLE: ' + unicode(self.songnumber) for (verselabel, verse) in self.verses: - print "VERSE " + verselabel + ": " + verse + print u'VERSE ' + verselabel + u': ' + verse print u'ORDER: ' + unicode(self.order) for author in self.authors: print u'AUTHORS: ' + author @@ -436,69 +441,9 @@ class sofsong: sof = sofimport() sof.start_ooo() -sof.open_sof_file("/home/jonathan/sof.rtf") -#sof.open_sof_file("c:\users\jonathan\Desktop\sof3words.rtf") -#sof.open_sof_file("c:\users\jonathan\Desktop\sof4words.rtf") +sof.open_sof_file(u'/home/jonathan/sof.rtf') +#sof.open_sof_file(u'c:\users\jonathan\Desktop\sof3words.rtf') +#sof.open_sof_file(u'c:\users\jonathan\Desktop\sof4words.rtf') sof.process_doc() sof.close_ooo() -""" - - -Sub FinishSong() - - sql = "SELECT songid FROM songs where songtitle = '" & Title & "'" - set rs = db.Execute(sql) - If Not rs.EOF Then - rs.MoveFirst - sid = rs("songid") - sql = "UPDATE songs SET songtitle='" & title & "', lyrics='" & lyrics & "', copyrightinfo='" & _ - Copyright & "', settingsid=0 WHERE songid=" & sid - db.Execute(sql) - Else - sql = "INSERT INTO songs ('songtitle', 'lyrics', 'copyrightinfo', 'settingsid') VALUES ('" & _ - Title & "', '" & Lyrics & "', '" & Copyright & "',0)" - db.Execute(sql) - sql = "SELECT songid FROM songs where songtitle = '" & Title & "'" - set rs = db.Execute(sql) - db.Execute(sql) - rs.MoveFirst - sid = rs("songid") - End If - For aut = LBound(Authors) To UBound(Authors) - Authors(Aut) = Trim(Authors(aut)) - If InStr(1, Authors(aut), " ") = 0 And aut < UBound(Authors) Then - temp = Split(Authors(aut+1), " ") - Authors(aut) = Authors(aut) + " " + temp(UBound(temp)) - End If - If Right(Authors(aut), 1) = "." Then Authors(aut) = Left(Authors(aut), Len(Authors(aut)) - 1) - Authors(aut) = Replace(Authors(aut), "'", "''") - sql = "SELECT authorid FROM authors where authorname = '" & Authors(aut) & "'" - set rs = db.Execute(sql) - If Not rs.EOF Then - rs.MoveFirst - aid = rs("authorid") - Else - sql = "INSERT INTO authors ('authorname') VALUES ('" & Authors(aut) & "')" - db.Execute(sql) - sql = "SELECT authorid FROM authors where authorname = '" & Authors(aut) & "'" - set rs = db.Execute(sql) - rs.MoveFirst - aid = rs("authorid") - End If - ' REPLACE seemed to insert a second duplicate row, so need to do select/insert instead. - sql = "SELECT count(*) FROM songauthors where songid = " & sid & " and authorid = " & aid - set rs = db.Execute(sql) - rs.MoveFirst - If rs(0)=0 Then - sql = "INSERT INTO songauthors VALUES (" & aid & "," & sid &")" - db.Execute(sql) - End If - Next - Exit Sub -End Sub - - - -""" - From 1f41039e07a93481713982c101c57ac29b90709b Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Thu, 1 Apr 2010 22:36:03 +0100 Subject: [PATCH 3/4] Split song and sof specifics --- openlp/plugins/songs/lib/sofimport.py | 604 ++++++++++++++----------- openlp/plugins/songs/lib/songimport.py | 259 +++++++++++ 2 files changed, 597 insertions(+), 266 deletions(-) create mode 100644 openlp/plugins/songs/lib/songimport.py diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index 5c9cf1778..c73449d44 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -31,8 +31,9 @@ import re import os -import time +import time from PyQt4 import QtCore +from songimport import SongImport if os.name == u'nt': from win32com.client import Dispatch @@ -48,19 +49,44 @@ else: from com.sun.star.awt.FontSlant import ITALIC from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH -class sofimport: - def __init__(self): +class SofImport(object): + """ + Import songs provided on disks with the Songs of Fellowship music books + VOLS1_2.RTF, sof3words.rtf and sof4words.rtf + + Use OpenOffice.org Writer for processing the rtf file + + The three books are not only inconsistant with each other, they are + inconsistant in themselves too with their formatting. Not only this, but + the 1+2 book does not space out verses correctly. This script attempts + to sort it out, but doesn't get it 100% right. But better than having to + type them all out! + + It attempts to detect italiced verses, and treats these as choruses in + the verse ordering. Again not perfect, but a start. + """ + def __init__(self, songmanager): + """ + Initialise the class. Requires a songmanager class which is passed + to SongImport for writing song to disk + """ self.song = None - self.new_song() + self.manager = songmanager def start_ooo(self): + """ + Start OpenOffice.org process + TODO: The presentation/Impress plugin may already have it running + """ if os.name == u'nt': manager = Dispatch(u'com.sun.star.ServiceManager') manager._FlagAsMethod(u'Bridge_GetStruct') manager._FlagAsMethod(u'Bridge_GetValueObject') self.desktop = manager.createInstance(u'com.sun.star.frame.Desktop') else: - cmd = u'openoffice.org -nologo -norestore -minimized -invisible -nofirststartwizard -accept="socket,host=localhost,port=2002;urp;"' + cmd = u'openoffice.org -nologo -norestore -minimized -invisible ' \ + + u'-nofirststartwizard ' \ + + '-accept="socket,host=localhost,port=2002;urp;"' process = QtCore.QProcess() process.startDetached(cmd) process.waitForStarted() @@ -69,17 +95,22 @@ class sofimport: u'com.sun.star.bridge.UnoUrlResolver', context) ctx = None loop = 0 - while ctx is None and loop < 3: + while ctx is None and loop < 5: try: - ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') - except: - time.sleep(1) - loop += 1 + ctx = resolver.resolve(u'uno:socket,host=localhost,' \ + + 'port=2002;urp;StarOffice.ComponentContext') + except: + pass + time.sleep(1) + loop += 1 manager = ctx.ServiceManager self.desktop = manager.createInstanceWithContext( "com.sun.star.frame.Desktop", ctx ) - def open_sof_file(self, filepath): + def open_ooo_file(self, filepath): + """ + Open the passed file in OpenOffice.org Writer + """ if os.name == u'nt': url = u'file:///' + filepath.replace(u'\\', u'/') url = url.replace(u':', u'|').replace(u' ', u'%20') @@ -91,10 +122,18 @@ class sofimport: 0, properties) def close_ooo(self): + """ + Close down OpenOffice.org. + TODO: Further checks that it have other docs open, e.g. Impress! + """ self.desktop.terminate() - def process_doc(self): + def process_doc(self): + """ + Process the RTF file, a paragraph at a time + """ self.blanklines = 0 + self.new_song() paragraphs = self.document.getText().createEnumeration() while paragraphs.hasMoreElements(): paragraph = paragraphs.nextElement() @@ -105,6 +144,16 @@ class sofimport: self.song = None def process_paragraph(self, paragraph): + """ + Process a paragraph. + In the first book, a paragraph is a single line. In the latter ones + they may contain multiple lines. + Each paragraph contains textportions. Each textportion has it's own + styling, e.g. italics, bold etc. + Also check for page breaks, which indicates a new song in books 1+2. + In later books, there may not be line breaks, so check for 3 or more + newlines + """ text = u'' textportions = paragraph.createEnumeration() while textportions.hasMoreElements(): @@ -120,29 +169,36 @@ class sofimport: text = u'' self.process_paragraph_text(text) - def process_paragraph_text(self, text): + def process_paragraph_text(self, text): + """ + Split the paragraph text into multiple lines and process + """ for line in text.split(u'\n'): self.process_paragraph_line(line) if self.blanklines > 2: self.new_song() - def process_paragraph_line(self, text): + def process_paragraph_line(self, text): + """ + Process a single line. Throw away that text which isn't relevant, i.e. + stuff that appears at the end of the song. + Anything that is OK, append to the current verse + """ text = text.strip() if text == u'': self.blanklines += 1 if self.blanklines > 1: return - if self.song.title != u'': - self.song.finish_verse() + if self.song.get_title() != u'': + self.finish_verse() return - #print ">" + text + "<" self.blanklines = 0 if self.skip_to_close_bracket: if text.endswith(u')'): self.skip_to_close_bracket = False return if text.startswith(u'CCL Licence'): - self.in_chorus = False + self.italics = False return if text == u'A Songs of Fellowship Worship Resource': return @@ -151,299 +207,315 @@ class sofimport: self.skip_to_close_bracket = True return if text.startswith(u'Copyright'): - self.song.copyright = text + self.song.add_copyright(text) return if text == u'(Repeat)': + self.finish_verse() self.song.repeat_verse() return - if self.song.title == u'': - if self.song.copyright == u'': - self.song.add_author(text) + if self.song.get_title() == u'': + if self.song.get_copyright() == u'': + self.add_author(text) else: - self.song.copyright += u' ' + text + self.song.add_copyright(text) return - self.song.add_verse_line(text, self.in_chorus) + self.add_verse_line(text) - def process_textportion(self, textportion): + def process_textportion(self, textportion): + """ + Process a text portion. Here we just get the text and detect if + it's bold or italics. If it's bold then its a song number or song title. + Song titles are in all capitals, so we must bring the capitalization + into line + """ text = textportion.getString() text = self.tidy_text(text) if text.strip() == u'': return text if textportion.CharWeight == BOLD: boldtext = text.strip() - if boldtext.isdigit() and self.song.songnumber == 0: - self.song.songnumber = int(boldtext) + if boldtext.isdigit() and self.song.get_song_number() == '': + self.add_songnumber(boldtext) return u'' - if self.song.title == u'': - text = self.uncap_text(text) - title = text.strip() - if title.startswith(u'\''): - title = title[1:] - if title.endswith(u','): - title = title[:-1] - self.song.title = title + if self.song.get_title() == u'': + text = self.uncap_text(text) + self.add_title(text) return text if text.strip().startswith(u'('): return text - self.in_chorus = (textportion.CharPosture == ITALIC) + self.italics = (textportion.CharPosture == ITALIC) return text - def new_song(self): + def new_song(self): + """ + A change of song. Store the old, create a new + ... but only if the last song was complete. If not, stick with it + """ if self.song: - if not self.song.finish(): + self.finish_verse() + if not self.song.check_complete(): return - self.song = sofsong() + self.song.finish() + self.song = SongImport(self.manager) self.skip_to_close_bracket = False - self.in_chorus = False - - def tidy_text(self, text): - text = text.replace(u'\t', u' ') - text = text.replace(u'\r', u'\n') - text = text.replace(u'\u2018', u'\'') - text = text.replace(u'\u2019', u'\'') - text = text.replace(u'\u201c', u'"') - text = text.replace(u'\u201d', u'"') - text = text.replace(u'\u2026', u'...') - text = text.replace(u'\u2013', u'-') - text = text.replace(u'\u2014', u'-') - return text - - def uncap_text(self, text): - textarr = re.split(u'(\W+)', text) - textarr[0] = textarr[0].capitalize() - for i in range(1, len(textarr)): - # Do not translate these. Fixed strings in SOF song file - if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', - u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', - u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', - u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', - u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', - u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', - u'FATHER\'S', u'ELIJAH'): - textarr[i] = textarr[i].capitalize() - else: - textarr[i] = textarr[i].lower() - text = u''.join(textarr) - return text - -class sofsong: - def __init__(self): - self.songnumber = 0 - self.title = u'' - self.ischorus = False - self.versecount = 0 - self.choruscount = 0 - self.verses = [] - self.order = [] - self.authors = [] - self.copyright = u'' - self.book = u'' - self.currentverse = u'' + self.is_chorus = False + self.italics = False + self.currentverse = u'' - def finish_verse(self): + def add_songnumber(self, song_no): + """ + Add a song number, store as alternate title. Also use the song + number to work out which songbook we're in + """ + self.song.set_song_number(song_no) + if int(song_no) <= 640: + self.song.set_song_book(u'Songs of Fellowship 1', + 'Kingsway\'s Thankyou Music') + elif int(song_no) <= 1150: + self.song.set_song_book(u'Songs of Fellowship 2', + 'Kingsway\'s Thankyou Music') + elif int(song_no) <= 1690: + self.song.set_song_book(u'Songs of Fellowship 3', + 'Kingsway\'s Thankyou Music') + else: + self.song.set_song_book(u'Songs of Fellowship 4', + 'Kingsway\'s Thankyou Music') + + def add_title(self, text): + """ + Add the title to the song. Strip some leading/trailing punctuation that + we don't want in a title + """ + title = text.strip() + if title.startswith(u'\''): + title = title[1:] + if title.endswith(u','): + title = title[:-1] + self.song.set_title(title) + + def add_author(self, text): + """ + Add the author. OpenLP stores them individually so split by 'and', '&' + and comma. + However need to check for "Mr and Mrs Smith" and turn it to + "Mr Smith" and "Mrs Smith". + """ + text = text.replace(u' and ', u' & ') + for author in text.split(u','): + authors = author.split(u'&') + for i in range(len(authors)): + author2 = authors[i].strip() + if author2.find(u' ') == -1 and i < len(authors) - 1: + author2 = author2 + u' ' \ + + authors[i + 1].strip().split(u' ')[-1] + self.song.add_author(author2) + + def add_verse_line(self, text): + """ + Add a line to the current verse. If the formatting has changed and + we're beyond the second line of first verse, then this indicates + a change of verse. Italics are a chorus + """ + if self.italics != self.is_chorus and ((len(self.song.verses) > 0) or + (self.currentverse.count(u'\n') > 1)): + self.finish_verse() + if self.italics: + self.is_chorus = True + self.currentverse += text + u'\n' + + def finish_verse(self): + """ + Verse is finished, store it. Note in book 1+2, some songs are formatted + incorrectly. Here we try and split songs with missing line breaks into + the correct number of verses. + """ if self.currentverse.strip() == u'': - return - if self.ischorus: - splitat = None - else: - splitat = self.verse_splits() + return + if self.is_chorus: + versetag = 'C' + splitat = None + else: + versetag = 'V' + splitat = self.verse_splits(self.song.get_song_number()) if splitat: ln = 0 verse = u'' for line in self.currentverse.split(u'\n'): ln += 1 - if line == u'' or ln > splitat: - self.append_verse(verse) - ln = 0 + if line == u'' or ln > splitat: + self.song.add_verse(verse, versetag) + ln = 0 if line: - verse = line + u'\n' - else: + verse = line + u'\n' + else: verse = u'' else: verse += line + u'\n' if verse: - self.append_verse(verse) + self.song.add_verse(verse, versetag) else: - self.append_verse(self.currentverse) + self.song.add_verse(self.currentverse, versetag) self.currentverse = u'' - self.ischorus = False + self.is_chorus = False - def append_verse(self, verse): - if self.ischorus: - self.choruscount += 1 - versetag = u'C' + unicode(self.choruscount) - else: - self.versecount += 1 - versetag = u'V' + unicode(self.versecount) - self.verses.append([versetag, verse]) - self.order.append(versetag) - if self.choruscount > 0 and not self.ischorus: - self.order.append(u'C' + unicode(self.choruscount)) + def tidy_text(self, text): + """ + Get rid of some dodgy unicode and formatting characters we're not + interested in. Some can be converted to ascii. + """ + text = text.replace(u'\t', u' ') + text = text.replace(u'\r', u'\n') + text = text.replace(u'\u2018', u'\'') + text = text.replace(u'\u2019', u'\'') + text = text.replace(u'\u201c', u'"') + text = text.replace(u'\u201d', u'"') + text = text.replace(u'\u2026', u'...') + text = text.replace(u'\u2013', u'-') + text = text.replace(u'\u2014', u'-') + return text - def repeat_verse(self): - self.finish_verse() - self.order.append(self.order[-1]) - - def add_verse_line(self, text, inchorus): - if inchorus != self.ischorus and ((len(self.verses) > 0) or - (self.currentverse.count(u'\n') > 1)): - self.finish_verse() - if inchorus: - self.ischorus = True - self.currentverse += text + u'\n' - - def add_author(self, text): - text = text.replace(u' and ', u' & ') - for author in text.split(u','): - authors = author.split(u'&') - for i in range(len(authors)): - author2 = authors[i].strip() - if author2.find(u' ') == -1 and i < len(authors) - 1: - author2 = author2 + u' ' + authors[i + 1].split(u' ')[-1] - self.authors.append(author2) + def uncap_text(self, text): + """ + Words in the title are in all capitals, so we lowercase them. + However some of these words, e.g. referring to God need a leading + capital letter. + + There is a complicated word "One", which is sometimes lower and + sometimes upper depending on context. Never mind, keep it lower. + """ + textarr = re.split(u'(\W+)', text) + textarr[0] = textarr[0].capitalize() + for i in range(1, len(textarr)): + # Do not translate these. Fixed strings in SOF song file + if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', + u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', + u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', + u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', + u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', + u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', + u'FATHER\'S', u'ELIJAH'): + textarr[i] = textarr[i].capitalize() + else: + textarr[i] = textarr[i].lower() + text = u''.join(textarr) + return text - def finish(self): - self.finish_verse() - if self.songnumber == 0 \ - or self.title == u'' \ - or len(self.verses) == 0: - return False - if len(self.authors) == 0: - self.authors.append(u'Author Unknown') - if self.songnumber <= 640: - self.book = u'Songs of Fellowship 1' - elif self.songnumber <= 1150: - self.book = u'Songs of Fellowship 2' - elif self.songnumber <= 1690: - self.book = u'Songs of Fellowship 3' - else: - self.book = u'Songs of Fellowship 4' - self.print_song() - return True - - def print_song(self): - print u'===== TITLE: ' + self.title + u' =====' - print u'ALTTITLE: ' + unicode(self.songnumber) - for (verselabel, verse) in self.verses: - print u'VERSE ' + verselabel + u': ' + verse - print u'ORDER: ' + unicode(self.order) - for author in self.authors: - print u'AUTHORS: ' + author - print u'COPYRIGHT: ' + self.copyright - print u'BOOK: ' + self.book - - def verse_splits(self): + def verse_splits(self, song_number): """ Because someone at Kingsway forgot to check the 1+2 RTF file, some verses were not formatted correctly. """ - if self.songnumber == 11: return 8 - if self.songnumber == 18: return 5 - if self.songnumber == 21: return 6 - if self.songnumber == 23: return 4 - if self.songnumber == 24: return 7 - if self.songnumber == 27: return 4 - if self.songnumber == 31: return 6 - if self.songnumber == 49: return 4 - if self.songnumber == 50: return 8 - if self.songnumber == 70: return 4 - if self.songnumber == 75: return 8 - if self.songnumber == 79: return 6 - if self.songnumber == 97: return 7 - if self.songnumber == 107: return 4 - if self.songnumber == 109: return 4 - if self.songnumber == 133: return 4 - if self.songnumber == 155: return 10 - if self.songnumber == 156: return 8 - if self.songnumber == 171: return 4 - if self.songnumber == 188: return 7 - if self.songnumber == 192: return 4 - if self.songnumber == 208: return 8 - if self.songnumber == 215: return 8 - if self.songnumber == 220: return 4 - if self.songnumber == 247: return 6 - if self.songnumber == 248: return 6 - if self.songnumber == 251: return 8 - if self.songnumber == 295: return 8 - if self.songnumber == 307: return 5 - if self.songnumber == 314: return 6 - if self.songnumber == 325: return 8 - if self.songnumber == 386: return 6 - if self.songnumber == 415: return 4 - if self.songnumber == 426: return 4 - if self.songnumber == 434: return 5 - if self.songnumber == 437: return 4 - if self.songnumber == 438: return 6 - if self.songnumber == 456: return 8 - if self.songnumber == 461: return 4 - if self.songnumber == 469: return 4 - if self.songnumber == 470: return 5 - if self.songnumber == 476: return 6 - if self.songnumber == 477: return 7 - if self.songnumber == 480: return 8 - if self.songnumber == 482: return 4 - if self.songnumber == 512: return 4 - if self.songnumber == 513: return 8 - if self.songnumber == 518: return 5 - if self.songnumber == 520: return 4 - if self.songnumber == 523: return 6 - if self.songnumber == 526: return 8 - if self.songnumber == 527: return 4 - if self.songnumber == 529: return 4 - if self.songnumber == 537: return 4 - if self.songnumber == 555: return 6 - if self.songnumber == 581: return 4 - if self.songnumber == 589: return 6 - if self.songnumber == 590: return 4 - if self.songnumber == 593: return 8 - if self.songnumber == 596: return 4 - if self.songnumber == 610: return 6 - if self.songnumber == 611: return 6 - if self.songnumber == 619: return 8 - if self.songnumber == 645: return 5 - if self.songnumber == 653: return 6 - if self.songnumber == 683: return 7 - if self.songnumber == 686: return 4 - if self.songnumber == 697: return 8 - if self.songnumber == 698: return 4 - if self.songnumber == 704: return 6 - if self.songnumber == 716: return 4 - if self.songnumber == 717: return 6 - if self.songnumber == 730: return 4 - if self.songnumber == 731: return 8 - if self.songnumber == 732: return 8 - if self.songnumber == 738: return 4 - if self.songnumber == 756: return 9 - if self.songnumber == 815: return 6 - if self.songnumber == 830: return 8 - if self.songnumber == 831: return 4 - if self.songnumber == 876: return 6 - if self.songnumber == 877: return 6 - if self.songnumber == 892: return 4 - if self.songnumber == 894: return 6 - if self.songnumber == 902: return 8 - if self.songnumber == 905: return 8 - if self.songnumber == 921: return 6 - if self.songnumber == 940: return 7 - if self.songnumber == 955: return 9 - if self.songnumber == 968: return 8 - if self.songnumber == 972: return 7 - if self.songnumber == 974: return 4 - if self.songnumber == 988: return 6 - if self.songnumber == 991: return 5 - if self.songnumber == 1002: return 8 - if self.songnumber == 1024: return 8 - if self.songnumber == 1044: return 9 - if self.songnumber == 1088: return 6 - if self.songnumber == 1117: return 6 - if self.songnumber == 1119: return 7 + if song_number == 11: return 8 + if song_number == 18: return 5 + if song_number == 21: return 6 + if song_number == 23: return 4 + if song_number == 24: return 7 + if song_number == 27: return 4 + if song_number == 31: return 6 + if song_number == 49: return 4 + if song_number == 50: return 8 + if song_number == 70: return 4 + if song_number == 75: return 8 + if song_number == 79: return 6 + if song_number == 97: return 7 + if song_number == 107: return 4 + if song_number == 109: return 4 + if song_number == 133: return 4 + if song_number == 155: return 10 + if song_number == 156: return 8 + if song_number == 171: return 4 + if song_number == 188: return 7 + if song_number == 192: return 4 + if song_number == 208: return 8 + if song_number == 215: return 8 + if song_number == 220: return 4 + if song_number == 247: return 6 + if song_number == 248: return 6 + if song_number == 251: return 8 + if song_number == 295: return 8 + if song_number == 307: return 5 + if song_number == 314: return 6 + if song_number == 325: return 8 + if song_number == 386: return 6 + if song_number == 415: return 4 + if song_number == 426: return 4 + if song_number == 434: return 5 + if song_number == 437: return 4 + if song_number == 438: return 6 + if song_number == 456: return 8 + if song_number == 461: return 4 + if song_number == 469: return 4 + if song_number == 470: return 5 + if song_number == 476: return 6 + if song_number == 477: return 7 + if song_number == 480: return 8 + if song_number == 482: return 4 + if song_number == 512: return 4 + if song_number == 513: return 8 + if song_number == 518: return 5 + if song_number == 520: return 4 + if song_number == 523: return 6 + if song_number == 526: return 8 + if song_number == 527: return 4 + if song_number == 529: return 4 + if song_number == 537: return 4 + if song_number == 555: return 6 + if song_number == 581: return 4 + if song_number == 589: return 6 + if song_number == 590: return 4 + if song_number == 593: return 8 + if song_number == 596: return 4 + if song_number == 610: return 6 + if song_number == 611: return 6 + if song_number == 619: return 8 + if song_number == 645: return 5 + if song_number == 653: return 6 + if song_number == 683: return 7 + if song_number == 686: return 4 + if song_number == 697: return 8 + if song_number == 698: return 4 + if song_number == 704: return 6 + if song_number == 716: return 4 + if song_number == 717: return 6 + if song_number == 730: return 4 + if song_number == 731: return 8 + if song_number == 732: return 8 + if song_number == 738: return 4 + if song_number == 756: return 9 + if song_number == 815: return 6 + if song_number == 830: return 8 + if song_number == 831: return 4 + if song_number == 876: return 6 + if song_number == 877: return 6 + if song_number == 892: return 4 + if song_number == 894: return 6 + if song_number == 902: return 8 + if song_number == 905: return 8 + if song_number == 921: return 6 + if song_number == 940: return 7 + if song_number == 955: return 9 + if song_number == 968: return 8 + if song_number == 972: return 7 + if song_number == 974: return 4 + if song_number == 988: return 6 + if song_number == 991: return 5 + if song_number == 1002: return 8 + if song_number == 1024: return 8 + if song_number == 1044: return 9 + if song_number == 1088: return 6 + if song_number == 1117: return 6 + if song_number == 1119: return 7 return None - -sof = sofimport() + +#config = None +man = None +#man = SongManager(config) +sof = SofImport(man) sof.start_ooo() -sof.open_sof_file(u'/home/jonathan/sof.rtf') -#sof.open_sof_file(u'c:\users\jonathan\Desktop\sof3words.rtf') -#sof.open_sof_file(u'c:\users\jonathan\Desktop\sof4words.rtf') +#sof.open_ooo_file(u'/home/jonathan/sof.rtf') +sof.open_ooo_file(u'/home/jonathan/Documents/VOLS1_2.RTF') +#sof.open_ooo_file(u'c:\users\jonathan\Desktop\sof3words.rtf') +#sof.open_ooo_file(u'c:\users\jonathan\Desktop\sof4words.rtf') sof.process_doc() sof.close_ooo() diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py new file mode 100644 index 000000000..ff31152bf --- /dev/null +++ b/openlp/plugins/songs/lib/songimport.py @@ -0,0 +1,259 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # +# Thompson, Jon Tibble, Carsten Tinggaard # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import string +from openlp.core.lib import SongXMLBuilder +from openlp.plugins.songs.lib.models import Song + +class SongImport(object): + """ + Helper class for import a song from a third party source into OpenLP + + This class just takes the raw strings, and will work out for itself + whether the authors etc already exist and add them or refer to them + as necessary + """ + + def __init__(self, song_manager): + """ + Initialise and create defaults for properties + + song_manager is an instance of a SongManager, through which all + database access is performed + """ + self.song_manager = song_manager + self.title = u'' + self.song_number = u'' + self.copyright = u'' + self.comment = u'' + self.theme_name = u'' + self.ccli_number = u'' + self.authors = [] + self.topics = [] + self.song_book_name = u'' + self.song_book_pub = u'' + self.verse_order_list = [] + self.verses = [] + self.versecount = 0 + self.choruscount = 0 + + def get_title(self): + """ + Return the title + """ + return self.title + + def get_copyright(self): + """ + Return the copyright + """ + return self.copyright + + def get_song_number(self): + """ + Return the song number (also known as alternate title) + """ + return self.song_number + + def set_title(self, title): + """ + Set the title + """ + self.title = title + + def set_song_number(self, song_number): + """ + Set the song number/alternate title + """ + self.song_number = song_number + + def set_song_book(self, song_book, publisher): + """ + Set the song book name and publisher + """ + self.song_book_name = song_book + self.song_book_pub = publisher + + def add_copyright(self, copyright): + """ + Build the copyright field + """ + if self.copyright != u'': + self.copyright += ' ' + self.copyright += copyright + + def add_author(self, text): + """ + Add an author to the list + """ + self.authors.append(text) + + def add_verse(self, verse, versetag): + """ + Add a verse. This is the whole verse, lines split by \n + Verse tag can be V1/C1/B1 etc, or 'V' and 'C' (will count the verses/ + choruses itself) or None, where it will assume verse + It will also attempt to detect duplicates. In this case it will just + add to the verse order + """ + for (oldversetag, oldverse) in self.verses: + if oldverse.strip() == verse.strip(): + self.verse_order_list.append(oldversetag) + return + if versetag == u'C': + self.choruscount += 1 + versetag += unicode(self.choruscount) + if versetag == u'V' or not versetag: + self.versecount += 1 + versetag = u'V' + unicode(self.versecount) + self.verses.append([versetag, verse]) + self.verse_order_list.append(versetag) + if self.choruscount > 0 and not versetag.startswith(u'C'): + self.verse_order_list.append(u'C1') + + def repeat_verse(self): + """ + Repeat the previous verse in the verse order + """ + self.verse_order_list.append(self.verse_order_list[-1]) + + def check_complete(self): + """ + Check the mandatory fields are entered (i.e. title and a verse) + Author not checked here, if no author then "Author unknown" is + automatically added + """ + if self.title == u'' or len(self.verses) == 0: + return False + else: + return True + + def remove_punctuation(self, text): + """ + Remove punctuation from the string for searchable fields + """ + return text.translate(string.maketrans(u'',u''), string.punctuation) + + def finish(self): + """ + All fields have been set to this song. Write it away + """ + if len(self.authors) == 0: + self.authors.append(u'Author unknown') + #self.commit_song() + self.print_song() + + def commit_song(): + """ + Write the song and it's fields to disk + """ + song = Song() + song.title = self.title + song.search_title = self.remove_punctuation(self.title) + song.song_number = self.song_number + song.search_lyrics = u'' + sxml = SongXMLBuilder() + sxml.new_document() + sxml.add_lyrics_to_song() + for (versetag, versetext) in self.verses: + if versetag[0] == u'C': + versetype = u'Chorus' + elif versetag[0] == u'V': + versetype = u'Verse' + elif versetag[0] == u'B': + versetype = u'Bridge' + elif versetag[0] == u'I': + versetype = u'Intro' + elif versetag[0] == u'P': + versetype = u'Prechorus' + elif versetag[0] == u'E': + versetype = u'Ending' + else: + versetype = u'Other' + sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext) + song.search_lyrics += u' ' + self.remove_punctuation(versetext) + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + song.verse_order = u' '.join(self.verse_order_list) + song.copyright = self.copyright + song.comment = self.comment + song.theme_name = self.theme_name + song.ccli_number = self.ccli_number + for authortext in self.authors: + author = None + # read the author here + if author is None: + author = Author() + author.display_name = authortext + author.last_name = authortext.split(u' ')[-1] + author.first_name = u' '.join(authortext.split(u' ')[:-1]) + # write the author here + song.authors.append(author) + if self.song_book_name: + song_book = None + # read the book here + if song_book is None: + song_book = Book() + song_book.name = self.song_book_name + song_book.publisher = self.song_book_pub + # write the song book here + song.song_book_id = song_book.id + for topictext in self.topics: + topic = None + # read the topic here + if topic is None: + topic = Topic() + topic.name = topictext + # write the topic here + song.topics.append(topictext) + # write the song here + + def print_song(self): + """ + For debugging + """ + print u'========================================' \ + + u'========================================' + print u'TITLE: ' + self.title + for (versetag, versetext) in self.verses: + print u'VERSE ' + versetag + u': ' + versetext + print u'ORDER: ' + u' '.join(self.verse_order_list) + for author in self.authors: + print u'AUTHOR: ' + author + if self.copyright: + print u'COPYRIGHT: ' + self.copyright + if self.song_book_name: + print u'BOOK: ' + self.song_book_name + if self.song_number: + print u'NUMBER: ' + self.song_number + for topictext in self.topics: + print u'TOPIC: ' + topictext + if self.comment: + print u'COMMENT: ' + self.comment + if self.theme_name: + print u'THEME: ' + self.theme_name + if self.ccli_number: + print u'CCLI: ' + self.ccli_number + + From 2cabfc67f3094fca3e158fa66fc8062074fa50b4 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Fri, 2 Apr 2010 15:10:10 +0100 Subject: [PATCH 4/4] Hook it all together --- openlp/plugins/songs/lib/__init__.py | 2 ++ openlp/plugins/songs/lib/manager.py | 18 ++++++++++++ openlp/plugins/songs/lib/sofimport.py | 28 ++++++++---------- openlp/plugins/songs/lib/songimport.py | 39 +++++++++++++------------- openlp/plugins/songs/songsplugin.py | 31 ++++++++++++++++---- 5 files changed, 77 insertions(+), 41 deletions(-) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 338a88b91..4ed56d06b 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -26,3 +26,5 @@ from manager import SongManager from songstab import SongsTab from mediaitem import SongMediaItem +from sofimport import SofImport +from songimport import SongImport diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 87f0e6132..dcb49bfcd 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -133,6 +133,12 @@ class SongManager(): """ return self.session.query(Author).get(id) + def get_author_by_name(self, name): + """ + Get author by display name + """ + return self.session.query(Author).filter_by(display_name=name).first() + def save_author(self, author): """ Save the Author and refresh the cache @@ -172,6 +178,12 @@ class SongManager(): """ return self.session.query(Topic).get(id) + def get_topic_by_name(self, name): + """ + Get topic by name + """ + return self.session.query(Topic).filter_by(name=name).first() + def save_topic(self, topic): """ Save the Topic @@ -211,6 +223,12 @@ class SongManager(): """ return self.session.query(Book).get(id) + def get_book_by_name(self, name): + """ + Get book by name + """ + return self.session.query(Book).filter_by(name=name).first() + def save_book(self, book): """ Save the Book diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index c73449d44..63870f35c 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -73,6 +73,12 @@ class SofImport(object): self.song = None self.manager = songmanager + def import_sof(self, filename): + self.start_ooo() + self.open_ooo_file(filename) + self.process_doc() + self.close_ooo() + def start_ooo(self): """ Start OpenOffice.org process @@ -270,16 +276,16 @@ class SofImport(object): self.song.set_song_number(song_no) if int(song_no) <= 640: self.song.set_song_book(u'Songs of Fellowship 1', - 'Kingsway\'s Thankyou Music') + u'Kingsway Publications') elif int(song_no) <= 1150: self.song.set_song_book(u'Songs of Fellowship 2', - 'Kingsway\'s Thankyou Music') + u'Kingsway Publications') elif int(song_no) <= 1690: self.song.set_song_book(u'Songs of Fellowship 3', - 'Kingsway\'s Thankyou Music') + u'Kingsway Publications') else: self.song.set_song_book(u'Songs of Fellowship 4', - 'Kingsway\'s Thankyou Music') + u'Kingsway Publications') def add_title(self, text): """ @@ -506,16 +512,4 @@ class SofImport(object): if song_number == 1117: return 6 if song_number == 1119: return 7 return None - -#config = None -man = None -#man = SongManager(config) -sof = SofImport(man) -sof.start_ooo() -#sof.open_ooo_file(u'/home/jonathan/sof.rtf') -sof.open_ooo_file(u'/home/jonathan/Documents/VOLS1_2.RTF') -#sof.open_ooo_file(u'c:\users\jonathan\Desktop\sof3words.rtf') -#sof.open_ooo_file(u'c:\users\jonathan\Desktop\sof4words.rtf') -sof.process_doc() -sof.close_ooo() - + diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index ff31152bf..aa9a73fd8 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -25,7 +25,7 @@ import string from openlp.core.lib import SongXMLBuilder -from openlp.plugins.songs.lib.models import Song +from openlp.plugins.songs.lib.models import Song, Author, Topic, Book class SongImport(object): """ @@ -43,7 +43,7 @@ class SongImport(object): song_manager is an instance of a SongManager, through which all database access is performed """ - self.song_manager = song_manager + self.manager = song_manager self.title = u'' self.song_number = u'' self.copyright = u'' @@ -153,8 +153,10 @@ class SongImport(object): def remove_punctuation(self, text): """ Remove punctuation from the string for searchable fields - """ - return text.translate(string.maketrans(u'',u''), string.punctuation) + """ + for c in string.punctuation: + text = text.replace(c, u'') + return text def finish(self): """ @@ -162,10 +164,10 @@ class SongImport(object): """ if len(self.authors) == 0: self.authors.append(u'Author unknown') - #self.commit_song() - self.print_song() + self.commit_song() + #self.print_song() - def commit_song(): + def commit_song(self): """ Write the song and it's fields to disk """ @@ -201,33 +203,30 @@ class SongImport(object): song.theme_name = self.theme_name song.ccli_number = self.ccli_number for authortext in self.authors: - author = None - # read the author here + author = self.manager.get_author_by_name(authortext) if author is None: author = Author() author.display_name = authortext author.last_name = authortext.split(u' ')[-1] author.first_name = u' '.join(authortext.split(u' ')[:-1]) - # write the author here + self.manager.save_author(author) song.authors.append(author) if self.song_book_name: - song_book = None - # read the book here + song_book = self.manager.get_book_by_name(self.song_book_name) if song_book is None: song_book = Book() song_book.name = self.song_book_name song_book.publisher = self.song_book_pub - # write the song book here + self.manager.save_book(song_book) song.song_book_id = song_book.id for topictext in self.topics: - topic = None - # read the topic here + topic = self.manager.get_topic_by_name(topictext) if topic is None: topic = Topic() - topic.name = topictext - # write the topic here - song.topics.append(topictext) - # write the song here + topic.name = topictext + self.manager.save_topic(topic) + song.topics.append(topictext) + self.manager.save_song(song) def print_song(self): """ @@ -245,6 +244,8 @@ class SongImport(object): print u'COPYRIGHT: ' + self.copyright if self.song_book_name: print u'BOOK: ' + self.song_book_name + if self.song_book_pub: + print u'BOOK PUBLISHER: ' + self.song_book_pub if self.song_number: print u'NUMBER: ' + self.song_number for topictext in self.topics: diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 152392443..6d39daa48 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -28,7 +28,8 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, build_icon, PluginStatus -from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab +from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \ + SofImport from openlp.plugins.songs.forms import OpenLPImportForm, OpenSongExportForm, \ OpenSongImportForm, OpenLPExportForm @@ -102,24 +103,35 @@ class SongsPlugin(Plugin): self.ImportOpenlp1Item.setObjectName(u'ImportOpenlp1Item') self.ImportOpenlp2Item = QtGui.QAction(import_menu) self.ImportOpenlp2Item.setObjectName(u'ImportOpenlp2Item') + self.ImportSofItem = QtGui.QAction(import_menu) + self.ImportSofItem.setObjectName(u'ImportSofItem') # Add to menus self.ImportSongMenu.addAction(self.ImportOpenlp1Item) self.ImportSongMenu.addAction(self.ImportOpenlp2Item) self.ImportSongMenu.addAction(self.ImportOpenSongItem) + self.ImportSongMenu.addAction(self.ImportSofItem) import_menu.addAction(self.ImportSongMenu.menuAction()) # Translations... self.ImportSongMenu.setTitle(import_menu.trUtf8('&Song')) self.ImportOpenSongItem.setText(import_menu.trUtf8('OpenSong')) self.ImportOpenlp1Item.setText(import_menu.trUtf8('openlp.org 1.0')) self.ImportOpenlp1Item.setToolTip( - import_menu.trUtf8('Export songs in openlp.org 1.0 format')) + import_menu.trUtf8('Import songs in openlp.org 1.0 format')) self.ImportOpenlp1Item.setStatusTip( - import_menu.trUtf8('Export songs in openlp.org 1.0 format')) + import_menu.trUtf8('Import songs in openlp.org 1.0 format')) self.ImportOpenlp2Item.setText(import_menu.trUtf8('OpenLP 2.0')) self.ImportOpenlp2Item.setToolTip( - import_menu.trUtf8('Export songs in OpenLP 2.0 format')) + import_menu.trUtf8('Import songs in OpenLP 2.0 format')) self.ImportOpenlp2Item.setStatusTip( - import_menu.trUtf8('Export songs in OpenLP 2.0 format')) + import_menu.trUtf8('Import songs in OpenLP 2.0 format')) + self.ImportSofItem.setText( + import_menu.trUtf8('Songs of Fellowship')) + self.ImportSofItem.setToolTip( + import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \ + + '.rtf and sof4words.rtf supplied with the music books')) + self.ImportSofItem.setStatusTip( + import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \ + + '.rtf and sof4words.rtf supplied with the music books')) # Signals and slots QtCore.QObject.connect(self.ImportOpenlp1Item, QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick) @@ -127,6 +139,8 @@ class SongsPlugin(Plugin): QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick) QtCore.QObject.connect(self.ImportOpenSongItem, QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick) + QtCore.QObject.connect(self.ImportSofItem, + QtCore.SIGNAL(u'triggered()'), self.onImportSofItemClick) self.ImportSongMenu.menuAction().setVisible(False) def add_export_menu_item(self, export_menu): @@ -169,6 +183,13 @@ class SongsPlugin(Plugin): def onImportOpenSongItemClick(self): self.opensong_import_form.show() + def onImportSofItemClick(self): + filename = QtGui.QFileDialog.getOpenFileName( + None, self.trUtf8('Open Songs of Fellowship file'), + u'', u'Songs of Fellowship file (*.rtf *.RTF)') + sofimport = SofImport(self.songmanager) + sofimport.import_sof(unicode(filename)) + def onExportOpenlp1ItemClicked(self): self.openlp_export_form.show()