This commit is contained in:
Samuel Findlay 2012-07-09 10:34:35 +10:00
commit f83d48293f
45 changed files with 33732 additions and 33281 deletions

View File

@ -39,7 +39,8 @@ log = logging.getLogger(__name__)
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
ItemCapabilities, SettingsManager, translate, str_to_bool ItemCapabilities, SettingsManager, translate, str_to_bool, \
check_directory_exists
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.settings import Settings from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
@ -556,8 +557,7 @@ class ServiceManager(QtGui.QWidget):
audio_from = os.path.join(self.servicePath, audio_from) audio_from = os.path.join(self.servicePath, audio_from)
save_file = os.path.join(self.servicePath, audio_to) save_file = os.path.join(self.servicePath, audio_to)
save_path = os.path.split(save_file)[0] save_path = os.path.split(save_file)[0]
if not os.path.exists(save_path): check_directory_exists(save_path)
os.makedirs(save_path)
if not os.path.exists(save_file): if not os.path.exists(save_file):
shutil.copy(audio_from, save_file) shutil.copy(audio_from, save_file)
zip.write(audio_from, audio_to.encode(u'utf-8')) zip.write(audio_from, audio_to.encode(u'utf-8'))

View File

@ -226,7 +226,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
def onCurrentIdChanged(self, pageId): def onCurrentIdChanged(self, pageId):
""" """
Detects Page changes and updates as approprate. Detects Page changes and updates as appropriate.
""" """
enabled = self.page(pageId) == self.areaPositionPage enabled = self.page(pageId) == self.areaPositionPage
self.setOption(QtGui.QWizard.HaveCustomButton1, enabled) self.setOption(QtGui.QWizard.HaveCustomButton1, enabled)

View File

@ -172,6 +172,11 @@ def _get_os_dir_path(dir_type):
u'Library', u'Application Support', u'openlp') u'Library', u'Application Support', u'openlp')
else: else:
if dir_type == AppLocation.LanguageDir: if dir_type == AppLocation.LanguageDir:
prefixes = [u'/usr/local', u'/usr']
for prefix in prefixes:
directory = os.path.join(prefix, u'share', u'openlp')
if os.path.exists(directory):
return directory
return os.path.join(u'/usr', u'share', u'openlp') return os.path.join(u'/usr', u'share', u'openlp')
if XDG_BASE_AVAILABLE: if XDG_BASE_AVAILABLE:
if dir_type == AppLocation.ConfigDir: if dir_type == AppLocation.ConfigDir:

View File

@ -227,9 +227,6 @@ class ImpressDocument(PresentationDocument):
OpenOffice task started earlier. If OpenOffice is not present is is OpenOffice task started earlier. If OpenOffice is not present is is
started. Once the environment is available the presentation is loaded started. Once the environment is available the presentation is loaded
and started. and started.
``presentation``
The file name of the presentatios to the run.
""" """
log.debug(u'Load Presentation OpenOffice') log.debug(u'Load Presentation OpenOffice')
if os.name == u'nt': if os.name == u'nt':

View File

@ -119,10 +119,7 @@ class PowerpointDocument(PresentationDocument):
def load_presentation(self): def load_presentation(self):
""" """
Called when a presentation is added to the SlideController. Called when a presentation is added to the SlideController.
Opens the PowerPoint file using the process created earlier Opens the PowerPoint file using the process created earlier.
``presentation``
The file name of the presentations to run.
""" """
log.debug(u'load_presentation') log.debug(u'load_presentation')
if not self.controller.process or not self.controller.process.Visible: if not self.controller.process or not self.controller.process.Visible:

View File

@ -118,9 +118,6 @@ class PptviewDocument(PresentationDocument):
Called when a presentation is added to the SlideController. Called when a presentation is added to the SlideController.
It builds the environment, starts communcations with the background It builds the environment, starts communcations with the background
PptView task started earlier. PptView task started earlier.
``presentation``
The file name of the presentations to run.
""" """
log.debug(u'LoadPresentation') log.debug(u'LoadPresentation')
renderer = self.controller.plugin.renderer renderer = self.controller.plugin.renderer

View File

