From 6b6da86c54cbd64b6044a2b30df7aaaa5ed6efc1 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Fri, 27 Aug 2010 20:53:22 +0100 Subject: [PATCH 1/6] wow_import implemented in to import wizard bug fix in wizzard, so that it starts from the first page if used previously bux fix in importer, so that it resets the defualts after commiting a song to the db --- openlp/plugins/songs/forms/songimportform.py | 3 ++- openlp/plugins/songs/lib/importer.py | 3 +++ openlp/plugins/songs/lib/songimport.py | 16 +++++++++------- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 68bba299d..6fb6b38a0 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -160,7 +160,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard): self.openSongAddButton.setFocus() return False elif source_format == SongFormat.WordsOfWorship: - if self.wordsOfWorshipListWidget.count() == 0: + if self.wordsOfWorshipFileListWidget.count() == 0: QtGui.QMessageBox.critical(self, translate('SongsPlugin.ImportWizardForm', 'No Words of Worship Files Selected'), @@ -315,6 +315,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard): pass def setDefaults(self): + self.restart() self.formatComboBox.setCurrentIndex(0) self.openLP2FilenameEdit.setText(u'') self.openLP1FilenameEdit.setText(u'') diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 7410a5184..ae18f4389 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -29,6 +29,7 @@ from olpimport import OpenLPSongImport try: from sofimport import SofImport from oooimport import OooImport + from wowimport import WowImport except ImportError: pass @@ -63,6 +64,8 @@ class SongFormat(object): return OpenSongImport elif format == SongFormat.SongsOfFellowship: return SofImport + elif format == SongFormat.WordsOfWorship: + return WowImport elif format == SongFormat.Generic: return OooImport # else: diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 2ffb0beda..84f0ffd93 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -52,6 +52,13 @@ class SongImport(QtCore.QObject): """ self.manager = manager self.stop_import_flag = False + self.copyright_string = unicode(translate( + 'SongsPlugin.SongImport', 'copyright')) + self.copyright_symbol = unicode(translate( + 'SongsPlugin.SongImport', '\xa9')) + self.setDefaults() + + def setDefaults(self): self.title = u'' self.song_number = u'' self.alternate_title = u'' @@ -67,13 +74,7 @@ class SongImport(QtCore.QObject): self.verses = [] self.versecount = 0 self.choruscount = 0 - self.copyright_string = unicode(translate( - 'SongsPlugin.SongImport', 'copyright')) - self.copyright_symbol = unicode(translate( - 'SongsPlugin.SongImport', '\xa9')) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'songs_stop_import'), self.stop_import) - + def stop_import(self): """ Sets the flag for importers to stop their import @@ -298,6 +299,7 @@ class SongImport(QtCore.QObject): topic = Topic.populate(name=topictext) song.topics.append(topic) self.manager.save_object(song) + self.setDefaults() def print_song(self): """ From 4e059f8cc5dc81e0886ac79907b3d2ea6460d07c Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Fri, 27 Aug 2010 21:02:59 +0100 Subject: [PATCH 2/6] Forgot to add the wowimport.py file --- openlp/plugins/songs/lib/wowimport.py | 170 ++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 openlp/plugins/songs/lib/wowimport.py diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py new file mode 100644 index 000000000..78a9aed5a --- /dev/null +++ b/openlp/plugins/songs/lib/wowimport.py @@ -0,0 +1,170 @@ +# -*- 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, Meinert Jordan, Andreas Preikschat, Christian # +# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`wowimport` module provides the functionality for importing Words of +Worship songs into the OpenLP database. +""" +import os +import logging + +from openlp.plugins.songs.lib.songimport import SongImport + +BLOCK_TYPES = (u'V', u'C', u'B') + +log = logging.getLogger(__name__) + +class WowImport(SongImport): + """ + The :class:`WowImport` class provides the ability to import song files from + Words of Worship. + + Words Of Worship Song File Format + ````````````````````````````````` + + The Words Of Worship song file format is as follows: + + * The song title is the file name minus the extension. + * The song has a header, a number of blocks, followed by footer containing + the author and the copyright. + * A block can be a verse, chorus or bridge. + + File Header: + Bytes are counted from one, i.e. the first byte is byte 1. These bytes, + up to the 56 byte, can change but no real meaning has been found. The + 56th byte specifies how many blocks there are. The first block starts + with byte 83 after the "CSongDoc::CBlock" declaration. + + Blocks: + Each block has a starting header, some lines of text, and an ending + footer. Each block starts with 4 bytes, the first byte specifies how + many lines are in that block, the next three bytes are null bytes. + + Each block ends with 4 bytes, the first of which defines what type of + block it is, and the rest which are null bytes: + + * ``NUL`` (\x00) - Verse + * ``SOH`` (\x01) - Chorus + * ``STX`` (\x02) - Bridge + + Blocks are seperated by two bytes. The first byte is ``SOH`` (\x01), + and the second byte is ``€`` (\x80). + + Lines: + Each line starts with a byte which specifies how long that line is, + the line text, and ends with a null byte. + + + Footer: + The footer follows on after the last block, the first byte specifies + the length of the author text, followed by the author text, if + this byte is null, then there is no author text. The byte after the + author text specifies the length of the copyright text, followed + by the copyright text. + + The file is ended with four null bytes. + + Valid extensions for a Words of Worship song file are: + + * .wsg + * .wow-song + """ + + def __init__(self, master_manager, **kwargs): + """ + Initialise the import. + + ``master_manager`` + The song manager for the running OpenLP installation. + """ + SongImport.__init__(self, master_manager) + self.master_manager = master_manager + if kwargs.has_key(u'filename'): + self.import_source = kwargs[u'filename'] + if kwargs.has_key(u'filenames'): + self.import_source = kwargs[u'filenames'] + log.debug(self.import_source) + + def do_import(self): + """ + Recieve a single file, or a list of files to import. + """ + + if isinstance(self.import_source, list): + self.import_wizard.importProgressBar.setMaximum( + len(self.import_source)) + for file in self.import_source: + # TODO: check that it is a valid words of worship file (could check + # header for WoW File Song Word) + self.author = u'' + self.copyright= u'' + # Get the song title + self.file_name = os.path.split(file)[1] + self.import_wizard.incrementProgressBar("Importing %s" % (self.file_name), 0) + self.title = self.file_name.rpartition(u'.')[0] + self.songData = open(file, 'rb') + # Seek to byte which stores number of blocks in the song + self.songData.seek(56) + self.no_of_blocks = ord(self.songData.read(1)) + # Seek to the beging of the first block + self.songData.seek(82) + for block in range(self.no_of_blocks): + self.lines_to_read = ord(self.songData.read(1)) + # Skip 3 nulls to the beginnig of the 1st line + self.songData.seek(3, os.SEEK_CUR) + self.block_text = u'' + while self.lines_to_read: + self.length_of_line = ord(self.songData.read(1)) + self.line_text = unicode( + self.songData.read(self.length_of_line), u'cp1252') + self.songData.seek(1, os.SEEK_CUR) + if self.block_text != u'': + self.block_text += u'\n' + self.block_text += self.line_text + self.lines_to_read -= 1 + self.block_type = BLOCK_TYPES[ord(self.songData.read(1))] + # Skip 3 nulls at the end of the block + self.songData.seek(3, os.SEEK_CUR) + # Blocks are seperated by 2 bytes, skip them, but not if + # this is the last block! + if (block + 1) < self.no_of_blocks: + self.songData.seek(2, os.SEEK_CUR) + self.add_verse(self.block_text, self.block_type) + # Now to extact the author + self.author_length = ord(self.songData.read(1)) + if self.author_length != 0: + self.author = unicode(self.songData.read(self.author_length), + u'cp1252') + # Finally the copyright + self.copyright_length = ord(self.songData.read(1)) + if self.copyright_length != 0: + self.copyright = unicode(self.songData.read(self.copyright_length), + u'cp1252') + self.parse_author(self.author) + self.add_copyright(self.copyright) + self.songData.close() + self.finish() + self.import_wizard.incrementProgressBar("Importing %s" % (self.file_name)) + return True From e4f4626f046b2f5e8a7f88a83aba0ee174256d56 Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Fri, 27 Aug 2010 21:14:23 +0100 Subject: [PATCH 3/6] shortened some long lines. --- openlp/plugins/songs/lib/wowimport.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index 78a9aed5a..cb4ebf9ae 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -116,13 +116,14 @@ class WowImport(SongImport): self.import_wizard.importProgressBar.setMaximum( len(self.import_source)) for file in self.import_source: - # TODO: check that it is a valid words of worship file (could check - # header for WoW File Song Word) + # TODO: check that it is a valid words of worship file (could + # check header for WoW File Song Word) self.author = u'' self.copyright= u'' # Get the song title self.file_name = os.path.split(file)[1] - self.import_wizard.incrementProgressBar("Importing %s" % (self.file_name), 0) + self.import_wizard.incrementProgressBar( + "Importing %s" % (self.file_name), 0) self.title = self.file_name.rpartition(u'.')[0] self.songData = open(file, 'rb') # Seek to byte which stores number of blocks in the song @@ -155,16 +156,17 @@ class WowImport(SongImport): # Now to extact the author self.author_length = ord(self.songData.read(1)) if self.author_length != 0: - self.author = unicode(self.songData.read(self.author_length), - u'cp1252') + self.author = unicode( + self.songData.read(self.author_length), u'cp1252') # Finally the copyright self.copyright_length = ord(self.songData.read(1)) if self.copyright_length != 0: - self.copyright = unicode(self.songData.read(self.copyright_length), - u'cp1252') + self.copyright = unicode( + self.songData.read(self.copyright_length), u'cp1252') self.parse_author(self.author) self.add_copyright(self.copyright) self.songData.close() self.finish() - self.import_wizard.incrementProgressBar("Importing %s" % (self.file_name)) + self.import_wizard.incrementProgressBar( + "Importing %s" % (self.file_name)) return True From 1611251ec24746edb4572383514c294c4ddbabbe Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Fri, 27 Aug 2010 21:18:48 +0100 Subject: [PATCH 4/6] and an empty line at the end --- openlp/plugins/songs/lib/wowimport.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index cb4ebf9ae..dd09034d1 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -170,3 +170,4 @@ class WowImport(SongImport): self.import_wizard.incrementProgressBar( "Importing %s" % (self.file_name)) return True + From f712ccca50f645728df54728fa49bc9d53d4af5a Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sat, 28 Aug 2010 03:51:29 +0100 Subject: [PATCH 5/6] Signal fix as mentioned by Meths --- openlp/plugins/songs/lib/songimport.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 84f0ffd93..e270ee09d 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -56,6 +56,8 @@ class SongImport(QtCore.QObject): 'SongsPlugin.SongImport', 'copyright')) self.copyright_symbol = unicode(translate( 'SongsPlugin.SongImport', '\xa9')) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'songs_stop_import'), self.stop_import) self.setDefaults() def setDefaults(self): From 271bbe22b25b5d3ce89ae738833a93425192e63b Mon Sep 17 00:00:00 2001 From: Philip Ridout Date: Sat, 28 Aug 2010 21:46:03 +0100 Subject: [PATCH 6/6] Made the constants more like constants! --- openlp/plugins/songs/lib/songimport.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index e270ee09d..dd83c679d 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -43,6 +43,12 @@ class SongImport(QtCore.QObject): whether the authors etc already exist and add them or refer to them as necessary """ + + COPYRIGHT_STRING = unicode(translate( + 'SongsPlugin.SongImport', 'copyright')) + COPYRIGHT_SYMBOL = unicode(translate( + 'SongsPlugin.SongImport', '\xa9')) + def __init__(self, manager): """ Initialise and create defaults for properties @@ -52,10 +58,6 @@ class SongImport(QtCore.QObject): """ self.manager = manager self.stop_import_flag = False - self.copyright_string = unicode(translate( - 'SongsPlugin.SongImport', 'copyright')) - self.copyright_symbol = unicode(translate( - 'SongsPlugin.SongImport', '\xa9')) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_stop_import'), self.stop_import) self.setDefaults() @@ -129,13 +131,13 @@ class SongImport(QtCore.QObject): def process_verse_text(self, text): lines = text.split(u'\n') - if text.lower().find(self.copyright_string) >= 0 \ - or text.lower().find(self.copyright_symbol) >= 0: + if text.lower().find(COPYRIGHT_STRING) >= 0 \ + or text.lower().find(COPYRIGHT_SYMBOL) >= 0: copyright_found = False for line in lines: if (copyright_found or - line.lower().find(self.copyright_string) >= 0 or - line.lower().find(self.copyright_symbol) >= 0): + line.lower().find(COPYRIGHT_STRING) >= 0 or + line.lower().find(COPYRIGHT_SYMBOL) >= 0): copyright_found = True self.add_copyright(line) else: