This commit is contained in:
Andreas Preikschat 2011-01-18 18:49:19 +01:00
commit 8fe427ed32
13 changed files with 565 additions and 180 deletions

View File

@ -28,9 +28,9 @@ import re
try:
import enchant
from enchant import DictNotFoundError
enchant_available = True
ENCHANT_AVAILABLE = True
except ImportError:
enchant_available = False
ENCHANT_AVAILABLE = False
# based on code from
# http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check
@ -45,7 +45,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
def __init__(self, *args):
QtGui.QPlainTextEdit.__init__(self, *args)
# Default dictionary based on the current locale.
if enchant_available:
if ENCHANT_AVAILABLE:
try:
self.dict = enchant.Dict()
except DictNotFoundError:
@ -72,7 +72,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
self.setTextCursor(cursor)
# Check if the selected word is misspelled and offer spelling
# suggestions if it is.
if enchant_available and self.textCursor().hasSelection():
if ENCHANT_AVAILABLE and self.textCursor().hasSelection():
text = unicode(self.textCursor().selectedText())
if not self.dict.check(text):
spell_menu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',

View File

@ -72,6 +72,14 @@ class AdvancedTab(SettingsTab):
u'enableAutoCloseCheckBox')
self.uiLayout.addRow(self.enableAutoCloseCheckBox)
self.leftLayout.addWidget(self.uiGroupBox)
self.hideMouseGroupBox = QtGui.QGroupBox(self.leftColumn)
self.hideMouseGroupBox.setObjectName(u'hideMouseGroupBox')
self.hideMouseLayout = QtGui.QVBoxLayout(self.hideMouseGroupBox)
self.hideMouseLayout.setObjectName(u'hideMouseLayout')
self.hideMouseCheckBox = QtGui.QCheckBox(self.hideMouseGroupBox)
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.leftLayout.addWidget(self.hideMouseGroupBox)
# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftColumn)
# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
# self.sharedDirLayout = QtGui.QFormLayout(self.sharedDirGroupBox)
@ -117,6 +125,10 @@ class AdvancedTab(SettingsTab):
'Expand new service items on creation'))
self.enableAutoCloseCheckBox.setText(translate('OpenLP.AdvancedTab',
'Enable application exit confirmation'))
self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab',
'Mouse Cursor'))
self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab',
'Hide the mouse cursor when moved over the display window'))
# self.sharedDirGroupBox.setTitle(
# translate('AdvancedTab', 'Central Data Store'))
# self.sharedCheckBox.setText(
@ -150,6 +162,8 @@ class AdvancedTab(SettingsTab):
self.enableAutoCloseCheckBox.setChecked(
settings.value(u'enable exit confirmation',
QtCore.QVariant(True)).toBool())
self.hideMouseCheckBox.setChecked(
settings.value(u'hide mouse', QtCore.QVariant(False)).toBool())
settings.endGroup()
def save(self):
@ -168,6 +182,8 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(self.expandServiceItemCheckBox.isChecked()))
settings.setValue(u'enable exit confirmation',
QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked()))
settings.setValue(u'hide mouse',
QtCore.QVariant(self.hideMouseCheckBox.isChecked()))
settings.endGroup()
# def onSharedCheckBoxChanged(self, checked):

View File

@ -435,6 +435,14 @@ class MainDisplay(DisplayWidget):
# if was hidden keep it hidden
if self.hideMode and self.isLive:
self.hideDisplay(self.hideMode)
# Hide mouse cursor when moved over display if enabled in settings
settings = QtCore.QSettings()
if settings.value(u'advanced/hide mouse', QtCore.QVariant(False)).toBool():
self.setCursor(QtCore.Qt.BlankCursor)
self.frame.evaluateJavaScript('document.body.style.cursor = "none"')
else:
self.setCursor(QtCore.Qt.ArrowCursor)
self.frame.evaluateJavaScript('document.body.style.cursor = "auto"')
def footer(self, text):
"""

View File

@ -26,7 +26,6 @@
"""
The :mod:`utils` module provides the utility libraries for OpenLP
"""
import logging
import os
import re
@ -36,12 +35,18 @@ import urllib2
from datetime import datetime
from PyQt4 import QtGui, QtCore
if sys.platform != u'win32' and sys.platform != u'darwin':
try:
from xdg import BaseDirectory
XDG_BASE_AVAILABLE = True
except ImportError:
XDG_BASE_AVAILABLE = False
import openlp
from openlp.core.lib import Receiver, translate
log = logging.getLogger(__name__)
images_filter = None
IMAGES_FILTER = None
class VersionThread(QtCore.QThread):
"""
@ -113,77 +118,46 @@ class AppLocation(object):
The directory type you want, for instance the data directory.
"""
if dir_type == AppLocation.AppDir:
if hasattr(sys, u'frozen') and sys.frozen == 1:
app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
else:
app_path = os.path.split(openlp.__file__)[0]
return app_path
return _get_frozen_path(
os.path.abspath(os.path.split(sys.argv[0])[0]),
os.path.split(openlp.__file__)[0])
elif dir_type == AppLocation.ConfigDir:
if sys.platform == u'win32':
path = os.path.join(os.getenv(u'APPDATA'), u'openlp')
elif sys.platform == u'darwin':
path = os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp')
else:
try:
from xdg import BaseDirectory
path = os.path.join(
BaseDirectory.xdg_config_home, u'openlp')
except ImportError:
path = os.path.join(os.getenv(u'HOME'), u'.openlp')
return path
return _get_os_dir_path(u'openlp',
os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp'),
os.path.join(BaseDirectory.xdg_config_home, u'openlp'),
os.path.join(os.getenv(u'HOME'), u'.openlp'))
elif dir_type == AppLocation.DataDir:
if sys.platform == u'win32':
path = os.path.join(os.getenv(u'APPDATA'), u'openlp', u'data')
elif sys.platform == u'darwin':
path = os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp', u'Data')
else:
try:
from xdg import BaseDirectory
path = os.path.join(BaseDirectory.xdg_data_home, u'openlp')
except ImportError:
path = os.path.join(os.getenv(u'HOME'), u'.openlp', u'data')
return path
return _get_os_dir_path(os.path.join(u'openlp', u'data'),
os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp', u'Data'),
os.path.join(BaseDirectory.xdg_data_home, u'openlp'),
os.path.join(os.getenv(u'HOME'), u'.openlp', u'data'))
elif dir_type == AppLocation.PluginsDir:
plugin_path = None
app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
if hasattr(sys, u'frozen') and sys.frozen == 1:
plugin_path = os.path.join(app_path, u'plugins')
else:
plugin_path = os.path.join(
os.path.split(openlp.__file__)[0], u'plugins')
return plugin_path
return _get_frozen_path(os.path.join(app_path, u'plugins'),
os.path.join(os.path.split(openlp.__file__)[0], u'plugins'))
elif dir_type == AppLocation.VersionDir:
if hasattr(sys, u'frozen') and sys.frozen == 1:
version_path = os.path.abspath(os.path.split(sys.argv[0])[0])
else:
version_path = os.path.split(openlp.__file__)[0]
return version_path
return _get_frozen_path(
os.path.abspath(os.path.split(sys.argv[0])[0]),
os.path.split(openlp.__file__)[0])
elif dir_type == AppLocation.CacheDir:
if sys.platform == u'win32':
path = os.path.join(os.getenv(u'APPDATA'), u'openlp')
elif sys.platform == u'darwin':
path = os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp')
else:
try:
from xdg import BaseDirectory
path = os.path.join(
BaseDirectory.xdg_cache_home, u'openlp')
except ImportError:
path = os.path.join(os.getenv(u'HOME'), u'.openlp')
return path
return _get_os_dir_path(u'openlp',
os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp'),
os.path.join(BaseDirectory.xdg_cache_home, u'openlp'),
os.path.join(os.getenv(u'HOME'), u'.openlp'))
if dir_type == AppLocation.LanguageDir:
if hasattr(sys, u'frozen') and sys.frozen == 1:
app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
else:
app_path = os.path.split(openlp.__file__)[0]
app_path = _get_frozen_path(
os.path.abspath(os.path.split(sys.argv[0])[0]),
os.path.split(openlp.__file__)[0])
return os.path.join(app_path, u'i18n')
@staticmethod
def get_data_path():
"""
Return the path OpenLP stores all its data under.
"""
path = AppLocation.get_directory(AppLocation.DataDir)
if not os.path.exists(path):
os.makedirs(path)
@ -191,12 +165,38 @@ class AppLocation(object):
@staticmethod
def get_section_data_path(section):
"""
Return the path a particular module stores its data under.
"""
data_path = AppLocation.get_data_path()
path = os.path.join(data_path, section)
if not os.path.exists(path):
os.makedirs(path)
return path
def _get_os_dir_path(win_option, darwin_option, base_dir_option,
non_base_dir_option):
"""
Return a path based on which OS and environment we are running in.
"""
if sys.platform == u'win32':
return os.path.join(os.getenv(u'APPDATA'), win_option)
elif sys.platform == u'darwin':
return darwin_option
else:
if XDG_BASE_AVAILABLE:
return base_dir_option
else:
return non_base_dir_option
def _get_frozen_path(frozen_option, non_frozen_option):
"""
Return a path based on the system status.
"""
if hasattr(sys, u'frozen') and sys.frozen == 1:
return frozen_option
else:
return non_frozen_option
def check_latest_version(current_version):
"""
@ -225,9 +225,8 @@ def check_latest_version(current_version):
remote_version = None
try:
remote_version = unicode(urllib2.urlopen(req, None).read()).strip()
except IOError, e:
if hasattr(e, u'reason'):
log.exception(u'Reason for failure: %s', e.reason)
except IOError:
log.exception(u'Failed to download the latest OpenLP version file')
if remote_version:
version_string = remote_version
return version_string
@ -264,18 +263,21 @@ def get_images_filter():
Returns a filter string for a file dialog containing all the supported
image formats.
"""
global images_filter
if not images_filter:
global IMAGES_FILTER
if not IMAGES_FILTER:
log.debug(u'Generating images filter.')
formats = [unicode(fmt)
for fmt in QtGui.QImageReader.supportedImageFormats()]
visible_formats = u'(*.%s)' % u'; *.'.join(formats)
actual_formats = u'(*.%s)' % u' *.'.join(formats)
images_filter = u'%s %s %s' % (translate('OpenLP', 'Image Files'),
IMAGES_FILTER = u'%s %s %s' % (translate('OpenLP', 'Image Files'),
visible_formats, actual_formats)
return images_filter
return IMAGES_FILTER
def split_filename(path):
"""
Return a list of the parts in a given path.
"""
path = os.path.abspath(path)
if not os.path.isfile(path):
return path, u''

View File

@ -128,6 +128,9 @@ class SongImportForm(OpenLPWizard):
QtCore.QObject.connect(self.genericRemoveButton,
QtCore.SIGNAL(u'clicked()'),
self.onGenericRemoveButtonClicked)
QtCore.QObject.connect(self.easiSlidesBrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onEasiSlidesBrowseButtonClicked)
QtCore.QObject.connect(self.ewBrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onEWBrowseButtonClicked)
@ -177,6 +180,8 @@ class SongImportForm(OpenLPWizard):
self.addMultiFileSelectItem(u'songsOfFellowship', None, True)
# Generic Document/Presentation import
self.addMultiFileSelectItem(u'generic', None, True)
# EasySlides
self.addSingleFileSelectItem(u'easiSlides')
# EasyWorship
self.addSingleFileSelectItem(u'ew')
# Words of Worship
@ -226,10 +231,12 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm',
'Generic Document/Presentation'))
self.formatComboBox.setItemText(8,
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
translate('SongsPlugin.ImportWizardForm', 'EasiSlides'))
self.formatComboBox.setItemText(9,
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
self.formatComboBox.setItemText(10,
translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
# self.formatComboBox.setItemText(9,
# self.formatComboBox.setItemText(11,
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
self.openLP2FilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
@ -281,6 +288,10 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'The generic document/'
'presentation importer has been disabled because OpenLP cannot '
'find OpenOffice.org on your computer.'))
self.easiSlidesFilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.easiSlidesBrowseButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Browse...'))
self.ewFilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.ewBrowseButton.setText(
@ -311,6 +322,8 @@ class SongImportForm(OpenLPWizard):
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.openLP1FormLabelSpacer.changeSize(width, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.easiSlidesFormLabelSpacer.changeSize(width, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Fixed)
# self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
@ -404,6 +417,16 @@ class SongImportForm(OpenLPWizard):
'presentation file to import from.'))
self.genericAddButton.setFocus()
return False
elif source_format == SongFormat.EasiSlides:
if self.easiSlidesFilenameEdit.text().isEmpty():
criticalErrorMessageBox(
translate('SongsPlugin.ImportWizardForm',
'No Easislides Songs file selected'),
translate('SongsPlugin.ImportWizardForm',
'You need to select an xml song file exported from '
'EasiSlides, to import from.'))
self.easiSlidesBrowseButton.setFocus()
return False
elif source_format == SongFormat.EasyWorship:
if self.ewFilenameEdit.text().isEmpty():
criticalErrorMessageBox(
@ -625,6 +648,13 @@ class SongImportForm(OpenLPWizard):
"""
self.removeSelectedItems(self.genericFileListWidget)
def onEasiSlidesBrowseButtonClicked(self):
self.getFileName(
translate('SongsPlugin.ImportWizardForm',
'Select EasiSlides songfile'),
self.easiSlidesFilenameEdit
)
def onEWBrowseButtonClicked(self):
"""
Get EasyWorship song database files
@ -674,6 +704,7 @@ class SongImportForm(OpenLPWizard):
self.ccliFileListWidget.clear()
self.songsOfFellowshipFileListWidget.clear()
self.genericFileListWidget.clear()
self.easiSlidesFilenameEdit.setText(u'')
self.ewFilenameEdit.setText(u'')
self.songBeamerFileListWidget.clear()
#self.csvFilenameEdit.setText(u'')
@ -737,8 +768,13 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.Generic,
filenames=self.getListOfFiles(self.genericFileListWidget)
)
elif source_format == SongFormat.EasiSlides:
# Import an EasiSlides export file
importer = self.plugin.importSongs(SongFormat.EasiSlides,
filename=unicode(self.easiSlidesFilenameEdit.text())
)
elif source_format == SongFormat.EasyWorship:
# Import an OpenLP 2.0 database
# Import an EasyWorship database
importer = self.plugin.importSongs(SongFormat.EasyWorship,
filename=unicode(self.ewFilenameEdit.text())
)

View File

@ -48,49 +48,27 @@ class VerseType(object):
``verse_type``
The type to return a string for
"""
if verse_type == VerseType.Verse:
return translate('SongsPlugin.VerseType', 'Verse')
elif verse_type == VerseType.Chorus:
return translate('SongsPlugin.VerseType', 'Chorus')
elif verse_type == VerseType.Bridge:
return translate('SongsPlugin.VerseType', 'Bridge')
elif verse_type == VerseType.PreChorus:
return translate('SongsPlugin.VerseType', 'Pre-Chorus')
elif verse_type == VerseType.Intro:
return translate('SongsPlugin.VerseType', 'Intro')
elif verse_type == VerseType.Ending:
return translate('SongsPlugin.VerseType', 'Ending')
elif verse_type == VerseType.Other:
return translate('SongsPlugin.VerseType', 'Other')
@staticmethod
def expand_string(verse_type):
"""
Return the VerseType for a given string
``verse_type``
The string to return a VerseType for
"""
verse_type = verse_type.lower()
if verse_type == \
if not isinstance(verse_type, int):
verse_type = verse_type.lower()
if verse_type == VerseType.Verse or verse_type == \
unicode(VerseType.to_string(VerseType.Verse)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Verse')
elif verse_type == \
elif verse_type == VerseType.Chorus or verse_type == \
unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Chorus')
elif verse_type == \
elif verse_type == VerseType.Bridge or verse_type == \
unicode(VerseType.to_string(VerseType.Bridge)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Bridge')
elif verse_type == \
elif verse_type == VerseType.PreChorus or verse_type == \
unicode(VerseType.to_string(VerseType.PreChorus)).lower()[0]:
return translate('SongsPlugin.VerseType', 'PreChorus')
elif verse_type == \
return translate('SongsPlugin.VerseType', 'Pre-Chorus')
elif verse_type == VerseType.Intro or verse_type == \
unicode(VerseType.to_string(VerseType.Intro)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Intro')
elif verse_type == \
elif verse_type == VerseType.Ending or verse_type == \
unicode(VerseType.to_string(VerseType.Ending)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Ending')
elif verse_type == \
elif verse_type == VerseType.Other or verse_type == \
unicode(VerseType.to_string(VerseType.Other)).lower()[0]:
return translate('SongsPlugin.VerseType', 'Other')
@ -163,7 +141,7 @@ def retrieve_windows_encoding(recommendation=None):
translate('SongsPlugin', 'Character Encoding'),
translate('SongsPlugin', 'The codepage setting is responsible\n'
'for the correct character representation.\n'
'Usually you are fine with the preselected choise.'),
'Usually you are fine with the preselected choice.'),
[pair[1] for pair in encodings], recommended_index, False)
else:
choice = QtGui.QInputDialog.getItem(None,

View File

@ -0,0 +1,341 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, 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 #
###############################################################################
import logging
import os
from lxml import etree, objectify
from lxml.etree import Error, LxmlError
import re
from openlp.core.lib import translate
from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
class EasiSlidesImport(SongImport):
"""
Import songs exported from EasiSlides
The format example is here:
http://wiki.openlp.org/Development:EasiSlides_-_Song_Data_Format
"""
def __init__(self, manager, **kwargs):
"""
Initialise the class.
"""
SongImport.__init__(self, manager)
self.filename = kwargs[u'filename']
self.song = None
self.commit = True
def do_import(self):
"""
Import either each of the files in self.filenames - 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).
"""
self.import_wizard.progressBar.setMaximum(1)
log.info(u'Importing EasiSlides XML file %s', self.filename)
parser = etree.XMLParser(remove_blank_text=True)
file = etree.parse(self.filename, parser)
xml = unicode(etree.tostring(file))
song_xml = objectify.fromstring(xml)
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm',
u'Importing %s...')) % os.path.split(self.filename)[-1])
self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
for song in song_xml.Item:
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm',
u'Importing %s, song %s...')) %
(os.path.split(self.filename)[-1], song.Title1))
success = self._parse_song(song)
if not success or self.stop_import_flag:
return False
elif self.commit:
self.finish()
return True
def _parse_song(self, song):
self._success = True
self._add_title(song)
self._add_alttitle(song)
self._add_number(song)
self._add_authors(song)
self._add_copyright(song)
self._add_book(song)
self._parse_and_add_lyrics(song)
return self._success
def _add_title(self, song):
try:
self.title = unicode(song.Title1).strip()
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Title1')
self._success = False
except AttributeError:
log.exception(u'no Title1')
self._success = False
def _add_alttitle(self, song):
try:
self.alternate_title = unicode(song.Title2).strip()
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Title2')
self._success = False
except AttributeError:
pass
def _add_number(self, song):
try:
number = unicode(song.SongNumber)
if number != u'0':
self.song_number = number
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding SongNumber')
self._success = False
except AttributeError:
pass
def _add_authors(self, song):
try:
authors = unicode(song.Writer).split(u',')
for author in authors:
author = author.strip()
if len(author) > 0:
self.authors.append(author)
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Writer')
self._success = False
except AttributeError:
pass
def _add_copyright(self, song):
copyright = []
try:
copyright.append(unicode(song.Copyright).strip())
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Copyright')
self._success = False
except AttributeError:
pass
try:
copyright.append(unicode(song.LicenceAdmin1).strip())
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding LicenceAdmin1')
self._success = False
except AttributeError:
pass
try:
copyright.append(unicode(song.LicenceAdmin2).strip())
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding LicenceAdmin2')
self._success = False
except AttributeError:
pass
self.add_copyright(u' '.join(copyright))
def _add_book(self, song):
try:
self.song_book_name = unicode(song.BookReference).strip()
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding BookReference')
self._success = False
except AttributeError:
pass
def _parse_and_add_lyrics(self, song):
try:
lyrics = unicode(song.Contents).strip()
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Contents')
self._success = False
except AttributeError:
log.exception(u'no Contents')
self._success = False
lines = lyrics.split(u'\n')
# we go over all lines first, to determine information,
# which tells us how to parse verses later
regionlines = {}
separatorlines = 0
for line in lines:
line = line.strip()
if len(line) == 0:
continue
elif line[1:7] == u'region':
# this is region separator, probably [region 2]
region = self._extractRegion(line)
if regionlines.has_key(region):
regionlines[region] = regionlines[region] + 1
else:
regionlines[region] = 1
elif line[0] == u'[':
separatorlines = separatorlines + 1
# if the song has separators
separators = (separatorlines > 0)
# the number of different regions in song - 1
if len(regionlines) > 1:
log.info(u'EasiSlidesImport: the file contained a song named "%s"'
u'with more than two regions, but only two regions are',
u'tested, encountered regions were: %s',
self.title, u','.join(regionlines.keys()))
# if the song has regions
regions = (len(regionlines) > 0)
# if the regions are inside verses
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
MarkTypes = {
u'CHORUS': u'C',
u'VERSE': u'V',
u'INTRO': u'I',
u'ENDING': u'E',
u'BRIDGE': u'B',
u'PRECHORUS': u'P'}
verses = {}
# list as [region, versetype, versenum, instance]
our_verse_order = []
defaultregion = u'1'
reg = defaultregion
verses[reg] = {}
# instance differentiates occurrences of same verse tag
vt = u'V'
vn = u'1'
inst = 1
for line in lines:
line = line.strip()
if len(line) == 0:
if separators:
# separators are used, so empty line means slide break
# inside verse
if self._listHas(verses, [reg, vt, vn, inst]):
inst = inst + 1
else:
# separators are not used, so empty line starts a new verse
vt = u'V'
if verses[reg].has_key(vt):
vn = len(verses[reg][vt].keys())+1
else:
vn = u'1'
inst = 1
elif line[0:7] == u'[region':
reg = self._extractRegion(line)
if not verses.has_key(reg):
verses[reg] = {}
if not regionsInVerses:
vt = u'V'
vn = u'1'
inst = 1
elif line[0] == u'[':
# this is a normal section marker
marker = line[1:line.find(u']')].upper()
vn = u'1'
# have we got any digits?
# If so, versenumber is everything from the digits to the end
match = re.match(u'(.*)(\d+.*)', marker)
if match:
marker = match.group(1).strip()
vn = match.group(2)
if len(marker) == 0:
vt = u'V'
elif MarkTypes.has_key(marker):
vt = MarkTypes[marker]
else:
vt = u'O'
if regionsInVerses:
region = defaultregion
inst = 1
if self._listHas(verses, [reg, vt, vn, inst]):
inst = len(verses[reg][vt][vn])+1
else:
if not [reg, vt, vn, inst] in our_verse_order:
our_verse_order.append([reg, vt, vn, inst])
if not verses[reg].has_key(vt):
verses[reg][vt] = {}
if not verses[reg][vt].has_key(vn):
verses[reg][vt][vn] = {}
if not verses[reg][vt][vn].has_key(inst):
verses[reg][vt][vn][inst] = []
words = self.tidy_text(line)
verses[reg][vt][vn][inst].append(words)
# done parsing
versetags = []
# we use our_verse_order to ensure, we insert lyrics in the same order
# as these appeared originally in the file
for [reg, vt, vn, inst] in our_verse_order:
if self._listHas(verses, [reg, vt, vn, inst]):
versetag = u'%s%s' % (vt, vn)
versetags.append(versetag)
lines = u'\n'.join(verses[reg][vt][vn][inst])
self.verses.append([versetag, lines])
SeqTypes = {
u'p': u'P1',
u'q': u'P2',
u'c': u'C1',
u't': u'C2',
u'b': u'B1',
u'w': u'B2',
u'e': u'E1'}
# Make use of Sequence data, determining the order of verses
try:
order = unicode(song.Sequence).strip().split(u',')
for tag in order:
if len(tag) == 0:
continue
elif tag[0].isdigit():
tag = u'V' + tag
elif SeqTypes.has_key(tag.lower()):
tag = SeqTypes[tag.lower()]
else:
continue
if tag in versetags:
self.verse_order_list.append(tag)
else:
log.info(u'Got order item %s, which is not in versetags,'
u'dropping item from presentation order', tag)
except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Sequence')
self._success = False
except AttributeError:
pass
def _listHas(self, lst, subitems):
for i in subitems:
if type(lst) == type({}) and lst.has_key(i):
lst = lst[i]
elif type(lst) == type([]) and i in lst:
lst = lst[i]
else:
return False
return True
def _extractRegion(self, line):
# this was true already: line[0:7] == u'[region':
right_bracket = line.find(u']')
return line[7:right_bracket].strip()