@ -47,7 +47,7 @@ class PresentationDocument(object):
**Hook Functions** **Hook Functions**
``load_presentation(presentation)`` ``load_presentation()``
Load a presentation file Load a presentation file
``close_presentation()`` ``close_presentation()``
@ -104,11 +104,8 @@ class PresentationDocument(object):
def load_presentation(self): def load_presentation(self):
""" """
Called when a presentation is added to the SlideController. Called when a presentation is added to the SlideController. Loads the
Loads the presentation and starts it presentation and starts it.
``presentation``
The file name of the presentations to the run.
Returns False if the file could not be opened Returns False if the file could not be opened
""" """

View File

@ -61,14 +61,14 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
def onFirstNameEditTextEdited(self, display_name): def onFirstNameEditTextEdited(self, display_name):
if not self._autoDisplayName: if not self._autoDisplayName:
return return
if not self.lastNameEdit.text(): if self.lastNameEdit.text():
display_name = display_name + u' ' + self.lastNameEdit.text() display_name = display_name + u' ' + self.lastNameEdit.text()
self.displayEdit.setText(display_name) self.displayEdit.setText(display_name)
def onLastNameEditTextEdited(self, display_name): def onLastNameEditTextEdited(self, display_name):
if not self._autoDisplayName: if not self._autoDisplayName:
return return
if not self.firstNameEdit.text(): if self.firstNameEdit.text():
display_name = self.firstNameEdit.text() + u' ' + display_name display_name = self.firstNameEdit.text() + u' ' + display_name
self.displayEdit.setText(display_name) self.displayEdit.setText(display_name)

View File

@ -34,7 +34,7 @@ import shutil
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import PluginStatus, Receiver, MediaType, translate, \ from openlp.core.lib import PluginStatus, Receiver, MediaType, translate, \
create_separated_list create_separated_list, check_directory_exists
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \ from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
critical_error_message_box, find_and_set_in_combo_box critical_error_message_box, find_and_set_in_combo_box
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
@ -880,8 +880,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
save_path = os.path.join( save_path = os.path.join(
AppLocation.get_section_data_path(self.mediaitem.plugin.name), AppLocation.get_section_data_path(self.mediaitem.plugin.name),
'audio', str(self.song.id)) 'audio', str(self.song.id))
if not os.path.exists(save_path): check_directory_exists(save_path)
os.makedirs(save_path)
self.song.media_files = [] self.song.media_files = []
files = [] files = []
for row in xrange(self.audioListWidget.count()): for row in xrange(self.audioListWidget.count()):

View File

@ -541,12 +541,13 @@ class SongImportSourcePage(QtGui.QWizardPage):
if wizard.formatWidgets[format][u'fileListWidget'].count() > 0: if wizard.formatWidgets[format][u'fileListWidget'].count() > 0:
return True return True
else: else:
filepath = wizard.formatWidgets[format][u'filepathEdit'].text() filepath = unicode(
if not filepath.isEmpty(): wizard.formatWidgets[format][u'filepathEdit'].text())
if select_mode == SongFormatSelect.SingleFile \ if filepath:
and os.path.isfile(filepath): if select_mode == SongFormatSelect.SingleFile and \
os.path.isfile(filepath):
return True return True
elif select_mode == SongFormatSelect.SingleFolder \ elif select_mode == SongFormatSelect.SingleFolder and \
and os.path.isdir(filepath): os.path.isdir(filepath):
return True return True
return False return False

View File

@ -476,7 +476,7 @@ def get_encoding(font, font_table, default_encoding, failed=False):
Dictionary of fonts and respective encodings. Dictionary of fonts and respective encodings.
``default_encoding`` ``default_encoding``
The defaul encoding to use when font_table is empty or no font is used. The default encoding to use when font_table is empty or no font is used.
``failed`` ``failed``
A boolean indicating whether the previous encoding didn't work. A boolean indicating whether the previous encoding didn't work.

View File

@ -48,15 +48,8 @@ class EasySlidesImport(SongImport):
Initialise the class. Initialise the class.
""" """
SongImport.__init__(self, manager, **kwargs) SongImport.__init__(self, manager, **kwargs)
self.commit = True
def doImport(self): def doImport(self):
"""
Import either each of the files in self.importSources - each element of
which can be either a single opensong file, or a zipfile containing
multiple opensong files. If `self.commit` is set False, the
import will not be committed to the database (useful for test scripts).
"""
log.info(u'Importing EasySlides XML file %s', self.importSource) log.info(u'Importing EasySlides XML file %s', self.importSource)
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
parsed_file = etree.parse(self.importSource, parser) parsed_file = etree.parse(self.importSource, parser)

View File

