forked from openlp/openlp
Added ZionWorx importer. Added descriptionLabel to song import wizard.
bzr-revno: 1986
This commit is contained in:
commit
f1afae1813
@ -80,6 +80,10 @@ class UiStrings(object):
|
|||||||
self.Help = translate('OpenLP.Ui', 'Help')
|
self.Help = translate('OpenLP.Ui', 'Help')
|
||||||
self.Hours = translate('OpenLP.Ui', 'h',
|
self.Hours = translate('OpenLP.Ui', 'h',
|
||||||
'The abbreviated unit for hours')
|
'The abbreviated unit for hours')
|
||||||
|
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected',
|
||||||
|
'Singular')
|
||||||
|
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
|
||||||
|
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
|
||||||
self.Image = translate('OpenLP.Ui', 'Image')
|
self.Image = translate('OpenLP.Ui', 'Image')
|
||||||
self.Import = translate('OpenLP.Ui', 'Import')
|
self.Import = translate('OpenLP.Ui', 'Import')
|
||||||
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
||||||
|
@ -44,20 +44,9 @@ class WizardStrings(object):
|
|||||||
# Applications/Formats we import from or export to. These get used in
|
# Applications/Formats we import from or export to. These get used in
|
||||||
# multiple places but do not need translating unless you find evidence of
|
# multiple places but do not need translating unless you find evidence of
|
||||||
# the writers translating their own product name.
|
# the writers translating their own product name.
|
||||||
CCLI = u'CCLI/SongSelect'
|
|
||||||
CSV = u'CSV'
|
CSV = u'CSV'
|
||||||
DB = u'DreamBeam'
|
|
||||||
EW = u'EasyWorship'
|
|
||||||
ES = u'EasySlides'
|
|
||||||
FP = u'Foilpresenter'
|
|
||||||
OL = u'OpenLyrics'
|
|
||||||
OS = u'OpenSong'
|
OS = u'OpenSong'
|
||||||
OSIS = u'OSIS'
|
OSIS = u'OSIS'
|
||||||
PS = u'PowerSong 1.0'
|
|
||||||
SB = u'SongBeamer'
|
|
||||||
SoF = u'Songs of Fellowship'
|
|
||||||
SSP = u'SongShow Plus'
|
|
||||||
WoW = u'Words of Worship'
|
|
||||||
# These strings should need a good reason to be retranslated elsewhere.
|
# These strings should need a good reason to be retranslated elsewhere.
|
||||||
FinishedImport = translate('OpenLP.Ui', 'Finished import.')
|
FinishedImport = translate('OpenLP.Ui', 'Finished import.')
|
||||||
FormatLabel = translate('OpenLP.Ui', 'Format:')
|
FormatLabel = translate('OpenLP.Ui', 'Format:')
|
||||||
@ -76,10 +65,12 @@ class WizardStrings(object):
|
|||||||
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
|
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
|
||||||
Ready = translate('OpenLP.Ui', 'Ready.')
|
Ready = translate('OpenLP.Ui', 'Ready.')
|
||||||
StartingImport = translate('OpenLP.Ui', 'Starting import...')
|
StartingImport = translate('OpenLP.Ui', 'Starting import...')
|
||||||
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at '
|
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify one '
|
||||||
|
'%s file to import from.', 'A file type e.g. OpenSong'))
|
||||||
|
YouSpecifyFiles = unicode(translate('OpenLP.Ui', 'You need to specify at '
|
||||||
'least one %s file to import from.', 'A file type e.g. OpenSong'))
|
'least one %s file to import from.', 'A file type e.g. OpenSong'))
|
||||||
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a '
|
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify one '
|
||||||
'%s folder to import from.', 'A file type e.g. OpenSong'))
|
'%s folder to import from.', 'A song format e.g. PowerSong'))
|
||||||
|
|
||||||
|
|
||||||
class OpenLPWizard(QtGui.QWizard):
|
class OpenLPWizard(QtGui.QWizard):
|
||||||
@ -108,7 +99,7 @@ class OpenLPWizard(QtGui.QWizard):
|
|||||||
|
|
||||||
def setupUi(self, image):
|
def setupUi(self, image):
|
||||||
"""
|
"""
|
||||||
Set up the wizard UI
|
Set up the wizard UI.
|
||||||
"""
|
"""
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWizardStyle(QtGui.QWizard.ModernStyle)
|
self.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||||
|
@ -73,7 +73,7 @@ class CSVBible(BibleDB):
|
|||||||
|
|
||||||
def __init__(self, parent, **kwargs):
|
def __init__(self, parent, **kwargs):
|
||||||
"""
|
"""
|
||||||
Loads a Bible from a set of CVS files.
|
Loads a Bible from a set of CSV files.
|
||||||
This class assumes the files contain all the information and
|
This class assumes the files contain all the information and
|
||||||
a clean bible is being loaded.
|
a clean bible is being loaded.
|
||||||
"""
|
"""
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,9 @@ The :mod:`importer` modules provides the general song import functionality.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from openlp.core.lib import translate
|
||||||
|
from openlp.core.lib.ui import UiStrings
|
||||||
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
from opensongimport import OpenSongImport
|
from opensongimport import OpenSongImport
|
||||||
from easyslidesimport import EasySlidesImport
|
from easyslidesimport import EasySlidesImport
|
||||||
from olpimport import OpenLPSongImport
|
from olpimport import OpenLPSongImport
|
||||||
@ -41,6 +44,7 @@ from ewimport import EasyWorshipSongImport
|
|||||||
from songbeamerimport import SongBeamerImport
|
from songbeamerimport import SongBeamerImport
|
||||||
from songshowplusimport import SongShowPlusImport
|
from songshowplusimport import SongShowPlusImport
|
||||||
from foilpresenterimport import FoilPresenterImport
|
from foilpresenterimport import FoilPresenterImport
|
||||||
|
from zionworximport import ZionWorxImport
|
||||||
# Imports that might fail
|
# Imports that might fail
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
try:
|
try:
|
||||||
@ -62,13 +66,58 @@ except ImportError:
|
|||||||
log.exception('Error importing %s', 'OooImport')
|
log.exception('Error importing %s', 'OooImport')
|
||||||
HAS_OOO = False
|
HAS_OOO = False
|
||||||
|
|
||||||
|
class SongFormatSelect(object):
|
||||||
|
"""
|
||||||
|
This is a special enumeration class listing available file selection modes.
|
||||||
|
"""
|
||||||
|
SingleFile = 0
|
||||||
|
MultipleFiles = 1
|
||||||
|
SingleFolder = 2
|
||||||
|
|
||||||
class SongFormat(object):
|
class SongFormat(object):
|
||||||
"""
|
"""
|
||||||
This is a special enumeration class that holds the various types of songs,
|
This is a special static class that holds an enumeration of the various
|
||||||
plus a few helper functions to facilitate generic handling of song types
|
song formats handled by the importer, the attributes of each song format,
|
||||||
for importing.
|
and a few helper functions.
|
||||||
|
|
||||||
|
Required attributes for each song format:
|
||||||
|
|
||||||
|
``u'class'``
|
||||||
|
Import class, e.g. ``OpenLyricsImport``
|
||||||
|
``u'name'``
|
||||||
|
Name of the format, e.g. ``u'OpenLyrics'``
|
||||||
|
``u'prefix'``
|
||||||
|
Prefix for Qt objects. Use mixedCase, e.g. ``u'openLyrics'``
|
||||||
|
See ``SongImportForm.addFileSelectItem()``
|
||||||
|
|
||||||
|
Optional attributes for each song format:
|
||||||
|
|
||||||
|
``u'canDisable'``
|
||||||
|
Whether song format importer is disablable.
|
||||||
|
``u'availability'``
|
||||||
|
Whether song format importer is available.
|
||||||
|
``u'selectMode'``
|
||||||
|
Whether format accepts single file, multiple files, or single folder
|
||||||
|
(as per ``SongFormatSelect`` options).
|
||||||
|
``u'filter'``
|
||||||
|
File extension filter for ``QFileDialog``.
|
||||||
|
|
||||||
|
Optional/custom text Strings for ``SongImportForm`` widgets:
|
||||||
|
|
||||||
|
``u'comboBoxText'``
|
||||||
|
Combo box selector (default value is the format's ``u'name'``).
|
||||||
|
``u'disabledLabelText'``
|
||||||
|
Required for disablable song formats.
|
||||||
|
``u'getFilesTitle'``
|
||||||
|
Title for ``QFileDialog`` (default includes the format's ``u'name'``).
|
||||||
|
``u'invalidSourceMsg'``
|
||||||
|
Message displayed if ``isValidSource()`` returns ``False``.
|
||||||
|
``u'descriptionText'``
|
||||||
|
Short description (1-2 lines) about the song format.
|
||||||
"""
|
"""
|
||||||
_format_availability = {}
|
# Song formats (ordered alphabetically after Generic)
|
||||||
|
# * Numerical order of song formats is significant as it determines the
|
||||||
|
# order used by formatComboBox.
|
||||||
Unknown = -1
|
Unknown = -1
|
||||||
OpenLyrics = 0
|
OpenLyrics = 0
|
||||||
OpenLP2 = 1
|
OpenLP2 = 1
|
||||||
@ -85,50 +134,164 @@ class SongFormat(object):
|
|||||||
SongShowPlus = 12
|
SongShowPlus = 12
|
||||||
SongsOfFellowship = 13
|
SongsOfFellowship = 13
|
||||||
WordsOfWorship = 14
|
WordsOfWorship = 14
|
||||||
#CSV = 15
|
ZionWorx = 15
|
||||||
|
#CSV = 16
|
||||||
|
|
||||||
|
# Set optional attribute defaults
|
||||||
|
__defaults__ = {
|
||||||
|
u'canDisable': False,
|
||||||
|
u'availability': True,
|
||||||
|
u'selectMode': SongFormatSelect.MultipleFiles,
|
||||||
|
u'filter': u'',
|
||||||
|
u'comboBoxText': None,
|
||||||
|
u'disabledLabelText': u'',
|
||||||
|
u'getFilesTitle': None,
|
||||||
|
u'invalidSourceMsg': None,
|
||||||
|
u'descriptionText': None
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set attribute values for each Song Format
|
||||||
|
__attributes__ = {
|
||||||
|
OpenLyrics: {
|
||||||
|
u'class': OpenLyricsImport,
|
||||||
|
u'name': u'OpenLyrics',
|
||||||
|
u'prefix': u'openLyrics',
|
||||||
|
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'OpenLyrics Files'),
|
||||||
|
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'OpenLyrics or OpenLP 2.0 Exported Song')
|
||||||
|
},
|
||||||
|
OpenLP2: {
|
||||||
|
u'class': OpenLPSongImport,
|
||||||
|
u'name': UiStrings().OLPV2,
|
||||||
|
u'prefix': u'openLP2',
|
||||||
|
u'selectMode': SongFormatSelect.SingleFile,
|
||||||
|
u'filter': u'%s (*.sqlite)' % (translate(
|
||||||
|
'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases'))
|
||||||
|
},
|
||||||
|
OpenLP1: {
|
||||||
|
u'name': UiStrings().OLPV1,
|
||||||
|
u'prefix': u'openLP1',
|
||||||
|
u'canDisable': True,
|
||||||
|
u'selectMode': SongFormatSelect.SingleFile,
|
||||||
|
u'filter': u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'openlp.org v1.x Databases'),
|
||||||
|
u'disabledLabelText': WizardStrings.NoSqlite
|
||||||
|
},
|
||||||
|
Generic: {
|
||||||
|
u'name': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'Generic Document/Presentation'),
|
||||||
|
u'prefix': u'generic',
|
||||||
|
u'canDisable': True,
|
||||||
|
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'The generic document/presentation importer has been disabled '
|
||||||
|
'because OpenLP cannot access OpenOffice or LibreOffice.'),
|
||||||
|
u'getFilesTitle': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'Select Document/Presentation Files')
|
||||||
|
},
|
||||||
|
CCLI: {
|
||||||
|
u'class': CCLIFileImport,
|
||||||
|
u'name': u'CCLI/SongSelect',
|
||||||
|
u'prefix': u'ccli',
|
||||||
|
u'filter': u'%s (*.usr *.txt)' % translate(
|
||||||
|
'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files')
|
||||||
|
},
|
||||||
|
DreamBeam: {
|
||||||
|
u'class': DreamBeamImport,
|
||||||
|
u'name': u'DreamBeam',
|
||||||
|
u'prefix': u'dreamBeam',
|
||||||
|
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'DreamBeam Song Files')
|
||||||
|
},
|
||||||
|
EasySlides: {
|
||||||
|
u'class': EasySlidesImport,
|
||||||
|
u'name': u'EasySlides',
|
||||||
|
u'prefix': u'easySlides',
|
||||||
|
u'selectMode': SongFormatSelect.SingleFile,
|
||||||
|
u'filter': u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'EasySlides XML File')
|
||||||
|
},
|
||||||
|
EasyWorship: {
|
||||||
|
u'class': EasyWorshipSongImport,
|
||||||
|
u'name': u'EasyWorship',
|
||||||
|
u'prefix': u'ew',
|
||||||
|
u'selectMode': SongFormatSelect.SingleFile,
|
||||||
|
u'filter': u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'EasyWorship Song Database')
|
||||||
|
},
|
||||||
|
FoilPresenter: {
|
||||||
|
u'class': FoilPresenterImport,
|
||||||
|
u'name': u'Foilpresenter',
|
||||||
|
u'prefix': u'foilPresenter',
|
||||||
|
u'filter': u'%s (*.foil)' % translate(
|
||||||
|
'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files')
|
||||||
|
},
|
||||||
|
OpenSong: {
|
||||||
|
u'class': OpenSongImport,
|
||||||
|
u'name': WizardStrings.OS,
|
||||||
|
u'prefix': u'openSong'
|
||||||
|
},
|
||||||
|
PowerSong: {
|
||||||
|
u'class': PowerSongImport,
|
||||||
|
u'name': u'PowerSong 1.0',
|
||||||
|
u'prefix': u'powerSong',
|
||||||
|
u'selectMode': SongFormatSelect.SingleFolder,
|
||||||
|
u'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'You need to specify a valid PowerSong 1.0 database folder.')
|
||||||
|
},
|
||||||
|
SongBeamer: {
|
||||||
|
u'class': SongBeamerImport,
|
||||||
|
u'name': u'SongBeamer',
|
||||||
|
u'prefix': u'songBeamer',
|
||||||
|
u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'SongBeamer Files')
|
||||||
|
},
|
||||||
|
SongShowPlus: {
|
||||||
|
u'class': SongShowPlusImport,
|
||||||
|
u'name': u'SongShow Plus',
|
||||||
|
u'prefix': u'songShowPlus',
|
||||||
|
u'filter': u'%s (*.sbsong)' % translate(
|
||||||
|
'SongsPlugin.ImportWizardForm', 'SongShow Plus Song Files')
|
||||||
|
},
|
||||||
|
SongsOfFellowship: {
|
||||||
|
u'name': u'Songs of Fellowship',
|
||||||
|
u'prefix': u'songsOfFellowship',
|
||||||
|
u'canDisable': True,
|
||||||
|
u'filter': u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'Songs Of Fellowship Song Files'),
|
||||||
|
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'The Songs of Fellowship importer has been disabled because '
|
||||||
|
'OpenLP cannot access OpenOffice or LibreOffice.')
|
||||||
|
},
|
||||||
|
WordsOfWorship: {
|
||||||
|
u'class': WowImport,
|
||||||
|
u'name': u'Words of Worship',
|
||||||
|
u'prefix': u'wordsOfWorship',
|
||||||
|
u'filter': u'%s (*.wsg *.wow-song)' % translate(
|
||||||
|
'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files')
|
||||||
|
},
|
||||||
|
ZionWorx: {
|
||||||
|
u'class': ZionWorxImport,
|
||||||
|
u'name': u'ZionWorx',
|
||||||
|
u'prefix': u'zionWorx',
|
||||||
|
u'selectMode': SongFormatSelect.SingleFile,
|
||||||
|
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'ZionWorx (CSV)'),
|
||||||
|
u'descriptionText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'First convert your ZionWorx database to a CSV text file, as '
|
||||||
|
'explained in the <a href="http://manual.openlp.org/songs.html'
|
||||||
|
'#importing-from-zionworx">User Manual</a>.')
|
||||||
|
# },
|
||||||
|
# CSV: {
|
||||||
|
# u'class': CSVImport,
|
||||||
|
# u'name': WizardStrings.CSV,
|
||||||
|
# u'prefix': u'csv',
|
||||||
|
# u'selectMode': SongFormatSelect.SingleFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_class(format):
|
def get_format_list():
|
||||||
"""
|
|
||||||
Return the appropriate implementation class.
|
|
||||||
|
|
||||||
``format``
|
|
||||||
The song format.
|
|
||||||
"""
|
|
||||||
if format == SongFormat.OpenLP2:
|
|
||||||
return OpenLPSongImport
|
|
||||||
elif format == SongFormat.OpenLP1:
|
|
||||||
return OpenLP1SongImport
|
|
||||||
elif format == SongFormat.OpenLyrics:
|
|
||||||
return OpenLyricsImport
|
|
||||||
elif format == SongFormat.OpenSong:
|
|
||||||
return OpenSongImport
|
|
||||||
elif format == SongFormat.SongsOfFellowship:
|
|
||||||
return SofImport
|
|
||||||
elif format == SongFormat.WordsOfWorship:
|
|
||||||
return WowImport
|
|
||||||
elif format == SongFormat.Generic:
|
|
||||||
return OooImport
|
|
||||||
elif format == SongFormat.CCLI:
|
|
||||||
return CCLIFileImport
|
|
||||||
elif format == SongFormat.DreamBeam:
|
|
||||||
return DreamBeamImport
|
|
||||||
elif format == SongFormat.PowerSong:
|
|
||||||
return PowerSongImport
|
|
||||||
elif format == SongFormat.EasySlides:
|
|
||||||
return EasySlidesImport
|
|
||||||
elif format == SongFormat.EasyWorship:
|
|
||||||
return EasyWorshipSongImport
|
|
||||||
elif format == SongFormat.SongBeamer:
|
|
||||||
return SongBeamerImport
|
|
||||||
elif format == SongFormat.SongShowPlus:
|
|
||||||
return SongShowPlusImport
|
|
||||||
elif format == SongFormat.FoilPresenter:
|
|
||||||
return FoilPresenterImport
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_formats_list():
|
|
||||||
"""
|
"""
|
||||||
Return a list of the supported song formats.
|
Return a list of the supported song formats.
|
||||||
"""
|
"""
|
||||||
@ -147,26 +310,55 @@ class SongFormat(object):
|
|||||||
SongFormat.SongBeamer,
|
SongFormat.SongBeamer,
|
||||||
SongFormat.SongShowPlus,
|
SongFormat.SongShowPlus,
|
||||||
SongFormat.SongsOfFellowship,
|
SongFormat.SongsOfFellowship,
|
||||||
SongFormat.WordsOfWorship
|
SongFormat.WordsOfWorship,
|
||||||
|
SongFormat.ZionWorx
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_availability(format, available):
|
def get(format, *attributes):
|
||||||
"""
|
"""
|
||||||
Set the availability for a given song format.
|
Return requested song format attribute(s).
|
||||||
|
|
||||||
|
``format``
|
||||||
|
A song format from SongFormat.
|
||||||
|
|
||||||
|
``*attributes``
|
||||||
|
Zero or more song format attributes from SongFormat.
|
||||||
|
|
||||||
|
Return type depends on number of supplied attributes:
|
||||||
|
:0: Return dict containing all defined attributes for the format.
|
||||||
|
:1: Return the attribute value.
|
||||||
|
:>1: Return tuple of requested attribute values.
|
||||||
"""
|
"""
|
||||||
SongFormat._format_availability[format] = available
|
if not attributes:
|
||||||
|
return SongFormat.__attributes__.get(format)
|
||||||
|
elif len(attributes) == 1:
|
||||||
|
default = SongFormat.__defaults__.get(attributes[0])
|
||||||
|
return SongFormat.__attributes__[format].get(attributes[0],
|
||||||
|
default)
|
||||||
|
else:
|
||||||
|
values = []
|
||||||
|
for attr in attributes:
|
||||||
|
default = SongFormat.__defaults__.get(attr)
|
||||||
|
values.append(SongFormat.__attributes__[format].get(attr,
|
||||||
|
default))
|
||||||
|
return tuple(values)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_availability(format):
|
def set(format, attribute, value):
|
||||||
"""
|
"""
|
||||||
Return the availability of a given song format.
|
Set specified song format attribute to the supplied value.
|
||||||
"""
|
"""
|
||||||
return SongFormat._format_availability.get(format, True)
|
SongFormat.__attributes__[format][attribute] = value
|
||||||
|
|
||||||
SongFormat.set_availability(SongFormat.OpenLP1, HAS_OPENLP1)
|
SongFormat.set(SongFormat.OpenLP1, u'availability', HAS_OPENLP1)
|
||||||
SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF)
|
if HAS_OPENLP1:
|
||||||
SongFormat.set_availability(SongFormat.Generic, HAS_OOO)
|
SongFormat.set(SongFormat.OpenLP1, u'class', OpenLP1SongImport)
|
||||||
|
SongFormat.set(SongFormat.SongsOfFellowship, u'availability', HAS_SOF)
|
||||||
__all__ = [u'SongFormat']
|
if HAS_SOF:
|
||||||
|
SongFormat.set(SongFormat.SongsOfFellowship, u'class', SofImport)
|
||||||
|
SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO)
|
||||||
|
if HAS_OOO:
|
||||||
|
SongFormat.set(SongFormat.Generic, u'class', OooImport)
|
||||||
|
|
||||||
|
__all__ = [u'SongFormat', u'SongFormatSelect']
|
||||||
|
@ -33,7 +33,6 @@ import fnmatch
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from openlp.core.lib import translate
|
from openlp.core.lib import translate
|
||||||
from openlp.core.ui.wizard import WizardStrings
|
|
||||||
from openlp.plugins.songs.lib.songimport import SongImport
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -71,26 +70,25 @@ class PowerSongImport(SongImport):
|
|||||||
|
|
||||||
* .song
|
* .song
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidSource(**kwargs):
|
def isValidSource(import_source):
|
||||||
"""
|
"""
|
||||||
Checks if source is a PowerSong 1.0 folder:
|
Checks if source is a PowerSong 1.0 folder:
|
||||||
* is a directory
|
* is a directory
|
||||||
* contains at least one *.song file
|
* contains at least one *.song file
|
||||||
"""
|
"""
|
||||||
if u'folder' in kwargs:
|
if os.path.isdir(import_source):
|
||||||
dir = kwargs[u'folder']
|
for file in os.listdir(import_source):
|
||||||
if os.path.isdir(dir):
|
if fnmatch.fnmatch(file, u'*.song'):
|
||||||
for file in os.listdir(dir):
|
return True
|
||||||
if fnmatch.fnmatch(file, u'*.song'):
|
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def doImport(self):
|
def doImport(self):
|
||||||
"""
|
"""
|
||||||
Receive either a list of files or a folder (unicode) to import.
|
Receive either a list of files or a folder (unicode) to import.
|
||||||
"""
|
"""
|
||||||
|
from importer import SongFormat
|
||||||
|
PS_string = SongFormat.get(SongFormat.PowerSong, u'name')
|
||||||
if isinstance(self.importSource, unicode):
|
if isinstance(self.importSource, unicode):
|
||||||
if os.path.isdir(self.importSource):
|
if os.path.isdir(self.importSource):
|
||||||
dir = self.importSource
|
dir = self.importSource
|
||||||
@ -104,7 +102,7 @@ class PowerSongImport(SongImport):
|
|||||||
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
|
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
|
||||||
'No songs to import.')),
|
'No songs to import.')),
|
||||||
unicode(translate('SongsPlugin.PowerSongImport',
|
unicode(translate('SongsPlugin.PowerSongImport',
|
||||||
'No %s files found.' % WizardStrings.PS)))
|
'No %s files found.' % PS_string)))
|
||||||
return
|
return
|
||||||
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
||||||
for file in self.importSource:
|
for file in self.importSource:
|
||||||
@ -124,7 +122,7 @@ class PowerSongImport(SongImport):
|
|||||||
self.logError(os.path.basename(file), unicode(
|
self.logError(os.path.basename(file), unicode(
|
||||||
translate('SongsPlugin.PowerSongImport',
|
translate('SongsPlugin.PowerSongImport',
|
||||||
'Invalid %s file. Unexpected byte value.'
|
'Invalid %s file. Unexpected byte value.'
|
||||||
% WizardStrings.PS)))
|
% PS_string)))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if label == u'TITLE':
|
if label == u'TITLE':
|
||||||
@ -142,15 +140,14 @@ class PowerSongImport(SongImport):
|
|||||||
if not self.title:
|
if not self.title:
|
||||||
self.logError(os.path.basename(file), unicode(
|
self.logError(os.path.basename(file), unicode(
|
||||||
translate('SongsPlugin.PowerSongImport',
|
translate('SongsPlugin.PowerSongImport',
|
||||||
'Invalid %s file. Missing "TITLE" header.'
|
'Invalid %s file. Missing "TITLE" header.' % PS_string)))
|
||||||
% WizardStrings.PS)))
|
|
||||||
continue
|
continue
|
||||||
# Check that file had COPYRIGHTLINE label
|
# Check that file had COPYRIGHTLINE label
|
||||||
if not found_copyright:
|
if not found_copyright:
|
||||||
self.logError(self.title, unicode(
|
self.logError(self.title, unicode(
|
||||||
translate('SongsPlugin.PowerSongImport',
|
translate('SongsPlugin.PowerSongImport',
|
||||||
'Invalid %s file. Missing "COPYRIGHTLINE" '
|
'Invalid %s file. Missing "COPYRIGHTLINE" '
|
||||||
'header.' % WizardStrings.PS)))
|
'header.' % PS_string)))
|
||||||
continue
|
continue
|
||||||
# Check that file had at least one verse
|
# Check that file had at least one verse
|
||||||
if not self.verses:
|
if not self.verses:
|
||||||
|
@ -51,11 +51,11 @@ class SongImport(QtCore.QObject):
|
|||||||
as necessary
|
as necessary
|
||||||
"""
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidSource(**kwargs):
|
def isValidSource(import_source):
|
||||||
"""
|
"""
|
||||||
Override this method to validate the source prior to import.
|
Override this method to validate the source prior to import.
|
||||||
"""
|
"""
|
||||||
pass
|
return True
|
||||||
|
|
||||||
def __init__(self, manager, **kwargs):
|
def __init__(self, manager, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
142
openlp/plugins/songs/lib/zionworximport.py
Normal file
142
openlp/plugins/songs/lib/zionworximport.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# -*- 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, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||||
|
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||||
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, 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:`zionworximport` module provides the functionality for importing
|
||||||
|
ZionWorx songs into the OpenLP database.
|
||||||
|
"""
|
||||||
|
import csv
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from openlp.core.lib import translate
|
||||||
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class ZionWorxImport(SongImport):
|
||||||
|
"""
|
||||||
|
The :class:`ZionWorxImport` class provides the ability to import songs
|
||||||
|
from ZionWorx, via a dump of the ZionWorx database to a CSV file.
|
||||||
|
|
||||||
|
ZionWorx song database fields:
|
||||||
|
|
||||||
|
* ``SongNum`` Song ID. (Discarded by importer)
|
||||||
|
* ``Title1`` Main Title.
|
||||||
|
* ``Title2`` Alternate Title.
|
||||||
|
* ``Lyrics`` Song verses, separated by blank lines.
|
||||||
|
* ``Writer`` Song author(s).
|
||||||
|
* ``Copyright`` Copyright information
|
||||||
|
* ``Keywords`` (Discarded by importer)
|
||||||
|
* ``DefaultStyle`` (Discarded by importer)
|
||||||
|
|
||||||
|
ZionWorx has no native export function; it uses the proprietary TurboDB
|
||||||
|
database engine. The TurboDB vendor, dataWeb, provides tools which can
|
||||||
|
export TurboDB tables to other formats, such as freeware console tool
|
||||||
|
TurboDB Data Exchange which is available for Windows and Linux. This command
|
||||||
|
exports the ZionWorx songs table to a CSV file:
|
||||||
|
|
||||||
|
``tdbdatax MainTable.dat songstable.csv -fsdf -s, -qd``
|
||||||
|
|
||||||
|
* -f Table format: ``sdf`` denotes text file.
|
||||||
|
* -s Separator character between fields.
|
||||||
|
* -q Quote character surrounding fields. ``d`` denotes double-quote.
|
||||||
|
|
||||||
|
CSV format expected by importer:
|
||||||
|
|
||||||
|
* Field separator character is comma ``,``
|
||||||
|
* Fields surrounded by double-quotes ``"``. This enables fields (such as
|
||||||
|
Lyrics) to include new-lines and commas. Double-quotes within a field
|
||||||
|
are denoted by two double-quotes ``""``
|
||||||
|
* Note: This is the default format of the Python ``csv`` module.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def doImport(self):
|
||||||
|
"""
|
||||||
|
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:
|
||||||
|
fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics',
|
||||||
|
u'Writer', u'Copyright', u'Keywords', u'DefaultStyle']
|
||||||
|
songs_reader = csv.DictReader(songs_file, fieldnames)
|
||||||
|
try:
|
||||||
|
records = list(songs_reader)
|
||||||
|
except csv.Error, e:
|
||||||
|
self.logError(unicode(translate('SongsPlugin.ZionWorxImport',
|
||||||
|
'Error reading CSV file.')),
|
||||||
|
unicode(translate('SongsPlugin.ZionWorxImport',
|
||||||
|
'Line %d: %s' % (songs_reader.line_num, e))))
|
||||||
|
return
|
||||||
|
num_records = len(records)
|
||||||
|
log.info(u'%s records found in CSV file' % num_records)
|
||||||
|
self.importWizard.progressBar.setMaximum(num_records)
|
||||||
|
for index, record in enumerate(records, 1):
|
||||||
|
if self.stopImportFlag:
|
||||||
|
return
|
||||||
|
self.setDefaults()
|
||||||
|
try:
|
||||||
|
self.title = self._decode(record[u'Title1'])
|
||||||
|
if record[u'Title2']:
|
||||||
|
self.alternateTitle = self._decode(record[u'Title2'])
|
||||||
|
self.parseAuthor(self._decode(record[u'Writer']))
|
||||||
|
self.addCopyright(self._decode(record[u'Copyright']))
|
||||||
|
lyrics = self._decode(record[u'Lyrics'])
|
||||||
|
except UnicodeDecodeError, e:
|
||||||
|
self.logError(unicode(translate(
|
||||||
|
'SongsPlugin.ZionWorxImport', 'Record %d' % index)),
|
||||||
|
unicode(translate('SongsPlugin.ZionWorxImport',
|
||||||
|
'Decoding error: %s' % e)))
|
||||||
|
continue
|
||||||
|
except TypeError, e:
|
||||||
|
self.logError(unicode(translate(
|
||||||
|
'SongsPlugin.ZionWorxImport', 'File not valid ZionWorx '
|
||||||
|
'CSV format.')), u'TypeError: %s' % e)
|
||||||
|
return
|
||||||
|
verse = u''
|
||||||
|
for line in lyrics.splitlines():
|
||||||
|
if line and not line.isspace():
|
||||||
|
verse += line + u'\n'
|
||||||
|
elif verse:
|
||||||
|
self.addVerse(verse)
|
||||||
|
verse = u''
|
||||||
|
if verse:
|
||||||
|
self.addVerse(verse)
|
||||||
|
title = self.title
|
||||||
|
if not self.finish():
|
||||||
|
self.logError(unicode(translate(
|
||||||
|
'SongsPlugin.ZionWorxImport', 'Record %d' % index))
|
||||||
|
+ (u': "' + title + u'"' if title else u''))
|
||||||
|
|
||||||
|
def _decode(self, str):
|
||||||
|
"""
|
||||||
|
Decodes CSV input to unicode, stripping all control characters (except
|
||||||
|
new lines).
|
||||||
|
"""
|
||||||
|
# This encoding choice seems OK. ZionWorx has no option for setting the
|
||||||
|
# encoding for its songs, so we assume encoding is always the same.
|
||||||
|
return unicode(str, u'cp1252').translate(self.control_chars_map)
|
@ -194,7 +194,7 @@ class SongsPlugin(Plugin):
|
|||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
|
|
||||||
def importSongs(self, format, **kwargs):
|
def importSongs(self, format, **kwargs):
|
||||||
class_ = SongFormat.get_class(format)
|
class_ = SongFormat.get(format, u'class')
|
||||||
importer = class_(self.manager, **kwargs)
|
importer = class_(self.manager, **kwargs)
|
||||||
importer.register(self.mediaItem.importWizard)
|
importer.register(self.mediaItem.importWizard)
|
||||||
return importer
|
return importer
|
||||||
|
Loading…
Reference in New Issue
Block a user