View File

@ -23,8 +23,11 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`importer` modules provides the general song import functionality.
"""
from opensongimport import OpenSongImport
from easislidesimport import EasiSlidesImport
from olpimport import OpenLPSongImport
from openlyricsimport import OpenLyricsImport
from wowimport import WowImport
@ -34,19 +37,19 @@ from songbeamerimport import SongBeamerImport
# Imports that might fail
try:
from olp1import import OpenLP1SongImport
has_openlp1 = True
HAS_OPENLP1 = True
except ImportError:
has_openlp1 = False
HAS_OPENLP1 = False
try:
from sofimport import SofImport
has_sof = True
HAS_SOF = True
except ImportError:
has_sof = False
HAS_SOF = False
try:
from oooimport import OooImport
has_ooo = True
HAS_OOO = True
except ImportError:
has_ooo = False
HAS_OOO = False
class SongFormat(object):
"""
@ -65,8 +68,9 @@ class SongFormat(object):
SongsOfFellowship = 6
Generic = 7
#CSV = 8
EasyWorship = 8
SongBeamer = 9
EasiSlides = 8
EasyWorship = 9
SongBeamer = 10
@staticmethod
def get_class(format):
@ -92,6 +96,8 @@ class SongFormat(object):
return OooImport
elif format == SongFormat.CCLI:
return CCLIFileImport
elif format == SongFormat.EasiSlides:
return EasiSlidesImport
elif format == SongFormat.EasyWorship:
return EasyWorshipSongImport
elif format == SongFormat.SongBeamer:
@ -112,20 +118,28 @@ class SongFormat(object):
SongFormat.CCLI,
SongFormat.SongsOfFellowship,
SongFormat.Generic,
SongFormat.EasiSlides,
SongFormat.EasyWorship,
SongFormat.SongBeamer
]
@staticmethod
def set_availability(format, available):
"""
Set the availability for a given song format.
"""
SongFormat._format_availability[format] = available
@staticmethod
def get_availability(format):
"""
Return the availability of a given song format.
"""
return SongFormat._format_availability.get(format, True)
SongFormat.set_availability(SongFormat.OpenLP1, has_openlp1)
SongFormat.set_availability(SongFormat.SongsOfFellowship, has_sof)
SongFormat.set_availability(SongFormat.Generic, has_ooo)
SongFormat.set_availability(SongFormat.OpenLP1, HAS_OPENLP1)
SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF)
SongFormat.set_availability(SongFormat.Generic, HAS_OOO)
__all__ = [u'SongFormat']
__all__ = [u'SongFormat']