@ -28,6 +28,7 @@
""" """
The :mod:`importer` modules provides the general song import functionality. The :mod:`importer` modules provides the general song import functionality.
""" """
import os
import logging import logging
from openlp.core.lib import translate from openlp.core.lib import translate
@ -44,6 +45,7 @@ from powersongimport import PowerSongImport
from ewimport import EasyWorshipSongImport from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport from songshowplusimport import SongShowPlusImport
from songproimport import SongProImport
from sundayplusimport import SundayPlusImport from sundayplusimport import SundayPlusImport
from foilpresenterimport import FoilPresenterImport from foilpresenterimport import FoilPresenterImport
from zionworximport import ZionWorxImport from zionworximport import ZionWorxImport
@ -67,6 +69,13 @@ try:
except ImportError: except ImportError:
log.exception('Error importing %s', 'OooImport') log.exception('Error importing %s', 'OooImport')
HAS_OOO = False HAS_OOO = False
HAS_MEDIASHOUT = False
if os.name == u'nt':
try:
from mediashoutimport import MediaShoutImport
HAS_MEDIASHOUT = True
except ImportError:
log.exception('Error importing %s', 'MediaShoutImport')
class SongFormatSelect(object): class SongFormatSelect(object):
@ -100,6 +109,7 @@ class SongFormat(object):
``u'canDisable'`` ``u'canDisable'``
Whether song format importer is disablable. Whether song format importer is disablable.
If ``True``, then ``u'disabledLabelText'`` must also be defined.
``u'availability'`` ``u'availability'``
Whether song format importer is available. Whether song format importer is available.
@ -141,15 +151,16 @@ class SongFormat(object):
EasySlides = 6 EasySlides = 6
EasyWorship = 7 EasyWorship = 7
FoilPresenter = 8 FoilPresenter = 8
OpenSong = 9 MediaShout = 9
PowerSong = 10 OpenSong = 10
SongBeamer = 11 PowerSong = 11
SongShowPlus = 12 SongBeamer = 12
SongsOfFellowship = 13 SongPro = 13
SundayPlus = 14 SongShowPlus = 14
WordsOfWorship = 15 SongsOfFellowship = 15
ZionWorx = 16 SundayPlus = 16
#CSV = 17 WordsOfWorship = 17
ZionWorx = 18
# Set optional attribute defaults # Set optional attribute defaults
__defaults__ = { __defaults__ = {
@ -240,6 +251,14 @@ class SongFormat(object):
u'filter': u'%s (*.foil)' % translate( u'filter': u'%s (*.foil)' % translate(
'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files') 'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files')
}, },
MediaShout: {
u'name': u'MediaShout',
u'prefix': u'mediaShout',
u'canDisable': True,
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.mdb)' % translate('SongsPlugin.ImportWizardForm',
'MediaShout Database')
},
OpenSong: { OpenSong: {
u'class': OpenSongImport, u'class': OpenSongImport,
u'name': WizardStrings.OS, u'name': WizardStrings.OS,
@ -260,6 +279,18 @@ class SongFormat(object):
u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
'SongBeamer Files') 'SongBeamer Files')
}, },
SongPro: {
u'class': SongProImport,
u'name': u'SongPro',
u'prefix': u'songPro',
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.txt)' % translate('SongsPlugin.ImportWizardForm',
'SongPro Text Files'),
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
'SongPro (Export File)'),
u'descriptionText': translate('SongsPlugin.ImportWizardForm',
'In SongPro, export your songs using the File -> Export menu')
},
SongShowPlus: { SongShowPlus: {
u'class': SongShowPlusImport, u'class': SongShowPlusImport,
u'name': u'SongShow Plus', u'name': u'SongShow Plus',
@ -302,12 +333,6 @@ class SongFormat(object):
'First convert your ZionWorx database to a CSV text file, as ' 'First convert your ZionWorx database to a CSV text file, as '
'explained in the <a href="http://manual.openlp.org/songs.html' 'explained in the <a href="http://manual.openlp.org/songs.html'
'#importing-from-zionworx">User Manual</a>.') '#importing-from-zionworx">User Manual</a>.')
# },
# CSV: {
# u'class': CSVImport,
# u'name': WizardStrings.CSV,
# u'prefix': u'csv',
# u'selectMode': SongFormatSelect.SingleFile
} }
} }
@ -326,9 +351,11 @@ class SongFormat(object):
SongFormat.EasySlides, SongFormat.EasySlides,
SongFormat.EasyWorship, SongFormat.EasyWorship,
SongFormat.FoilPresenter, SongFormat.FoilPresenter,
SongFormat.MediaShout,
SongFormat.OpenSong, SongFormat.OpenSong,
SongFormat.PowerSong, SongFormat.PowerSong,
SongFormat.SongBeamer, SongFormat.SongBeamer,
SongFormat.SongPro,
SongFormat.SongShowPlus, SongFormat.SongShowPlus,
SongFormat.SongsOfFellowship, SongFormat.SongsOfFellowship,
SongFormat.SundayPlus, SongFormat.SundayPlus,
@ -383,5 +410,8 @@ if HAS_SOF:
SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO) SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO)
if HAS_OOO: if HAS_OOO:
SongFormat.set(SongFormat.Generic, u'class', OooImport) SongFormat.set(SongFormat.Generic, u'class', OooImport)
SongFormat.set(SongFormat.MediaShout, u'availability', HAS_MEDIASHOUT)
if HAS_MEDIASHOUT:
SongFormat.set(SongFormat.MediaShout, u'class', MediaShoutImport)
__all__ = [u'SongFormat', u'SongFormatSelect'] __all__ = [u'SongFormat', u'SongFormatSelect']

