forked from openlp/openlp
head
This commit is contained in:
commit
5881af9151
@ -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,19 @@ 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()
|
||||||
|
if options.portable:
|
||||||
|
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')
|
||||||
|
else:
|
||||||
|
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||||
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 +273,9 @@ 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)
|
|
||||||
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
|
||||||
|
@ -545,6 +545,10 @@ class AdvancedTab(SettingsTab):
|
|||||||
self.currentDataPath))
|
self.currentDataPath))
|
||||||
self.defaultColorButton.setStyleSheet(
|
self.defaultColorButton.setStyleSheet(
|
||||||
u'background-color: %s' % self.defaultColor)
|
u'background-color: %s' % self.defaultColor)
|
||||||
|
# Don't allow data directory move if running portable.
|
||||||
|
if Settings().value(u'advanced/is portable',
|
||||||
|
QtCore.QVariant(False)).toBool():
|
||||||
|
self.dataDirectoryGroupBox.hide()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
|
@ -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,
|
||||||
@ -145,6 +145,9 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
|
|||||||
"""
|
"""
|
||||||
if self.selected != -1:
|
if self.selected != -1:
|
||||||
FormattingTags.remove_html_tag(self.selected)
|
FormattingTags.remove_html_tag(self.selected)
|
||||||
|
# As the first items are protected we should not have to take care
|
||||||
|
# of negative indexes causing tracebacks.
|
||||||
|
self.tagTableWidget.selectRow(self.selected - 1)
|
||||||
self.selected = -1
|
self.selected = -1
|
||||||
FormattingTags.save_html_tags()
|
FormattingTags.save_html_tags()
|
||||||
self._reloadTable()
|
self._reloadTable()
|
||||||
|
@ -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'))
|
||||||
|
@ -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:
|
||||||
|
@ -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':
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
"""
|
"""
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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()):
|
||||||
|
@ -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)
|
||||||
|
@ -483,8 +483,11 @@ class FoilPresenter(object):
|
|||||||
# Process verse order
|
# Process verse order
|
||||||
verse_order = []
|
verse_order = []
|
||||||
verse_strophenr = []
|
verse_strophenr = []
|
||||||
|
try:
|
||||||
for strophennummer in foilpresenterfolie.reihenfolge.strophennummer:
|
for strophennummer in foilpresenterfolie.reihenfolge.strophennummer:
|
||||||
verse_strophenr.append(strophennummer)
|
verse_strophenr.append(strophennummer)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
# Currently we do not support different "parts"!
|
# Currently we do not support different "parts"!
|
||||||
if u'0' in temp_verse_order:
|
if u'0' in temp_verse_order:
|
||||||
for vers in temp_verse_order_backup:
|
for vers in temp_verse_order_backup:
|
||||||
@ -538,12 +541,17 @@ class FoilPresenter(object):
|
|||||||
``song``
|
``song``
|
||||||
The song object.
|
The song object.
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
for title_string in foilpresenterfolie.titel.titelstring:
|
for title_string in foilpresenterfolie.titel.titelstring:
|
||||||
if not song.title:
|
if not song.title:
|
||||||
song.title = self._child(title_string)
|
song.title = self._child(title_string)
|
||||||
song.alternate_title = u''
|
song.alternate_title = u''
|
||||||
else:
|
else:
|
||||||
song.alternate_title = self._child(title_string)
|
song.alternate_title = self._child(title_string)
|
||||||
|
except AttributeError:
|
||||||
|
# Use first line of first verse
|
||||||
|
first_line = self._child(foilpresenterfolie.strophen.strophe.text_)
|
||||||
|
song.title = first_line.split('\n')[0]
|
||||||
|
|
||||||
def _process_topics(self, foilpresenterfolie, song):
|
def _process_topics(self, foilpresenterfolie, song):
|
||||||
"""
|
"""
|
||||||
|
@ -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']
|
||||||
|
@ -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),
|
||||||
|
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()
|
@ -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])
|
||||||
|
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