View File

@ -194,8 +194,7 @@ class SongMediaItem(MediaManagerItem):
elif search_type == 5:
log.debug(u'Theme Search')
search_results = self.parent.manager.get_all_objects(Song,
Song.theme_name == search_keywords,
Song.search_lyrics.asc())
Song.theme_name == search_keywords, Song.search_lyrics.asc())
self.displayResultsSong(search_results)
def onSongListLoad(self):

View File

@ -83,7 +83,7 @@ class SongBeamerImport(SongImport):
def do_import(self):
"""
Recieve a single file, or a list of files to import.
Receive a single file or a list of files to import.
"""
if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(
@ -94,21 +94,21 @@ class SongBeamerImport(SongImport):
self.current_verse = u''
self.current_verse_type = u'V'
read_verses = False
self.file_name = os.path.split(file)[1]
file_name = os.path.split(file)[1]
self.import_wizard.incrementProgressBar(
u'Importing %s' % (self.file_name), 0)
u'Importing %s' % (file_name), 0)
if os.path.isfile(file):
detect_file = open(file, u'r')
details = chardet.detect(detect_file.read(2048))
detect_file.close()
infile = codecs.open(file, u'r', details['encoding'])
self.songData = infile.readlines()
songData = infile.readlines()
infile.close()
else:
return False
self.title = self.file_name.split('.sng')[0]
self.title = file_name.split('.sng')[0]
read_verses = False
for line in self.songData:
for line in songData:
# Just make sure that the line is of the type 'Unicode'.
line = unicode(line).strip()
if line.startswith(u'#') and not read_verses:
@ -136,7 +136,7 @@ class SongBeamerImport(SongImport):
self.finish()
self.import_wizard.incrementProgressBar(unicode(translate(
'SongsPlugin.SongBeamerImport', 'Importing %s...')) %
self.file_name)
file_name)
return True
def replace_html_tags(self):