View File

@ -36,7 +36,8 @@ from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_ from sqlalchemy.sql import or_
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_item_selected, PluginStatus, create_separated_list translate, check_item_selected, PluginStatus, create_separated_list, \
check_directory_exists
from openlp.core.lib.ui import UiStrings, create_widget_action from openlp.core.lib.ui import UiStrings, create_widget_action
from openlp.core.lib.settings import Settings from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
@ -89,8 +90,7 @@ class SongMediaItem(MediaManagerItem):
dest_file = os.path.join( dest_file = os.path.join(
AppLocation.get_section_data_path(self.plugin.name), AppLocation.get_section_data_path(self.plugin.name),
u'audio', str(song.id), os.path.split(bga)[1]) u'audio', str(song.id), os.path.split(bga)[1])
if not os.path.exists(os.path.split(dest_file)[0]): check_directory_exists(os.path.split(dest_file)[0])
os.makedirs(os.path.split(dest_file)[0])
shutil.copyfile(os.path.join( shutil.copyfile(os.path.join(
AppLocation.get_section_data_path( AppLocation.get_section_data_path(
u'servicemanager'), bga), u'servicemanager'), bga),

View File

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, 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:`mediashoutimport` module provides the functionality for importing
a MediaShout database into the OpenLP database.
"""
import re
import os
import pyodbc
from openlp.core.lib import translate
from openlp.plugins.songs.lib.songimport import SongImport
VERSE_TAGS = [u'V', u'C', u'B', u'O', u'P', u'I', u'E']
class MediaShoutImport(SongImport):
"""
The :class:`MediaShoutImport` class provides the ability to import the
MediaShout Access Database
"""
def __init__(self, manager, **kwargs):
"""
Initialise the MediaShout importer.
"""
SongImport.__init__(self, manager, **kwargs)
def doImport(self):
"""
Receive a single file to import.
"""
try:
conn = pyodbc.connect(u'DRIVER={Microsoft Access Driver (*.mdb)};'
u'DBQ=%s;PWD=6NOZ4eHK7k' % self.importSource)
except:
# Unfortunately no specific exception type
self.logError(self.importSource,
translate('SongsPlugin.MediaShoutImport',
'Unable to open the MediaShout database.'))
return
cursor = conn.cursor()
cursor.execute(u'SELECT Record, Title, Author, Copyright, '
u'SongID, CCLI, Notes FROM Songs ORDER BY Title')
songs = cursor.fetchall()
self.importWizard.progressBar.setMaximum(len(songs))
for song in songs:
if self.stopImportFlag:
break
cursor.execute(u'SELECT Type, Number, Text FROM Verses '
u'WHERE Record = %s ORDER BY Type, Number' % song.Record)
verses = cursor.fetchall()
cursor.execute(u'SELECT Type, Number, POrder FROM PlayOrder '
u'WHERE Record = %s ORDER BY POrder' % song.Record)
verse_order = cursor.fetchall()
cursor.execute(u'SELECT Name FROM Themes INNER JOIN SongThemes '
u'ON SongThemes.ThemeId = Themes.ThemeId '
u'WHERE SongThemes.Record = %s' % song.Record)
topics = cursor.fetchall()
cursor.execute(u'SELECT Name FROM Groups INNER JOIN SongGroups '
u'ON SongGroups.GroupId = Groups.GroupId '
u'WHERE SongGroups.Record = %s' % song.Record)
topics += cursor.fetchall()
self.processSong(song, verses, verse_order, topics)
def processSong(self, song, verses, verse_order, topics):
"""
Create the song, i.e. title, verse etc.
"""
self.setDefaults()
self.title = song.Title
self.parseAuthor(song.Author)
self.addCopyright(song.Copyright)
self.comments = song.Notes
for topic in topics:
self.topics.append(topic.Name)
if u'-' in song.SongID:
self.songBookName, self.songNumber = song.SongID.split(u'-', 1)
else:
self.songBookName = song.SongID
for verse in verses:
tag = VERSE_TAGS[verse.Type] + unicode(verse.Number) \
if verse.Type < len(VERSE_TAGS) else u'O'
self.addVerse(verse.Text, tag)
for order in verse_order:
if order.Type < len(VERSE_TAGS):
self.verseOrderList.append(VERSE_TAGS[order.Type]
+ unicode(order.Number))
self.finish()

View File

@ -33,7 +33,7 @@ import os
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate, check_directory_exists
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib import clean_song, VerseType
@ -388,8 +388,7 @@ class SongImport(QtCore.QObject):
AppLocation.get_section_data_path( AppLocation.get_section_data_path(
self.importWizard.plugin.name), self.importWizard.plugin.name),
'audio', str(song_id)) 'audio', str(song_id))
if not os.path.exists(self.save_path): check_directory_exists(self.save_path)
os.makedirs(self.save_path)
if not filename.startswith(self.save_path): if not filename.startswith(self.save_path):
oldfile, filename = filename, os.path.join(self.save_path, oldfile, filename = filename, os.path.join(self.save_path,
os.path.split(filename)[1]) os.path.split(filename)[1])

View File

@ -0,0 +1,143 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, 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:`songproimport` module provides the functionality for importing SongPro
songs into the OpenLP database.
"""
import re
import os
from openlp.core.lib import translate
from openlp.plugins.songs.lib import strip_rtf
from openlp.plugins.songs.lib.songimport import SongImport
class SongProImport(SongImport):
"""
The :class:`SongProImport` class provides the ability to import song files
from SongPro export files.
**SongPro Song File Format:**
SongPro has the option to export under its File menu
This produces files containing single or multiple songs
The file is text with lines tagged with # followed by an identifier.
This is documented here: http://creationsoftware.com/ImportIdentifiers.php
An example here: http://creationsoftware.com/ExampleImportingManySongs.txt
#A - next line is the Song Author
#B - the lines following until next tagged line are the "Bridge" words
(can be in rtf or plain text) which we map as B1
#C - the lines following until next tagged line are the chorus words
(can be in rtf or plain text)
which we map as C1
#D - the lines following until next tagged line are the "Ending" words
(can be in rtf or plain text) which we map as E1
#E - this song ends here, so we process the song -
and start again at the next line
#G - next line is the Group
#M - next line is the Song Number
#N - next line are Notes
#R - next line is the SongCopyright
#O - next line is the Verse Sequence
#T - next line is the Song Title
#1 - #7 the lines following until next tagged line are the verse x words
(can be in rtf or plain text)
"""
def __init__(self, manager, **kwargs):
"""
Initialise the SongPro importer.
"""
SongImport.__init__(self, manager, **kwargs)
def doImport(self):
"""
Receive a single file or a list of files to import.
"""
self.encoding = None
with open(self.importSource, 'r') as songs_file:
self.importWizard.progressBar.setMaximum(0)
tag = u''
text = u''
for file_line in songs_file:
if self.stopImportFlag:
break
file_line = unicode(file_line, u'cp1252')
file_text = file_line.rstrip()
if file_text and file_text[0] == u'#':
self.processSection(tag, text.rstrip())
tag = file_text[1:]
text = u''
else:
text += file_line
def processSection(self, tag, text):
"""
Process a section of the song, i.e. title, verse etc.
"""
if tag == u'T':
self.setDefaults()
if text:
self.title = text
return
elif tag == u'E':
self.finish()
return
if u'rtf1' in text:
text, self.encoding = strip_rtf(text, self.encoding)
text = text.rstrip()
if not text:
return
if tag == u'A':
self.parseAuthor(text)
elif tag in [u'B', u'C']:
self.addVerse(text, tag)
elif tag == u'D':
self.addVerse(text, u'E')
elif tag == u'G':
self.topics.append(text)
elif tag == u'M':
matches = re.findall(r'\d+', text)
if matches:
self.songNumber = matches[-1]
self.songBookName = text[:text.rfind(self.songNumber)]
elif tag == u'N':
self.comments = text
elif tag == u'O':
for char in text:
if char == u'C':
self.verseOrderList.append(u'C1')
elif char == u'B':
self.verseOrderList.append(u'B1')
elif char == u'D':
self.verseOrderList.append(u'E1')
elif u'1' <= char <= u'7':
self.verseOrderList.append(u'V' + char)
elif tag == u'R':
self.addCopyright(text)
elif u'1' <= tag <= u'7':
self.addVerse(text, u'V' + tag[1:])

View File

@ -37,6 +37,9 @@ from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# Used to strip control chars (except 10=LF, 13=CR)
CONTROL_CHARS_MAP = dict.fromkeys(range(10) + [11, 12] + range(14,32) + [127])
class ZionWorxImport(SongImport): class ZionWorxImport(SongImport):
""" """
The :class:`ZionWorxImport` class provides the ability to import songs The :class:`ZionWorxImport` class provides the ability to import songs
@ -78,13 +81,10 @@ class ZionWorxImport(SongImport):
""" """
Receive a CSV file (from a ZionWorx database dump) to import. Receive a CSV file (from a ZionWorx database dump) to import.
""" """
# Used to strip control chars (10=LF, 13=CR, 127=DEL)
self.control_chars_map = dict.fromkeys(
range(10) + [11, 12] + range(14,32) + [127])
with open(self.importSource, 'rb') as songs_file: with open(self.importSource, 'rb') as songs_file:
fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics', field_names = [u'SongNum', u'Title1', u'Title2', u'Lyrics',
u'Writer', u'Copyright', u'Keywords', u'DefaultStyle'] u'Writer', u'Copyright', u'Keywords', u'DefaultStyle']
songs_reader = csv.DictReader(songs_file, fieldnames) songs_reader = csv.DictReader(songs_file, field_names)
try: try:
records = list(songs_reader) records = list(songs_reader)
except csv.Error, e: except csv.Error, e:
@ -140,4 +140,4 @@ class ZionWorxImport(SongImport):
""" """
# This encoding choice seems OK. ZionWorx has no option for setting the # This encoding choice seems OK. ZionWorx has no option for setting the
# encoding for its songs, so we assume encoding is always the same. # encoding for its songs, so we assume encoding is always the same.
return unicode(str, u'cp1252').translate(self.control_chars_map) return unicode(str, u'cp1252').translate(CONTROL_CHARS_MAP)

