forked from openlp/openlp
Head 794
This commit is contained in:
commit
d96126ee55
@ -78,9 +78,7 @@ class OpenLP(QtGui.QApplication):
|
||||
Run the OpenLP application.
|
||||
"""
|
||||
#Load and store current Application Version
|
||||
filepath = AppLocation.get_directory(AppLocation.AppDir)
|
||||
if not hasattr(sys, u'frozen'):
|
||||
filepath = os.path.join(filepath, u'openlp')
|
||||
filepath = AppLocation.get_directory(AppLocation.VersionDir)
|
||||
filepath = os.path.join(filepath, u'.version')
|
||||
fversion = None
|
||||
try:
|
||||
|
@ -139,8 +139,9 @@ class PluginConfig(object):
|
||||
list = []
|
||||
if list_count > 0:
|
||||
for counter in range(0, list_count):
|
||||
item = unicode(self.get_config(u'%s %d' % (name, counter)))
|
||||
list.append(item)
|
||||
item = self.get_config(u'%s %d' % (name, counter))
|
||||
if item:
|
||||
list.append(item)
|
||||
return list
|
||||
|
||||
def set_list(self, name, list):
|
||||
|
@ -43,9 +43,10 @@ class AppLocation(object):
|
||||
ConfigDir = 2
|
||||
DataDir = 3
|
||||
PluginsDir = 4
|
||||
VersionDir = 5
|
||||
|
||||
@staticmethod
|
||||
def get_directory(dir_type):
|
||||
def get_directory(dir_type=1):
|
||||
"""
|
||||
Return the appropriate directory according to the directory type.
|
||||
|
||||
@ -83,17 +84,18 @@ class AppLocation(object):
|
||||
elif dir_type == AppLocation.PluginsDir:
|
||||
plugin_path = None
|
||||
app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
|
||||
if sys.platform == u'win32':
|
||||
if hasattr(sys, u'frozen') and sys.frozen == 1:
|
||||
plugin_path = os.path.join(app_path, u'plugins')
|
||||
else:
|
||||
plugin_path = os.path.join(app_path, u'openlp', u'plugins')
|
||||
elif sys.platform == u'darwin':
|
||||
if hasattr(sys, u'frozen') and sys.frozen == 1:
|
||||
plugin_path = os.path.join(app_path, u'plugins')
|
||||
else:
|
||||
plugin_path = os.path.join(
|
||||
os.path.split(openlp.__file__)[0], u'plugins')
|
||||
return plugin_path
|
||||
elif dir_type == AppLocation.VersionDir:
|
||||
if hasattr(sys, u'frozen') and sys.frozen == 1:
|
||||
plugin_path = os.path.abspath(os.path.split(sys.argv[0])[0])
|
||||
else:
|
||||
plugin_path = os.path.split(openlp.__file__)[0]
|
||||
return plugin_path
|
||||
|
||||
|
||||
def check_latest_version(config, current_version):
|
||||
|
@ -41,15 +41,17 @@ class Registry(object):
|
||||
"""
|
||||
Check if a value exists.
|
||||
"""
|
||||
return self.config.has_option(section, key)
|
||||
return self.config.has_option(section.encode('utf-8'),
|
||||
key.encode('utf-8'))
|
||||
|
||||
def get_value(self, section, key, default=None):
|
||||
"""
|
||||
Get a single value from the registry.
|
||||
"""
|
||||
try:
|
||||
if self.config.get(section, key):
|
||||
return self.config.get(section, key)
|
||||
if self.config.get(section.encode('utf-8'), key.encode('utf-8')):
|
||||
return self.config.get(section.encode('utf-8'),
|
||||
key.encode('utf-8')).decode('utf-8')
|
||||
else:
|
||||
return default
|
||||
except:
|
||||
@ -60,7 +62,8 @@ class Registry(object):
|
||||
Set a single value in the registry.
|
||||
"""
|
||||
try :
|
||||
self.config.set(section, key, unicode(value))
|
||||
self.config.set(section.encode('utf-8'), key.encode('utf-8'),
|
||||
unicode(value).encode('utf-8'))
|
||||
return self._save()
|
||||
except:
|
||||
return False
|
||||
@ -70,7 +73,8 @@ class Registry(object):
|
||||
Delete a single value from the registry.
|
||||
"""
|
||||
try:
|
||||
self.config.remove_option(section, key)
|
||||
self.config.remove_option(section.encode('utf-8'),
|
||||
key.encode('utf-8'))
|
||||
return self._save()
|
||||
except:
|
||||
return False
|
||||
@ -79,14 +83,14 @@ class Registry(object):
|
||||
"""
|
||||
Check if a section exists.
|
||||
"""
|
||||
return self.config.has_section(section)
|
||||
return self.config.has_section(section.encode('utf-8'))
|
||||
|
||||
def create_section(self, section):
|
||||
"""
|
||||
Create a new section in the registry.
|
||||
"""
|
||||
try:
|
||||
self.config.add_section(section)
|
||||
self.config.add_section(section.encode('utf-8'))
|
||||
return self._save()
|
||||
except:
|
||||
return False
|
||||
@ -96,7 +100,7 @@ class Registry(object):
|
||||
Delete a section (including all values).
|
||||
"""
|
||||
try:
|
||||
self.config.remove_section(section)
|
||||
self.config.remove_section(section.encode('utf-8'))
|
||||
return self._save()
|
||||
except:
|
||||
return False
|
||||
|
@ -27,7 +27,6 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, str_to_bool
|
||||
from openlp.plugins.alerts.lib.models import AlertItem
|
||||
from openlp.plugins.alerts.lib import alertsmanager
|
||||
|
||||
class AlertsTab(SettingsTab):
|
||||
"""
|
||||
|
@ -27,4 +27,5 @@ from manager import SongManager
|
||||
from songstab import SongsTab
|
||||
from mediaitem import SongMediaItem
|
||||
from sofimport import SofImport
|
||||
from oooimport import OooImport
|
||||
from songimport import SongImport
|
||||
|
197
openlp/plugins/songs/lib/oooimport.py
Normal file
197
openlp/plugins/songs/lib/oooimport.py
Normal file
@ -0,0 +1,197 @@
|
||||
# -*- 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 os
|
||||
from PyQt4 import QtCore
|
||||
from songimport import SongImport
|
||||
|
||||
if os.name == u'nt':
|
||||
from win32com.client import Dispatch
|
||||
PAGE_BEFORE = 4
|
||||
PAGE_AFTER = 5
|
||||
PAGE_BOTH = 6
|
||||
else:
|
||||
try:
|
||||
import uno
|
||||
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
|
||||
except:
|
||||
pass
|
||||
class OooImport(object):
|
||||
"""
|
||||
Import songs from Impress/Powerpoint docs using Impress
|
||||
"""
|
||||
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.manager = songmanager
|
||||
self.document = None
|
||||
self.process_started = False
|
||||
|
||||
def import_docs(self, filenames):
|
||||
self.start_ooo()
|
||||
for filename in filenames:
|
||||
filename = unicode(filename)
|
||||
if os.path.isfile(filename):
|
||||
self.open_ooo_file(filename)
|
||||
if self.document:
|
||||
if self.document.supportsService(
|
||||
"com.sun.star.presentation.PresentationDocument"):
|
||||
self.process_pres()
|
||||
if self.document.supportsService(
|
||||
"com.sun.star.text.TextDocument"):
|
||||
self.process_doc()
|
||||
self.close_ooo_file()
|
||||
self.close_ooo()
|
||||
|
||||
def start_ooo(self):
|
||||
"""
|
||||
Start OpenOffice.org process
|
||||
TODO: The presentation/Impress plugin may already have it running
|
||||
"""
|
||||
if os.name == u'nt':
|
||||
self.start_ooo_process()
|
||||
self.desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
||||
else:
|
||||
context = uno.getComponentContext()
|
||||
resolver = context.ServiceManager.createInstanceWithContext(
|
||||
u'com.sun.star.bridge.UnoUrlResolver', context)
|
||||
ctx = None
|
||||
loop = 0
|
||||
while ctx is None and loop < 5:
|
||||
try:
|
||||
ctx = resolver.resolve(u'uno:socket,host=localhost,' \
|
||||
+ 'port=2002;urp;StarOffice.ComponentContext')
|
||||
except:
|
||||
pass
|
||||
self.start_ooo_process()
|
||||
loop += 1
|
||||
manager = ctx.ServiceManager
|
||||
self.desktop = manager.createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", ctx )
|
||||
|
||||
def start_ooo_process(self):
|
||||
try:
|
||||
if os.name == u'nt':
|
||||
self.manager = Dispatch(u'com.sun.star.ServiceManager')
|
||||
self.manager._FlagAsMethod(u'Bridge_GetStruct')
|
||||
self.manager._FlagAsMethod(u'Bridge_GetValueObject')
|
||||
else:
|
||||
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()
|
||||
self.process_started = True
|
||||
except:
|
||||
pass
|
||||
|
||||
def open_ooo_file(self, filepath):
|
||||
"""
|
||||
Open the passed file in OpenOffice.org Impress
|
||||
"""
|
||||
if os.name == u'nt':
|
||||
url = u'file:///' + filepath.replace(u'\\', u'/')
|
||||
url = url.replace(u':', u'|').replace(u' ', u'%20')
|
||||
else:
|
||||
url = uno.systemPathToFileUrl(filepath)
|
||||
properties = []
|
||||
properties = tuple(properties)
|
||||
try:
|
||||
self.document = self.desktop.loadComponentFromURL(url, u'_blank',
|
||||
0, properties)
|
||||
if not self.document.supportsService(
|
||||
"com.sun.star.presentation.PresentationDocument") \
|
||||
and not self.document.supportsService(
|
||||
"com.sun.star.text.TextDocument"):
|
||||
self.close_ooo_file()
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
def close_ooo_file(self):
|
||||
"""
|
||||
Close file.
|
||||
"""
|
||||
self.document.close(True)
|
||||
self.document = None
|
||||
|
||||
def close_ooo(self):
|
||||
"""
|
||||
Close OOo. But only if we started it and not on windows
|
||||
"""
|
||||
if self.process_started:
|
||||
self.desktop.terminate()
|
||||
|
||||
def process_pres(self):
|
||||
"""
|
||||
Process the file
|
||||
"""
|
||||
doc = self.document
|
||||
slides = doc.getDrawPages()
|
||||
text = u''
|
||||
for slide_no in range(slides.getCount()):
|
||||
slide = slides.getByIndex(slide_no)
|
||||
slidetext = u''
|
||||
for idx in range(slide.getCount()):
|
||||
shape = slide.getByIndex(idx)
|
||||
if shape.supportsService("com.sun.star.drawing.Text"):
|
||||
if shape.getString().strip() != u'':
|
||||
slidetext += shape.getString().strip() + u'\n\n'
|
||||
if slidetext.strip() == u'':
|
||||
slidetext = u'\f'
|
||||
text += slidetext
|
||||
song = SongImport(self.manager)
|
||||
songs = SongImport.process_songs_text(self.manager, text)
|
||||
for song in songs:
|
||||
song.finish()
|
||||
return
|
||||
|
||||
def process_doc(self):
|
||||
"""
|
||||
Process the doc file, a paragraph at a time
|
||||
"""
|
||||
text = u''
|
||||
paragraphs = self.document.getText().createEnumeration()
|
||||
while paragraphs.hasMoreElements():
|
||||
paratext = u''
|
||||
paragraph = paragraphs.nextElement()
|
||||
if paragraph.supportsService("com.sun.star.text.Paragraph"):
|
||||
textportions = paragraph.createEnumeration()
|
||||
while textportions.hasMoreElements():
|
||||
textportion = textportions.nextElement()
|
||||
if textportion.BreakType in (PAGE_BEFORE, PAGE_BOTH):
|
||||
paratext += u'\f'
|
||||
paratext += textportion.getString()
|
||||
if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH):
|
||||
paratext += u'\f'
|
||||
text += paratext + u'\n'
|
||||
songs = SongImport.process_songs_text(self.manager, text)
|
||||
for song in songs:
|
||||
song.finish()
|
||||
|
@ -24,23 +24,24 @@
|
||||
###############################################################################
|
||||
|
||||
# OOo API documentation:
|
||||
# http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Structure_of_Text_Documents
|
||||
# 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
|
||||
import time
|
||||
from PyQt4 import QtCore
|
||||
from songimport import SongImport
|
||||
|
||||
from songimport import SongImport
|
||||
from oooimport import OooImport
|
||||
|
||||
if os.name == u'nt':
|
||||
from win32com.client import Dispatch
|
||||
BOLD = 150.0
|
||||
ITALIC = 2
|
||||
PAGE_BEFORE = 4
|
||||
PAGE_AFTER = 5
|
||||
ITALIC = 2
|
||||
PAGE_BEFORE = 4
|
||||
PAGE_AFTER = 5
|
||||
PAGE_BOTH = 6
|
||||
else:
|
||||
import uno
|
||||
@ -48,7 +49,7 @@ else:
|
||||
from com.sun.star.awt.FontSlant import ITALIC
|
||||
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
|
||||
|
||||
class SofImport(object):
|
||||
class SofImport(OooImport):
|
||||
"""
|
||||
Import songs provided on disks with the Songs of Fellowship music books
|
||||
VOLS1_2.RTF, sof3words.rtf and sof4words.rtf
|
||||
@ -69,95 +70,28 @@ class SofImport(object):
|
||||
Initialise the class. Requires a songmanager class which is passed
|
||||
to SongImport for writing song to disk
|
||||
"""
|
||||
self.song = None
|
||||
self.manager = songmanager
|
||||
self.process_started = False
|
||||
OooImport.__init__(self,songmanager)
|
||||
|
||||
def import_sof(self, filename):
|
||||
self.start_ooo()
|
||||
self.open_ooo_file(filename)
|
||||
self.process_doc()
|
||||
self.process_sof_file()
|
||||
self.close_ooo_file()
|
||||
self.close_ooo()
|
||||
|
||||
def start_ooo(self):
|
||||
"""
|
||||
Start OpenOffice.org process
|
||||
TODO: The presentation/Impress plugin may already have it running
|
||||
"""
|
||||
if os.name == u'nt':
|
||||
self.start_ooo_process()
|
||||
self.desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
|
||||
else:
|
||||
context = uno.getComponentContext()
|
||||
resolver = context.ServiceManager.createInstanceWithContext(
|
||||
u'com.sun.star.bridge.UnoUrlResolver', context)
|
||||
ctx = None
|
||||
loop = 0
|
||||
while ctx is None and loop < 5:
|
||||
try:
|
||||
ctx = resolver.resolve(u'uno:socket,host=localhost,' \
|
||||
+ 'port=2002;urp;StarOffice.ComponentContext')
|
||||
except:
|
||||
pass
|
||||
self.start_ooo_process()
|
||||
loop += 1
|
||||
manager = ctx.ServiceManager
|
||||
self.desktop = manager.createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", ctx )
|
||||
|
||||
def start_ooo_process(self):
|
||||
try:
|
||||
if os.name == u'nt':
|
||||
self.manager = Dispatch(u'com.sun.star.ServiceManager')
|
||||
self.manager._FlagAsMethod(u'Bridge_GetStruct')
|
||||
self.manager._FlagAsMethod(u'Bridge_GetValueObject')
|
||||
else:
|
||||
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()
|
||||
self.process_started = True
|
||||
except:
|
||||
pass
|
||||
|
||||
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')
|
||||
else:
|
||||
url = uno.systemPathToFileUrl(filepath)
|
||||
properties = []
|
||||
properties = tuple(properties)
|
||||
self.document = self.desktop.loadComponentFromURL(url, u'_blank',
|
||||
0, properties)
|
||||
|
||||
def close_ooo(self):
|
||||
"""
|
||||
Close RTF file. Note, on Windows we'll leave OOo running
|
||||
Leave running on Windows
|
||||
"""
|
||||
self.document.close(True)
|
||||
if self.process_started:
|
||||
self.desktop.terminate()
|
||||
|
||||
def process_doc(self):
|
||||
def process_sof_file(self):
|
||||
"""
|
||||
Process the RTF file, a paragraph at a time
|
||||
"""
|
||||
"""
|
||||
self.blanklines = 0
|
||||
self.new_song()
|
||||
self.new_song()
|
||||
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.process_paragraph(paragraph)
|
||||
if self.song:
|
||||
self.song.finish()
|
||||
self.song = None
|
||||
|
||||
def process_paragraph(self, paragraph):
|
||||
@ -171,71 +105,71 @@ class SofImport(object):
|
||||
In later books, there may not be line breaks, so check for 3 or more
|
||||
newlines
|
||||
"""
|
||||
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 = u''
|
||||
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 = u''
|
||||
text += self.process_textportion(textportion)
|
||||
if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH):
|
||||
self.process_paragraph_text(text)
|
||||
self.new_song()
|
||||
text = u''
|
||||
self.process_paragraph_text(text)
|
||||
|
||||
if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH):
|
||||
self.process_paragraph_text(text)
|
||||
self.new_song()
|
||||
text = u''
|
||||
self.process_paragraph_text(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()
|
||||
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
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.get_title() != u'':
|
||||
self.finish_verse()
|
||||
return
|
||||
self.blanklines = 0
|
||||
if self.skip_to_close_bracket:
|
||||
if text.endswith(u')'):
|
||||
self.skip_to_close_bracket = False
|
||||
return
|
||||
"""
|
||||
text = text.strip()
|
||||
if text == u'':
|
||||
self.blanklines += 1
|
||||
if self.blanklines > 1:
|
||||
return
|
||||
if self.song.get_title() != u'':
|
||||
self.finish_verse()
|
||||
return
|
||||
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.italics = False
|
||||
return
|
||||
if text == u'A Songs of Fellowship Worship Resource':
|
||||
return
|
||||
self.italics = False
|
||||
return
|
||||
if text == u'A Songs of Fellowship Worship Resource':
|
||||
return
|
||||
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(u'Copyright'):
|
||||
self.song.add_copyright(text)
|
||||
return
|
||||
if text == u'(Repeat)':
|
||||
self.finish_verse()
|
||||
self.song.repeat_verse()
|
||||
return
|
||||
or text.startswith(u'(From'):
|
||||
self.skip_to_close_bracket = True
|
||||
return
|
||||
if text.startswith(u'Copyright'):
|
||||
self.song.add_copyright(text)
|
||||
return
|
||||
if text == u'(Repeat)':
|
||||
self.finish_verse()
|
||||
self.song.repeat_verse()
|
||||
return
|
||||
if self.song.get_title() == u'':
|
||||
if self.song.get_copyright() == u'':
|
||||
self.add_author(text)
|
||||
else:
|
||||
self.song.add_copyright(text)
|
||||
return
|
||||
if self.song.get_copyright() == u'':
|
||||
self.add_author(text)
|
||||
else:
|
||||
self.song.add_copyright(text)
|
||||
return
|
||||
self.add_verse_line(text)
|
||||
|
||||
def process_textportion(self, textportion):
|
||||
@ -244,157 +178,132 @@ class SofImport(object):
|
||||
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)
|
||||
text = SongImport.tidy_text(text)
|
||||
if text.strip() == u'':
|
||||
return text
|
||||
if textportion.CharWeight == BOLD:
|
||||
boldtext = text.strip()
|
||||
if boldtext.isdigit() and self.song.get_song_number() == '':
|
||||
self.add_songnumber(boldtext)
|
||||
return u''
|
||||
return text
|
||||
if textportion.CharWeight == BOLD:
|
||||
boldtext = text.strip()
|
||||
if boldtext.isdigit() and self.song.get_song_number() == '':
|
||||
self.add_songnumber(boldtext)
|
||||
return u''
|
||||
if self.song.get_title() == u'':
|
||||
text = self.uncap_text(text)
|
||||
self.add_title(text)
|
||||
text = self.uncap_text(text)
|
||||
self.add_title(text)
|
||||
return text
|
||||
if text.strip().startswith(u'('):
|
||||
return text
|
||||
self.italics = (textportion.CharPosture == ITALIC)
|
||||
return text
|
||||
|
||||
return text
|
||||
self.italics = (textportion.CharPosture == ITALIC)
|
||||
return text
|
||||
|
||||
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:
|
||||
self.finish_verse()
|
||||
"""
|
||||
if self.song:
|
||||
self.finish_verse()
|
||||
if not self.song.check_complete():
|
||||
return
|
||||
self.song.finish()
|
||||
return
|
||||
self.song.finish()
|
||||
self.song = SongImport(self.manager)
|
||||
self.skip_to_close_bracket = False
|
||||
self.is_chorus = False
|
||||
self.is_chorus = False
|
||||
self.italics = False
|
||||
self.currentverse = u''
|
||||
|
||||
|
||||
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)
|
||||
self.song.set_alternate_title(song_no + u'.')
|
||||
if int(song_no) <= 640:
|
||||
self.song.set_song_book(u'Songs of Fellowship 1',
|
||||
u'Kingsway Publications')
|
||||
elif int(song_no) <= 1150:
|
||||
self.song.set_song_book(u'Songs of Fellowship 2',
|
||||
u'Kingsway Publications')
|
||||
elif int(song_no) <= 1690:
|
||||
self.song.set_song_book(u'Songs of Fellowship 3',
|
||||
u'Kingsway Publications')
|
||||
else:
|
||||
self.song.set_song_book(u'Songs of Fellowship 4',
|
||||
u'Kingsway Publications')
|
||||
self.song.set_alternate_title(song_no + u'.')
|
||||
if int(song_no) <= 640:
|
||||
self.song.set_song_book(u'Songs of Fellowship 1',
|
||||
u'Kingsway Publications')
|
||||
elif int(song_no) <= 1150:
|
||||
self.song.set_song_book(u'Songs of Fellowship 2',
|
||||
u'Kingsway Publications')
|
||||
elif int(song_no) <= 1690:
|
||||
self.song.set_song_book(u'Songs of Fellowship 3',
|
||||
u'Kingsway Publications')
|
||||
else:
|
||||
self.song.set_song_book(u'Songs of Fellowship 4',
|
||||
u'Kingsway Publications')
|
||||
|
||||
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)
|
||||
|
||||
"""
|
||||
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]
|
||||
if author2.endswith(u'.'):
|
||||
author2 = author2[:-1]
|
||||
if author2:
|
||||
self.song.add_author(author2)
|
||||
|
||||
"""
|
||||
text = text.replace(u' and ', u' & ')
|
||||
self.song.parse_author(text)
|
||||
|
||||
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'
|
||||
|
||||
"""
|
||||
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.is_chorus:
|
||||
versetag = u'C'
|
||||
splitat = None
|
||||
else:
|
||||
versetag = u'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.song.add_verse(verse, versetag)
|
||||
ln = 0
|
||||
if line:
|
||||
verse = line + u'\n'
|
||||
else:
|
||||
verse = u''
|
||||
else:
|
||||
verse += line + u'\n'
|
||||
if verse:
|
||||
self.song.add_verse(verse, versetag)
|
||||
else:
|
||||
self.song.add_verse(self.currentverse, versetag)
|
||||
self.currentverse = u''
|
||||
self.is_chorus = False
|
||||
|
||||
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
|
||||
|
||||
if self.currentverse.strip() == u'':
|
||||
return
|
||||
if self.is_chorus:
|
||||
versetag = u'C'
|
||||
splitat = None
|
||||
else:
|
||||
versetag = u'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.song.add_verse(verse, versetag)
|
||||
ln = 0
|
||||
if line:
|
||||
verse = line + u'\n'
|
||||
else:
|
||||
verse = u''
|
||||
else:
|
||||
verse += line + u'\n'
|
||||
if verse:
|
||||
self.song.add_verse(verse, versetag)
|
||||
else:
|
||||
self.song.add_verse(self.currentverse, versetag)
|
||||
self.currentverse = u''
|
||||
self.is_chorus = False
|
||||
|
||||
|
||||
def uncap_text(self, text):
|
||||
"""
|
||||
Words in the title are in all capitals, so we lowercase them.
|
||||
@ -403,128 +312,128 @@ class SofImport(object):
|
||||
|
||||
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 verse_splits(self, song_number):
|
||||
"""
|
||||
Because someone at Kingsway forgot to check the 1+2 RTF file,
|
||||
some verses were not formatted correctly.
|
||||
"""
|
||||
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
|
||||
"""
|
||||
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 verse_splits(self, song_number):
|
||||
"""
|
||||
Because someone at Kingsway forgot to check the 1+2 RTF file,
|
||||
some verses were not formatted correctly.
|
||||
"""
|
||||
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
|
||||
|
||||
|
@ -24,9 +24,10 @@
|
||||
###############################################################################
|
||||
|
||||
import string
|
||||
from openlp.core.lib import SongXMLBuilder
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from openlp.core.lib import SongXMLBuilder
|
||||
from openlp.plugins.songs.lib.models import Song, Author, Topic, Book
|
||||
|
||||
|
||||
class SongImport(object):
|
||||
"""
|
||||
Helper class for import a song from a third party source into OpenLP
|
||||
@ -42,232 +43,328 @@ class SongImport(object):
|
||||
|
||||
song_manager is an instance of a SongManager, through which all
|
||||
database access is performed
|
||||
"""
|
||||
"""
|
||||
self.manager = song_manager
|
||||
self.title = u''
|
||||
self.title = u''
|
||||
self.song_number = u''
|
||||
self.alternate_title = 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
|
||||
|
||||
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
|
||||
self.copyright_string = unicode(QtGui.QApplication.translate( \
|
||||
u'SongImport', u'copyright'))
|
||||
self.copyright_symbol = unicode(QtGui.QApplication.translate( \
|
||||
u'SongImport', u'©'))
|
||||
|
||||
@staticmethod
|
||||
def process_songs_text(manager, text):
|
||||
songs = []
|
||||
songtexts = SongImport.tidy_text(text).split(u'\f')
|
||||
song = SongImport(manager)
|
||||
for songtext in songtexts:
|
||||
if songtext.strip():
|
||||
song.process_song_text(songtext.strip())
|
||||
if song.check_complete():
|
||||
songs.append(song)
|
||||
song = SongImport(manager)
|
||||
if song.check_complete():
|
||||
songs.append(song)
|
||||
return songs
|
||||
|
||||
@staticmethod
|
||||
def tidy_text(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\n', u'\n')
|
||||
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'-')
|
||||
# Remove surplus blank lines, spaces, trailing/leading spaces
|
||||
while text.find(u' ') >= 0:
|
||||
text = text.replace(u' ', u' ')
|
||||
text = text.replace(u'\n ', u'\n')
|
||||
text = text.replace(u' \n', u'\n')
|
||||
text = text.replace(u'\n\n\n\n\n', u'\f')
|
||||
text = text.replace(u'\f ', u'\f')
|
||||
text = text.replace(u' \f', u'\f')
|
||||
while text.find(u'\f\f') >= 0:
|
||||
text = text.replace(u'\f\f', u'\f')
|
||||
return text
|
||||
|
||||
def process_song_text(self, text):
|
||||
versetexts = text.split(u'\n\n')
|
||||
for versetext in versetexts:
|
||||
if versetext.strip() != u'':
|
||||
self.process_verse_text(versetext.strip())
|
||||
|
||||
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:
|
||||
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:
|
||||
copyright_found = True
|
||||
self.add_copyright(line)
|
||||
else:
|
||||
self.parse_author(line)
|
||||
return
|
||||
if len(lines) == 1:
|
||||
self.parse_author(lines[0])
|
||||
return
|
||||
if not self.get_title():
|
||||
self.set_title(lines[0])
|
||||
self.add_verse(text)
|
||||
|
||||
def get_title(self):
|
||||
"""
|
||||
Return the title
|
||||
"""
|
||||
return self.title
|
||||
|
||||
"""
|
||||
return self.title
|
||||
|
||||
def get_copyright(self):
|
||||
"""
|
||||
Return the copyright
|
||||
"""
|
||||
return self.copyright
|
||||
|
||||
"""
|
||||
return self.copyright
|
||||
|
||||
def get_song_number(self):
|
||||
"""
|
||||
Return the song number
|
||||
"""
|
||||
return self.song_number
|
||||
|
||||
"""
|
||||
return self.song_number
|
||||
|
||||
def set_title(self, title):
|
||||
"""
|
||||
Set the title
|
||||
"""
|
||||
self.title = title
|
||||
"""
|
||||
self.title = title
|
||||
|
||||
def set_alternate_title(self, title):
|
||||
"""
|
||||
Set the alternate title
|
||||
"""
|
||||
self.alternate_title = title
|
||||
|
||||
"""
|
||||
self.alternate_title = title
|
||||
|
||||
def set_song_number(self, song_number):
|
||||
"""
|
||||
Set the song number
|
||||
"""
|
||||
self.song_number = song_number
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
if self.copyright.find(copyright) >= 0:
|
||||
return
|
||||
if self.copyright != u'':
|
||||
self.copyright += ' '
|
||||
self.copyright += copyright
|
||||
|
||||
def parse_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".
|
||||
"""
|
||||
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]
|
||||
if author2.endswith(u'.'):
|
||||
author2 = author2[:-1]
|
||||
if author2:
|
||||
self.add_author(author2)
|
||||
|
||||
def add_author(self, author):
|
||||
"""
|
||||
Add an author to the list
|
||||
"""
|
||||
self.authors.append(text)
|
||||
|
||||
def add_verse(self, verse, versetag):
|
||||
"""
|
||||
if author in self.authors:
|
||||
return
|
||||
self.authors.append(author)
|
||||
|
||||
def add_verse(self, verse, versetag=None):
|
||||
"""
|
||||
Add a verse. This is the whole verse, lines split by \n
|
||||
Verse tag can be V1/C1/B 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)
|
||||
"""
|
||||
for (oldversetag, oldverse) in self.verses:
|
||||
if oldverse.strip() == verse.strip():
|
||||
self.verse_order_list.append(oldversetag)
|
||||
return
|
||||
if versetag.startswith(u'C'):
|
||||
self.choruscount += 1
|
||||
if versetag == u'C':
|
||||
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.rstrip()])
|
||||
self.verse_order_list.append(versetag)
|
||||
if versetag.startswith(u'V') and self.contains_verse(u'C1'):
|
||||
self.verse_order_list.append(u'C1')
|
||||
|
||||
if versetag == u'V' or not versetag:
|
||||
self.versecount += 1
|
||||
versetag = u'V' + unicode(self.versecount)
|
||||
if versetag.startswith(u'C'):
|
||||
self.choruscount += 1
|
||||
if versetag == u'C':
|
||||
versetag += unicode(self.choruscount)
|
||||
self.verses.append([versetag, verse.rstrip()])
|
||||
self.verse_order_list.append(versetag)
|
||||
if versetag.startswith(u'V') and self.contains_verse(u'C1'):
|
||||
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])
|
||||
"""
|
||||
self.verse_order_list.append(self.verse_order_list[-1])
|
||||
|
||||
def contains_verse(self, versetag):
|
||||
return versetag in self.verse_order_list
|
||||
|
||||
|
||||
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
|
||||
|
||||
"""
|
||||
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
|
||||
"""
|
||||
for c in string.punctuation:
|
||||
for c in string.punctuation:
|
||||
text = text.replace(c, u'')
|
||||
return text
|
||||
|
||||
return text
|
||||
|
||||
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()
|
||||
"""
|
||||
if len(self.authors) == 0:
|
||||
self.authors.append(u'Author unknown')
|
||||
self.commit_song()
|
||||
#self.print_song()
|
||||
|
||||
|
||||
def commit_song(self):
|
||||
"""
|
||||
Write the song and it's fields to disk
|
||||
"""
|
||||
song = Song()
|
||||
song.title = self.title
|
||||
"""
|
||||
song = Song()
|
||||
song.title = self.title
|
||||
song.search_title = self.remove_punctuation(self.title) \
|
||||
+ '@' + self.alternate_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 = 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])
|
||||
self.manager.save_author(author)
|
||||
song.authors.append(author)
|
||||
if self.song_book_name:
|
||||
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
|
||||
self.manager.save_book(song_book)
|
||||
song.song_book_id = song_book.id
|
||||
for topictext in self.topics:
|
||||
topic = self.manager.get_topic_by_name(topictext)
|
||||
if topic is None:
|
||||
topic = Topic()
|
||||
+ '@' + self.alternate_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 = 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])
|
||||
self.manager.save_author(author)
|
||||
song.authors.append(author)
|
||||
if self.song_book_name:
|
||||
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
|
||||
self.manager.save_book(song_book)
|
||||
song.song_book_id = song_book.id
|
||||
for topictext in self.topics:
|
||||
topic = self.manager.get_topic_by_name(topictext)
|
||||
if topic is None:
|
||||
topic = Topic()
|
||||
topic.name = topictext
|
||||
self.manager.save_topic(topic)
|
||||
self.manager.save_topic(topic)
|
||||
song.topics.append(topictext)
|
||||
self.manager.save_song(song)
|
||||
|
||||
def print_song(self):
|
||||
"""
|
||||
For debugging
|
||||
"""
|
||||
print u'========================================' \
|
||||
+ u'========================================'
|
||||
print u'TITLE: ' + self.title
|
||||
print u'ALT TITLE: ' + self.alternate_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_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:
|
||||
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
|
||||
|
||||
self.manager.save_song(song)
|
||||
|
||||
def print_song(self):
|
||||
"""
|
||||
For debugging
|
||||
"""
|
||||
print u'========================================' \
|
||||
+ u'========================================'
|
||||
print u'TITLE: ' + self.title
|
||||
print u'ALT TITLE: ' + self.alternate_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_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:
|
||||
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
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver
|
||||
from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \
|
||||
SofImport
|
||||
SofImport, OooImport
|
||||
from openlp.plugins.songs.forms import OpenLPImportForm, OpenSongExportForm, \
|
||||
OpenSongImportForm, OpenLPExportForm
|
||||
|
||||
@ -105,11 +105,14 @@ class SongsPlugin(Plugin):
|
||||
self.ImportOpenlp2Item.setObjectName(u'ImportOpenlp2Item')
|
||||
self.ImportSofItem = QtGui.QAction(import_menu)
|
||||
self.ImportSofItem.setObjectName(u'ImportSofItem')
|
||||
self.ImportOooItem = QtGui.QAction(import_menu)
|
||||
self.ImportOooItem.setObjectName(u'ImportOooItem')
|
||||
# Add to menus
|
||||
self.ImportSongMenu.addAction(self.ImportOpenlp1Item)
|
||||
self.ImportSongMenu.addAction(self.ImportOpenlp2Item)
|
||||
self.ImportSongMenu.addAction(self.ImportOpenSongItem)
|
||||
self.ImportSongMenu.addAction(self.ImportSofItem)
|
||||
self.ImportSongMenu.addAction(self.ImportOooItem)
|
||||
import_menu.addAction(self.ImportSongMenu.menuAction())
|
||||
# Translations...
|
||||
self.ImportSongMenu.setTitle(import_menu.trUtf8('&Song'))
|
||||
@ -132,6 +135,12 @@ class SongsPlugin(Plugin):
|
||||
self.ImportSofItem.setStatusTip(
|
||||
import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \
|
||||
+ '.rtf and sof4words.rtf supplied with the music books'))
|
||||
self.ImportOooItem.setText(
|
||||
import_menu.trUtf8('Generic Document/Presentation Import'))
|
||||
self.ImportOooItem.setToolTip(
|
||||
import_menu.trUtf8('Import songs from Word/Writer/Powerpoint/Impress'))
|
||||
self.ImportOooItem.setStatusTip(
|
||||
import_menu.trUtf8('Import songs from Word/Writer/Powerpoint/Impress'))
|
||||
# Signals and slots
|
||||
QtCore.QObject.connect(self.ImportOpenlp1Item,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick)
|
||||
@ -141,6 +150,8 @@ class SongsPlugin(Plugin):
|
||||
QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick)
|
||||
QtCore.QObject.connect(self.ImportSofItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onImportSofItemClick)
|
||||
QtCore.QObject.connect(self.ImportOooItem,
|
||||
QtCore.SIGNAL(u'triggered()'), self.onImportOooItemClick)
|
||||
self.ImportSongMenu.menuAction().setVisible(False)
|
||||
|
||||
def add_export_menu_item(self, export_menu):
|
||||
@ -184,12 +195,13 @@ class SongsPlugin(Plugin):
|
||||
self.opensong_import_form.show()
|
||||
|
||||
def onImportSofItemClick(self):
|
||||
filename = QtGui.QFileDialog.getOpenFileName(
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(
|
||||
None, self.trUtf8('Open Songs of Fellowship file'),
|
||||
u'', u'Songs of Fellowship file (*.rtf *.RTF)')
|
||||
try:
|
||||
sofimport = SofImport(self.songmanager)
|
||||
sofimport.import_sof(unicode(filename))
|
||||
for filename in filenames:
|
||||
sofimport = SofImport(self.songmanager)
|
||||
sofimport.import_sof(unicode(filename))
|
||||
except:
|
||||
log.exception('Could not import SoF file')
|
||||
QtGui.QMessageBox.critical(None,
|
||||
@ -202,6 +214,14 @@ class SongsPlugin(Plugin):
|
||||
QtGui.QMessageBox.Ok)
|
||||
Receiver.send_message(u'load_song_list')
|
||||
|
||||
def onImportOooItemClick(self):
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(
|
||||
None, self.trUtf8('Open documents or presentations'),
|
||||
u'', u'All Files(*.*)')
|
||||
oooimport = OooImport(self.songmanager)
|
||||
oooimport.import_docs(filenames)
|
||||
Receiver.send_message(u'load_song_list')
|
||||
|
||||
def onExportOpenlp1ItemClicked(self):
|
||||
self.openlp_export_form.show()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user