View File

@ -62,7 +62,6 @@ class SongImport(QtCore.QObject):
Create defaults for properties - call this before each song
if importing many songs at once to ensure a clean beginning
"""
self.authors = []
self.title = u''
self.song_number = u''
self.alternate_title = u''
@ -251,20 +250,15 @@ class SongImport(QtCore.QObject):
def finish(self):
"""
All fields have been set to this song. Write it away
All fields have been set to this song. Write the song to disk.
"""
if not self.authors:
self.authors.append(unicode(translate('SongsPlugin.SongImport',
'Author unknown')))
self.commit_song()
def commit_song(self):
"""
Write the song and its fields to disk
"""
log.info(u'commiting song %s to database', self.title)
song = Song()
song.title = self.title
song.alternate_title = self.alternate_title
song.search_title = self.remove_punctuation(self.title).lower() \
+ '@' + self.remove_punctuation(self.alternate_title).lower()
song.song_number = self.song_number

View File

@ -107,63 +107,60 @@ class WowImport(SongImport):
def do_import(self):
"""
Recieve a single file, or a list of files to import.
Receive a single file or a list of files to import.
"""
if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(len(self.import_source))
for file in self.import_source:
self.author = u''
self.copyright = u''
self.file_name = os.path.split(file)[1]
author = u''
copyright = u''
file_name = os.path.split(file)[1]
self.import_wizard.incrementProgressBar(
u'Importing %s' % (self.file_name), 0)
u'Importing %s' % (file_name), 0)
# Get the song title
self.title = self.file_name.rpartition(u'.')[0]
self.songData = open(file, 'rb')
if self.songData.read(19) != u'WoW File\nSong Words':
self.title = file_name.rpartition(u'.')[0]
songData = open(file, 'rb')
if songData.read(19) != u'WoW File\nSong Words':
continue
# Seek to byte which stores number of blocks in the song
self.songData.seek(56)
self.no_of_blocks = ord(self.songData.read(1))
songData.seek(56)
no_of_blocks = ord(songData.read(1))
# Seek to the beging of the first block
self.songData.seek(82)
for block in range(self.no_of_blocks):
self.lines_to_read = ord(self.songData.read(1))
songData.seek(82)
for block in range(no_of_blocks):
self.lines_to_read = ord(songData.read(1))
# Skip 3 nulls to the beginnig of the 1st line
self.songData.seek(3, os.SEEK_CUR)
self.block_text = u''
songData.seek(3, os.SEEK_CUR)
block_text = u''
while self.lines_to_read:
self.length_of_line = ord(self.songData.read(1))
self.line_text = unicode(
self.songData.read(self.length_of_line), u'cp1252')
self.songData.seek(1, os.SEEK_CUR)
if self.block_text != u'':
self.block_text += u'\n'
self.block_text += self.line_text
songData.read(ord(songData.read(1))), u'cp1252')
songData.seek(1, os.SEEK_CUR)
if block_text != u'':
block_text += u'\n'
block_text += self.line_text
self.lines_to_read -= 1
self.block_type = BLOCK_TYPES[ord(self.songData.read(1))]
block_type = BLOCK_TYPES[ord(songData.read(1))]
# Skip 3 nulls at the end of the block
self.songData.seek(3, os.SEEK_CUR)
songData.seek(3, os.SEEK_CUR)
# Blocks are seperated by 2 bytes, skip them, but not if
# this is the last block!
if (block + 1) < self.no_of_blocks:
self.songData.seek(2, os.SEEK_CUR)
self.add_verse(self.block_text, self.block_type)
# Now to extact the author
self.author_length = ord(self.songData.read(1))
if self.author_length != 0:
self.author = unicode(
self.songData.read(self.author_length), u'cp1252')
if (block + 1) < no_of_blocks:
songData.seek(2, os.SEEK_CUR)
self.add_verse(block_text, block_type)
# Now to extract the author
author_length = ord(songData.read(1))
if author_length != 0:
author = unicode(songData.read(author_length), u'cp1252')
# Finally the copyright
self.copyright_length = ord(self.songData.read(1))
if self.copyright_length != 0:
self.copyright = unicode(
self.songData.read(self.copyright_length), u'cp1252')
self.parse_author(self.author)
self.add_copyright(self.copyright)
self.songData.close()
copyright_length = ord(songData.read(1))
if copyright_length != 0:
copyright = unicode(
songData.read(copyright_length), u'cp1252')
self.parse_author(author)
self.add_copyright(copyright)
songData.close()
self.finish()
self.import_wizard.incrementProgressBar(
u'Importing %s' % (self.file_name))
u'Importing %s' % (file_name))
return True

View File

@ -435,7 +435,7 @@ class OpenLyrics(object):
text += u'\n'
text += u'\n'.join([unicode(line) for line in lines.line])
verse_name = self._get(verse, u'name')
verse_type = unicode(VerseType.expand_string(verse_name[0]))[0]
verse_type = unicode(VerseType.to_string(verse_name[0]))[0]
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name)
verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
# OpenLyrics allows e. g. "c", but we need "c1".