34
resources/__init__.py Normal file
View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, 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:`resources` module contains a bunch of resources for OpenLP.
DO NOT REMOVE THIS FILE, IT IS REQUIRED FOR INCLUDING THE RESOURCES ON SOME
PLATFORMS!
"""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -199,7 +199,11 @@ def download_translations():
request = urllib2.Request(url + '?details') request = urllib2.Request(url + '?details')
request.add_header('Authorization', auth_header) request.add_header('Authorization', auth_header)
print_verbose(u'Downloading list of languages from: %s' % url) print_verbose(u'Downloading list of languages from: %s' % url)
try:
json_response = urllib2.urlopen(request) json_response = urllib2.urlopen(request)
except urllib2.HTTPError:
print_quiet(u'Username or password incorrect.')
return False
json_dict = json.loads(json_response.read()) json_dict = json.loads(json_response.read())
languages = [lang[u'code'] for lang in json_dict[u'available_languages']] languages = [lang[u'code'] for lang in json_dict[u'available_languages']]
for language in languages: for language in languages:
@ -214,6 +218,7 @@ def download_translations():
fd.write(response.read()) fd.write(response.read())
fd.close() fd.close()
print_quiet(u' Done.') print_quiet(u' Done.')
return True
def prepare_project(): def prepare_project():
""" """
@ -310,7 +315,8 @@ def process_stack(command_stack):
for command in command_stack: for command in command_stack:
print_quiet(u'%d.' % (command_stack.current_index), False) print_quiet(u'%d.' % (command_stack.current_index), False)
if command == Command.Download: if command == Command.Download:
download_translations() if not download_translations():
return
elif command == Command.Prepare: elif command == Command.Prepare:
prepare_project() prepare_project()
elif command == Command.Update: elif command == Command.Update: