forked from openlp/openlp
r2031
This commit is contained in:
commit
a0012b794d
@ -208,6 +208,20 @@ class OpenLP(QtGui.QApplication):
|
|||||||
return QtGui.QApplication.event(self, event)
|
return QtGui.QApplication.event(self, event)
|
||||||
|
|
||||||
|
|
||||||
|
def set_up_logging(log_path):
|
||||||
|
"""
|
||||||
|
Setup our logging using log_path
|
||||||
|
"""
|
||||||
|
check_directory_exists(log_path)
|
||||||
|
filename = os.path.join(log_path, u'openlp.log')
|
||||||
|
logfile = logging.FileHandler(filename, u'w')
|
||||||
|
logfile.setFormatter(logging.Formatter(
|
||||||
|
u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
|
||||||
|
log.addHandler(logfile)
|
||||||
|
if log.isEnabledFor(logging.DEBUG):
|
||||||
|
print 'Logging to:', filename
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
"""
|
"""
|
||||||
The main function which parses command line options and then runs
|
The main function which parses command line options and then runs
|
||||||
@ -231,21 +245,12 @@ def main(args=None):
|
|||||||
help='Set the Qt4 style (passed directly to Qt4).')
|
help='Set the Qt4 style (passed directly to Qt4).')
|
||||||
parser.add_option('--testing', dest='testing',
|
parser.add_option('--testing', dest='testing',
|
||||||
action='store_true', help='Run by testing framework')
|
action='store_true', help='Run by testing framework')
|
||||||
# Set up logging
|
|
||||||
log_path = AppLocation.get_directory(AppLocation.CacheDir)
|
|
||||||
check_directory_exists(log_path)
|
|
||||||
filename = os.path.join(log_path, u'openlp.log')
|
|
||||||
logfile = logging.FileHandler(filename, u'w')
|
|
||||||
logfile.setFormatter(logging.Formatter(
|
|
||||||
u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
|
|
||||||
log.addHandler(logfile)
|
|
||||||
# Parse command line options and deal with them.
|
# Parse command line options and deal with them.
|
||||||
# Use args supplied programatically if possible.
|
# Use args supplied programatically if possible.
|
||||||
(options, args) = parser.parse_args(args) if args else parser.parse_args()
|
(options, args) = parser.parse_args(args) if args else parser.parse_args()
|
||||||
qt_args = []
|
qt_args = []
|
||||||
if options.loglevel.lower() in ['d', 'debug']:
|
if options.loglevel.lower() in ['d', 'debug']:
|
||||||
log.setLevel(logging.DEBUG)
|
log.setLevel(logging.DEBUG)
|
||||||
print 'Logging to:', filename
|
|
||||||
elif options.loglevel.lower() in ['w', 'warning']:
|
elif options.loglevel.lower() in ['w', 'warning']:
|
||||||
log.setLevel(logging.WARNING)
|
log.setLevel(logging.WARNING)
|
||||||
else:
|
else:
|
||||||
@ -261,11 +266,13 @@ def main(args=None):
|
|||||||
app.setOrganizationName(u'OpenLP')
|
app.setOrganizationName(u'OpenLP')
|
||||||
app.setOrganizationDomain(u'openlp.org')
|
app.setOrganizationDomain(u'openlp.org')
|
||||||
if options.portable:
|
if options.portable:
|
||||||
log.info(u'Running portable')
|
|
||||||
app.setApplicationName(u'OpenLPPortable')
|
app.setApplicationName(u'OpenLPPortable')
|
||||||
Settings.setDefaultFormat(Settings.IniFormat)
|
Settings.setDefaultFormat(Settings.IniFormat)
|
||||||
# Get location OpenLPPortable.ini
|
# Get location OpenLPPortable.ini
|
||||||
app_path = AppLocation.get_directory(AppLocation.AppDir)
|
app_path = AppLocation.get_directory(AppLocation.AppDir)
|
||||||
|
set_up_logging(os.path.abspath(os.path.join(app_path, u'..',
|
||||||
|
u'..', u'Other')))
|
||||||
|
log.info(u'Running portable')
|
||||||
portable_settings_file = os.path.abspath(os.path.join(app_path, u'..',
|
portable_settings_file = os.path.abspath(os.path.join(app_path, u'..',
|
||||||
u'..', u'Data', u'OpenLP.ini'))
|
u'..', u'Data', u'OpenLP.ini'))
|
||||||
# Make this our settings file
|
# Make this our settings file
|
||||||
@ -282,6 +289,7 @@ def main(args=None):
|
|||||||
portable_settings.sync()
|
portable_settings.sync()
|
||||||
else:
|
else:
|
||||||
app.setApplicationName(u'OpenLP')
|
app.setApplicationName(u'OpenLP')
|
||||||
|
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||||
app.setApplicationVersion(get_application_version()[u'version'])
|
app.setApplicationVersion(get_application_version()[u'version'])
|
||||||
# Instance check
|
# Instance check
|
||||||
if not options.testing:
|
if not options.testing:
|
||||||
|
@ -130,15 +130,15 @@ class Ui_FormattingTagDialog(object):
|
|||||||
translate('OpenLP.FormattingTagDialog', 'Description'))
|
translate('OpenLP.FormattingTagDialog', 'Description'))
|
||||||
self.tagLabel.setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
|
self.tagLabel.setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
|
||||||
self.startTagLabel.setText(
|
self.startTagLabel.setText(
|
||||||
translate('OpenLP.FormattingTagDialog', 'Start tag'))
|
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
|
||||||
self.endTagLabel.setText(
|
self.endTagLabel.setText(
|
||||||
translate('OpenLP.FormattingTagDialog', 'End tag'))
|
translate('OpenLP.FormattingTagDialog', 'End HTML'))
|
||||||
self.deletePushButton.setText(UiStrings().Delete)
|
self.deletePushButton.setText(UiStrings().Delete)
|
||||||
self.newPushButton.setText(UiStrings().New)
|
self.newPushButton.setText(UiStrings().New)
|
||||||
self.tagTableWidget.horizontalHeaderItem(0).setText(
|
self.tagTableWidget.horizontalHeaderItem(0).setText(
|
||||||
translate('OpenLP.FormattingTagDialog', 'Description'))
|
translate('OpenLP.FormattingTagDialog', 'Description'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(1).setText(
|
self.tagTableWidget.horizontalHeaderItem(1).setText(
|
||||||
translate('OpenLP.FormattingTagDialog', 'Tag Id'))
|
translate('OpenLP.FormattingTagDialog', 'Tag'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(2).setText(
|
self.tagTableWidget.horizontalHeaderItem(2).setText(
|
||||||
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
|
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
|
||||||
self.tagTableWidget.horizontalHeaderItem(3).setText(
|
self.tagTableWidget.horizontalHeaderItem(3).setText(
|
||||||
|
@ -49,7 +49,7 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
|
|||||||
QtGui.QDialog.__init__(self, parent)
|
QtGui.QDialog.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
QtCore.QObject.connect(self.tagTableWidget,
|
QtCore.QObject.connect(self.tagTableWidget,
|
||||||
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
|
QtCore.SIGNAL(u'itemSelectionChanged()'),self.onRowSelected)
|
||||||
QtCore.QObject.connect(self.newPushButton,
|
QtCore.QObject.connect(self.newPushButton,
|
||||||
QtCore.SIGNAL(u'clicked()'), self.onNewClicked)
|
QtCore.SIGNAL(u'clicked()'), self.onNewClicked)
|
||||||
QtCore.QObject.connect(self.savePushButton,
|
QtCore.QObject.connect(self.savePushButton,
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -569,7 +569,9 @@ class BibleMediaItem(MediaManagerItem):
|
|||||||
if bible:
|
if bible:
|
||||||
if QtGui.QMessageBox.question(self, UiStrings().ConfirmDelete,
|
if QtGui.QMessageBox.question(self, UiStrings().ConfirmDelete,
|
||||||
unicode(translate('BiblesPlugin.MediaItem',
|
unicode(translate('BiblesPlugin.MediaItem',
|
||||||
'Are you sure you want to delete "%s"?')) % bible,
|
'Are you sure you want to completely delete "%s" Bible from '
|
||||||
|
'OpenLP?\n\nYou will need to re-import this Bible to use it '
|
||||||
|
'again.'))% bible,
|
||||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||||
QtGui.QMessageBox.No),
|
QtGui.QMessageBox.No),
|
||||||
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
|
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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__ = {
|
||||||
@ -158,7 +169,8 @@ class SongFormat(object):
|
|||||||
u'selectMode': SongFormatSelect.MultipleFiles,
|
u'selectMode': SongFormatSelect.MultipleFiles,
|
||||||
u'filter': u'',
|
u'filter': u'',
|
||||||
u'comboBoxText': None,
|
u'comboBoxText': None,
|
||||||
u'disabledLabelText': u'',
|
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'This importer has been disabled.'),
|
||||||
u'getFilesTitle': None,
|
u'getFilesTitle': None,
|
||||||
u'invalidSourceMsg': None,
|
u'invalidSourceMsg': None,
|
||||||
u'descriptionText': None
|
u'descriptionText': None
|
||||||
@ -240,6 +252,19 @@ 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'),
|
||||||
|
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'The MediaShout importer is only supported on Windows. It has '
|
||||||
|
'been disabled due to a missing Python module. If you want to '
|
||||||
|
'use this importer, you will need to install the "pyodbc" '
|
||||||
|
'module.')
|
||||||
|
},
|
||||||
OpenSong: {
|
OpenSong: {
|
||||||
u'class': OpenSongImport,
|
u'class': OpenSongImport,
|
||||||
u'name': WizardStrings.OS,
|
u'name': WizardStrings.OS,
|
||||||
@ -260,6 +285,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 +339,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 +357,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 +416,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']
|
||||||
|
112
openlp/plugins/songs/lib/mediashoutimport.py
Normal file
112
openlp/plugins/songs/lib/mediashoutimport.py
Normal 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()
|
143
openlp/plugins/songs/lib/songproimport.py
Normal file
143
openlp/plugins/songs/lib/songproimport.py
Normal 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:])
|
@ -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
34
resources/__init__.py
Normal 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!
|
||||||
|
"""
|
||||||
|
|
49
setup.py
49
setup.py
@ -28,10 +28,56 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
import re
|
||||||
|
|
||||||
VERSION_FILE = 'openlp/.version'
|
VERSION_FILE = 'openlp/.version'
|
||||||
|
SPLIT_ALPHA_DIGITS = re.compile(r'(\d+|\D+)')
|
||||||
|
|
||||||
|
def try_int(s):
|
||||||
|
"""
|
||||||
|
Convert string s to an integer if possible. Fail silently and return
|
||||||
|
the string as-is if it isn't an integer.
|
||||||
|
|
||||||
|
``s``
|
||||||
|
The string to try to convert.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return int(s)
|
||||||
|
except Exception:
|
||||||
|
return s
|
||||||
|
|
||||||
|
def natural_sort_key(s):
|
||||||
|
"""
|
||||||
|
Return a tuple by which s is sorted.
|
||||||
|
|
||||||
|
``s``
|
||||||
|
A string value from the list we want to sort.
|
||||||
|
"""
|
||||||
|
return map(try_int, SPLIT_ALPHA_DIGITS.findall(s))
|
||||||
|
|
||||||
|
def natural_compare(a, b):
|
||||||
|
"""
|
||||||
|
Compare two strings naturally and return the result.
|
||||||
|
|
||||||
|
``a``
|
||||||
|
A string to compare.
|
||||||
|
|
||||||
|
``b``
|
||||||
|
A string to compare.
|
||||||
|
"""
|
||||||
|
return cmp(natural_sort_key(a), natural_sort_key(b))
|
||||||
|
|
||||||
|
def natural_sort(seq, compare=natural_compare):
|
||||||
|
"""
|
||||||
|
Returns a copy of seq, sorted by natural string sort.
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
temp = copy.copy(seq)
|
||||||
|
temp.sort(compare)
|
||||||
|
return temp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Try to import Bazaar
|
||||||
from bzrlib.branch import Branch
|
from bzrlib.branch import Branch
|
||||||
b = Branch.open_containing('.')[0]
|
b = Branch.open_containing('.')[0]
|
||||||
b.lock_read()
|
b.lock_read()
|
||||||
@ -46,7 +92,8 @@ try:
|
|||||||
if revision_id in tags:
|
if revision_id in tags:
|
||||||
version = u'%s' % tags[revision_id][0]
|
version = u'%s' % tags[revision_id][0]
|
||||||
else:
|
else:
|
||||||
version = '%s-bzr%s' % (sorted(b.tags.get_tag_dict().keys())[-1], revno)
|
version = '%s-bzr%s' % \
|
||||||
|
(natural_sort(b.tags.get_tag_dict().keys())[-1], revno)
|
||||||
ver_file = open(VERSION_FILE, u'w')
|
ver_file = open(VERSION_FILE, u'w')
|
||||||
ver_file.write(version)
|
ver_file.write(version)
|
||||||
ver_file.close()
|
ver_file.close()
|
||||||
|
Loading…
Reference in New Issue
Block a user